diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 5b12fe48..fef394fa 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -1,5 +1,6 @@ # This configuration file enables Dependabot version updates. # https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/about-dependabot-version-updates +# https://docs.github.com/en/code-security/reference/supply-chain-security/supported-ecosystems-and-repositories # https://github.com/dependabot/feedback/issues/551 version: 2 @@ -8,6 +9,8 @@ updates: directory: / schedule: interval: weekly + cooldown: + default-days: 3 commit-message: prefix: chore prefix-development: chore @@ -23,6 +26,8 @@ updates: directory: / schedule: interval: weekly + cooldown: + default-days: 3 commit-message: prefix: chore prefix-development: chore @@ -32,4 +37,25 @@ updates: # Add additional reviewers for PRs opened by Dependabot. For more information, see: # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#reviewers # reviewers: + # + +- package-ecosystem: pre-commit + directory: / + schedule: + interval: weekly + cooldown: + default-days: 3 + commit-message: + prefix: chore + prefix-development: chore + include: scope + target-branch: main + # Group updates into one pull request. See also: + # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#groups-- + groups: + pre-commit: + patterns: ['*'] + # Add additional reviewers for PRs opened by Dependabot. For more information, see: + # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#reviewers + # reviewers: # - diff --git a/.github/workflows/_build.yaml b/.github/workflows/_build.yaml index 0310704e..f3118e7e 100644 --- a/.github/workflows/_build.yaml +++ b/.github/workflows/_build.yaml @@ -6,7 +6,7 @@ # # Even though we run the build in a matrix to check against different platforms, due to a known # limitation of reusable workflows that do not support setting strategy property from the caller -# workflow, we only generate artifacts for ubuntu-latest and Python 3.13, which can be used to +# workflow, we only generate artifacts for ubuntu-latest and Python 3.14, which can be used to # create a release. For details see: # # https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations @@ -35,7 +35,7 @@ permissions: contents: read env: ARTIFACT_OS: ubuntu-latest # The default OS for release. - ARTIFACT_PYTHON: '3.13' # The default Python version for release. + ARTIFACT_PYTHON: '3.14' # The default Python version for release. jobs: build: @@ -51,22 +51,22 @@ jobs: # It is recommended to pin a Runner version specifically: # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners os: [ubuntu-latest, macos-latest, windows-latest] - python: ['3.10', '3.11', '3.12', '3.13'] + python: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} diff --git a/.github/workflows/_generate-rebase.yaml b/.github/workflows/_generate-rebase.yaml index eaa0cb53..54869af8 100644 --- a/.github/workflows/_generate-rebase.yaml +++ b/.github/workflows/_generate-rebase.yaml @@ -34,12 +34,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 token: ${{ secrets.REPO_ACCESS_TOKEN }} diff --git a/.github/workflows/_wiki-documentation.yaml b/.github/workflows/_wiki-documentation.yaml index f324a734..2edbbe8d 100644 --- a/.github/workflows/_wiki-documentation.yaml +++ b/.github/workflows/_wiki-documentation.yaml @@ -41,7 +41,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true @@ -49,7 +49,7 @@ jobs: # Check out the repository's Wiki repo into the wiki/ folder. The token is required # only for private repositories. - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: token: ${{ secrets.REPO_ACCESS_TOKEN }} repository: ${{ format('{0}.wiki', github.repository) }} diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 98699832..f722bbbb 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -29,20 +29,20 @@ jobs: matrix: # Learn more about CodeQL language support at https://git.io/codeql-language-support language: [python, actions] - python: ['3.13'] + python: ['3.14'] steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} @@ -54,7 +54,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: ${{ matrix.language }} config-file: .github/codeql/codeql-config.yaml @@ -67,4 +67,4 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 diff --git a/.github/workflows/dependabot-automerge.yaml b/.github/workflows/dependabot-automerge.yaml index aef76783..a6f53112 100644 --- a/.github/workflows/dependabot-automerge.yaml +++ b/.github/workflows/dependabot-automerge.yaml @@ -1,4 +1,5 @@ # Automatically merge Dependabot PRs upon approval. +# https://docs.github.com/en/code-security/tutorials/secure-your-dependencies/automating-dependabot-with-github-actions#enabling-automerge-on-a-pull-request name: Automerge Dependabot PR on: diff --git a/.github/workflows/macaron-analysis.yaml b/.github/workflows/macaron-analysis.yaml index e72f4df3..8b94386f 100644 --- a/.github/workflows/macaron-analysis.yaml +++ b/.github/workflows/macaron-analysis.yaml @@ -22,13 +22,13 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # Check the GitHub Actions workflows in the repository for vulnerabilities. - name: Run Macaron action - uses: oracle/macaron@b31acfe389133a5587d9639063ec70cb84e7bc47 # v0.23.0 + uses: oracle/macaron@4ddb55e3c9ef2c77b548be55c557078c4476fd9c # v0.24.0 with: repo_path: ./ policy_file: check-github-actions diff --git a/.github/workflows/pr-conventional-commits.yaml b/.github/workflows/pr-conventional-commits.yaml index 8a61b236..adf6c1a6 100644 --- a/.github/workflows/pr-conventional-commits.yaml +++ b/.github/workflows/pr-conventional-commits.yaml @@ -22,21 +22,21 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: '3.13' + python-version: '3.14' # Install Commitizen without using the package's Makefile: that's much faster than # creating a venv and installing heaps of dependencies that aren't required for this job. - name: Set up Commitizen run: | pip install --upgrade pip wheel - pip install 'commitizen ==4.13.9' + pip install 'commitizen ==4.16.2' # Run Commitizen to check the title of the PR which triggered this workflow, and check # all commit messages of the PR's branch. If any of the checks fails then this job fails. diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a9c1ec53..1ac67953 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,26 +30,26 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 token: ${{ secrets.REPO_ACCESS_TOKEN }} - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: '3.13' + python-version: '3.14' - name: Set up Commitizen run: | pip install --upgrade pip wheel - pip install 'commitizen ==4.13.9' + pip install 'commitizen ==4.16.2' - name: Set up user run: | @@ -98,20 +98,20 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Download artifact uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: - name: artifact-ubuntu-latest-python-3.13 + name: artifact-ubuntu-latest-python-3.14 path: dist # Verify hashes by first computing hashes for the artifacts and then comparing them @@ -126,14 +126,14 @@ jobs: # Create the Release Notes using commitizen. - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: '3.13' + python-version: '3.14' - name: Set up Commitizen run: | pip install --upgrade pip wheel - pip install 'commitizen ==4.13.9' + pip install 'commitizen ==4.16.2' - name: Create Release Notes run: cz changelog --dry-run "$(cz version --project)" > RELEASE_NOTES.md @@ -199,13 +199,13 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -250,7 +250,7 @@ jobs: # Github disallows passing environment variables as arguments to a reusable # workflow, so we have to duplicate these values here. Related discussion # here: https://github.com/actions/toolkit/issues/931 - artifact-name: artifact-ubuntu-latest-python-3.13 + artifact-name: artifact-ubuntu-latest-python-3.14 git-user-name: jenstroeger git-user-email: jenstroeger@users.noreply.github.com secrets: diff --git a/.github/workflows/scorecards-analysis.yaml b/.github/workflows/scorecards-analysis.yaml index 94664d97..2491d95b 100644 --- a/.github/workflows/scorecards-analysis.yaml +++ b/.github/workflows/scorecards-analysis.yaml @@ -26,13 +26,13 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs disable-sudo: true - name: Check out repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -59,6 +59,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: results.sarif diff --git a/.github/workflows/sync-with-upstream.yaml b/.github/workflows/sync-with-upstream.yaml index 0f0599f3..e77f8f35 100644 --- a/.github/workflows/sync-with-upstream.yaml +++ b/.github/workflows/sync-with-upstream.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Check out template repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # If you decide to change the upstream template repository to a private one, uncomment # the following argument to pass the required token to be able to check it out. @@ -31,7 +31,7 @@ jobs: path: template - name: Check out current repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: token: ${{ secrets.REPO_ACCESS_TOKEN }} fetch-depth: 0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3820efdf..9f0d551d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: # Commitizen enforces semantic and conventional commit messages. - repo: https://github.com/commitizen-tools/commitizen - rev: v4.13.9 + rev: 2ca29f9297911f8f5a4e8f97100b7832f045e8d3 # frozen: v4.13.10 hooks: - id: commitizen name: Check conventional commit message @@ -23,7 +23,7 @@ repos: # Sort imports. - repo: https://github.com/pycqa/isort - rev: 7.0.0 + rev: dac090ce4d9ee313d086e2e89ab1acb8c2664fa1 # frozen: 9.0.0a3 hooks: - id: isort name: Sort import statements @@ -32,22 +32,22 @@ repos: # Add Black code formatters. - repo: https://github.com/ambv/black - rev: 25.11.0 + rev: c6755bb741b6481d6b3d3bb563c83fa060db96c9 # frozen: 26.3.1 hooks: - id: black name: Format code args: [--config, pyproject.toml] - repo: https://github.com/asottile/blacken-docs - rev: 1.20.0 + rev: dda8db18cfc68df532abf33b185ecd12d5b7b326 # frozen: 1.20.0 hooks: - id: blacken-docs name: Format code in docstrings args: [--line-length, '120'] - additional_dependencies: [black==25.11.0] + additional_dependencies: [black==26.3.1] # Upgrade and rewrite Python idioms. - repo: https://github.com/asottile/pyupgrade - rev: v3.21.2 + rev: 75992aaa40730136014f34227e0135f63fc951b4 # frozen: v3.21.2 hooks: - id: pyupgrade name: Upgrade code idioms @@ -57,7 +57,7 @@ repos: # Similar to pylint, with a few more/different checks. For more available # extensions: https://github.com/DmytroLitvinov/awesome-flake8-extensions - repo: https://github.com/pycqa/flake8 - rev: 7.3.0 + rev: d93590f5be797aabb60e3b09f2f52dddb02f349f # frozen: 7.3.0 hooks: - id: flake8 name: Check flake8 issues @@ -91,7 +91,7 @@ repos: # Check for potential security issues. - repo: https://github.com/PyCQA/bandit - rev: 1.9.2 + rev: 92ae8b82fb422a639f0ed8d99e96cea769594e08 # frozen: 1.9.4 hooks: - id: bandit name: Check for security issues @@ -103,7 +103,7 @@ repos: # Enable a whole bunch of useful helper hooks, too. # See https://pre-commit.com/hooks.html for more hooks. - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - id: check-ast - id: check-case-conflict @@ -123,7 +123,7 @@ repos: - id: check-yaml - id: check-toml - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.10.0 + rev: 3a6eb0fadf60b3cccfd80bad9dbb6fae7e47b316 # frozen: v1.10.0 hooks: - id: python-check-blanket-noqa - id: python-check-blanket-type-ignore @@ -138,13 +138,13 @@ repos: # this package's documentation. # Commenting this out because https://github.com/Lucas-C/pre-commit-hooks-markup/issues/13 # - repo: https://github.com/Lucas-C/pre-commit-hooks-markup -# rev: v1.0.1 +# rev: 501f3d60cee13c712492103343bc23efdc7b3d1f # frozen: v1.0.1 # hooks: # - id: rst-linter # Check and prettify the configuration files. - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.15.0 + rev: 4380fbb73a154b5f5624794c1c78d9719ccc860f # frozen: v2.16.0 hooks: - id: pretty-format-ini args: [--autofix] @@ -156,18 +156,16 @@ repos: # Check GitHub Actions workflow files. - repo: https://github.com/Mateusz-Grzelinski/actionlint-py - rev: v1.7.9.24 + rev: c04ed26e40637cab1aa9879c693832a9c120fb20 # frozen: v1.7.12.24 hooks: - id: actionlint -# On push to the remote, run all tests. Note that the `COVERAGE_CORE` variable is required -# for Python 3.12+ to make sure Coverage uses the new Python monitoring module. -# See also: https://blog.trailofbits.com/2025/05/01/making-pypis-test-suite-81-faster/#optimizing-coverage-with-python-312s-sysmonitoring +# On push to the remote, run all tests. - repo: local hooks: - id: pytest name: Run unit tests - entry: env COVERAGE_CORE=sysmon pytest --config-file pyproject.toml --cov-config pyproject.toml -m 'not integration and not performance' src/package/ tests/ docs/ + entry: pytest --config-file pyproject.toml --cov-config pyproject.toml -m 'not integration and not performance' src/package/ tests/ docs/ language: python verbose: true always_run: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 9165651b..d5bea48b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -This project follows the [semantic versioning](https://packaging.python.org/en/latest/discussions/versioning/#semantic-versioning-vs-calendar-versioning) and [pre-release versioning](https://packaging.python.org/en/latest/discussions/versioning/) schemes recommended by the Python Packaging Authority [here](https://packaging.python.org/en/latest/specifications/version-specifiers/). +# Changelog + +All notable changes to this project will be documented in this file. + +This project adheres to [semantic versioning](https://packaging.python.org/en/latest/discussions/versioning/#semantic-versioning-vs-calendar-versioning) and [pre-release versioning](https://packaging.python.org/en/latest/discussions/versioning/) schemes recommended by the Python Packaging Authority [here](https://packaging.python.org/en/latest/specifications/version-specifiers/). The format of this file is loosely based on [Keep a Changelog](https://keepachangelog.com/). ## v2.19.1 (2026-04-24) diff --git a/Makefile b/Makefile index 729531eb..b1827425 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,20 @@ SHELL := bash PACKAGE_NAME := package PACKAGE_VERSION := $(shell python -c $$'try: import $(PACKAGE_NAME); print($(PACKAGE_NAME).__version__);\nexcept: print("unknown");') +# Put together the file names for both the source distribution package (sdist) +# and the binary distribution package (wheel). For more details on these two, +# see: https://packaging.python.org/en/latest/discussions/package-formats/ +# +# For the wheel, users may require additional code to generate the Python tag +# (py3), the ABI tag (none), and the platform tag (any) for the final wheel +# file name. +PACKAGE_BASE_NAME := $(PACKAGE_NAME)-$(PACKAGE_VERSION) +PACKAGE_SDIST_NAME := $(PACKAGE_BASE_NAME).tar.gz +PACKAGE_WHEEL_NAME := $(PACKAGE_BASE_NAME)-py3-none-any.whl + +# If a PYTHON environment variable exists then use that, else define it here. +PYTHON ?= python3.14 + # This variable contains the first goal that matches any of the listed goals # here, else it contains an empty string. The net effect is to filter out # whether this current run of `make` requires a Python virtual environment @@ -40,9 +54,11 @@ endif # If the project configuration file has been updated (package deps or # otherwise) then warn the user and suggest resolving the conflict. -ifeq ($(shell test pyproject.toml -nt .venv/upgraded-on; echo $$?),0) - $(warning pyproject.toml was updated, consider `make upgrade` if your packages have changed) - $(warning If this is not correct then run `make upgrade-quiet`) +ifneq ($(wildcard .venv/upgraded-on),) + ifeq ($(shell test pyproject.toml -nt .venv/upgraded-on; echo $$?),0) + $(warning pyproject.toml was updated, consider `make upgrade` if your packages have changed) + $(warning If this is not correct then run `make upgrade-quiet`) + endif endif # The SOURCE_DATE_EPOCH environment variable allows the `flit` tool to @@ -56,7 +72,7 @@ endif .PHONY: all all: check test dist docs -# Create a virtual environment, either for Python3.13 (default) or using +# Create a virtual environment, either for Python3.14 (default) or using # the Python interpreter specified in the PYTHON environment variable. Also # create an empty pip.conf file to ensure that `pip config` modifies this # venv only, unless told otherwise. For more background, see: @@ -69,13 +85,8 @@ venv: if [ -d .venv/ ]; then \ echo "Found an inactive Python virtual environment, please activate or nuke it" && exit 1; \ fi - if [ -z "${PYTHON}" ]; then \ - echo "Creating virtual environment in .venv/ for python3.13"; \ - python3.13 -m venv --upgrade-deps --prompt . .venv; \ - else \ - echo "Creating virtual environment in .venv/ for ${PYTHON}"; \ - ${PYTHON} -m venv --upgrade-deps --prompt . .venv; \ - fi + echo "Creating virtual environment in .venv/ for ${PYTHON}"; \ + ${PYTHON} -m venv --upgrade-deps --prompt . .venv; \ touch .venv/pip.conf # Set up a newly created virtual environment. Note: pre-commit uses the @@ -91,7 +102,7 @@ setup: force-upgrade # Install or upgrade an existing virtual environment based on the # package dependencies declared in pyproject.toml. -.PHONY: upgrade force-upgrade +.PHONY: upgrade force-upgrade upgrade-quiet upgrade: .venv/upgraded-on .venv/upgraded-on: pyproject.toml python -m pip install --upgrade pip setuptools @@ -107,7 +118,7 @@ upgrade-quiet: # Generate a Software Bill of Materials (SBOM). .PHONY: sbom sbom: requirements - python -m cyclonedx_py requirements --output-reproducible --output-format json --output-file dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-sbom.json + python -m cyclonedx_py requirements --output-reproducible --output-format json --output-file dist/$(PACKAGE_BASE_NAME)-sbom.json # Generate a requirements.txt file containing version and integrity hashes for all # packages currently installed in the virtual environment. There's no easy way to @@ -129,14 +140,14 @@ requirements.txt: pyproject.toml [[ $$pkg =~ (.*)==(.*) ]] && curl -s https://pypi.org/pypi/$${BASH_REMATCH[1]}/$${BASH_REMATCH[2]}/json | python -c "import json, sys; print(''.join(f''' \\\\\n --hash=sha256:{pkg['digests']['sha256']}''' for pkg in json.load(sys.stdin)['urls']));" >> requirements.txt; \ done echo -e -n "$(PACKAGE_NAME)==$(PACKAGE_VERSION)" >> requirements.txt - if [ -f dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz ]; then \ - echo -e -n " \\\\\n $$(python -m pip hash --algorithm sha256 dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz | grep '^\-\-hash')" >> requirements.txt; \ + if [ -f dist/$(PACKAGE_SDIST_NAME) ]; then \ + echo -e -n " \\\\\n $$(python -m pip hash --algorithm sha256 dist/$(PACKAGE_SDIST_NAME) | grep '^\-\-hash')" >> requirements.txt; \ fi - if [ -f dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl ]; then \ - echo -e -n " \\\\\n $$(python -m pip hash --algorithm sha256 dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl | grep '^\-\-hash')" >> requirements.txt; \ + if [ -f dist/$(PACKAGE_WHEEL_NAME) ]; then \ + echo -e -n " \\\\\n $$(python -m pip hash --algorithm sha256 dist/$(PACKAGE_WHEEL_NAME) | grep '^\-\-hash')" >> requirements.txt; \ fi echo "" >> requirements.txt - cp requirements.txt dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-requirements.txt + cp requirements.txt dist/$(PACKAGE_BASE_NAME)-requirements.txt # Audit the currently installed packages. Skip packages that are installed in # editable mode (like the one in development here) because they may not have @@ -171,7 +182,7 @@ check: .PHONY: test test-all test-unit test-integration test-performance test: test-unit test-unit: - COVERAGE_CORE=sysmon python -m pytest --config-file pyproject.toml --cov-config pyproject.toml -m 'not integration and not performance' src/package/ tests/ docs/ + python -m pytest --config-file pyproject.toml --cov-config pyproject.toml -m 'not integration and not performance' src/package/ tests/ docs/ test-integration: python -m pytest --config-file pyproject.toml --no-cov -m integration tests/ test-performance: @@ -182,20 +193,16 @@ test-all: test-unit test-integration test-performance # When building these artifacts, we need the environment variable SOURCE_DATE_EPOCH # set to the build date/epoch. For more details, see: https://flit.pypa.io/en/latest/reproducible.html .PHONY: dist -dist: dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt -dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl: check test-all dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt +dist: dist/$(PACKAGE_WHEEL_NAME) dist/$(PACKAGE_SDIST_NAME) dist/$(PACKAGE_BASE_NAME)-docs-html.zip dist/$(PACKAGE_BASE_NAME)-docs-md.zip +dist/$(PACKAGE_WHEEL_NAME): check test-all SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) python -m flit build --setup-py --format wheel -dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz: check test-all dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt + echo $(SOURCE_DATE_EPOCH) > dist/$(PACKAGE_BASE_NAME)-py3-none-any-build-epoch.txt +dist/$(PACKAGE_SDIST_NAME): check test-all SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) python -m flit build --no-setup-py --format sdist -dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip: docs-html - python -m zipfile -c dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-html.zip docs/_build/html/ -dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip: docs-md - python -m zipfile -c dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-docs-md.zip docs/_build/markdown/ - -# Keep this goal phony to ensure the epoch is always updated. -.PHONY: dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt -dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt: - echo $(SOURCE_DATE_EPOCH) > dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt +dist/$(PACKAGE_BASE_NAME)-docs-html.zip: docs-html + python -m zipfile -c dist/$(PACKAGE_BASE_NAME)-docs-html.zip docs/_build/html/ +dist/$(PACKAGE_BASE_NAME)-docs-md.zip: docs-md + python -m zipfile -c dist/$(PACKAGE_BASE_NAME)-docs-md.zip docs/_build/markdown/ # Build a PEP-503 compatible Simple Repository directory inside of dist/. For details on # the layout of that directory and the normalized project name, see: https://peps.python.org/pep-0503/ @@ -203,13 +210,13 @@ dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt: # its `--extra-index-url` argument: https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-extra-index-url PROJECT_NAME := $(shell python -c $$'import re; print(re.sub(r"[-_.]+", "-", "$(PACKAGE_NAME)").lower());') .PHONY: simple-index -simple-index: dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-py3-none-any.whl dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz +simple-index: dist/$(PACKAGE_WHEEL_NAME) dist/$(PACKAGE_SDIST_NAME) mkdir -p dist/simple-index/$(PROJECT_NAME) - echo -e "\n