CodeSampleX

샘플

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

컨트랙트

  1. 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.
  2. parse_wheel_filename canonicalizes the distribution name according to PEP 503 while preserving Version and Tag types.
  3. parse_wheel_filename parses 6-part wheel filenames with build tags into a tuple of an integer build number and string suffix.
  4. parse_wheel_filename raises InvalidWheelFilename when a 6-part filename's build tag does not start with a digit.
  5. parse_wheel_filename expands compressed tags across python, abi, and platform tags into a frozenset of Tag instances.
  6. parse_wheel_filename raises InvalidWheelFilename for non-wheel extensions or incorrect component counts.
  7. 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

소스 아티팩트 내려받기 (tar.gz)

소스

NOTES.md
# 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`.
csx.json
{"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"}
requirements.txt
packaging==24.2
test/contract.py
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.")

오리진 시더

csx-seed