Skip to content

Commit

Permalink
feature: Add pre-commit GH action workflow and swap in ruff (#7)
Browse files Browse the repository at this point in the history
* Add pre-commit GH action workflow and swap in ruff

* Adjust package file names

* Re-introduce Optional typing due to typer limitation
  • Loading branch information
mbeacom authored Jul 9, 2023
1 parent 3baca2c commit cd813ef
Show file tree
Hide file tree
Showing 9 changed files with 703 additions and 135 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: 'Run Pre-commit Hooks'

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

jobs:
publish:
name: Run Pre-commit Hooks
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Dependencies
uses: './.github/actions/deps'
with:
python-version: '3.11'
- name: Install MDL
run: echo $'source \'https://rubygems.org\'\ngem \'mdl\', \'~> 0.12.0\'' > Gemfile
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0' # Not needed with a .ruby-version file
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Install Pre-commit dependencies
run: poetry poe install
- uses: pre-commit/[email protected]
25 changes: 14 additions & 11 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
tags:
- '*'

env:
# TODO: Update the package name to match the name of your package.
PACKAGE_NAME: python_template_x

jobs:
publish:
name: Publish Release
Expand All @@ -20,8 +24,8 @@ jobs:
with:
python-version: '3.11'

- name: Run Safety Check
run: poetry poe safety
- name: Run Security Check
run: poetry poe security

- name: Get Python Module Version
run: |
Expand All @@ -35,18 +39,17 @@ jobs:
echo "Python Module Version: $MODULE_VERSION"
if [[ "$TAG_VERSION" != "$MODULE_VERSION" ]]; then exit 1; fi
# TODO: Enable this to push to PyPi.
# - name: Publish to PyPi
# run: poetry publish --build
# env:
# POETRY_PYPI_TOKEN_PYPI: ${{ secrets.POETRY_PYPI_TOKEN_PYPI }}
# TODO: Update the PyPi token to push to PyPi.
- name: Publish to PyPi
run: poetry publish --build
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.POETRY_PYPI_TOKEN_PYPI }}

- name: Release
uses: softprops/action-gh-release@v1
with:
discussion_category_name: announcements
generate_release_notes: true
# TODO: Update this to push PyPi package files to this release.
# files: |
# dist/app-${{env.MODULE_VERSION}}.tar.gz
# dist/app-${{env.MODULE_VERSION}}-py3-none-any.whl
files: |
dist/${{env.PACKAGE_NAME}}-${{env.MODULE_VERSION}}.tar.gz
dist/${{env.PACKAGE_NAME}}-${{env.MODULE_VERSION}}-py3-none-any.whl
13 changes: 10 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ repos:
additional_dependencies: [ "bandit[toml]" ]
args: ["-c", "pyproject.toml"]

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: 95f113d6340ab4348ecc5d912cf6e6b3465bfb86 # frozen: v0.0.277
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]

- repo: https://github.com/psf/black
rev: bf7a16254ec96b084a6caf3d435ec18f0f245cc7 # frozen: 23.3.0
hooks:
Expand All @@ -39,8 +46,8 @@ repos:
- id: isort
name: isort

- repo: https://github.com/astral-sh/ruff-pre-commit
- repo: https://github.com/markdownlint/markdownlint
# Ruff version.
rev: 9f69b173ce0f0aee69b40a82938f8385e39a1b26 # frozen: v0.0.276
rev: 5a6cc38e9dd10830df11fa5f6a5f44cfe83df389 # frozen: v0.12.0
hooks:
- id: ruff
- id: markdownlint
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,31 @@
# python-template
This project is an opinionated python template

This project is an opinionated python template.

## Usage

This project uses:

- [poetry](https://python-poetry.org/) for dependency management and packaging.
- [poethepoet](https://poethepoet.natn.io/) for task running.
- [pytest](https://docs.pytest.org/en/stable/) for testing.
- [black](https://black.readthedocs.io/en/stable/) for auto-formatting.
- [mypy](https://mypy.readthedocs.io/en/stable/) for static type checking.
- [pre-commit](https://pre-commit.com/) for git hooks.
- [ruff](https://beta.ruff.rs/docs/) for linting.
- [mkdocs](https://www.mkdocs.org/) for documentation.

Ensure you have installed the relevant dependencies before continuing.

### Install dependencies

```bash
poetry install
```

### Run tests

```bash
poetry poe test
# or: poetry run poe test
```
606 changes: 504 additions & 102 deletions poetry.lock

Large diffs are not rendered by default.

108 changes: 99 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.poetry]
name = "app"
name = "python-template-x"
version = "0.0.0"
description = "This is a python template."
authors = ["Mark Beacom <[email protected]>"]
Expand Down Expand Up @@ -38,19 +38,108 @@ line-length = 120
target-version = ["py311"]

[tool.ruff]
# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = [
"E", # pycodestyle errors
"F", # pyflakes
"B", # bugbear
"W", # pycodestyle warnings
"C90", # McCabe complexity
"I", # isort
"N", # pep8-naming
"D", # pydocstyle
"UP", # pyupgrade
"ANN", # flake8-annotations
"S", # bandit
"ASYNC", # flake8-async
"BLE", # flake8-blind-except
"FBT", # flake8-boolean-trap
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"DTZ", # flake8-datetimez
"T10", # flake8-debugger
"EM", # flake8-errmsg
"EXE", # flake8-executable
"FA", # flake8-future-annotations
"ISC", # flake8-implicit-str-concat
"G", # flake8-logging-format
"PT", # flake8-pytest-style
"Q", # flake8-quotes
"RSE", # flake8-raise
"RET", # flake8-return
"SLF", # flake8-self
"SLOT", # flake8-slots
"SIM", # flake8-simplify
"TCH", # flake8-type-checking
"FLY", # flynt
]
# Ignore E501 (bugbear line length) by default.
ignore = [
"E501", # line-too-long
"D203", # one-blank-line-before-class
"D213", # multi-line-summary-second-line - Multi-line docstring summary should start at the second line
]

# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []

# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
]

# Same as our 120 Black setting.
line-length = 120

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

# Assume Python 3.11.
target-version = "py311"

[tool.ruff.per-file-ignores]
"tests/**/*.py" = [
"S101", # Ignore assert statements in tests
"ARG", # Ignore unused function args, e.g., fixtures
"FBT", # Ignore booleans as positional arguments in tests, e.g., @pytest.mark.parametrize()
]

[tool.poe.tasks]
isort = "isort --profile=black ."
black = "black ."
check-black = {cmd = "black . --check --diff", help = "Validate styling with black"}
check-isort = {cmd = "isort --check --profile=black .", help = "Validate import ordering with isort"}
check-docstrings = "pydocstyle -e ."
update-precommit-hooks = {cmd = "pre-commit autoupdate --freeze", help = "Update pre-commit hooks and freeze to SHAs"}
check-precommit-hooks = {cmd = "pre-commit run --all-files", help = "Run pre-commit hooks on all files"}
check-ruff = "ruff check python_template"
check = ["check-isort", "check-black"]
lint = ["check-docstrings", "check-ruff"]
fix = ["isort", "black", "ruff"]
check-mypy = "mypy python_template"
check = ["check-ruff", "check-isort", "check-black", "check-mypy"]
lint = ["ruff"]
fix = ["ruff", "isort", "black"]
test = "pytest --cov=python_template --cov-report=xml --cov-report=term"
ruff = "ruff check --fix python_template"
safety = "safety check"
Expand All @@ -64,26 +153,27 @@ build = "poetry build"
python = "^3.8"
typer = {extras = ["all"], version = "^0.9.0"}


[tool.poetry.group.test.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
coverage = "^7.2.7"


[tool.poetry.group.dev.dependencies]
isort = {extras = ["toml"], version = "^5.12.0"}
black = "^23.3.0"
pydocstyle = "^6.3.0"
mypy = "^1.4.1"
debugpy = "^1.6.7"
ruff = "^0.0.277"

poethepoet = "^0.20.0"

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

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

[build-system]
requires = ["poetry-core"]
Expand Down
4 changes: 3 additions & 1 deletion python_template/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Handle initialization routines for the app module.
Attributes:
Attributes
----------
__version__: The version of the this module.
"""
from __future__ import annotations

__version__: str = "0.0.0"
15 changes: 9 additions & 6 deletions python_template/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
from typing import Optional

import typer
from rich.console import Console

from python_template import __version__

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


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


@app.command()
def main(
version: Optional[bool] = typer.Option(
None, "--version", callback=version_callback, is_eager=True, help="Display the current python template version"
# UP007 ignored here due to: https://github.com/tiangolo/typer/pull/522
version: Optional[bool] = typer.Option( # noqa: B008, UP007
None,
"--version",
callback=version_callback,
is_eager=True,
help="Display the current python template version",
),
) -> None:
"""Run the main python template logic."""
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import typer


@pytest.fixture
def app():
@pytest.fixture()
def app() -> typer.Typer:
"""Define the Typer CLI fixture."""
return typer.Typer()

0 comments on commit cd813ef

Please sign in to comment.