Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lykhvar committed Oct 3, 2024
0 parents commit fd4a751
Show file tree
Hide file tree
Showing 14 changed files with 607 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
30 changes: 30 additions & 0 deletions .github/workflows/auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: auto-merge

on:
pull_request_target:
types:
- opened
- reopened
- synchronize
branches:
- main

jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}

steps:
- name: Wait for tests to succeed
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.ref }}
check-name: check
wait-interval: 10
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Enable auto-merge for Dependabot PRs
run: gh pr merge --auto --squash ${{ github.event.pull_request.html_url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50 changes: 50 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: test

on:
push:
branches:
- main
pull_request:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

env:
STABLE_PYTHON_VERSION: '3.12'
PYTHONUNBUFFERED: "1"
FORCE_COLOR: "1"

jobs:
run:
name: Python ${{ matrix.python-version }} on ${{ startsWith(matrix.os, 'macos-') && 'macOS' || startsWith(matrix.os, 'windows-') && 'Windows' || 'Linux' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Ensure latest pip
run: python -m pip install --upgrade pip

- name: Install hatch
run: |
pip install hatch
- name: Run static analysis
run: hatch run lint:style

- name: Run tests
run: hatch run test
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
__pycache__/
*.py[cod]
*.dll
*.so
*.log
*.swp
/.benchmarks/
/.cache/
/.env/
/.idea/
/.mypy_cache/
/.pytest_cache/
/.ruff_cache/
/.vscode/
/backend/dist/
/dist/
/site/
/.coverage*
/coverage.*

21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023-present Artem Lykhvar <me@a10r.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# ppcli

[![PyPI - Version](https://img.shields.io/pypi/v/ppcli.svg)](https://pypi.org/project/ppcli)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ppcli.svg)](https://pypi.org/project/ppcli)

-----
`ppcli` stands for **pyproject CLI**. It is a Python package designed to provide an easy way to specify and manage auxiliary commands within a `pyproject.toml` file for any Python project.

## Purpose

The primary purpose of `ppcli` is to allow developers to define and manage common project tasks, such as test, lint, and migration commands, directly within the `pyproject.toml` file. This ensures that all project-specific commands are centralized and easily accessible.

## Installation

You can install `ppcli` via pip:

```console
pip install ppcli
```

## Usage
After installing ppcli, you can define your project-specific commands within your pyproject.toml file under the `[tool.ppcli]` section.

### Example pyproject.toml Configuration
```toml
[tool.ppcli]
lint="black --check --diff ."
fmt="black ."
clean = [
"find . -type d -name __pycache__ -empty -print0 | xargs --null --no-run-if-empty rmdir",
"coverage erase",
]
test = [
"clean",
"pytest --cov --blockage -x -s --no-header -ra",
]
```
### Defining and Combining Commands
* **Single Command**: Each key under [tool.ppcli] represents a command that can be executed. The value can be a single command string or a list of commands.
* **Combined Commands**: Use the keys of other commands to create combined tasks. In the example above, the test command executes the clean command followed by pytest.

### Running Commands

To execute the defined commands, simply run the ppcli tool followed by the command name:

```console
ppcli <command>
```
For example:

```console
ppcli lint
ppcli fmt
ppcli test
```

## Contributing

Contributions are welcome! Please open an issue or a pull request to contribute.

## License
This project is licensed under the [MIT](https://spdx.org/licenses/MIT.html) License. See the [LICENSE](/LICENSE) file for more details.

194 changes: 194 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "ppcli"
dynamic = ["version"]
description = "Dynamic CLI tool to manage project-specific commands using pyproject.toml configuration"
readme = "README.md"
requires-python = ">=3.8"
license = "MIT"
keywords = [
"cli",
"pyproject",
"task-runner",
"automation",
"command-line",
"project-management",
"dev-tools",
"configuration",
"utility",
"scripting",
"tooling",
"developer-tools",
]
authors = [
{ name = "Artem Lykhvar", email = "me@a10r.com" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"click>=8.0.6",
]

[project.urls]
Documentation = "https://github.com/lykhvar/ppcli#readme"
Issues = "https://github.com/lykhvar/ppcli/issues"
Source = "https://github.com/lykhvar/ppcli"

[project.scripts]
ppcli = "ppcli.app:cli"

[tool.hatch.version]
path = "src/ppcli/__about__.py"

[tool.hatch.build.targets.sdist]
exclude = [
"/.github",
"/scripts",
"/tests",
]

[tool.hatch.build.targets.wheel]
packages = ["src/ppcli"]

[tool.hatch.envs.default]
dependencies = [
"coverage[toml]>=6.5",
"pytest",
"pytest-cov",
"pytest-rerunfailures",
"pytest-xdist",
]
[tool.hatch.envs.default.scripts]
test = "pytest {args:tests}"
test-cov = "pytest --cov --cov-report={env:COVERAGE_REPORT:term-missing} --cov-config=pyproject.toml"
full = "test-cov -n auto --reruns 5 --reruns-delay 3 -r aR {args:tests}"

[[tool.hatch.envs.all.matrix]]
python = ["3.8", "3.9", "3.10", "3.11", "3.12"]

[tool.hatch.envs.lint]
detached = true
dependencies = [
"black>=23.1.0",
"mypy>=1.0.0",
"ruff>=0.0.243",
]

[tool.hatch.envs.lint.scripts]
typing = "mypy --install-types --non-interactive {args:src/ppcli tests}"
style = [
"ruff check {args:.}",
"black --check --diff {args:.}",
]
fmt = [
"black {args:.}",
"ruff check --fix {args:.}",
"style",
]
all = [
"style",
"typing",
]

[tool.hatch.envs.coverage]
detached = true
dependencies = [
"coverage[toml]>=6.2",
"lxml",
]

[tool.hatch.envs.coverage.scripts]
combine = "coverage combine {args}"
report-xml = "coverage xml"
report-uncovered-html = "coverage html --skip-covered --skip-empty"
generate-summary = "python scripts/generate_coverage_summary.py"
write-summary-report = "python scripts/write_coverage_summary_report.py"

[tool.black]
target-version = ["py38"]
line-length = 79
skip-string-normalization = true

[tool.ruff]
target-version = "py38"
line-length = 79

[tool.ruff.lint]
select = [
"A",
"ARG",
"B",
"C",
"DTZ",
"E",
"EM",
"F",
"FBT",
"I",
"ICN",
"N",
"PLC",
"PLE",
"PLR",
"PLW",
"Q",
"RUF",
"S",
"T",
"TID",
"UP",
"W",
"YTT",
]
ignore = [
# Allow non-abstract empty methods in abstract base classes
"B027",
# Allow boolean positional values in function calls, like `dict.get(... True)`
"FBT003",
# Ignore checks for possible passwords
"S105", "S106", "S107",
# Ignore complexity
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915",
"EM101"
]
unfixable = [
# Don't touch unused imports
"F401",
]

[tool.ruff.lint.isort]
known-first-party = ["ppcli"]

[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"

[tool.ruff.lint.per-file-ignores]
# Tests can use magic values, assertions, and relative imports
"tests/**/*" = ["PLR2004", "S101", "TID252"]

[tool.coverage.run]
source_pkgs = ["ppcli", "tests"]
branch = true
parallel = true

[tool.coverage.paths]
ppcli = ["src/ppcli", "*/ppcli/src/ppcli"]
tests = ["tests", "*/ppcli/tests"]

[tool.coverage.report]
show_missing = true
exclude_lines = [
"no cov",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
]
4 changes: 4 additions & 0 deletions src/ppcli/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: 2023-present Artem Lykhvar <me@a10r.com>
#
# SPDX-License-Identifier: MIT
__version__ = "0.0.1"
Loading

0 comments on commit fd4a751

Please sign in to comment.