CodeSampleX

示例

importlib-metadata 9.0.0: Resolve installed package versions when distribution names differ from top-level import names without PackageNotFoundError

已验证示例 — pypi importlib-metadata 9.0.0: Resolve installed package versions when distribution names differ from top-level import names without…

sha256:beb8b3121c3cddc83a0038650f092bd1609123c82e31e1209dc60f07e688d56f

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 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-15
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
目标
Resolve installed package versions when distribution names differ from top-level import names without PackageNotFoundError
包
符号
  • importlib_metadata.version
  • importlib_metadata.PackageNotFoundError
  • importlib_metadata.packages_distributions
  • importlib_metadata.distribution
环境
python
创建时间
2026-08-16T06:31:23Z

契约

  1. assert version() queries distribution name and raises PackageNotFoundError when given top-level import package name
  2. assert PackageNotFoundError inherits from ModuleNotFoundError and ImportError but not KeyError
  3. assert distribution name normalization under PEP 503 equates hyphens, underscores, dots, and case variants
  4. assert packages_distributions() maps import package names to list of distribution names
  5. assert passing module object or non-string to version() raises TypeError

文件

  • NOTES.md
  • csx.json
  • requirements.txt
  • src/__init__.py
  • src/resolver.py
  • test/contract.py

下载源代码构件 (tar.gz)

源代码

NOTES.md
# importlib-metadata Distribution Name vs Import Name Traps

## CSX Search Result
`search_known_solution` answered MISS (no existing samples found for `importlib-metadata` distribution-vs-import package name resolution; returned unrelated alternatives).

## What a Model Would Have Written Instead
A model would assume that `importlib_metadata.version(name)` accepts the top-level Python import package name (such as `version("yaml")`, `version("PIL")`, `version("sklearn")`) or imported module objects (`version(mod)`), expecting it to return the version directly or return `None`/`KeyError` if absent.

## How the Wrong Version Fails
It fails loudly at runtime with `importlib_metadata.PackageNotFoundError` whenever the top-level import name differs from the installed distribution name (even when the module is imported and functioning), and fails with `TypeError` if passed a module object instead of a string.
csx.json
{"case":{"caseId":"case:sha256:eefb19e24a51e90936bad25255107c269b62ef1ee7ee776eb6006475252aac08","constraints":{"runtime":"python"},"contract":["assert version() queries distribution name and raises PackageNotFoundError when given top-level import package name","assert PackageNotFoundError inherits from ModuleNotFoundError and ImportError but not KeyError","assert distribution name normalization under PEP 503 equates hyphens, underscores, dots, and case variants","assert packages_distributions() maps import package names to list of distribution names","assert passing module object or non-string to version() raises TypeError"],"goal":"Resolve installed package versions when distribution names differ from top-level import names without PackageNotFoundError","kind":"HOW","packages":["pkg:pypi/importlib-metadata@9.0.0","pkg:pypi/zipp@4.1.0"],"schemaVersion":1,"symbols":["importlib_metadata.version","importlib_metadata.PackageNotFoundError","importlib_metadata.packages_distributions","importlib_metadata.distribution"]},"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/importlib-metadata@9.0.0","pkg:pypi/zipp@4.1.0"],"schemaVersion":1,"symbols":["importlib_metadata.version","importlib_metadata.PackageNotFoundError","importlib_metadata.packages_distributions","importlib_metadata.distribution"],"verifierAdapter":"python@1"}
requirements.txt
importlib-metadata==9.0.0
zipp==4.1.0
src/__init__.py
"""Package initialization."""
src/resolver.py
"""Distribution and import package metadata version resolver utilities."""

from typing import List, Optional, Tuple, Union
import importlib_metadata


def resolve_distribution_version(distribution_name: str) -> str:
    """Retrieve the version for an installed distribution name.

    Distribution names are normalized (case-insensitive, hyphens/underscores/dots
    are equivalent under PEP 503). Raises PackageNotFoundError if not installed.
    """
    return importlib_metadata.version(distribution_name)


def resolve_import_package_version(import_name: str) -> List[Tuple[str, str]]:
    """Resolve distribution versions for a top-level Python import package name.

    Top-level import package names (e.g. 'yaml', 'PIL', 'sklearn') differ from
    their distribution names ('PyYAML', 'Pillow', 'scikit-learn').
    Directly calling version(import_name) raises PackageNotFoundError.
    This function queries packages_distributions() to find the distribution name(s),
    then retrieves their versions.
    """
    pkg_to_dists = importlib_metadata.packages_distributions()
    dist_names = pkg_to_dists.get(import_name, [])
    results: List[Tuple[str, str]] = []
    for dist_name in dist_names:
        ver = importlib_metadata.version(dist_name)
        results.append((dist_name, ver))
    return results


def safe_get_version(target: Union[str, object]) -> Optional[str]:
    """Safely obtain package version given either a distribution name or an import name.

    Returns the resolved version string, or None if no distribution metadata is found.
    Raises TypeError if target is not a string.
    """
    if not isinstance(target, str):
        raise TypeError(f"Expected str, got {type(target).__name__}")

    try:
        return importlib_metadata.version(target)
    except importlib_metadata.PackageNotFoundError:
        # Fall back to looking up import name in packages_distributions
        pkg_to_dists = importlib_metadata.packages_distributions()
        dist_names = pkg_to_dists.get(target)
        if dist_names:
            return importlib_metadata.version(dist_names[0])
        return None
test/contract.py
import os
import shutil
import sys
import tempfile

# Ensure project root is in sys.path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import importlib_metadata
from src.resolver import (
    resolve_distribution_version,
    resolve_import_package_version,
    safe_get_version,
)


def create_fixture_distribution(
    base_dir: str, dist_name: str, version: str, top_level_modules: list
) -> None:
    """Create a minimal .dist-info fixture directory on sys.path."""
    safe_name = dist_name.replace("-", "_")
    dist_info_dir = os.path.join(base_dir, f"{safe_name}-{version}.dist-info")
    os.makedirs(dist_info_dir, exist_ok=True)
    with open(os.path.join(dist_info_dir, "METADATA"), "w", encoding="utf-8") as f:
        f.write(f"Metadata-Version: 2.1\nName: {dist_name}\nVersion: {version}\n")
    with open(os.path.join(dist_info_dir, "top_level.txt"), "w", encoding="utf-8") as f:
        for mod in top_level_modules:
            f.write(f"{mod}\n")


# Set up an isolated temporary directory with custom distribution fixtures
temp_dir = tempfile.mkdtemp()
try:
    # Fixture 1: Distribution name 'Custom-Toolkit' provides import package 'toolkit_core'
    create_fixture_distribution(temp_dir, "Custom-Toolkit", "3.2.1", ["toolkit_core"])
    # Fixture 2: Namespace package 'shared_ns' provided by two distributions
    create_fixture_distribution(temp_dir, "Plugin-Alpha", "1.0.0", ["shared_ns"])
    create_fixture_distribution(temp_dir, "Plugin-Beta", "2.0.0", ["shared_ns"])

    sys.path.insert(0, temp_dir)

    # -----------------------------------------------------------------------------
    # 1. Distribution Name vs Import Name Trap
    # Naive model expectation: version("toolkit_core") returns "3.2.1" because
    # toolkit_core is the imported module name.
    # importlib-metadata reality: version() accepts ONLY distribution names. Passing
    # the top-level import name raises PackageNotFoundError.
    # -----------------------------------------------------------------------------
    assert resolve_distribution_version("Custom-Toolkit") == "3.2.1"

    raised_package_not_found = False
    try:
        importlib_metadata.version("toolkit_core")
    except importlib_metadata.PackageNotFoundError:
        raised_package_not_found = True
    assert raised_package_not_found, (
        "Calling version() with top-level import name must raise PackageNotFoundError"
    )

    # -----------------------------------------------------------------------------
    # 2. Exception Hierarchy Trap
    # Naive model expectation: Mismatches raise KeyError (like dict lookup) or
    # ValueError.
    # importlib-metadata reality: PackageNotFoundError inherits from ModuleNotFoundError
    # and ImportError, but NOT KeyError.
    # -----------------------------------------------------------------------------
    assert issubclass(importlib_metadata.PackageNotFoundError, ModuleNotFoundError)
    assert issubclass(importlib_metadata.PackageNotFoundError, ImportError)
    assert not issubclass(importlib_metadata.PackageNotFoundError, KeyError)

    # -----------------------------------------------------------------------------
    # 3. PEP 503 / PEP 566 Distribution Name Normalization
    # Naive model expectation: Lookup is strict case-sensitive string matching where
    # hyphens and underscores are incompatible.
    # importlib-metadata reality: All punctuation (-, _, .) and case variants of
    # a distribution name normalize to the same distribution.
    # -----------------------------------------------------------------------------
    assert resolve_distribution_version("custom-toolkit") == "3.2.1"
    assert resolve_distribution_version("CUSTOM_TOOLKIT") == "3.2.1"
    assert resolve_distribution_version("custom.toolkit") == "3.2.1"

    # Real installed distribution normalization check
    assert resolve_distribution_version("importlib-metadata") == "9.0.0"
    assert resolve_distribution_version("importlib_metadata") == "9.0.0"
    assert resolve_distribution_version("IMPORTLIB-METADATA") == "9.0.0"

    # -----------------------------------------------------------------------------
    # 4. Resolving Import Names via packages_distributions()
    # Naive model expectation: packages_distributions() returns a 1:1 dict[str, str].
    # importlib-metadata reality: It returns dict[str, list[str]] because multiple
    # distributions can provide the same top-level package or namespace.
    # -----------------------------------------------------------------------------
    resolved_single = resolve_import_package_version("toolkit_core")
    assert resolved_single == [("Custom-Toolkit", "3.2.1")]

    resolved_multi = resolve_import_package_version("shared_ns")
    assert len(resolved_multi) == 2
    assert ("Plugin-Alpha", "1.0.0") in resolved_multi
    assert ("Plugin-Beta", "2.0.0") in resolved_multi

    # safe_get_version resolves both distribution names and import package names
    assert safe_get_version("Custom-Toolkit") == "3.2.1"
    assert safe_get_version("toolkit_core") == "3.2.1"
    assert safe_get_version("nonexistent_pkg") is None

    # -----------------------------------------------------------------------------
    # 5. Non-String / Module Object Input Trap
    # Naive model expectation: Passing an imported module object (e.g. version(mod))
    # reads mod.__version__.
    # importlib-metadata reality: version() accepts only string names; passing a module
    # or non-string raises TypeError.
    # -----------------------------------------------------------------------------
    raised_type_error = False
    try:
        importlib_metadata.version(importlib_metadata)
    except TypeError:
        raised_type_error = True
    assert raised_type_error, "Passing module object to version() must raise TypeError"

    raised_type_error_int = False
    try:
        safe_get_version(12345)
    except TypeError:
        raised_type_error_int = True
    assert raised_type_error_int, "Passing non-string must raise TypeError"

    print("CONTRACT PASS: importlib-metadata distribution vs import name resolution verified")
finally:
    if temp_dir in sys.path:
        sys.path.remove(temp_dir)
    shutil.rmtree(temp_dir, ignore_errors=True)

原始种子者

csx-seed