fix(linalg): stop sybil double-importing UnitsMatrix under a combined pytest run - #887
Merged
nstarman merged 3 commits intoAug 16, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Sybil/pytest namespace-package edge case where doctests in packages/unxts.linalg/src can be imported under an incorrect leaf module name (linalg.*), causing duplicate module trees and type identity mismatches (e.g., UnitsMatrix) in combined pytest runs.
Changes:
- Skips Sybil doctest collection for
packages/unxts.linalg/src/via the existing_DOCTEST_MODULE_SRCmechanism to prevent mis-import/double-import during combined sessions. - Aligns the
unxts-linalgCI job’s src-doctest invocation with otherunxts.*namespace packages by running pytest doctests with--import-mode=importlibandconsider_namespace_packages=true.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
conftest.py |
Adds unxts.linalg to the Sybil doctest skip list to avoid leaf-based mis-import under PEP 420. |
.github/workflows/ci.yml |
Updates the unxts-linalg CI job to run src doctests via pytest’s namespace-aware doctest collection settings. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… pytest run Sybil computes a doctest module's import name by walking up through `__init__.py` directories, so at the `unxts` PEP 420 namespace boundary it imports `packages/unxts.linalg/src` doctests as `linalg.*` instead of `unxts.linalg.*`. Unlike gala/xarray/hypothesis, `linalg` has no installed package to collide with, so the mis-import "succeeds" -- silently building a second module tree and duplicating classes like `UnitsMatrix`. Whichever copy a doctest sees is `!=` the copy the rest of the session imports, so `isinstance` checks and plum's return-type conversion both fail wherever a `-> UnitsMatrix` dispatch is exercised in the same session as its own doctests (`pytest packages/unxts.linalg`). Add `unxts.linalg/src` to the existing `_DOCTEST_MODULE_SRC` skip list (same fix already applied for gala/xarray/hypothesis) and move its CI job onto the namespace-aware `--doctest-modules --import-mode=importlib` invocation used by those packages, so src doctests still run, just under the correct module name. Fixes GalacticDynamics#881 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Trim the unxts.linalg explanation added for GalacticDynamics#881 down to the one fact that isn't already covered by the surrounding paragraph, and drop the "!=`-different classes" phrasing a review flagged as suggesting value inequality rather than the actual identity mismatch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…solves correctly GalacticDynamics#880 shipped this test pre-xfailed pending the fix in this branch; it now passes under the same combined pytest session the xfail called out. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
nstarman
force-pushed
the
claude/issue-881-fix-7ae8ba
branch
from
August 15, 2026 08:47
e40a378 to
327a382
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #887 +/- ##
==========================================
+ Coverage 99.82% 99.96% +0.13%
==========================================
Files 84 46 -38
Lines 3998 2693 -1305
Branches 311 162 -149
==========================================
- Hits 3991 2692 -1299
+ Misses 3 0 -3
+ Partials 4 1 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
nstarman
added a commit
that referenced
this pull request
Aug 17, 2026
…ouble-importing UnitsMatrix under a combined pytest run) (#890) * Backport PR #887: fix(linalg): stop sybil double-importing UnitsMatrix under a combined pytest run * fix(test): ignore astropy's XDG config-dir race warning under pytest-xdist pytest-xdist workers race to create ~/.astropy/config on first astropy import; whichever worker loses the race gets an AstropyUserWarning that pytest's filterwarnings=error turns into a collection-crashing error, producing "Different tests were collected between gw2 and gw3" (fixed in PR #883's -n logical --dist=loadfile parallelization). Filter category is UserWarning, not astropy's own AstropyUserWarning class: resolving that class name requires importing astropy, which can re-trigger the same warning before the ignore rule itself is applied. Co-authored-by: Nathaniel Starkman <nstarman@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #881.
Sybil computes a doctest module's import name by walking up through
__init__.pydirectories, so at theunxtsPEP 420 namespace boundary it importspackages/unxts.linalg/srcdoctests aslinalg.*instead ofunxts.linalg.*. Unlikeunxts.interop.gala/unxts.interop.xarray/unxts.hypothesis— which hit this same mechanism but fail loudly because their leaf name collides with an installed library —linalghas no installed package to collide with, so the mis-import silently "succeeds": it builds a second, wrongly-named module tree alongside the realunxts.linalgone, duplicating any class defined there (e.g.UnitsMatrix). Whichever copy a doctest sees is a!=-different class from the copy the rest of the pytest session imports, soisinstancechecks and plum's return-type conversion both fail wherever a-> UnitsMatrixdispatch (likeunit_of) is exercised in the same session as the package's own doctests — i.e.pytest packages/unxts.linalg(src + tests together).Confirmed the mechanism directly: a debug test dumping
sys.modulesmid-run shows two liveUnitsMatrixclasses with differentid()s, one underlinalg._src._units_matrix(sybil's leaf-based name) and one underunxts.linalg._src._units_matrix(the real one).The repo already has the fix for this exact class of bug —
conftest.py's_DOCTEST_MODULE_SRCskip-list plus a namespace-aware--doctest-modules --import-mode=importlibCI step, applied for gala/xarray/hypothesis. This PR applies the same fix tounxts.linalg.Changes
conftest.py: addpackages/unxts.linalg/src/to_DOCTEST_MODULE_SRCso sybil skips collecting its doctests under the wrong module name (in any combined session, not just CI); broadened the explanatory comment to cover the silent-duplicate-class failure mode, not just the loud import-collision one..github/workflows/ci.yml: switch theunxts-linalgjob's src-doctest step to the same--doctest-modules -o addopts="--import-mode=importlib" -o consider_namespace_packages=true -o doctest_optionflags="ELLIPSIS NORMALIZE_WHITESPACE"invocation already used for gala/xarray/hypothesis, so src doctests keep running under the correct module name. (The job's previous split-invocation comment was a workaround for CI specifically; it didn't help local combined runs, which is what plum return conversion forUnitsMatrixfails under a combined pytest session (Cannot convert UnitsMatrix to UnitsMatrix) #881 reports.)Test plan
pytest packages/unxts.linalg(src + tests together, the exact repro from plum return conversion forUnitsMatrixfails under a combined pytest session (Cannot convert UnitsMatrix to UnitsMatrix) #881) — was 8 failed, now 374 passedpytest packages/unxts.linalg/src --doctest-modules -o addopts="--import-mode=importlib" -o consider_namespace_packages=true -o doctest_optionflags="ELLIPSIS NORMALIZE_WHITESPACE"(new CI step) — 42 passed, same doctest-bearing functions/classes as before, just one item per docstring instead of per sybil example-regionpytest packages/unxts.linalg/tests— 262 passed, unaffectedpytest packages/unxts.linalg src/unxt(sanity check against the rest of the tree) — 2397 passed🤖 Generated with Claude Code