You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
pip install -e ".[dev]" produces an environment where pytest cannot start #110
Separately, on this machine no interpreter can import paramiko — a hard runtime dependency — across anaconda base, homebrew, system, and mambaforge. There is no project venv. import clustrix fails everywhere, which is why every coverage figure in issues #61/#86/#98-#106 is unverifiable.
Undeclared test dependencies cause 6 collection errors on a clean [dev] install:
tests/real_world/test_container_registry_comprehensive.py:571 — SyntaxError: f-string expression part cannot include a backslash. This blocks collection of the whole run on Python <=3.11 even under -m "not real_world".
Also in scope
requires-python = ">=3.8" (pyproject.toml:14, setup.py:32). Python 3.8 and 3.9 are both past end-of-life. The f-string bug above is precisely a <=3.11 issue.
Acceptance criteria
pip install -e ".[dev]" on a clean machine yields an environment where pytest starts and collects with zero errors.
[dev] includes everything addopts and the tests require: pytest-xdist, numpy, pandas, scikit-learn (or the tests needing them are moved behind an extra and marked).
New evidence from PR #129: unbounded dependency pins make CI fail with no code change.
While landing #109, CI failed on Lint with black with "19 files would be reformatted" — none of which the PR touched.
Cause: pyproject.toml:86,135 declared "black>=21.0" with no upper bound, so pip install -e ".[dev,...]" resolved black 26.5.1, whose new stable style reformats 19 existing files. .pre-commit-config.yaml separately pins rev: 25.1.0. Local pre-commit and CI were therefore running different formatters, and CI could turn red spontaneously whenever black published a release.
Reproduced exactly by installing 26.5.1 locally: 19 files would be reformatted, 276 files would be left unchanged.
Fixed in #129 by pinning black==25.1.0; python_version >= "3.9" and running lint once on ubuntu/3.11. The tree passes cleanly under 25.1.0, so no files needed reformatting.
Still outstanding for this issue — the same unbounded pattern applies to the other linters, and they carry identical drift risk:
Pin flake8 and mypy to versions the tree currently passes under
Consider pinning or constraining the runtime deps too — 6 of the 127 failures in Fix the 127 test failures and 8 collection errors that CI never sees #114 are TypeError: __init__() missing 1 required keyword-only argument: response, which is googleapiclient changing under an unpinned requirement. Same root cause, different package.
This is worth treating as part of this issue's "reproducible dev-env bootstrap" AC: an environment is not reproducible if pip install -e ".[dev]" resolves differently today than yesterday.
Dependabot alert #1 — caused by the black pin in #129
black==25.1.0 (pinned in PR #129 to stop CI drift) falls inside a high-severity advisory range:
black >= 24.3.0, < 26.3.1
Arbitrary file writes from unsanitized user input in cache file name
Full disclosure: the previous unbounded black>=21.0 would have resolved to 26.5.1, which is patched. So the pin fixed a CI-determinism problem and introduced a (low-practical-risk) advisory. Both facts belong on the record.
Practical risk
The vector is a cache filename derived from untrusted input. black here runs over the project's own source, in CI and pre-commit, with no attacker-controlled paths. Real exposure is close to nil — but the alert stays red until resolved, and "red alerts we have decided to ignore" is exactly the habit this repo is trying to break.
The awkward part
The patched line (>=26.3.1) requires Python >=3.10, and the CI matrix still includes 3.8 and 3.9. So a straight bump is impossible without one of:
(a) Raise the floor. Drop 3.8/3.9 and set requires-python = ">=3.10" — already an AC of this issue, and both are long EOL (3.8 Oct 2024, 3.9 Oct 2025). Then pin black==26.5.1 and reformat the 19 files it restyles in one dedicated commit.
(b) Environment markers — black==26.5.1; python_version >= "3.10" plus an older pin below. Then two formatters disagree, which is the original bug in a new costume. Not recommended.
(c) Stop installing black per-matrix-entry.#129 already gated lint steps to ubuntu/3.11 only; the logical next step is moving linting into its own job with its own pinned toolchain, so formatter version stops being coupled to the Python support matrix. Cleanest fix, and it makes (a) independent rather than a prerequisite.
Recommendation
Do (c), then (a). Together they clear this alert, remove the 3.8/3.9 EOL exposure, and decouple lint tooling from the runtime support matrix — the underlying design problem, not the black version.
The same unbounded-pin risk still applies to flake8>=3.8 and mypy>=0.812 (pyproject.toml:87-88,136-137) and to unpinned runtime deps — 6 of the 127 failures in #114 are googleapiclient changing under an unpinned requirement.
That line is from the closed epic branch, not master. On master at a9393b7, pyproject.toml's addopts was -v --tb=short — no -n, no --dist.
More importantly, it did not matter what it said. pytest.ini sat in the repo root with the section header [tool:pytest], which is valid only in setup.cfg. pytest still selectedpytest.ini as its config file, and having selected one it stops searching — so pyproject.toml's [tool.pytest.ini_options] was never read. On master, addopts from either file was inert:
So pip install -e ".[dev]" did not fail with unrecognized arguments: -n --dist loadfile on master — that reproduces only where pytest.ini is absent. Any statement about "the addopts" needs to name which config was live. Full analysis in #130.
The underlying dependency point still stands and is now recorded in pyproject.toml: pytest-xdist is in [test], not [dev], so -n must not be added to addopts without moving it first. There is a comment above addopts saying so.
2. scikit-learn does not cause collection errors
sklearn -> 2 further failures
Not at collection time. Every sklearn import under tests/ is inside a function body (test_notebook_magic_real.py:450, test_decorator_real.py:463-467, reference_workflows/kubernetes_workflows.py:68-70), so it is never executed during collection. With numpy and pandas installed and nothing else, collection is clean:
sklearn may still be needed to run those tests; it is not needed to collect them.
3. Two acceptance-criteria items are done (in #130's PR)
tests/real_world/test_container_registry_comprehensive.py:571 syntax error fixed. The backslash was inside an f-string expression, a SyntaxError on every Python before 3.12 while requires-python says >=3.8. The split() is now hoisted out. An AST parse over all of tests/ and clustrix/ confirms it was the only such error in the tree.
numpy and pandas added to the [dev] extra. These were the real cause of the collection errors. On master a clean [dev] install gave 6 collection errors; it now gives 0.
Still open here: pytest-xdist placement, the requires-python floor, the bootstrap command, and the CI job that installs only [dev] and asserts collection succeeds.
The verification command in this issue's "Verification" section now passes:
Each named cause is gone: addopts carries no -n, so xdist is not required to start; requires-python = ">=3.10" (pyproject.toml:19, setup.py:31) with a CI matrix of 3.10/3.11/3.12; [dev] declares numpy, pandas, scikit-learn, ipywidgets, ipython and pytest-timeout; the file carrying the f-string SyntaxError no longer exists. fast_ci.yml:47 installs only .[dev] and runs the suite green.
The one item not done is a make dev bootstrap. There is no Makefile, and CONTRIBUTING.md documents the pip command instead — a documentation nicety rather than the defect this issue describes.
Activity
Issue #110: Pin black - unbounded ">=" made CI fail with no code change
Issue #110: Restrict black pin to py>=3.9 and run linting once
jeremymanning commentedon Aug 17, 2026
New evidence from PR #129: unbounded dependency pins make CI fail with no code change.
While landing #109, CI failed on
Lint with blackwith "19 files would be reformatted" — none of which the PR touched.Cause:
pyproject.toml:86,135declared"black>=21.0"with no upper bound, sopip install -e ".[dev,...]"resolved black 26.5.1, whose new stable style reformats 19 existing files..pre-commit-config.yamlseparately pinsrev: 25.1.0. Local pre-commit and CI were therefore running different formatters, and CI could turn red spontaneously whenever black published a release.Reproduced exactly by installing 26.5.1 locally:
19 files would be reformatted, 276 files would be left unchanged.Fixed in #129 by pinning
black==25.1.0; python_version >= "3.9"and running lint once on ubuntu/3.11. The tree passes cleanly under 25.1.0, so no files needed reformatting.Still outstanding for this issue — the same unbounded pattern applies to the other linters, and they carry identical drift risk:
flake8andmypyto versions the tree currently passes underTypeError: __init__() missing 1 required keyword-only argument: response, which isgoogleapiclientchanging under an unpinned requirement. Same root cause, different package.This is worth treating as part of this issue's "reproducible dev-env bootstrap" AC: an environment is not reproducible if
pip install -e ".[dev]"resolves differently today than yesterday.jeremymanning commentedon Aug 17, 2026
Dependabot alert #1 — caused by the black pin in #129
black==25.1.0(pinned in PR #129 to stop CI drift) falls inside a high-severity advisory range:Full disclosure: the previous unbounded
black>=21.0would have resolved to 26.5.1, which is patched. So the pin fixed a CI-determinism problem and introduced a (low-practical-risk) advisory. Both facts belong on the record.Practical risk
The vector is a cache filename derived from untrusted input. black here runs over the project's own source, in CI and pre-commit, with no attacker-controlled paths. Real exposure is close to nil — but the alert stays red until resolved, and "red alerts we have decided to ignore" is exactly the habit this repo is trying to break.
The awkward part
The patched line (>=26.3.1) requires Python >=3.10, and the CI matrix still includes 3.8 and 3.9. So a straight bump is impossible without one of:
(a) Raise the floor. Drop 3.8/3.9 and set
requires-python = ">=3.10"— already an AC of this issue, and both are long EOL (3.8 Oct 2024, 3.9 Oct 2025). Then pinblack==26.5.1and reformat the 19 files it restyles in one dedicated commit.(b) Environment markers —
black==26.5.1; python_version >= "3.10"plus an older pin below. Then two formatters disagree, which is the original bug in a new costume. Not recommended.(c) Stop installing black per-matrix-entry. #129 already gated lint steps to ubuntu/3.11 only; the logical next step is moving linting into its own job with its own pinned toolchain, so formatter version stops being coupled to the Python support matrix. Cleanest fix, and it makes (a) independent rather than a prerequisite.
Recommendation
Do (c), then (a). Together they clear this alert, remove the 3.8/3.9 EOL exposure, and decouple lint tooling from the runtime support matrix — the underlying design problem, not the black version.
The same unbounded-pin risk still applies to
flake8>=3.8andmypy>=0.812(pyproject.toml:87-88,136-137) and to unpinned runtime deps — 6 of the 127 failures in #114 aregoogleapiclientchanging under an unpinned requirement.jeremymanning commentedon Aug 17, 2026
Correction: the
addoptspremise in this issue does not describemasterFound while fixing #130. Two claims here need amending, and one acceptance-criteria item is now done.
1. The quoted
addoptswas never live onmasterThis issue opens with:
That line is from the closed epic branch, not
master. Onmasterata9393b7,pyproject.toml'saddoptswas-v --tb=short— no-n, no--dist.More importantly, it did not matter what it said.
pytest.inisat in the repo root with the section header[tool:pytest], which is valid only insetup.cfg. pytest still selectedpytest.inias its config file, and having selected one it stops searching — sopyproject.toml's[tool.pytest.ini_options]was never read. Onmaster,addoptsfrom either file was inert:So
pip install -e ".[dev]"did not fail withunrecognized arguments: -n --dist loadfileonmaster— that reproduces only wherepytest.iniis absent. Any statement about "the addopts" needs to name which config was live. Full analysis in #130.The underlying dependency point still stands and is now recorded in
pyproject.toml:pytest-xdistis in[test], not[dev], so-nmust not be added toaddoptswithout moving it first. There is a comment aboveaddoptssaying so.2.
scikit-learndoes not cause collection errorsNot at collection time. Every
sklearnimport undertests/is inside a function body (test_notebook_magic_real.py:450,test_decorator_real.py:463-467,reference_workflows/kubernetes_workflows.py:68-70), so it is never executed during collection. Withnumpyandpandasinstalled and nothing else, collection is clean:sklearnmay still be needed to run those tests; it is not needed to collect them.3. Two acceptance-criteria items are done (in #130's PR)
tests/real_world/test_container_registry_comprehensive.py:571syntax error fixed. The backslash was inside an f-string expression, aSyntaxErroron every Python before 3.12 whilerequires-pythonsays>=3.8. Thesplit()is now hoisted out. An AST parse over all oftests/andclustrix/confirms it was the only such error in the tree.numpyandpandasadded to the[dev]extra. These were the real cause of the collection errors. Onmastera clean[dev]install gave 6 collection errors; it now gives 0.Still open here:
pytest-xdistplacement, therequires-pythonfloor, the bootstrap command, and the CI job that installs only[dev]and asserts collection succeeds.The verification command in this issue's "Verification" section now passes:
Issue #130: pytest.ini was dead config shadowing pyproject.toml (#134)
Issue #110/#135: Correct the Python floor, and make fast_ci.yml parse
Take the black security update, and stop two hooks fighting over the …
Make the suite and the profile store work on Windows
jeremymanning commentedon Aug 20, 2026
Closed — the environment starts pytest
Each named cause is gone:
addoptscarries no-n, so xdist is not required to start;requires-python = ">=3.10"(pyproject.toml:19,setup.py:31) with a CI matrix of 3.10/3.11/3.12;[dev]declares numpy, pandas, scikit-learn, ipywidgets, ipython and pytest-timeout; the file carrying the f-stringSyntaxErrorno longer exists.fast_ci.yml:47installs only.[dev]and runs the suite green.The one item not done is a
make devbootstrap. There is no Makefile, andCONTRIBUTING.mddocuments the pip command instead — a documentation nicety rather than the defect this issue describes.