Skip to content
Open
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
30 changes: 9 additions & 21 deletions project_template/.github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,53 +1,41 @@
name: CD

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
release:
types:
- published

jobs:
dist:
needs: [pre-commit]
name: Distribution build
name: Build distribution
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Build sdist and wheel
run: pipx run build

- uses: actions/upload-artifact@v3
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- run: uv build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist

- name: Check products
run: pipx run twine check dist/*

publish:
needs: [dist]
name: Publish to PyPI
environment: pypi
permissions:
id-token: write
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'

steps:
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: artifact
name: dist
path: dist

- uses: pypa/gh-action-pypi-publish@release/v1
if: github.event_name == 'release' && github.event.action == 'published'
with:
# Remove this line to publish to PyPI
repository-url: https://test.pypi.org/legacy/
65 changes: 30 additions & 35 deletions project_template/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,54 +1,49 @@
name: CI

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
branches: [main]
pull_request:

concurrency:
group: {% raw %}${{ github.workflow }}-${{ github.ref }}{% endraw %}
cancel-in-progress: true

jobs:
pre-commit:
name: Format + lint code
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: "3.x"
- uses: pre-commit/action@v3.0.0
enable-cache: true
- run: uv run ruff check --output-format=github .
- run: uv run ruff format --check .

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
extra_args: --hook-stage manual --all-files
enable-cache: true
- run: uvx ty check

checks:
name: {% raw %}Run tests for Python ${{ matrix.python-version }} on ${{ matrix.runs-on }}{% endraw %}
runs-on: {% raw %}${{ matrix.runs-on }}{% endraw %}
needs: [pre-commit]
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["{{ min_python_version }}", "3.12"] # test oldest and latest supported versions
runs-on: [ubuntu-latest, macos-latest] # can be extended to other OSes, e.g. [ubuntu-latest, macos-latest, windows-latest]

python-version: [{% for v in range(min_python_version.split('.')[1]|int, 14) %}"3.{{ v }}"{% if not loop.last %}, {% endif %}{% endfor %}]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-python@v4
- uses: astral-sh/setup-uv@v5
with:
python-version: {% raw %}${{ matrix.python-version }}{% endraw %}
allow-prereleases: true

- name: Install package
run: python -m pip install .[dev]

- name: Test package
run: >-
python -m pytest -ra --cov --cov-report=xml --cov-report=term
--durations=20

- name: Upload coverage report
uses: codecov/codecov-action@v3.1.4
enable-cache: true
- run: uv sync --locked --group test
- run: uv run pytest --cov --cov-report=xml
- uses: codecov/codecov-action@v5
if: {% raw %}matrix.python-version == '3.13'{% endraw %}
with:
files: coverage.xml
48 changes: 20 additions & 28 deletions project_template/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,39 +1,31 @@
ci:
autoupdate_commit_msg: "chore: update pre-commit hooks"
autofix_commit_msg: "style: pre-commit fixes"

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v6.0.0"
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-merge-conflict
- id: check-added-large-files
- id: debug-statements
- id: end-of-file-fixer
- id: mixed-line-ending
- id: name-tests-test
args: ["--pytest-test-first"]
- id: requirements-txt-fixer
- id: trailing-whitespace

- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24
hooks:
- id: validate-pyproject

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.15.6"
rev: v0.15.6
hooks:
# first, lint + autofix
- id: ruff
types_or: [python, pyi, jupyter]
args: ["--fix", "--show-fixes"]
# then, format
- id: ruff-check
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.19.1"
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.10.9
hooks:
- id: mypy
files: src
args: []
additional_dependencies:
- pytest
- id: uv-lock

# NOTE: ty pre-commit hook not yet available (astral-sh/ty#269).
# Add it here when Astral ships an official hook.
91 changes: 35 additions & 56 deletions project_template/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ test = [
lint = [
"ruff>=0.15",
]
{%- if include_docs %}
docs = [
"mkdocs-material>=9.0",
"mkdocstrings[python]>=0.27",
]
{%- endif %}

[project.urls]
Homepage = "{{ url }}"
Expand Down Expand Up @@ -77,67 +83,40 @@ port.exclude_lines = [
'if typing.TYPE_CHECKING:',
]

{% if typing != "no_typing" -%}
[tool.mypy]
files = ["src", "tests"]
python_version = "{{ min_python_version }}"
show_error_codes = true
warn_unreachable = true
disallow_untyped_defs = false
disallow_incomplete_defs = false
check_untyped_defs = true
{% if typing == "loose" -%}
strict = false
{% elif typing == "strict" -%}
strict = true
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
[tool.ty.environment]
python-version = "{{ min_python_version }}"

[[tool.mypy.overrides]]
module = "{{ python_name }}.*"
disallow_untyped_defs = true
disallow_incomplete_defs = true
{%- endif %}
{%- endif %}
[tool.ty.rules]
unused-ignore-comment = "warn"

[tool.ty.src]
include = ["src", "tests"]

[tool.ruff]
line-length = 88
target-version = "py{{ min_python_version | replace('.', '') }}"
src = ["src"]
exclude = []
line-length = 88 # how long you want lines to be

[tool.ruff.format]
docstring-code-format = true # code snippets in docstrings will be formatted

[tool.ruff.lint]
select = [
"E", "F", "W", # flake8
"B", # flake8-bugbear
"I", # isort
"ARG", # flake8-unused-arguments
"C4", # flake8-comprehensions
"EM", # flake8-errmsg
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"G", # flake8-logging-format
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PT", # flake8-pytest-style
"RET", # flake8-return
"RUF", # Ruff-specific
"SIM", # flake8-simplify
"UP", # pyupgrade
"YTT", # flake8-2020
"EXE", # flake8-executable
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"C4", # flake8-comprehensions
"RUF", # Ruff-specific rules
]
ignore = [
"PLR", # Design related pylint codes
"ISC001", # Conflicts with formatter
]
unfixable = [
"F401", # Would remove unused imports
"F841", # Would remove unused variables
]
flake8-unused-arguments.ignore-variadic-names = true # allow unused *args/**kwargs
{%- if typing != "no_typing" -%}
isort.required-imports = ["from __future__ import annotations"]
{%- endif %}
ignore = ["E501"]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "D"]

[tool.ruff.lint.isort]
known-first-party = ["{{ python_name }}"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# {{ project_name }}

{{ project_short_description }}

<!-- TODO: Add project overview, installation instructions, and quickstart guide. -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# API Reference

::: {{ python_name }}
26 changes: 26 additions & 0 deletions project_template/{% if include_docs %}mkdocs.yml{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
site_name: "{{ project_name }}"
site_url: "https://{{ org }}.github.io/{{ project_name }}"
repo_url: "{{ url }}"

theme:
name: material
features:
- content.code.copy
- navigation.sections
- search.highlight

plugins:
- search
- mkdocstrings:
handlers:
python:
paths: [src]

nav:
- Home: index.md
- API Reference: reference.md

markdown_extensions:
- admonition
- pymdownx.highlight
- pymdownx.superfences
Loading