Skip to content

fix: resolve ruff and mypy from the generator's own environment - #6

Merged
goduni merged 1 commit into
mainfrom
feat/ruff-mypy-env-fix
Aug 7, 2026
Merged

fix: resolve ruff and mypy from the generator's own environment#6
goduni merged 1 commit into
mainfrom
feat/ruff-mypy-env-fix

Conversation

@goduni

@goduni goduni commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Both tools are invoked at runtime, but they were looked up with shutil.which(), which searches PATH. That is the wrong place: uv tool install and pipx expose only the console scripts a distribution declares, so the copies installed alongside the generator are not on PATH and an unrelated system install wins instead. The bug reproduced in this very repo, where PATH resolved to ruff 0.15.10 / mypy 1.20.0 while the pinned environment held 0.15.15 / 2.1.0 -- generated code was being formatted and checked by versions nobody selected.

Add tooling.py, which searches the environment the generator was installed into before anything ambient. Its first candidate is derived from this module's own location, because ruff arrived through the same install; sysconfig's default scheme cannot stand in for it, since under pip install --user that names the system bin while the generator and its ruff live under the user scheme, letting a too-old system ruff win. The remaining candidates are the active environment, the interpreter's own directory, the user scheme and the base prefix, with PATH last.

ruff is resolved to a binary path rather than run as python -m ruff, which measured 4.4x slower per call (12.7ms -> 56.5ms) and is invoked twice per generated file. mypy runs as python -m mypy, a single call where the interpreter also determines what it resolves imports against.

Promote mypy from the check extra to a core dependency, since --check is documented as a headline feature and the extra left it absent by default. The extra stays, now empty, so existing [check] installs keep resolving.

--check gains --python-executable pointing at an activated virtualenv when that differs from the generator's own environment. Without it, moving mypy off PATH would have regressed standalone installs: the generator's environment has ruff and mypy but not unihttp or the serializer, so every generated import would fail to resolve. Environment roots are compared rather than interpreters, because venvs built from one base python share a bin/python symlink target and would otherwise look identical.

Both tools are invoked at runtime, but they were looked up with
shutil.which(), which searches PATH. That is the wrong place: uv tool
install and pipx expose only the console scripts a distribution declares,
so the copies installed alongside the generator are not on PATH and an
unrelated system install wins instead. The bug reproduced in this very
repo, where PATH resolved to ruff 0.15.10 / mypy 1.20.0 while the pinned
environment held 0.15.15 / 2.1.0 -- generated code was being formatted and
checked by versions nobody selected.

Add tooling.py, which searches the environment the generator was installed
into before anything ambient. Its first candidate is derived from this
module's own location, because ruff arrived through the same install;
sysconfig's default scheme cannot stand in for it, since under
`pip install --user` that names the system bin while the generator and its
ruff live under the user scheme, letting a too-old system ruff win. The
remaining candidates are the active environment, the interpreter's own
directory, the user scheme and the base prefix, with PATH last.

ruff is resolved to a binary path rather than run as `python -m ruff`,
which measured 4.4x slower per call (12.7ms -> 56.5ms) and is invoked twice
per generated file. mypy runs as `python -m mypy`, a single call where the
interpreter also determines what it resolves imports against.

Promote mypy from the `check` extra to a core dependency, since --check is
documented as a headline feature and the extra left it absent by default.
The extra stays, now empty, so existing [check] installs keep resolving.

--check gains --python-executable pointing at an activated virtualenv when
that differs from the generator's own environment. Without it, moving mypy
off PATH would have regressed standalone installs: the generator's
environment has ruff and mypy but not unihttp or the serializer, so every
generated import would fail to resolve. Environment roots are compared
rather than interpreters, because venvs built from one base python share a
bin/python symlink target and would otherwise look identical.
@goduni
goduni merged commit 9f18d6f into main Aug 7, 2026
4 checks passed
@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (9ca381d) to head (757b137).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main        #6   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           29        30    +1     
  Lines         2557      2604   +47     
=========================================
+ Hits          2557      2604   +47     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@goduni
goduni deleted the feat/ruff-mypy-env-fix branch August 7, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant