Repository navigation
🐛 fix(seed): keep console script names that are not version suffixes - #3451
Open
JingHao-Leon wants to merge 4 commits into
Open
JingHao-Leon wants to merge 4 commits into
JingHao-Leon wants to merge 4 commits into
Conversation
The console_scripts name normalization matched a prefix with re.match and a lazy (.*?), so the first digit run anywhere in a name was treated as a version suffix and the rest of the name discarded. A wheel declaring python3-config was seeded as python, replacing the environment's interpreter executable and leaving the environment unusable; 2to3 and 3to2 collapsed to an empty base name and produced scripts called " ", " 3" and "3.13". Anchor the match to the whole remainder of the name and require the base to start with a letter, so only a real trailing version such as pip3, pip3.13 or pip-3.13 is folded onto its base name.
for more information, see https://pre-commit.ci
The folding test read the private _console_scripts mapping, which trips ruff's private-member-access rule. Assert on the scripts that end up in the bin directory instead: one folded base regenerates pip, pip3, pip3.13 and pip-3.13, while not folding would add a name per declared alias.
virtualenv names changelog fragments after the pull request that adds them (3441.bugfix.rst for pypa#3441, 3435.bugfix.rst for pypa#3435, 3434.bugfix.rst for pypa#3434), even when the pull request references a separate issue. This one is pull request pypa#3451 and fixes issue pypa#3450, so the fragment is renamed from 3450.bugfix.rst to 3451.bugfix.rst. The content is unchanged.
This branch has not been deployed
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.
Thanks for contributing, make sure you address all the checklists (for details on how see development documentation)
ruff check/ruff format, with the minimal config below)docs/changelogfolderWhat breaks
Seeding a wheel whose
entry_points.txtdeclares aconsole_scriptsentry whose name contains digits renamesthe script. The worst case is
python3-config: it is truncated topython, so the generated launcher replacesthe environment's
pythonexecutable and the environment can no longer run anything.env/bin/pythonis a symlink into the base interpreter before seeding and a generated console script afterwards.Activation scripts and
pyvenv.cfgboth point at that path.python3-configpython,python3,python-3.13,python3.132to3/3to2" "," 3","3.13"flake8flake,flake3,flake3.13pip3,pip3.13pip,pip3,pip3.13(intended)The seed packages themselves are unaffected, because
pip/pip3/pip3.13all fold ontopipas intended.Root cause
src/virtualenv/seed/embed/via_app_data/pip_install/base.py, the_console_scriptsproperty:re.matchanchors only at the start of the string and(.*?)is lazy, so the first digit run anywhere in thename is consumed as a version suffix and the rest of the name is discarded. The name is truncated at its first
digit rather than at a trailing version.
The fix
Anchor the match to the whole remainder of the name and require the base to start with a letter, so only a real
trailing version is folded onto its base name:
pip3,pip3.13andpip-3.13still fold ontopip;python3-config,2to3and3to2now keep their names.This only changes which name a script is written under. A wheel declaring
pipandpip3is unaffected, and nodownloaded file is executed as code — the name is used as a filename and embedded in the generated shebang, exactly
as before.
Before / after
Seeding a wheel that declares
python3-config = example:main:env/bin/pythonis a symlink again after seeding.Tests
New tests extend the existing entry-points coverage in
tests/unit/seed/embed/test_bootstrap_link_via_app_data.py.Whole seed unit suite plus the other unit directories, against the clone's
src(not site-packages), compared tothe same subset on unmodified upstream
main:+5, which are exactly the new tests; no existing test changed state.
Linting, with the minimal config for the older ruff available here (line length 120):
I could not run
tox -e fixortox run -e 3.9,3.15: this machine only has CPython 3.13.9, and the repository'stoxenvironments are not installed. I ran the test subset and the linters directly instead.Follow-up: the folding test asserted on a private attribute
The first pre-commit run failed
ruffwithprivate-member-accessontest_seed_entry_points_still_fold_version_suffixed_names, which readinstaller._console_scripts. The test nowasserts on the scripts that appear in
bininstead: one folded base regeneratespip,pip3,pip3.13andpip-3.13, whereas not folding would emit a name per declared alias. Same guarantee, no private access.Fixes #3450
CI status
The upstream workflows for this head have not run. GitHub recorded all of them
with
conclusion: action_required— the runs are blocked awaiting approval(for workflows triggered from a fork, GitHub requires a maintainer to approve
them before they execute). The affected workflows are:
🧪 check(.github/workflows/check.yaml)🔍 dependency review(.github/workflows/dependency-review.yaml)🔎 CodeQL(.github/workflows/codeql.yaml)gh pr checksreports only the two checks that do not need approval — the Readthe Docs build and
pre-commit.ci— and both of them pass. It does not reportthe workflows listed above, so there is no upstream CI verdict to report. The
test and lint output above comes from local runs against the patched tree.
This change was prepared with the assistance of an AI coding agent.