From bef5699e430472f9099aa2ba28eb8f9b4e24160a Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:20:51 -0400 Subject: [PATCH 1/3] ci: move pandas/scipy stubs to pypi deps so typing works in test-nightly --- pixi.toml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pixi.toml b/pixi.toml index 2abe0dfd01a..64b02374a85 100644 --- a/pixi.toml +++ b/pixi.toml @@ -254,8 +254,6 @@ mypy = "==1.19.1" pyright = "*" hypothesis = "*" lxml = "*" -pandas-stubs = "<=2.3.3.251219" -scipy-stubs = ">=1.17.1.2" types-colorama = "*" types-docutils = "*" types-decorator = "*" @@ -272,6 +270,12 @@ typing_extensions = "*" pip = "*" [feature.typing.pypi-dependencies] +# Declared as PyPI deps (not conda) so they don't pull conda numpy/scipy. As +# conda deps they would conflict with the `nightly` feature's PyPI numpy/scipy +# overrides (pixi cannot override a conda dep with a PyPI one), which is why the +# `typing` feature was previously excluded from the `test-nightly` environment. +pandas-stubs = "<=2.3.3.251219" +scipy-stubs = ">=1.17.1.2" types-defusedxml = "*" types-pexpect = "*" @@ -387,7 +391,7 @@ test-nightly = { features = [ "py313", "nightly", "test", - # "typing", + "typing", ], no-default-feature = true } From 5a205405ba598de1c7820e10f55c0127f864b297 Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:47:20 -0400 Subject: [PATCH 2/3] ci: confine pypi stubs to nightly env --- pixi.toml | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pixi.toml b/pixi.toml index 64b02374a85..24835e80dd4 100644 --- a/pixi.toml +++ b/pixi.toml @@ -200,6 +200,11 @@ pydap = "*" cartopy = "*" seaborn = "*" +# Sourced from PyPI here (rather than via the conda `typing-stubs` feature) so +# they don't pull conda numpy/scipy and clash with the PyPI overrides above. +pandas-stubs = "<=2.3.3.251219" +scipy-stubs = ">=1.17.1.2" + [feature.test.dependencies] pytest = "*" pytest-asyncio = "*" @@ -270,15 +275,19 @@ typing_extensions = "*" pip = "*" [feature.typing.pypi-dependencies] -# Declared as PyPI deps (not conda) so they don't pull conda numpy/scipy. As -# conda deps they would conflict with the `nightly` feature's PyPI numpy/scipy -# overrides (pixi cannot override a conda dep with a PyPI one), which is why the -# `typing` feature was previously excluded from the `test-nightly` environment. -pandas-stubs = "<=2.3.3.251219" -scipy-stubs = ">=1.17.1.2" types-defusedxml = "*" types-pexpect = "*" +# pandas-stubs / scipy-stubs live in their own feature, rather than in `typing`, +# so that `test-nightly` can source them from PyPI (see the `nightly` feature) +# while every other typing env keeps the conda builds. As conda deps they pull in +# conda numpy/scipy, which conflicts with the `nightly` feature's PyPI numpy/scipy +# overrides (pixi cannot override a conda dep with a PyPI one) — that conflict is +# why the `typing` feature used to be excluded from `test-nightly` entirely. +[feature.typing-stubs.dependencies] +pandas-stubs = "<=2.3.3.251219" +scipy-stubs = ">=1.17.1.2" + [feature.typing.tasks] mypy = { cmd = "mypy --install-types --non-interactive --cobertura-xml-report mypy_report", description = "Run mypy type checking and generate a Cobertura XML report." } @@ -416,6 +425,7 @@ test-py311-with-typing = { features = [ "viz", "extras", "typing", + "typing-stubs", ] } test-py313-with-typing = { features = [ @@ -428,6 +438,7 @@ test-py313-with-typing = { features = [ "viz", "extras", "typing", + "typing-stubs", ] } test-py311-bare-minimum = { features = ["test", "minimal"] } @@ -445,7 +456,7 @@ test-py311-min-versions = { features = [ # Extra -typing = { features = ["typing"] } +typing = { features = ["typing", "typing-stubs"] } doc = { features = [ "doc", "backends", From 274782163b2da8194e8f9582a214451d09e093fc Mon Sep 17 00:00:00 2001 From: Max Jones <14077947+maxrjones@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:59:25 -0400 Subject: [PATCH 3/3] ci: type-check the dev stack in a dedicated mypy-upstream env --- .github/workflows/upstream-dev-ci.yaml | 2 +- pixi.toml | 36 ++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/.github/workflows/upstream-dev-ci.yaml b/.github/workflows/upstream-dev-ci.yaml index 0adb0877b70..2e7f229c7b8 100644 --- a/.github/workflows/upstream-dev-ci.yaml +++ b/.github/workflows/upstream-dev-ci.yaml @@ -168,7 +168,7 @@ jobs: strategy: fail-fast: false matrix: - pixi-env: ["test-nightly"] + pixi-env: ["mypy-upstream"] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/pixi.toml b/pixi.toml index 24835e80dd4..3e429f6f6eb 100644 --- a/pixi.toml +++ b/pixi.toml @@ -200,11 +200,6 @@ pydap = "*" cartopy = "*" seaborn = "*" -# Sourced from PyPI here (rather than via the conda `typing-stubs` feature) so -# they don't pull conda numpy/scipy and clash with the PyPI overrides above. -pandas-stubs = "<=2.3.3.251219" -scipy-stubs = ">=1.17.1.2" - [feature.test.dependencies] pytest = "*" pytest-asyncio = "*" @@ -288,6 +283,22 @@ types-pexpect = "*" pandas-stubs = "<=2.3.3.251219" scipy-stubs = ">=1.17.1.2" +# Stubs sourced from PyPI rather than conda, used only by the `mypy-upstream` +# environment. That env pairs the `nightly` feature (which overrides numpy/scipy +# to PyPI nightly wheels) with type stubs; conda stubs would pull conda +# numpy/scipy that pixi cannot reconcile with those PyPI overrides, so they must +# come from PyPI here. +# +# NOTE: these stubs cap numpy below the nightly wheel (scipy-stubs via optype -> +# numpy-typing-compat needs numpy<2.5; pandas-stubs needs numpy<=2.3.5), so numpy +# in `mypy-upstream` resolves to the latest release. We accept that: dropping the +# stubs to free up numpy would leave pandas/scipy untyped and flood mypy with +# import-untyped errors. The upstream *test* job (`test-nightly`) is kept separate +# precisely so it still gets the genuine nightly numpy. +[feature.typing-stubs-nightly.pypi-dependencies] +pandas-stubs = "<=2.3.3.251219" +scipy-stubs = ">=1.17.1.2" + [feature.typing.tasks] mypy = { cmd = "mypy --install-types --non-interactive --cobertura-xml-report mypy_report", description = "Run mypy type checking and generate a Cobertura XML report." } @@ -397,10 +408,25 @@ test-py313 = { features = [ "extras", ] } test-nightly = { features = [ + "py313", + "nightly", + "test", + # Deliberately no "typing": type stubs cap numpy<2.5 and would displace the + # nightly numpy wheel this env's pytest job needs. Type checking against the + # dev stack lives in the separate `mypy-upstream` environment below. +], no-default-feature = true } + +# Type-checking against the development stack (used by the `mypy-upstream-dev` CI +# job). Same as `test-nightly` plus the typing toolchain and PyPI-sourced stubs. +# numpy resolves to the latest release here (the stubs cap it below the nightly +# wheel); every other dependency still comes from the nightly wheels / git, so +# this catches typing breakage from upstream development versions. +mypy-upstream = { features = [ "py313", "nightly", "test", "typing", + "typing-stubs-nightly", ], no-default-feature = true }