From 8d11d5298fc3c53a2f4139f10cd00b89575efb0f Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Wed, 7 Oct 2026 20:44:10 +0200 Subject: [PATCH 1/9] docs: update developing.rst and add readthedocs integration --- .readthedocs.yaml | 34 +++++++++++++++++++++ doc/developing.rst | 73 ++++++++++++++++++++++++++++------------------ 2 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..a5fcb53 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,34 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-lts-latest + tools: + python: "3.14" + +# Build documentation in the "doc/" directory with Sphinx +sphinx: + configuration: doc/conf.py + # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs + # builder: "dirhtml" + # Fail on all warnings to avoid broken references + # fail_on_warning: true + +# Optionally build your docs in additional formats such as PDF and ePub +# formats: +# - pdf +# - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - method: pip + path: . + extra_requirements: + - docs \ No newline at end of file diff --git a/doc/developing.rst b/doc/developing.rst index a307f9f..959d1d1 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -17,9 +17,7 @@ Then go to the dectate directory:: $ cd dectate -Make sure you have virtualenv_ installed. - -Create a new virtualenv for Python 3 inside the dectate directory:: +Create a new virtualenv inside the dectate directory:: $ python -m venv --upgrade-deps .venv @@ -30,7 +28,7 @@ Activate the virtualenv:: Install the various dependencies and development tools from develop_requirements.txt:: - $ pip install -Ur develop_requirements.txt + (.venv) $ pip install -Ur develop_requirements.txt For upgrading the requirements just run the command again. @@ -39,7 +37,6 @@ For upgrading the requirements just run the command again. The following commands work only if you have the virtualenv activated. .. _github: https://docs.github.com/en/authentication/connecting-to-github-with-ssh -.. _virtualenv: https://pypi.org/project/virtualenv Install pre-commit hook for Black integration --------------------------------------------- @@ -47,7 +44,7 @@ Install pre-commit hook for Black integration We're using Black_ for formatting the code and it's recommended to install the `pre-commit hook`_ for Black integration before committing:: - $ pre-commit install + (.venv) $ pre-commit install .. _`pre-commit hook`: https://black.readthedocs.io/en/stable/integrations/source_version_control.html @@ -56,11 +53,11 @@ Running the tests You can run the tests using `pytest`_:: - $ pytest + (.venv) $ pytest To generate test coverage information as HTML do:: - $ pytest --cov --cov-report html + (.venv) $ pytest --cov --cov-report html You can then point your web browser to the ``htmlcov/index.html`` file in the project directory and click on modules to see detailed coverage @@ -73,13 +70,24 @@ Black To format the code with the `Black Code Formatter`_ run in the root directory:: - $ black dectate + (.venv) $ black dectate Black has also integration_ for the most popular editors. .. _`Black Code Formatter`: https://black.readthedocs.io .. _integration: https://black.readthedocs.io/en/stable/editor_integration.html +isort +----- + +To sort imports with isort_ from the project directory do:: + + (.venv) $ isort . + +isort uses the settings in ``pyproject.toml``. + +.. _isort: https://pycqa.github.io/isort/ + flake8 ------ @@ -88,21 +96,30 @@ mistakes using pyflakes_, checks for PEP8_ style compliance and can do `cyclomatic complexity`_ checking. To do pyflakes and pep8 checking do:: - $ flake8 dectate + (.venv) $ flake8 dectate To also show cyclomatic complexity, use this command:: - $ flake8 --max-complexity=10 dectate - + (.venv) $ flake8 --max-complexity=10 dectate .. _flake8: https://pypi.org/project/flake8 - .. _pyflakes: https://pypi.org/project/pyflakes - .. _pep8: https://peps.python.org/pep-0008 - .. _`cyclomatic complexity`: https://en.wikipedia.org/wiki/Cyclomatic_complexity +Type checking +------------- + +Dectate uses mypy_ and pyright_ for type checking. Run either checker +from the project directory:: + + (.venv) $ mypy + (.venv) $ pyright + +Both checkers use the settings in ``pyproject.toml``. + +.. _mypy: https://mypy.readthedocs.io/ +.. _pyright: https://microsoft.github.io/pyright/ Running the documentation tests ------------------------------- @@ -110,32 +127,32 @@ Running the documentation tests The documentation contains code. To check these code snippets, you can run this code using this command:: - (py3) $ sphinx-build -b doctest doc doc/build/doctest + (.venv) $ sphinx-build -b doctest doc doc/_build/doctest Or alternatively if you have ``Make`` installed:: - (py3) $ cd doc - (py3) $ make doctest + (.venv) $ cd doc + (.venv) $ make doctest Or from the Dectate project directory:: - (py3) $ make -C doc doctest + (.venv) $ make -C doc doctest Building the HTML documentation ------------------------------- To build the HTML documentation (output in ``doc/_build/html``), run:: - $ sphinx-build doc doc/_build/html + (.venv) $ sphinx-build doc doc/_build/html Or alternatively if you have ``Make`` installed:: - $ cd doc - $ make html + (.venv) $ cd doc + (.venv) $ make html Or from the Dectate project directory:: - $ make -C doc html + (.venv) $ make -C doc html Tox --- @@ -154,16 +171,16 @@ One tool you can use to install multiple versions of Python is pyenv_. To find out which test environments are defined for Dectate in tox.ini run:: - $ tox -l + (.venv) $ tox -l You can run all tox tests with:: - $ tox + (.venv) $ tox You can also specify a test environment to run e.g.:: - $ tox -e py311 - $ tox -e lint - $ tox -e docs + (.venv) $ tox -e py311 + (.venv) $ tox -e lint + (.venv) $ tox -e docs .. _pyenv: https://github.com/pyenv/pyenv From ce9d0492a3b4dc1f7f3461f7ea93860a2f9f78f2 Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Wed, 7 Oct 2026 21:41:16 +0200 Subject: [PATCH 2/9] chore: remove Python 3.10, add Python 3.15, switch to Pypy 3.12 and adjust code --- .github/workflows/main.yml | 2 +- .pre-commit-config.yaml | 2 +- dectate/app.py | 2 +- pyproject.toml | 30 +++++++++++++++--------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0fcdb62..4c5e82b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "pypy3.11"] + python-version: ["3.11", "3.12", "3.13", "3.14", "3.15", "pypy-3.12"] # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ea0c14..b692006 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,4 +12,4 @@ repos: rev: v3.21.2 hooks: - id: pyupgrade - args: [--py310-plus] + args: [--py311-plus] diff --git a/dectate/app.py b/dectate/app.py index c15e328..bc040e7 100644 --- a/dectate/app.py +++ b/dectate/app.py @@ -8,6 +8,7 @@ Concatenate, Generic, ParamSpec, + Self, TypeVar, cast, ) @@ -16,7 +17,6 @@ if TYPE_CHECKING: from collections.abc import Callable, Collection, Iterator - from typing_extensions import Self from .config import Action, Composite, DirectiveAbbreviation from .types import DirectiveCallable diff --git a/pyproject.toml b/pyproject.toml index 0f1f16e..921db18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,17 +16,17 @@ classifiers = [ "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Application Frameworks", "Programming Language :: Python", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Development Status :: 5 - Production/Stable", ] -requires-python = ">= 3.10" +requires-python = ">= 3.11" [project.urls] Documentation = "https://dectate.readthedocs.io" @@ -77,7 +77,7 @@ extend-select = ["TC", "TC1"] max-line-length = 88 [tool.mypy] -python_version = "3.10" +python_version = "3.11" strict = true files = ["."] warn_unreachable = true @@ -104,11 +104,11 @@ reportUntypedFunctionDecorator = "none" [tool.tox] requires = ["tox>=4"] env_list = [ - "py310", "py311", "py312", "py313", "py314", + "py315", "pypy3", "coverage", "pre-commit", @@ -119,12 +119,12 @@ env_list = [ skip_missing_interpreters = true [tool.tox.gh.python] -"3.10" = ["py310"] "3.11" = ["py311"] "3.12" = ["py312"] "3.13" = ["py313"] "3.14" = ["py314", "pre-commit", "coverage", "mypy", "pyright"] -"pypy-3.11" = ["pypy3"] +"3.15" = ["py315"] +"pypy-3.12" = ["pypy3"] [tool.tox.env_run_base] package = "editable" @@ -132,14 +132,14 @@ extras = ["test"] commands = [["pytest", "{posargs:dectate}"]] [tool.tox.env.coverage] -base_python = ["python3"] +base_python = ["python3.14"] extras = ["test", "coverage"] commands = [ ["pytest", "--cov", "--cov-fail-under=100", "{posargs:dectate}"], ] [tool.tox.env.pre-commit] -base_python = ["python3"] +base_python = ["python3.14"] package = "skip" deps = ["pre-commit"] commands = [ @@ -147,36 +147,36 @@ commands = [ ] [tool.tox.env.docs] -base_python = ["python3"] +base_python = ["python3.14"] extras = ["docs"] commands = [ ["sphinx-build", "-b", "doctest", "doc", "{env_tmp_dir}"], ] [tool.tox.env.mypy] -base_python = ["python3"] +base_python = ["python3.14"] extras = ["mypy", "docs"] commands = [ - ["mypy", "--python-version", "3.10"], ["mypy", "--python-version", "3.11"], ["mypy", "--python-version", "3.12"], ["mypy", "--python-version", "3.13"], ["mypy", "--python-version", "3.14"], + ["mypy", "--python-version", "3.15"], ] [tool.tox.env.pyright] -base_python = ["python3"] +base_python = ["python3.14"] extras = ["pyright", "docs"] commands = [ - ["pyright", "--pythonversion", "3.10"], ["pyright", "--pythonversion", "3.11"], ["pyright", "--pythonversion", "3.12"], ["pyright", "--pythonversion", "3.13"], ["pyright", "--pythonversion", "3.14"], + ["pyright", "--pythonversion", "3.15"], ] [tool.black] -target-version = ['py310', 'py311', 'py312', 'py313', 'py314'] +target-version = ['py311', 'py312', 'py313', 'py314', 'py315'] include = '\.pyi?$' exclude = ''' ( @@ -195,7 +195,7 @@ exclude = ''' [tool.isort] profile = 'black' -py_version = 310 +py_version = 311 skip_gitignore = true extra_standard_library = ["typing_extensions"] known_first_party = ["dectate", "importscan", "reg"] From e688c4025e136588ce69bdfd9ce2588784a0cb03 Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Wed, 7 Oct 2026 23:28:47 +0200 Subject: [PATCH 3/9] chore: remove coveralls integration --- .github/workflows/main.yml | 11 ----------- README.rst | 3 --- 2 files changed, 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4c5e82b..4454106 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,14 +32,3 @@ jobs: run: python -m pip install --upgrade pip tox tox-gh - name: "Run tox targets for ${{ matrix.python-version }}" run: "python -m tox" - - - name: "Report to coveralls" - # coverage is only created in the py314 environment - # --service=github is a workaround for bug - # https://github.com/coveralls-clients/coveralls-python/issues/251 - if: "matrix.python-version == '3.14'" - run: | - pip install coveralls - coveralls --service=github - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.rst b/README.rst index 26fc84e..d049a4a 100644 --- a/README.rst +++ b/README.rst @@ -2,9 +2,6 @@ :target: https://github.com/morepath/dectate/actions?workflow=CI :alt: CI Status -.. image:: https://coveralls.io/repos/github/morepath/dectate/badge.svg?branch=master - :target: https://coveralls.io/github/morepath/dectate?branch=master - .. image:: https://img.shields.io/pypi/v/dectate.svg :target: https://pypi.org/project/dectate/ From c49cd53185e73e52355e91b61a5296c908b8fabd Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Thu, 8 Oct 2026 17:33:15 +0200 Subject: [PATCH 4/9] chore: replace flake8, black, isort, pyupgrade and pre-commit with ruff --- .pre-commit-config.yaml | 15 ---------- develop_requirements.txt | 1 - doc/developing.rst | 63 ++++++++++------------------------------ pyproject.toml | 58 ++++++++++-------------------------- 4 files changed, 30 insertions(+), 107 deletions(-) delete mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index b692006..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,15 +0,0 @@ -repos: - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 26.10.0 - hooks: - - id: black - - repo: https://github.com/PyCQA/flake8 - rev: "7.4.1" - hooks: - - id: flake8 - additional_dependencies: [flake8-pyproject, flake8-type-checking] - - repo: https://github.com/asottile/pyupgrade - rev: v3.21.2 - hooks: - - id: pyupgrade - args: [--py311-plus] diff --git a/develop_requirements.txt b/develop_requirements.txt index f08b794..c1d8e4c 100644 --- a/develop_requirements.txt +++ b/develop_requirements.txt @@ -1,6 +1,5 @@ # development -e '.[test,coverage,lint,docs,mypy,pyright]' -pre-commit tox >= 4 # releaser diff --git a/doc/developing.rst b/doc/developing.rst index 959d1d1..a95d456 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -38,15 +38,24 @@ For upgrading the requirements just run the command again. .. _github: https://docs.github.com/en/authentication/connecting-to-github-with-ssh -Install pre-commit hook for Black integration ---------------------------------------------- +Code quality checks +------------------- -We're using Black_ for formatting the code and it's recommended to -install the `pre-commit hook`_ for Black integration before committing:: +Morepath uses Ruff_ for linting, import sorting, and code formatting. Run +the checks from the project directory with:: - (.venv) $ pre-commit install + (.venv) $ ruff check . + (.venv) $ ruff format --check . -.. _`pre-commit hook`: https://black.readthedocs.io/en/stable/integrations/source_version_control.html +To apply lint fixes and format the code, run:: + + (.venv) $ ruff check --fix . + (.venv) $ ruff format . + +Ruff uses the project settings in ``pyproject.toml``. The ``lint`` tox +environment runs both checks. + +.. _Ruff: https://docs.astral.sh/ruff/ Running the tests ----------------- @@ -65,48 +74,6 @@ information. .. _`pytest`: https://pytest.org -Black ------ - -To format the code with the `Black Code Formatter`_ run in the root directory:: - - (.venv) $ black dectate - -Black has also integration_ for the most popular editors. - -.. _`Black Code Formatter`: https://black.readthedocs.io -.. _integration: https://black.readthedocs.io/en/stable/editor_integration.html - -isort ------ - -To sort imports with isort_ from the project directory do:: - - (.venv) $ isort . - -isort uses the settings in ``pyproject.toml``. - -.. _isort: https://pycqa.github.io/isort/ - -flake8 ------- - -flake8_ is a tool that can do various checks for common Python -mistakes using pyflakes_, checks for PEP8_ style compliance and -can do `cyclomatic complexity`_ checking. To do pyflakes and pep8 -checking do:: - - (.venv) $ flake8 dectate - -To also show cyclomatic complexity, use this command:: - - (.venv) $ flake8 --max-complexity=10 dectate - -.. _flake8: https://pypi.org/project/flake8 -.. _pyflakes: https://pypi.org/project/pyflakes -.. _pep8: https://peps.python.org/pep-0008 -.. _`cyclomatic complexity`: https://en.wikipedia.org/wiki/Cyclomatic_complexity - Type checking ------------- diff --git a/pyproject.toml b/pyproject.toml index 921db18..7dc2070 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,13 +37,7 @@ Changelog = "https://github.com/morepath/dectate/blob/master/CHANGES.txt" [project.optional-dependencies] test = ["pytest >= 8", "pytest-env"] coverage = ["pytest-cov"] -lint = [ - "black", - "flake8", - "flake8-pyproject", - "flake8-type-checking", - "isort", -] +lint = ["ruff"] docs = ["sphinx < 9.1"] mypy = ["mypy", "pytest"] pyright = ["pyright", "pytest"] @@ -70,11 +64,14 @@ source = ["dectate"] [tool.coverage.report] show_missing = true -[tool.flake8] -show-source = true -ignore = ["E203", "E301", "E501", "E704", "W503", "W504"] -extend-select = ["TC", "TC1"] -max-line-length = 88 +[tool.ruff.lint] +select = ["E", "F", "W", "I", "TC", "UP", "RUF"] +ignore = ["E501", "RUF012"] +future-annotations = true + +[tool.ruff.lint.isort] +extra-standard-library = ["typing_extensions"] +known-first-party = ["dectate", "importscan", "reg"] [tool.mypy] python_version = "3.11" @@ -111,7 +108,7 @@ env_list = [ "py315", "pypy3", "coverage", - "pre-commit", + "lint", "docs", "mypy", "pyright", @@ -122,7 +119,7 @@ skip_missing_interpreters = true "3.11" = ["py311"] "3.12" = ["py312"] "3.13" = ["py313"] -"3.14" = ["py314", "pre-commit", "coverage", "mypy", "pyright"] +"3.14" = ["py314", "coverage", "lint", "mypy", "pyright"] "3.15" = ["py315"] "pypy-3.12" = ["pypy3"] @@ -138,12 +135,12 @@ commands = [ ["pytest", "--cov", "--cov-fail-under=100", "{posargs:dectate}"], ] -[tool.tox.env.pre-commit] +[tool.tox.env.lint] base_python = ["python3.14"] -package = "skip" -deps = ["pre-commit"] +extras = ["lint"] commands = [ - ["pre-commit", "run", "--all-files"], + ["ruff", "check", "."], + ["ruff", "format", "--check", "."], ] [tool.tox.env.docs] @@ -174,28 +171,3 @@ commands = [ ["pyright", "--pythonversion", "3.14"], ["pyright", "--pythonversion", "3.15"], ] - -[tool.black] -target-version = ['py311', 'py312', 'py313', 'py314', 'py315'] -include = '\.pyi?$' -exclude = ''' -( - /( - \.git - | \.tox - | env - | venv - | .venv - | __pycache__ - | build - | dist - )/ -) -''' - -[tool.isort] -profile = 'black' -py_version = 311 -skip_gitignore = true -extra_standard_library = ["typing_extensions"] -known_first_party = ["dectate", "importscan", "reg"] From 9f7bb51c6e4df7ae4cc7c449b402ba5abf761108 Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Thu, 8 Oct 2026 17:38:36 +0200 Subject: [PATCH 5/9] style: format and lint the codebase with ruff --- dectate/tests/test_directive.py | 4 +--- dectate/toposort.py | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dectate/tests/test_directive.py b/dectate/tests/test_directive.py index cbe8493..e42b9fd 100644 --- a/dectate/tests/test_directive.py +++ b/dectate/tests/test_directive.py @@ -112,9 +112,7 @@ def f() -> None: MyApp.commit() - MyApp.config.my[ - 0 - ].directive.directive_name == "foo" # pyright: ignore[reportUnusedExpression] + MyApp.config.my[0].directive.directive_name == "foo" # pyright: ignore[reportUnusedExpression] def test_conflict_same_directive() -> None: diff --git a/dectate/toposort.py b/dectate/toposort.py index 34636cf..b1a45b1 100644 --- a/dectate/toposort.py +++ b/dectate/toposort.py @@ -11,7 +11,7 @@ def topological_sort( - l: Iterable[_T], + items: Iterable[_T], get_depends: Callable[[_T], Iterable[_T]], ) -> list[_T]: """`Topological sort`_. @@ -24,7 +24,7 @@ def topological_sort( .. _DAG: https://en.wikipedia.org/wiki/Directed_acyclic_graph - :param l: an iterable of items to sort + :param items: an iterable of items to sort :param get_depends: a function that given an item gives other items that this item depends on. This item will be sorted after the items it depends on. @@ -47,6 +47,6 @@ def visit(n: _T) -> None: marked.add(n) result.append(n) - for n in l: + for n in items: visit(n) return result From 80ba8e7b2bea3c9bc5bb04be8dbfd4e4dc545da1 Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Thu, 8 Oct 2026 20:46:12 +0200 Subject: [PATCH 6/9] deploy: adjust deployment strategy and publish to pypi using gh-actions --- .github/workflows/main.yml | 7 +++++-- .github/workflows/release.yml | 39 +++++++++++++++++++++++++++++++++++ MANIFEST.in | 1 + pyproject.toml | 8 ++++++- 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4454106..6df12bd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,16 +18,19 @@ jobs: runs-on: "ubuntu-latest" strategy: + fail-fast: false matrix: python-version: ["3.11", "3.12", "3.13", "3.14", "3.15", "pypy-3.12"] # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: "actions/checkout@v6" - - uses: "actions/setup-python@v6" + - uses: "actions/checkout@v7" + - uses: "actions/setup-python@v7" with: python-version: "${{ matrix.python-version }}" + allow-prereleases: true + check-latest: true - name: "Install dependencies" run: python -m pip install --upgrade pip tox tox-gh - name: "Run tox targets for ${{ matrix.python-version }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..aad6a8a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: Release + +on: + push: + tags: ["v[0-9]*"] + +permissions: {} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + - uses: actions/setup-python@v7 + with: + python-version: "3.14" + - run: python -m pip install build + - run: python -m build + - uses: actions/upload-artifact@v7 + with: + name: dist + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/MANIFEST.in b/MANIFEST.in index 9c575dc..b511833 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,3 +4,4 @@ exclude .installed.cfg recursive-include dectate *.py py.typed recursive-include doc *.rst Makefile *.py *.bat recursive-include scenarios *.py *.txt +recursive-exclude scenarios/query/.venv * diff --git a/pyproject.toml b/pyproject.toml index 7dc2070..2e45522 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,7 +147,8 @@ commands = [ base_python = ["python3.14"] extras = ["docs"] commands = [ - ["sphinx-build", "-b", "doctest", "doc", "{env_tmp_dir}"], + ["sphinx-build", "-W", "-b", "doctest", "doc", "{env_tmp_dir}"], + ["sphinx-build", "-W", "-b", "html", "doc", "{env_tmp_dir}"], ] [tool.tox.env.mypy] @@ -171,3 +172,8 @@ commands = [ ["pyright", "--pythonversion", "3.14"], ["pyright", "--pythonversion", "3.15"], ] + +[tool.zest-releaser] +release = false +upload-pypi = false +tag-format = "v{version}" From 79932ebe21bede769752800e4c2e2591c42faccc Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Thu, 8 Oct 2026 22:13:40 +0200 Subject: [PATCH 7/9] docs: update CHANGES --- CHANGES.txt | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index bf07847..8b766f1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,29 +4,56 @@ CHANGES 1.0.0 (unreleased) ================== -- Add type hints +- Add type annotations and integrate ``mypy`` and ``pyright``. -- Add partial attribute to directive methods for better typing support +- Switch to ``pyproject.toml`` based project setup. + +- Add partial attribute to directive methods for better typing support. + +- Update scenarios to Dectate 0.12+ API and add type annotations. - Fix linting errors. -- Add support for Python 3.10, 3.11, 3.12, 3.13 and 3.14 +- Add support for Python 3.11, 3.12, 3.13, 3.14 and 3.15 + +- Drop support for Python 3.10 and below -- Drop support for Python 3.9 and below +- Support Pypy 3.12. - Use GitHub Actions instead of Travis for CI. (Travis no longer gives free credits to open source projects.) - Cleanup old Python 2 code with pyupgrade_. + .. _pyupgrade: https://github.com/asottile/pyupgrade + - Add tests for 100% coverage. -- Update docs. +- Update docs and fix sphinx config. -- Update scenarios to Dectate 0.12+ API and add type annotations. +- Make an overall cleanup. - .. _pyupgrade: https://github.com/asottile/pyupgrade +- Fix readthedocs integration. + +- Replace flake8, black, isort, pyupgrade and pre-commit with Ruff_. + + .. _Ruff: https://docs.astral.sh/ruff + +- Remove coveralls integration. + +- Adjust the deployment strategy: + + * Move the Pypi upload from ``zest.release`` to ``gh-actions``. + + * Use ``v`` + version as release tags like ``v1.0.0``. + * So we still use ``zest.release`` but without publishing to Pypi. + The Pypi upload is triggered by pushing the new release tag to GitHub. + This happens in the Release workflow in ``.github/workflows/release.yml``. + With this workflow we get Trusted Publishing with short-lived OIDC tokens + that PyPI issues to one specific repository, workflow file and environment (``pypi``). + We also get PEP 740 provenance and can set required reviewers for the environment + and a ruleset who can create release tags and trigger releases. 0.14 (2020-01-29) From 9a7bcb71a03f9411e32649fecf493552f96a389b Mon Sep 17 00:00:00 2001 From: Henri Hulski Date: Fri, 9 Oct 2026 19:55:13 +0200 Subject: [PATCH 8/9] chore: add tracked Git pre-commit hook for Ruff checks --- .gitattributes | 2 + .githooks/pre-commit | 93 ++++++++++++++++++++++++++++++++++++++++++++ CHANGES.txt | 2 + MANIFEST.in | 1 + doc/developing.rst | 17 ++++++++ 5 files changed, 115 insertions(+) create mode 100644 .gitattributes create mode 100755 .githooks/pre-commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e5c6b4a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +.githooks/* text eol=lf diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..2b3ce42 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +abort() { + printf '%s\n' "$@" >&2 + exit 1 +} + +tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/morepath-ruff.XXXXXX") || + abort 'Ruff pre-commit check: could not create a temporary directory.' +trap 'rm -rf "$tmpdir"' EXIT + +list_file=$tmpdir/staged-files +staged_file=$tmpdir/staged +formatted_file=$tmpdir/formatted + +# Write the list to a file first so a git failure is not silently ignored. +git diff --cached --name-only --diff-filter=ACMR -z -- '*.py' '*.pyi' \ + >"$list_file" || + abort 'Ruff pre-commit check: could not list the staged files.' + +python_files=() +while IFS= read -r -d '' path; do + python_files+=("$path") +done <"$list_file" + +if (( ${#python_files[@]} == 0 )); then + exit 0 +fi + +if [[ -x .venv/bin/ruff ]]; then + ruff_cmd=.venv/bin/ruff +elif [[ -f .venv/Scripts/ruff.exe ]]; then + ruff_cmd=.venv/Scripts/ruff.exe +elif command -v ruff >/dev/null 2>&1; then + ruff_cmd=$(command -v ruff) +elif command -v ruff.exe >/dev/null 2>&1; then + ruff_cmd=$(command -v ruff.exe) +else + abort 'Ruff not found in .venv or PATH.' \ + "Install it with pip install -e '.[lint]'" +fi + +# report