Skip to content

Commit cd813ef

Browse files
authored
feature: Add pre-commit GH action workflow and swap in ruff (#7)
* Add pre-commit GH action workflow and swap in ruff * Adjust package file names * Re-introduce Optional typing due to typer limitation
1 parent 3baca2c commit cd813ef

File tree

9 files changed

+703
-135
lines changed

9 files changed

+703
-135
lines changed

.github/workflows/pre-commit.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: 'Run Pre-commit Hooks'
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
jobs:
12+
publish:
13+
name: Run Pre-commit Hooks
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout Source
17+
uses: actions/checkout@v3
18+
with:
19+
fetch-depth: 0
20+
- name: Setup Dependencies
21+
uses: './.github/actions/deps'
22+
with:
23+
python-version: '3.11'
24+
- name: Install MDL
25+
run: echo $'source \'https://rubygems.org\'\ngem \'mdl\', \'~> 0.12.0\'' > Gemfile
26+
- uses: ruby/setup-ruby@v1
27+
with:
28+
ruby-version: '3.0' # Not needed with a .ruby-version file
29+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
30+
- name: Install Pre-commit dependencies
31+
run: poetry poe install
32+
- uses: pre-commit/action@v3.0.0

.github/workflows/publish.yaml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
tags:
66
- '*'
77

8+
env:
9+
# TODO: Update the package name to match the name of your package.
10+
PACKAGE_NAME: python_template_x
11+
812
jobs:
913
publish:
1014
name: Publish Release
@@ -20,8 +24,8 @@ jobs:
2024
with:
2125
python-version: '3.11'
2226

23-
- name: Run Safety Check
24-
run: poetry poe safety
27+
- name: Run Security Check
28+
run: poetry poe security
2529

2630
- name: Get Python Module Version
2731
run: |
@@ -35,18 +39,17 @@ jobs:
3539
echo "Python Module Version: $MODULE_VERSION"
3640
if [[ "$TAG_VERSION" != "$MODULE_VERSION" ]]; then exit 1; fi
3741
38-
# TODO: Enable this to push to PyPi.
39-
# - name: Publish to PyPi
40-
# run: poetry publish --build
41-
# env:
42-
# POETRY_PYPI_TOKEN_PYPI: ${{ secrets.POETRY_PYPI_TOKEN_PYPI }}
42+
# TODO: Update the PyPi token to push to PyPi.
43+
- name: Publish to PyPi
44+
run: poetry publish --build
45+
env:
46+
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.POETRY_PYPI_TOKEN_PYPI }}
4347

4448
- name: Release
4549
uses: softprops/action-gh-release@v1
4650
with:
4751
discussion_category_name: announcements
4852
generate_release_notes: true
49-
# TODO: Update this to push PyPi package files to this release.
50-
# files: |
51-
# dist/app-${{env.MODULE_VERSION}}.tar.gz
52-
# dist/app-${{env.MODULE_VERSION}}-py3-none-any.whl
53+
files: |
54+
dist/${{env.PACKAGE_NAME}}-${{env.MODULE_VERSION}}.tar.gz
55+
dist/${{env.PACKAGE_NAME}}-${{env.MODULE_VERSION}}-py3-none-any.whl

.pre-commit-config.yaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ repos:
2727
additional_dependencies: [ "bandit[toml]" ]
2828
args: ["-c", "pyproject.toml"]
2929

30+
- repo: https://github.com/astral-sh/ruff-pre-commit
31+
# Ruff version.
32+
rev: 95f113d6340ab4348ecc5d912cf6e6b3465bfb86 # frozen: v0.0.277
33+
hooks:
34+
- id: ruff
35+
args: [ --fix, --exit-non-zero-on-fix ]
36+
3037
- repo: https://github.com/psf/black
3138
rev: bf7a16254ec96b084a6caf3d435ec18f0f245cc7 # frozen: 23.3.0
3239
hooks:
@@ -39,8 +46,8 @@ repos:
3946
- id: isort
4047
name: isort
4148

42-
- repo: https://github.com/astral-sh/ruff-pre-commit
49+
- repo: https://github.com/markdownlint/markdownlint
4350
# Ruff version.
44-
rev: 9f69b173ce0f0aee69b40a82938f8385e39a1b26 # frozen: v0.0.276
51+
rev: 5a6cc38e9dd10830df11fa5f6a5f44cfe83df389 # frozen: v0.12.0
4552
hooks:
46-
- id: ruff
53+
- id: markdownlint

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,31 @@
11
# python-template
2-
This project is an opinionated python template
2+
3+
This project is an opinionated python template.
4+
5+
## Usage
6+
7+
This project uses:
8+
9+
- [poetry](https://python-poetry.org/) for dependency management and packaging.
10+
- [poethepoet](https://poethepoet.natn.io/) for task running.
11+
- [pytest](https://docs.pytest.org/en/stable/) for testing.
12+
- [black](https://black.readthedocs.io/en/stable/) for auto-formatting.
13+
- [mypy](https://mypy.readthedocs.io/en/stable/) for static type checking.
14+
- [pre-commit](https://pre-commit.com/) for git hooks.
15+
- [ruff](https://beta.ruff.rs/docs/) for linting.
16+
- [mkdocs](https://www.mkdocs.org/) for documentation.
17+
18+
Ensure you have installed the relevant dependencies before continuing.
19+
20+
### Install dependencies
21+
22+
```bash
23+
poetry install
24+
```
25+
26+
### Run tests
27+
28+
```bash
29+
poetry poe test
30+
# or: poetry run poe test
31+
```

poetry.lock

Lines changed: 504 additions & 102 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tool.poetry]
2-
name = "app"
2+
name = "python-template-x"
33
version = "0.0.0"
44
description = "This is a python template."
55
authors = ["Mark Beacom <m@beacom.dev>"]
@@ -38,19 +38,108 @@ line-length = 120
3838
target-version = ["py311"]
3939

4040
[tool.ruff]
41+
# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.
42+
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
43+
# McCabe complexity (`C901`) by default.
44+
select = [
45+
"E", # pycodestyle errors
46+
"F", # pyflakes
47+
"B", # bugbear
48+
"W", # pycodestyle warnings
49+
"C90", # McCabe complexity
50+
"I", # isort
51+
"N", # pep8-naming
52+
"D", # pydocstyle
53+
"UP", # pyupgrade
54+
"ANN", # flake8-annotations
55+
"S", # bandit
56+
"ASYNC", # flake8-async
57+
"BLE", # flake8-blind-except
58+
"FBT", # flake8-boolean-trap
59+
"A", # flake8-builtins
60+
"COM", # flake8-commas
61+
"C4", # flake8-comprehensions
62+
"DTZ", # flake8-datetimez
63+
"T10", # flake8-debugger
64+
"EM", # flake8-errmsg
65+
"EXE", # flake8-executable
66+
"FA", # flake8-future-annotations
67+
"ISC", # flake8-implicit-str-concat
68+
"G", # flake8-logging-format
69+
"PT", # flake8-pytest-style
70+
"Q", # flake8-quotes
71+
"RSE", # flake8-raise
72+
"RET", # flake8-return
73+
"SLF", # flake8-self
74+
"SLOT", # flake8-slots
75+
"SIM", # flake8-simplify
76+
"TCH", # flake8-type-checking
77+
"FLY", # flynt
78+
]
79+
# Ignore E501 (bugbear line length) by default.
80+
ignore = [
81+
"E501", # line-too-long
82+
"D203", # one-blank-line-before-class
83+
"D213", # multi-line-summary-second-line - Multi-line docstring summary should start at the second line
84+
]
85+
86+
# Allow autofix for all enabled rules (when `--fix`) is provided.
87+
fixable = ["ALL"]
88+
unfixable = []
89+
90+
# Exclude a variety of commonly ignored directories.
91+
exclude = [
92+
".bzr",
93+
".direnv",
94+
".eggs",
95+
".git",
96+
".git-rewrite",
97+
".hg",
98+
".mypy_cache",
99+
".nox",
100+
".pants.d",
101+
".pytype",
102+
".ruff_cache",
103+
".svn",
104+
".tox",
105+
".venv",
106+
"__pypackages__",
107+
"_build",
108+
"buck-out",
109+
"build",
110+
"dist",
111+
"node_modules",
112+
"venv",
113+
]
114+
115+
# Same as our 120 Black setting.
41116
line-length = 120
117+
118+
# Allow unused variables when underscore-prefixed.
119+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
120+
121+
# Assume Python 3.11.
42122
target-version = "py311"
43123

124+
[tool.ruff.per-file-ignores]
125+
"tests/**/*.py" = [
126+
"S101", # Ignore assert statements in tests
127+
"ARG", # Ignore unused function args, e.g., fixtures
128+
"FBT", # Ignore booleans as positional arguments in tests, e.g., @pytest.mark.parametrize()
129+
]
130+
44131
[tool.poe.tasks]
45132
isort = "isort --profile=black ."
46133
black = "black ."
47134
check-black = {cmd = "black . --check --diff", help = "Validate styling with black"}
48135
check-isort = {cmd = "isort --check --profile=black .", help = "Validate import ordering with isort"}
49-
check-docstrings = "pydocstyle -e ."
136+
update-precommit-hooks = {cmd = "pre-commit autoupdate --freeze", help = "Update pre-commit hooks and freeze to SHAs"}
137+
check-precommit-hooks = {cmd = "pre-commit run --all-files", help = "Run pre-commit hooks on all files"}
50138
check-ruff = "ruff check python_template"
51-
check = ["check-isort", "check-black"]
52-
lint = ["check-docstrings", "check-ruff"]
53-
fix = ["isort", "black", "ruff"]
139+
check-mypy = "mypy python_template"
140+
check = ["check-ruff", "check-isort", "check-black", "check-mypy"]
141+
lint = ["ruff"]
142+
fix = ["ruff", "isort", "black"]
54143
test = "pytest --cov=python_template --cov-report=xml --cov-report=term"
55144
ruff = "ruff check --fix python_template"
56145
safety = "safety check"
@@ -64,26 +153,27 @@ build = "poetry build"
64153
python = "^3.8"
65154
typer = {extras = ["all"], version = "^0.9.0"}
66155

67-
68156
[tool.poetry.group.test.dependencies]
69157
pytest = "^7.4.0"
70158
pytest-cov = "^4.1.0"
71159
coverage = "^7.2.7"
72160

73-
74161
[tool.poetry.group.dev.dependencies]
75162
isort = {extras = ["toml"], version = "^5.12.0"}
76163
black = "^23.3.0"
77-
pydocstyle = "^6.3.0"
78164
mypy = "^1.4.1"
79165
debugpy = "^1.6.7"
80166
ruff = "^0.0.277"
81-
167+
poethepoet = "^0.20.0"
82168

83169
[tool.poetry.group.security.dependencies]
84170
safety = "^2.3.5"
85171
bandit = {extras = ["toml"], version = "^1.7.5"}
86172

173+
[tool.poetry.group.docs.dependencies]
174+
mkdocs = "^1.4.3"
175+
mkdocs-material = "^9.1.18"
176+
mkdocstrings = {extras = ["python"], version = "^0.22.0"}
87177

88178
[build-system]
89179
requires = ["poetry-core"]

python_template/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"""Handle initialization routines for the app module.
22
3-
Attributes:
3+
Attributes
4+
----------
45
__version__: The version of the this module.
56
67
"""
8+
from __future__ import annotations
79

810
__version__: str = "0.0.0"

python_template/cli.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,28 @@
44
from typing import Optional
55

66
import typer
7-
from rich.console import Console
87

98
from python_template import __version__
109

1110
app = typer.Typer(help="This is a python template.")
12-
console = Console()
1311

1412

15-
def version_callback(value: bool) -> None:
13+
def version_callback(value: bool) -> None: # noqa: FBT001
1614
"""Handle the version callback."""
1715
if value:
1816
typer.secho(f"python-template version: {__version__}", fg=typer.colors.BRIGHT_GREEN, bold=True)
19-
raise typer.Exit()
17+
raise typer.Exit
2018

2119

2220
@app.command()
2321
def main(
24-
version: Optional[bool] = typer.Option(
25-
None, "--version", callback=version_callback, is_eager=True, help="Display the current python template version"
22+
# UP007 ignored here due to: https://github.com/tiangolo/typer/pull/522
23+
version: Optional[bool] = typer.Option( # noqa: B008, UP007
24+
None,
25+
"--version",
26+
callback=version_callback,
27+
is_eager=True,
28+
help="Display the current python template version",
2629
),
2730
) -> None:
2831
"""Run the main python template logic."""

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import typer
66

77

8-
@pytest.fixture
9-
def app():
8+
@pytest.fixture()
9+
def app() -> typer.Typer:
1010
"""Define the Typer CLI fixture."""
1111
return typer.Typer()

0 commit comments

Comments
 (0)