샘플
packaging 24.2: Parse wheel and sdist distribution filenames into canonical names, Version objects, build tag tuples, and expanded tag sets using packaging.utils
검증된 샘플 — pypi packaging 24.2: Parse wheel and sdist distribution filenames into canonical names, Version objects, build tag tuples, and expanded tag sets…
sha256:ee011019fcbe1934eb1046b1776996e547b79794ee7d9ae4e4e71982a6a12b18
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 3
- 빌드한 서명 키
- 3
선언된 환경
python linux x64 python python pip
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-17 |
| python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-18 |
| python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104… |
2026-09-08 |
케이스
HOW- 목표
- Parse wheel and sdist distribution filenames into canonical names, Version objects, build tag tuples, and expanded tag sets using packaging.utils
- 패키지
- 심벌
-
- packaging.utils.parse_wheel_filename
- packaging.utils.parse_sdist_filename
- packaging.utils.canonicalize_name
- 환경
- python
- 생성일
- 2026-08-17T19:41:39Z
컨트랙트
- parse_wheel_filename returns a 4-tuple of canonicalized name, parsed Version, integer-prefixed build tag tuple, and Cartesian-product expanded Tag frozenset, rejecting build tags without a leading digit.
- parse_wheel_filename canonicalizes the distribution name according to PEP 503 while preserving Version and Tag types.
- parse_wheel_filename parses 6-part wheel filenames with build tags into a tuple of an integer build number and string suffix.
- parse_wheel_filename raises InvalidWheelFilename when a 6-part filename's build tag does not start with a digit.
- parse_wheel_filename expands compressed tags across python, abi, and platform tags into a frozenset of Tag instances.
- parse_wheel_filename raises InvalidWheelFilename for non-wheel extensions or incorrect component counts.
- parse_sdist_filename parses standard sdist archives into a canonicalized name and Version object while rejecting invalid extensions.
파일
- NOTES.md
- csx.json
- requirements.txt
- test/contract.py
소스
# Packaging 24.2 Distribution Filename Parsing and Canonicalization
## Known Solutions Search
A search for existing verified samples for `packaging` at version 24.2 returned three matches focusing on `SpecifierSet` and prerelease handling:
- `sha256:f19dcaeb076fa504e3311b3a1df2fe75cfd5dc594f854b9f3986ce8a6589402a`: Auto-enable prerelease matching for '>' and '<' specifiers containing prereleases fixed in packaging 24.2
- `sha256:3808772890fedf57c4befd649f16e9078db6809d220103615d71d5ea553d4f50`: Demonstrate that SpecifierSet.contains excludes semantically matching pre-releases by default
- `sha256:2158f71f8f0182e574ebf8c6a651b8c00cc0e084fe82523db391f8d026016a3c`: Evaluate prereleases, epochs, and local versions in SpecifierSet without falling into PEP 440 exclusion traps
To provide distinct coverage within the library, this sample proves the behavior of distribution filename parsing (`parse_wheel_filename`, `parse_sdist_filename`) and name canonicalization in `packaging.utils`.
## Pinned Release
- `packaging==24.2` (`pkg:pypi/packaging@24.2`)
## Observed Behaviour
1. **Wheel Filename Parsing Tuple Structure**:
`packaging.utils.parse_wheel_filename` accepts a PEP 427 wheel filename and returns a 4-tuple: `(name: NormalizedName, version: Version, build: BuildTag, tags: FrozenSet[Tag])`.
2. **PEP 503 Name Canonicalization**:
The distribution name returned by `parse_wheel_filename` is canonicalized according to PEP 503 rules (lowercased and character runs of `[-_.]+` replaced with a single hyphen `-`).
3. **PEP 427 Build Tag Parsing and Validation**:
When a 6-part wheel filename includes a build tag, the build tag is parsed into a 2-tuple `(int, str)` where the first element is the integer build number and the second is the remaining string suffix (for example, `1rc2` becomes `(1, "rc2")`, and `1` becomes `(1, "")`). If the build tag does not start with an integer digit (such as `beta`), `InvalidWheelFilename` is raised loudly. Wheels without build tags return an empty tuple `()`.
4. **Cartesian Product Tag Expansion**:
Compressed wheel tags (such as `py2.py3-none-any` or multi-platform combinations) are expanded via Cartesian product into individual `packaging.tags.Tag` objects inside a `frozenset`.
5. **Source Distribution Parsing**:
`packaging.utils.parse_sdist_filename` parses standard `.tar.gz` and `.zip` archive names into a canonicalized name and a `Version` instance, rejecting `.whl` files or malformed names with `InvalidSdistFilename`.
## Failure Mode for Naive Assumptions
- Naive code assuming `parse_wheel_filename` returns raw strings or preserves original casing in distribution names fails assertions because names are normalized and versions/tags are returned as rich objects (`Version`, `Tag`).
- Code passing non-numeric build tags to wheel generators/parsers expecting them to be treated as plain string tags fails loudly with `InvalidWheelFilename`.
{"case":{"believed":"parse_wheel_filename preserves unnormalized distribution names and parses build tags as plain strings or leaves compressed wheel tags unexpanded","caseId":"case:sha256:da82f2398c5483667648b3e7f7b6be62fe7c078bcad1fc110ade574328d33e9a","contract":["parse_wheel_filename returns a 4-tuple of canonicalized name, parsed Version, integer-prefixed build tag tuple, and Cartesian-product expanded Tag frozenset, rejecting build tags without a leading digit.","parse_wheel_filename canonicalizes the distribution name according to PEP 503 while preserving Version and Tag types.","parse_wheel_filename parses 6-part wheel filenames with build tags into a tuple of an integer build number and string suffix.","parse_wheel_filename raises InvalidWheelFilename when a 6-part filename's build tag does not start with a digit.","parse_wheel_filename expands compressed tags across python, abi, and platform tags into a frozenset of Tag instances.","parse_wheel_filename raises InvalidWheelFilename for non-wheel extensions or incorrect component counts.","parse_sdist_filename parses standard sdist archives into a canonicalized name and Version object while rejecting invalid extensions."],"goal":"Parse wheel and sdist distribution filenames into canonical names, Version objects, build tag tuples, and expanded tag sets using packaging.utils","kind":"HOW","packages":["pkg:pypi/packaging@24.2"],"schemaVersion":1,"symbols":["packaging.utils.parse_wheel_filename","packaging.utils.parse_sdist_filename","packaging.utils.canonicalize_name"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/packaging@24.2"],"schemaVersion":1,"symbols":["packaging.utils.parse_wheel_filename","packaging.utils.parse_sdist_filename","packaging.utils.canonicalize_name"],"verifierAdapter":"python@1"}
packaging==24.2
from packaging.tags import Tag
from packaging.utils import (
InvalidSdistFilename,
InvalidWheelFilename,
canonicalize_name,
parse_sdist_filename,
parse_wheel_filename,
)
from packaging.version import Version
def test_parse_standard_wheel_filename():
filename = "Distribution_Name-1.0.0-py2.py3-none-any.whl"
name, version, build, tags = parse_wheel_filename(filename)
# Name is canonicalized according to PEP 503 (lowercased and underscores to dashes)
assert name == "distribution-name"
assert isinstance(name, str)
# Version is parsed as a Version instance
assert version == Version("1.0.0")
assert isinstance(version, Version)
# Wheel without build tag has an empty tuple build tag
assert build == ()
# Compressed tags 'py2.py3' expand into individual Tag objects in a frozenset
assert isinstance(tags, frozenset)
assert len(tags) == 2
assert Tag("py2", "none", "any") in tags
assert Tag("py3", "none", "any") in tags
def test_parse_wheel_with_build_tag_and_tag_expansion():
filename = "Distribution_Name-2.1.0-1rc2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
name, version, build, tags = parse_wheel_filename(filename)
assert name == "distribution-name"
assert version == Version("2.1.0")
# Build tag is parsed into a 2-tuple of (int, str)
assert build == (1, "rc2")
# Cartesian product expansion of 1 python tag x 1 abi tag x 2 platform tags = 2 tags
assert len(tags) == 2
assert Tag("cp310", "abi3", "manylinux_2_17_x86_64") in tags
assert Tag("cp310", "abi3", "manylinux2014_x86_64") in tags
def test_invalid_build_tag_rejected():
# PEP 427 mandates build numbers start with a digit; non-digit build tags raise InvalidWheelFilename
invalid_filename = "Distribution_Name-1.0.0-beta-py3-none-any.whl"
try:
parse_wheel_filename(invalid_filename)
raise AssertionError("Expected InvalidWheelFilename for non-digit build tag")
except InvalidWheelFilename:
pass
def test_invalid_wheel_filenames_rejected():
# Invalid extension
try:
parse_wheel_filename("package-1.0.0-py3-none-any.tar.gz")
raise AssertionError("Expected InvalidWheelFilename for non-.whl extension")
except InvalidWheelFilename:
pass
# Invalid component count (too few segments)
try:
parse_wheel_filename("package-1.0.0-any.whl")
raise AssertionError("Expected InvalidWheelFilename for too few components")
except InvalidWheelFilename:
pass
# Invalid component count (too many segments)
try:
parse_wheel_filename("package-1.0.0-1-2-py3-none-any.whl")
raise AssertionError("Expected InvalidWheelFilename for too many components")
except InvalidWheelFilename:
pass
def test_parse_sdist_filename():
name, version = parse_sdist_filename("Foo_Bar-1.2.3a4.tar.gz")
assert name == "foo-bar"
assert version == Version("1.2.3a4")
name_zip, version_zip = parse_sdist_filename("Foo_Bar-2.0.0.zip")
assert name_zip == "foo-bar"
assert version_zip == Version("2.0.0")
try:
parse_sdist_filename("Foo_Bar-1.0.0.whl")
raise AssertionError("Expected InvalidSdistFilename for .whl extension")
except InvalidSdistFilename:
pass
try:
parse_sdist_filename("Foo_Bar.tar.gz")
raise AssertionError("Expected InvalidSdistFilename for missing version")
except InvalidSdistFilename:
pass
def test_canonicalize_name():
assert canonicalize_name("Foo._-BAR") == "foo-bar"
assert canonicalize_name("foo---bar") == "foo-bar"
assert canonicalize_name("foo.bar") == "foo-bar"
if __name__ == "__main__":
test_parse_standard_wheel_filename()
test_parse_wheel_with_build_tag_and_tag_expansion()
test_invalid_build_tag_rejected()
test_invalid_wheel_filenames_rejected()
test_parse_sdist_filename()
test_canonicalize_name()
print("All packaging.utils contract assertions passed.")