Skip to content

Fix sdist extraction on older Python versions - #11037

Merged
radoering merged 1 commit into
python-poetry:mainfrom
fredrikblau:fix/older-python-sdist-extraction
Sep 5, 2026
Merged

Fix sdist extraction on older Python versions#11037
radoering merged 1 commit into
python-poetry:mainfrom
fredrikblau:fix/older-python-sdist-extraction

Conversation

@fredrikblau

Copy link
Copy Markdown
Contributor

Summary

The tar security fallback clears ownership names with None. Python versions before 3.10.12 and 3.11.4 pass those values to grp.getgrnam() / pwd.getpwnam(), causing root sdist installs to fail.

Use empty ownership names instead, which preserves the ownership-stripping behavior without triggering the older tarfile bug. Added a regression test that simulates the affected tarfile implementation.

Fixes #11036.

Tests

  • pytest tests/utils/test_helpers.py -q (50 passed)
  • pytest (2,935 passed, 28 skipped; 6 collection errors due missing deepdiff before installation, and one unrelated Python 3.14 platform-tag expectation)
  • ruff check tests/utils/test_helpers.py (passed; existing PLC0206 remains in src/poetry/utils/helpers.py)

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. If the owner-name workaround is wrong, extraction could fail or create files with an unintended owner or group, potentially affecting access to the extracted sdist. Reverting fixes future extractions, but already-created files and their ownership would remain until the archive is re-extracted or the metadata is corrected.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@fredrikblau
fredrikblau force-pushed the fix/older-python-sdist-extraction branch from 907013b to f89bbd6 Compare August 31, 2026 13:02

@radoering radoering left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are more spots with the pattern "try - except KeyError" and running the repro with Poetry from your branch still fails:

TypeError

  uid should be integer, not NoneType

(Just replace poetry==2.4.2 with git+https://github.com/fredrikblau/poetry.git@fix/older-python-sdist-extraction in the repro.)

@fredrikblau

Copy link
Copy Markdown
Contributor Author

Handled the missing-ownership case from the repro. The fallback now always sets uid/gid to -1, and the regression test simulates omitted fields.

pytest -q tests/utils passes: 378 passed, 21 skipped. Ruff reports the existing PLC0206 in helpers.py; git diff --check passes.

@fredrikblau
fredrikblau force-pushed the fix/older-python-sdist-extraction branch from 0114526 to 90b280f Compare September 2, 2026 15:24
@Pandorin

Pandorin commented Sep 2, 2026

Copy link
Copy Markdown

Tested 90b280f on the reproducer from #11036: it passes. 👍

@fredrikblau

Copy link
Copy Markdown
Contributor Author

Fixed the mypy failure in the regression setup by using object.setattr to simulate missing ownership fields.

Focused tests: 50 passed. The hosted Windows pytest failure is unrelated PermissionError in test_env.py.

Comment thread src/poetry/utils/helpers.py Outdated
Python versions without a working tarfile data filter fall back to the
filter copied from CPython, which clears ownership by setting uid, gid,
uname and gname to None. TarFile.chown() in those same versions cannot
cope with that: it passes the ids to os.chown() and resolves the names
with pwd/grp, catching only KeyError. Extracting an sdist therefore
failed with "uid should be integer, not NoneType", or a TypeError from
the name lookup when the archive itself carried no owner names.

Clear ownership with values those versions accept instead: -1 for the
ids, which os.chown() reads as "leave unchanged", and "" for the names,
which fails the lookup with KeyError and falls back to the ids.

Fixes: python-poetry#11036
@fredrikblau
fredrikblau force-pushed the fix/older-python-sdist-extraction branch from a31537b to f69a507 Compare September 4, 2026 22:45
@radoering
radoering merged commit 98df56f into python-poetry:main Sep 5, 2026
52 checks passed
radoering pushed a commit that referenced this pull request Sep 5, 2026
Python versions without a working tarfile data filter fall back to the
filter copied from CPython, which clears ownership by setting uid, gid,
uname and gname to None. TarFile.chown() in those same versions cannot
cope with that: it passes the ids to os.chown() and resolves the names
with pwd/grp, catching only KeyError. Extracting an sdist therefore
failed with "uid should be integer, not NoneType", or a TypeError from
the name lookup when the archive itself carried no owner names.

Clear ownership with values those versions accept instead: -1 for the
ids, which os.chown() reads as "leave unchanged", and "" for the names,
which fails the lookup with KeyError and falls back to the ids.

(cherry picked from commit 98df56f)
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.

Regression in 2.4.2: sdist install fails as root on Python < 3.10.12 / < 3.11.4 with TypeError: getgrnam() argument 'name' must be str, not None

3 participants