Repository navigation
fix(deps): a PEP 735 dev group, so uv run stops stripping the toolchain - #504
Merged
Merged
Conversation
…hain
The call-site half of this landed already: tests/test_daily_metrics_report.py
uses sys.executable rather than `uv run`. The other half did not, and the
defect it closes is still live on main -- it just is not reachable from the
suite any more.
pytest and ruff are declared ONLY in [project.optional-dependencies].dev. uv
installs GROUPS by default and extras NEVER, so any `uv run` fired from inside
this repository syncs the project venv down to the default dependency set and
prunes them out of it. Measured on this box against the real .venv,
`uv sync --dry-run`:
before would uninstall 9: pytest, ruff, iniconfig, pluggy, arxmcp,
pyinstaller, pyinstaller-hooks-contrib,
pefile, altgraph, pywin32-ctypes
after would uninstall 6: arxmcp + the PyInstaller stack only
pytest, ruff, iniconfig and pluggy are preserved. The residual is a different
thing and deliberately not addressed here: the PyInstaller build stack is
installed from requirements-build.txt, kept OUTSIDE pyproject/uv.lock by
apps/desktop/pyinstaller/desktop_package.py so the build venv is throwaway, so
uv correctly regards those as foreign to the project environment.
This matters because roughly twenty `uv run python -m tools.…` commands are
documented across tools/ docstrings and docs/ops/ runbooks. The failure mode
is the nasty kind: the in-flight command survives on already-imported modules
and appears to succeed, and the NEXT `make test` dies with "No module named
pytest".
The duplication between the extra and the group is load-bearing rather than an
oversight. `pip install -e ".[dev]"` (Makefile bootstrap, docs/install.md)
reads the extra; `uv sync` reads the group; neither table can reference the
other. tests/test_dev_toolchain_guard.py fails if they drift apart.
GUARD NARROWED, AND WHY. The guard as originally written banned every string
constant naming the uv binary anywhere under tests/. On current main that
flags tests/test_desktop_package.py:512, which is `shutil.which("uv")` -- a
PATH lookup that starts no process, syncs nothing and cannot prune a package.
It mirrors the precondition the packaging driver itself checks. Editing
working packaging code to satisfy an over-broad detector would be the wrong
direction, so the detector now exempts arguments to `which()` while still
catching argv lists, Windows `uv.exe` and hardcoded absolute paths.
Weakening a guard is only safe if the weakening is itself tested, so
TestDetectorItself drives the detector over synthetic source: presence checks
pass, invocation forms are still caught. One of those tests records a LIMIT
rather than a capability -- a `which()` result bound to a variable and then
passed to `run()` is invisible to any string-constant detector, with or
without the exemption -- so the guard does not imply cover it does not have.
uv.lock regenerated. Beyond the dev-group rows it also picks up the `contract`
extra (jsonschema + mfc), which pyproject declares and the lockfile did not
carry at all: pre-existing drift, repaired here because leaving it would mean
knowingly committing a lock that does not match its manifest. No pin changes.
Suite: 5406 passed, 188 skipped, 1 xfailed, 20 failed. All 20 failures are
pre-existing on origin/main and none are in the changed surface -- 16 in
test_formal_release_pin.py (`No module named 'mfc'`), 3 in
test_desktop_package.py (WinError 1314, symlink creation needs Developer
Mode), 1 in test_textbook_parser.py (`signal.SIGKILL` does not exist on
Windows; ingest/textbook_parser.py:551 is byte-identical to origin/main).
Ruff clean.
NOT FIXED HERE, and it is environmental rather than code: `uv lock` cannot run
on this machine without an explicit --python. C:\Users\cedar\bin\python3.exe is
a stub with no python.exe beside it, no pyvenv.cfg and no stdlib; uv selects it
because that directory is early on PATH, and any build backend that spawns the
sibling interpreter dies with `No Python at '"C:\Users\cedar\bin\python.exe'`
-- note the mangled quote. That stub is also what made this same test fail on
the July branch. No code change fixes it.
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.
The call-site half of this already landed —
tests/test_daily_metrics_report.pyusessys.executablerather thanuv run. The other half did not, and the defect it closes is still live onmain. It is simply no longer reachable from the suite.The defect
pytestandruffare declared only in[project.optional-dependencies].dev. uv installs groups by default and extras never, so anyuv runfired from inside this repository syncs the project venv down to the default dependency set and prunes them out of it.Measured on a Windows box against the real
.venv,uv sync --dry-run:pytest,ruff,iniconfig,pluggy,arxmcp,pyinstaller,pyinstaller-hooks-contrib,pefile,altgraph,pywin32-ctypesarxmcp+ the PyInstaller stack onlypytest,ruff,iniconfigandpluggyare preserved.The residual is a different thing and deliberately not addressed here: the PyInstaller build stack is installed from
requirements-build.txt, kept outsidepyproject.toml/uv.lockbyapps/desktop/pyinstaller/desktop_package.pyso the build venv stays throwaway. uv correctly regards those as foreign to the project environment.This matters because roughly twenty
uv run python -m tools.…commands are documented acrosstools/docstrings anddocs/ops/runbooks. The failure mode is the nasty kind: the in-flight command survives on already-imported modules and appears to succeed, and the nextmake testdies withNo module named pytest.The duplication between the extra and the group is load-bearing.
pip install -e ".[dev]"(Makefile bootstrap,docs/install.md) reads the extra;uv syncreads the group; neither table can reference the other.tests/test_dev_toolchain_guard.pyfails if they drift apart.The guard was narrowed — and the narrowing is tested
As originally written the guard banned every string constant naming the
uvbinary anywhere undertests/. On currentmainthat flagstests/test_desktop_package.py:512, which isshutil.which("uv")— a PATH lookup that starts no process, syncs nothing and cannot prune a package. It mirrors the precondition the packaging driver itself checks.Editing working packaging code to satisfy an over-broad detector is the wrong direction, so the detector now exempts arguments to
which()while still catching argv lists, Windowsuv.exe, and hardcoded absolute paths.Weakening a guard is only safe if the weakening is itself tested.
TestDetectorItselfdrives the detector over synthetic source: presence checks pass, invocation forms are still caught. One of those tests records a limit rather than a capability — awhich()result bound to a variable and then passed torun()is invisible to any string-constant detector, with or without the exemption — so the guard does not imply cover it does not have.Lockfile
Regenerated. Beyond the dev-group rows it also picks up the
contractextra (jsonschema+mfc), whichpyproject.tomldeclares and the lockfile did not carry at all. That is pre-existing drift, repaired here because leaving it out would mean knowingly committing a lock that does not match its manifest. No pin changes.Worth noting for whoever hits it next:
mfcis exactly the module missing in the 16test_formal_release_pin.pyfailures below.uv sync --extra contractshould clear them.Verification
origin/mainand none are in the changed surface:test_formal_release_pin.py—ModuleNotFoundError: No module named 'mfc'test_desktop_package.py—WinError 1314, symlink creation needs Developer Modetest_textbook_parser.py—signal.SIGKILLdoes not exist on Windows;ingest/textbook_parser.py:551is byte-identical toorigin/maintests/test_dev_toolchain_guard.py: 6/6.Not fixed here — environmental, not code
uv lockcannot run on this machine without an explicit--python.C:\Users\cedar\bin\python3.exeis a stub: nopython.exebeside it, nopyvenv.cfg, no stdlib. uv selects it because that directory is early onPATH, and any build backend that spawns the sibling interpreter dies with:Note the mangled quote. That same stub is what made
test_daily_metrics_reportfail on the July branch. No code change fixes it.