Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/action@v3.0.0
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 <m@beacom.dev>"]
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()