From 2007067bc64cddfe4893372e0ced746adbbfe6ac Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Tue, 22 Sep 2026 19:08:41 +0300 Subject: [PATCH] ci: resolve the declared dependency floors on every matrix entry --- .github/workflows/_checks.yml | 32 ++++++++++++++++++++++++++++++++ pyproject.toml | 25 +++++++++++++++---------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/.github/workflows/_checks.yml b/.github/workflows/_checks.yml index 4f07cd9..db9794e 100644 --- a/.github/workflows/_checks.yml +++ b/.github/workflows/_checks.yml @@ -59,6 +59,38 @@ jobs: - run: just install - run: uv run --no-sync python -c "import sys; assert not sys._is_gil_enabled(), 'GIL is enabled'" - run: just test-ci + floors: + # Every other job resolves newest, so the declared floors are a claim nothing installs. + # This one resolves the bottom of each range, on every matrix entry: wheel coverage is + # per interpreter, so two interpreters resolving the same versions can still disagree + # on whether those versions install. + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: + - "3.11" + - "3.12" + - "3.13" + - "3.14" + - "3.14t" + steps: + - uses: actions/checkout@v6 + - uses: astral-sh/setup-uv@v8.2.0 + with: + enable-cache: true + cache-dependency-glob: "**/pyproject.toml" + - run: uv python install ${{ matrix.python-version }} + - run: uv python pin ${{ matrix.python-version }} + # --no-build so a floor with no wheel for this interpreter fails here instead of + # quietly compiling its sdist; --no-install-project because that flag would refuse to + # build this project too, and the tests import it from the checkout. + - run: uv sync --all-extras --no-install-project --resolution lowest-direct --no-build + - run: uv run --no-sync pytest + env: + # The isolation tests spawn a fresh interpreter, which does not inherit pytest's sys.path. + PYTHONPATH: src + links: runs-on: ubuntu-latest steps: diff --git a/pyproject.toml b/pyproject.toml index b46096c..4a12803 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,14 +39,18 @@ dependencies = [ [project.optional-dependencies] pydantic = [ - "pydantic>=2.0,<3.0; python_version < '3.14'", - # pydantic-core ships no cp314 wheel before pydantic 2.12. + # pydantic-core ships no cp312 wheel before pydantic 2.1, no cp313 wheel before 2.8.1 and no + # cp314 wheel before 2.12. + "pydantic>=2.0,<3.0; python_version < '3.12'", + "pydantic>=2.1,<3.0; python_version == '3.12'", + "pydantic>=2.8.1,<3.0; python_version == '3.13'", "pydantic>=2.12,<3.0; python_version >= '3.14'", ] msgspec = [ # 0.18.5 is the first release whose can_decode agrees with decode on Annotated types; - # 0.20 is the first with a cp314 wheel. - "msgspec>=0.18.5; python_version < '3.14'", + # 0.19 is the first with a cp313 wheel and 0.20 the first with a cp314 one. + "msgspec>=0.18.5; python_version < '3.13'", + "msgspec>=0.19; python_version == '3.13'", "msgspec>=0.20; python_version >= '3.14'", ] otel = ["opentelemetry-api>=1.20"] @@ -68,13 +72,14 @@ module-name = "httpware" module-root = "src" [dependency-groups] +# Floored so `uv sync --resolution lowest-direct` resolves a usable harness, not each name's first release. dev = [ - "pytest", - "pytest-cov", - "pytest-asyncio", - "pytest-repeat", - "pytest-benchmark", - "hypothesis", + "pytest>=8", + "pytest-cov>=5", + "pytest-asyncio>=0.24", + "pytest-repeat>=0.9", + "pytest-benchmark>=4", + "hypothesis>=6.20", ] lint = [ "ruff",