From 1358297ac5ac0730de18f62486219ecbaff131ac Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 2 Dec 2025 09:00:40 -0800 Subject: [PATCH 1/2] Add Github action to automatically publish to PyPI --- .github/dependabot.yml | 2 + .github/workflows/build-docs.yml | 2 +- .github/workflows/ci.yml | 7 ++- .github/workflows/pre-commit.yml | 5 +- .github/workflows/publish_pypi.yml | 95 ++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 22 +++---- src/spatch/__init__.py | 8 ++- src/spatch/backend_system.py | 2 +- tests/test_context.py | 6 +- tests/test_general.py | 2 +- 10 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/publish_pypi.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9ecc51d..8c6b46b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,5 @@ updates: actions: patterns: - "*" + cooldown: + default-days: 14 diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 925dea0..d9624c4 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -39,7 +39,7 @@ jobs: python-version: "3.13" allow-prereleases: true - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4 - name: Install package run: uv sync diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dca9bc5..a412d79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,8 +9,6 @@ on: permissions: contents: read - pages: write - id-token: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -46,7 +44,7 @@ jobs: python-version: ${{ matrix.python-version }} allow-prereleases: true - - uses: astral-sh/setup-uv@v7 + - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4 - name: Install package run: uv sync @@ -58,6 +56,9 @@ jobs: docs: uses: ./.github/workflows/build-docs.yml + permissions: + pages: write + id-token: write with: # Deploy on tag pushes (assume that is a release) deploy: ${{ (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 9e5c4e1..61f79f7 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -6,6 +6,9 @@ on: push: branches: [main] +permissions: + contents: read + jobs: pre-commit: name: pre-commit-hooks @@ -18,6 +21,6 @@ jobs: - uses: actions/setup-python@v6 with: python-version: "3.13" - - uses: pre-commit/action@v3.0.1 + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 env: SKIP: "no-commit-to-branch" diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml new file mode 100644 index 0000000..ff103da --- /dev/null +++ b/.github/workflows/publish_pypi.yml @@ -0,0 +1,95 @@ +name: Builid Wheel and Release + +on: + pull_request: + push: + branches: + - main + tags: + - "[0-9]+.[0-9]+.[0-9]+*" + +permissions: + contents: read + +jobs: + build-artifacts: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + steps: + - name: Checkout + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + fetch-depth: 0 + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: "3.9" + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + python -m pip install build twine + - name: Build wheel and sdist + run: python -m build + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: releases + path: dist + if-no-files-found: error + - name: Check with twine + run: python -m twine check --strict dist/* + + upload-to-test-pypi: + needs: build-artifacts + runs-on: ubuntu-latest + if: github.repository == 'scientific-python/spatch' && startsWith(github.ref, 'refs/tags/') + + environment: + name: test-pypi + url: https://test.pypi.org/p/spatch + permissions: + id-token: write + + steps: + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + with: + name: releases + path: dist + - name: Publish to Test-PyPI + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + repository-url: https://test.pypi.org/legacy/ + print-hash: true + verbose: true + + upload-to-pypi: + needs: build-artifacts + runs-on: ubuntu-latest + if: github.repository == 'scientific-python/spatch' && startsWith(github.ref, 'refs/tags/') + + environment: + name: pypi + url: https://pypi.org/p/spatch + permissions: + id-token: write + attestations: write + + steps: + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + with: + name: releases + path: dist + + - name: Generate artifact attestation for sdist and wheel + uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 + with: + subject-path: "dist/spatch-*" + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + attestations: true + print-hash: true + verbose: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22fe6c5..d2f9920 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ default_language_version: python: python3 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: # Sanity checks - id: check-added-large-files @@ -55,22 +55,22 @@ repos: args: [--in-place] # Let's keep `pyupgrade` even though `ruff --fix` probably does most of it - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.2 hooks: - id: pyupgrade args: [--py310-plus] # black often looks better than ruff-format - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.1.0 + rev: 25.11.0 hooks: - id: black - repo: https://github.com/adamchainz/blacken-docs - rev: 1.19.1 + rev: 1.20.0 hooks: - id: blacken-docs additional_dependencies: [black==25.1.0] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.5 + rev: v0.14.7 hooks: - id: ruff-check args: [--fix-only, --show-fixes] @@ -87,7 +87,7 @@ repos: - id: auto-walrus args: [--line-length, "100"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.5 + rev: v0.14.7 hooks: - id: ruff-check # - id: ruff-format # Prefer black, but may temporarily uncomment this to see @@ -99,12 +99,12 @@ repos: # - id: pyroma # args: [-n, "9", .] # Need author email to score a 10 - repo: https://github.com/rbubley/mirrors-prettier - rev: v3.6.2 + rev: v3.7.3 hooks: - id: prettier args: [--prose-wrap=preserve] - repo: https://github.com/sphinx-contrib/sphinx-lint - rev: v1.0.0 + rev: v1.0.2 hooks: - id: sphinx-lint args: [--enable, all, "--disable=line-too-long,leaked-markup"] @@ -128,13 +128,13 @@ repos: hooks: - id: yamllint - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.33.2 + rev: 0.35.0 hooks: - id: check-dependabot - id: check-github-workflows # TODO: get zizmor to pass, and maybe set it up as a github action # - repo: https://github.com/woodruffw/zizmor-pre-commit - # rev: v1.11.0 + # rev: v1.18.0 # hooks: # - id: zizmor - repo: local @@ -154,7 +154,7 @@ repos: language: pygrep entry: "^permalink:.*_.*" - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: no-commit-to-branch # No commit directly to main - repo: meta diff --git a/src/spatch/__init__.py b/src/spatch/__init__.py index b248709..1ab8162 100644 --- a/src/spatch/__init__.py +++ b/src/spatch/__init__.py @@ -2,6 +2,8 @@ def __getattr__(name): if name == "__version__": from .utils import get_project_version - return get_project_version(__name__) - - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + rv = get_project_version(__name__) + else: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + globals()[name] = rv + return rv diff --git a/src/spatch/backend_system.py b/src/spatch/backend_system.py index 32e9931..d0c4833 100644 --- a/src/spatch/backend_system.py +++ b/src/spatch/backend_system.py @@ -983,7 +983,7 @@ def __call__(self, *args, **kwargs): # At this point dispatch_types is not filtered for known types. dispatch_types = {type(val) for val in dispatch_args} state = self._backend_system._dispatch_state.get() - ordered_backends, type_, prioritized, trace = state + ordered_backends, type_, _prioritized, trace = state if type_ is not None: dispatch_types.add(type_) diff --git a/tests/test_context.py b/tests/test_context.py index b440fa1..c4c207d 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -23,7 +23,7 @@ def test_context_basic(): def dummy_func(*args, **kwargs): return "fallback", args, kwargs - _, (ctx, *args), kwargs = dummy_func(1, 1.0) + _, (ctx, *_args), _kwargs = dummy_func(1, 1.0) assert ctx.name == "FloatWithContext" assert set(ctx.types) == {int, float} assert ctx.dispatch_args == (1, 1.0) @@ -33,7 +33,7 @@ class float_subclass(float): pass with bs.backend_opts(prioritize=("FloatWithContext",)): - _, (ctx, *args), kwargs = dummy_func(float_subclass(1.0)) + _, (ctx, *_args), _kwargs = dummy_func(float_subclass(1.0)) assert ctx.name == "FloatWithContext" assert set(ctx.types) == {float_subclass} assert ctx.dispatch_args == (float_subclass(1.0),) @@ -41,7 +41,7 @@ class float_subclass(float): with bs.backend_opts(type=float): # No argument, works if explicitly prioritized... - _, (ctx, *args), kwargs = dummy_func() + _, (ctx, *_args), _kwargs = dummy_func() assert ctx.name == "FloatWithContext" assert set(ctx.types) == {float} assert ctx.dispatch_args == () diff --git a/tests/test_general.py b/tests/test_general.py index 26c1e02..86dc0f1 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -5,6 +5,6 @@ def test___version__(): # Sanity check that __version__ exists and returns # something that faintly looks like a version string. v = spatch.__version__ - major, minor, *rest = v.split(".") + major, minor, *_rest = v.split(".") assert major.isdigit() assert minor.isdigit() From 6074bebfd4bfd38671a58e63eb770010bc01fda8 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 2 Dec 2025 09:28:22 -0800 Subject: [PATCH 2/2] typo --- .github/workflows/publish_pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index ff103da..c50268f 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -1,4 +1,4 @@ -name: Builid Wheel and Release +name: Build Wheel and Release on: pull_request: