CodeSampleX

Exemplo

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

Amostra verificada para pypi importlib-metadata 9.0.0: Resolve installed package versions when distribution names differ from top-level import names without…

sha256:beb8b3121c3cddc83a0038650f092bd1609123c82e31e1209dc60f07e688d56f

Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu. Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas. MIT-0

Evidência de execução

O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.

Base da evidência
Contrato assinado aprovado
Recibos de verificação
3
Chaves de assinatura que o compilaram
3
Ambiente declarado python linux x64 python python pip

Ambientes das execuções de verificação

Ambiente Contrato Etapas Execução
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

Caso

HOW
Objetivo
Resolve installed package versions when distribution names differ from top-level import names without PackageNotFoundError
Pacotes
Símbolos
  • importlib_metadata.version
  • importlib_metadata.PackageNotFoundError
  • importlib_metadata.packages_distributions
  • importlib_metadata.distribution
Ambiente
python
Criado
2026-08-16T06:31:23Z

Contrato

  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

Arquivos

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

Baixar o artefato de código-fonte (tar.gz)

Código-fonte

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)

Seeder de origem

csx-seed