From f52e8593091b0626f2332fb8a7a72d9c298188a9 Mon Sep 17 00:00:00 2001 From: Ilja Gubins Date: Sun, 2 Aug 2026 11:40:19 +0200 Subject: [PATCH 1/4] ci: restore and harden the pipeline - workflow_dispatch trigger so CI can run without a push (repo had zero surviving run records) - test matrix 3.9-3.14 plus two numpy axes: the declared 1.20 floor and newest numpy 1.x, alongside default numpy 2.x - coverage report step activates the fail_under=95 gate that was configured but never enforced (current coverage: 99%) - editable install in CI so coverage paths map back to src/ layout - release publish now requires the test suite to pass first - actions bumped to current majors and pinned by commit SHA; dependabot keeps the pins fresh - pre-commit: ruff v0.11.12->v0.16.1, pre-commit-hooks v5->v6 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE --- .github/CONTRIBUTING.md | 2 +- .github/dependabot.yml | 6 ++++++ .github/workflows/ci.yml | 31 +++++++++++++++++++----------- .github/workflows/pypi-publish.yml | 21 +++++++++++++++++--- .pre-commit-config.yaml | 4 ++-- 5 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1e36a61..7e157eb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -18,7 +18,7 @@ pip install -e .[all] 3. After you've finished with your changes, please run linter, tests and check that coverage didn't go down too much: ```bash -black tiler tests +ruff check . && ruff format . coverage run -m pytest coverage report ``` diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ca79ca5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f7bc1c..cdb07bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,36 +1,45 @@ name: CI -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: - python-version: 3.9 - - uses: pre-commit/action@v3.0.1 + python-version: "3.13" + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 test: runs-on: ubuntu-latest strategy: max-parallel: 5 matrix: - # 3.9 will reach EoL in October 2025 - # https://devguide.python.org/#status-of-python-branches - python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] + # https://devguide.python.org/versions/ + python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13", "3.14" ] + numpy: [ "" ] + include: + # oldest supported numpy (the floor declared in pyproject.toml) + - python-version: "3.9" + numpy: "==1.20.3" + # newest numpy 1.x + - python-version: "3.12" + numpy: "<2" steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} - run: | python -m pip install --upgrade pip - pip install .[test] + pip install -e .[test] + if [ -n "${{ matrix.numpy }}" ]; then pip install "numpy${{ matrix.numpy }}"; fi pip install coveralls - run: coverage run -m pytest -v + - run: coverage report - if: github.event_name != 'pull_request' run: coveralls env: diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml index dc1dee4..b89d24b 100644 --- a/.github/workflows/pypi-publish.yml +++ b/.github/workflows/pypi-publish.yml @@ -5,8 +5,23 @@ on: types: [published] jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ "3.9", "3.14" ] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: ${{ matrix.python-version }} + - run: | + pip install .[test] + pytest -v + deploy: name: Upload release to PyPI + needs: test runs-on: ubuntu-latest environment: name: pypi @@ -14,11 +29,11 @@ jobs: permissions: id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" @@ -26,7 +41,7 @@ jobs: - run: python -m build - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 with: verbose: true skip-existing: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 02b449b..8fe3689 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,13 +1,13 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.12 + rev: v0.16.1 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-ast - id: check-docstring-first From e17364a62fe296ded35e701cd27f45179a1890ee Mon Sep 17 00:00:00 2001 From: Ilja Gubins Date: Sun, 2 Aug 2026 11:40:19 +0200 Subject: [PATCH 2/4] build: PEP 639 license metadata, numpy floor, version classifiers - license = "MIT" SPDX expression + license-files (setuptools>=77), replacing the deprecated license table - numpy>=1.20: the floor numpy.typing has required all along; its absence made a user fork the project (#22) - per-version classifiers 3.9-3.14 so PyPI shows supported versions Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE --- pyproject.toml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3ef3db0..8799876 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,19 +6,25 @@ authors = [ {name = "the-lay", email = "ilja.gubin@gmail.com"} ] dependencies = [ - "numpy", + "numpy>=1.20", "tqdm", ] requires-python = ">=3.9" readme = "README.md" -license = {text = "MIT"} +license = "MIT" +license-files = ["LICENSE"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Topic :: Software Development :: Libraries :: Python Modules", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "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", ] [project.urls] @@ -41,7 +47,7 @@ all = [ ] [build-system] -requires = ["setuptools>=64", "setuptools-scm>=8"] +requires = ["setuptools>=77", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" [tool.setuptools_scm] From cfb48ccd9763c1b079db727329edaf2206e9b8f4 Mon Sep 17 00:00:00 2001 From: Ilja Gubins Date: Sun, 2 Aug 2026 11:40:19 +0200 Subject: [PATCH 3/4] feat: expose __version__; fix channel_dimension=0 skipping validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tiler.__version__ via importlib.metadata — CONTRIBUTING's first instruction to bug reporters finally works - the channel dimension guard used truthiness, so channel_dimension=0 bypassed bounds checking and surfaced as a raw IndexError instead of the documented ValueError; now consistent with the nine sibling `is not None` checks in the same file Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE --- src/tiler/__init__.py | 6 ++++++ src/tiler/tiler.py | 2 +- tests/test_tiler.py | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tiler/__init__.py b/src/tiler/__init__.py index e99c077..58320d4 100644 --- a/src/tiler/__init__.py +++ b/src/tiler/__init__.py @@ -1,3 +1,4 @@ +import importlib.metadata import sys from tiler.merger import Merger @@ -5,6 +6,11 @@ __all__ = ["Tiler", "Merger"] +try: + __version__ = importlib.metadata.version("tiler") +except importlib.metadata.PackageNotFoundError: # pragma: no cover + __version__ = "0+unknown" + # Import README file as a module general docstring, only when generating documentation # We also modify it to make it prettier if "pdoc" in sys.modules: # pragma: no cover diff --git a/src/tiler/tiler.py b/src/tiler/tiler.py index 5047953..75e8a06 100644 --- a/src/tiler/tiler.py +++ b/src/tiler/tiler.py @@ -133,7 +133,7 @@ def recalculate( # Channel dimension can be None which means we need to check for init too if not hasattr(self, "channel_dimension") or channel_dimension is not None: self.channel_dimension = channel_dimension - if self.channel_dimension: + if self.channel_dimension is not None: if (self.channel_dimension >= self._n_dim) or (self.channel_dimension < -self._n_dim): raise ValueError( f"Specified channel dimension is out of bounds " diff --git a/tests/test_tiler.py b/tests/test_tiler.py index f2fd2b4..00b29a4 100644 --- a/tests/test_tiler.py +++ b/tests/test_tiler.py @@ -2,10 +2,20 @@ import numpy as np +import tiler from tiler import Tiler class TestTilingCommon(unittest.TestCase): + def test_version(self): + self.assertIsInstance(tiler.__version__, str) + self.assertTrue(tiler.__version__) + + def test_channel_dimension_zero_bounds_check(self): + # channel_dimension=0 must go through the same bounds validation as any other value + with self.assertRaises(ValueError): + Tiler(data_shape=(), tile_shape=(), channel_dimension=0) + def test_init(self): with self.assertRaises(ValueError): Tiler(data_shape=(-10, -30), tile_shape=(10, 10)) From 46777c160981b5699221055ed376c4a7003c5671 Mon Sep 17 00:00:00 2001 From: Ilja Gubins Date: Sun, 2 Aug 2026 11:40:19 +0200 Subject: [PATCH 4/4] docs: fix broken install command, contributor steps and docs.sh - README from-source install was a bare `pip install` - CONTRIBUTING referenced black (dropped for ruff in 2025) and a version command that raised AttributeError - docs.sh dereferenced an undefined variable: run from the repo root it escaped to the parent directory and ran rm outside the repo; now anchored to the script location with set -euo pipefail, and the deprecated `magick convert` is plain `magick` Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE --- README.md | 2 +- misc/docs.sh | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0cbc4bd..c1085de 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Alternatively, you can clone the repository and install it manually: ```bash git clone git@github.com:the-lay/tiler.git cd tiler -pip install +pip install . ``` If you are planning to contribute, please take a look at the [contribution instructions](.github/CONTRIBUTING.md). diff --git a/misc/docs.sh b/misc/docs.sh index 0cc38ff..0855b7a 100755 --- a/misc/docs.sh +++ b/misc/docs.sh @@ -1,10 +1,12 @@ -cd "$(dirname "$file_name")"/.. || exit +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")/.." # build docs pdoc -o docs -d google src/tiler # add downsized teaser image to the docs directory -magick convert -resize 50% misc/teaser/tiler_teaser.png docs/tiler_teaser.png +magick misc/teaser/tiler_teaser.png -resize 50% docs/tiler_teaser.png # replace unnecessary index rm docs/index.html