Ejemplo
packaging 24.1: Evaluate prereleases, epochs, and local versions in SpecifierSet without falling into PEP 440 exclusion traps
Muestra verificada para pypi packaging 24.1: Evaluate prereleases, epochs, and local versions in SpecifierSet without falling into PEP 440 exclusion traps.…
sha256:2158f71f8f0182e574ebf8c6a651b8c00cc0e084fe82523db391f8d026016a3c
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 3
- Claves de firma que lo compilaron
- 3
Entorno declarado
python linux x64 python python pip
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| 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
- Evaluate prereleases, epochs, and local versions in SpecifierSet without falling into PEP 440 exclusion traps
- Paquetes
- Símbolos
-
- packaging.specifiers.SpecifierSet
- packaging.specifiers.InvalidSpecifier
- packaging.version.Version
- Entorno
- python
- Creado
- 2026-08-15T15:14:05Z
Contrato
- assert SpecifierSet('<2.0') excludes '2.0a1' even with prereleases=True
- assert SpecifierSet('<=2.0') includes '2.0a1' with prereleases=True
- assert specifier containing a prerelease auto-enables prerelease matching for the entire set
- assert epoch takes precedence over release segment in SpecifierSet and Version
- assert specifier without local version matches local versions but specifier with local version requires exact match
- assert relational operators with local versions raise InvalidSpecifier
- assert arbitrary equality === does not normalize version numbers or local tags
Archivos
- NOTES.md
- csx.json
- requirements.txt
- src/__init__.py
- src/specifier_rules.py
- test/contract.py
Código fuente
# Packaging SpecifierSet Traps (PEP 440)
## CSX Search Result
`search_known_solution` answered HIT with sample `sha256:45e2533fcb7653dca8198455b39aca51f65c0122bfe3026b03034516f955f76e` ("Check whether a version satisfies a requirement specifier in Python"). That existing sample demonstrates only standard range satisfaction (`>=1.0,<2.0`), explicit `prereleases=True` for a version strictly inside the range (`1.13.0rc1`), and basic `max(Version)` ordering. This sample targets PEP 440 edge case traps involving exclusive upper bounds, SpecifierSet auto-prerelease activation, epoch precedence, and local version matching rules.
## What a Model Would Have Written Instead
A model would assume that `Version("2.0a1") < Version("2.0")` implies `SpecifierSet("<2.0").contains("2.0a1", prereleases=True)` evaluates to `True`, that `SpecifierSet(">=1.0a1, <=2.0")` requires `prereleases=True` to match `"1.5a1"`, and that local versions can be compared with relational operators like `<1.0+local`.
## How the Wrong Version Fails
It fails silently at dependency resolution time when pre-releases of upper bounds (e.g., `2.0a1` against `<2.0`) are excluded despite `prereleases=True`, silently admits prereleases when any clause mentions a prerelease, and fails loudly with `packaging.specifiers.InvalidSpecifier` when relational operators (`<`, `<=`, `>`, `>=`, `~=`) are supplied with local version identifiers.
{"case":{"caseId":"case:sha256:21eebdd1d543f337b7cdef29ba141499500d7cf63385ffcf1b9056393433ca45","constraints":{"runtime":"python"},"contract":["assert SpecifierSet('\u003c2.0') excludes '2.0a1' even with prereleases=True","assert SpecifierSet('\u003c=2.0') includes '2.0a1' with prereleases=True","assert specifier containing a prerelease auto-enables prerelease matching for the entire set","assert epoch takes precedence over release segment in SpecifierSet and Version","assert specifier without local version matches local versions but specifier with local version requires exact match","assert relational operators with local versions raise InvalidSpecifier","assert arbitrary equality === does not normalize version numbers or local tags"],"goal":"Evaluate prereleases, epochs, and local versions in SpecifierSet without falling into PEP 440 exclusion traps","kind":"HOW","packages":["pkg:pypi/packaging@24.1"],"schemaVersion":1,"symbols":["packaging.specifiers.SpecifierSet","packaging.specifiers.InvalidSpecifier","packaging.version.Version"]},"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.1"],"schemaVersion":1,"symbols":["packaging.specifiers.SpecifierSet","packaging.specifiers.InvalidSpecifier","packaging.version.Version"],"verifierAdapter":"python@1"}
packaging==24.1
"""Package initialization."""
"""SpecifierSet evaluation rules for prereleases, epochs, and local versions."""
from packaging.specifiers import InvalidSpecifier, SpecifierSet
from packaging.version import Version
def matches_requirement(spec_str: str, version_str: str, prereleases=None) -> bool:
"""Check if version_str satisfies spec_str under PEP 440 semantics.
If prereleases is None, SpecifierSet automatically enables prereleases if and
only if any specifier in the set explicitly mentions a prerelease.
"""
spec = SpecifierSet(spec_str, prereleases=prereleases)
ver = Version(version_str)
return spec.contains(ver)
def can_construct_specifier(spec_str: str) -> bool:
"""Validate whether spec_str is a syntactically valid PEP 440 specifier.
Local versions are forbidden in relational operators (<, <=, >, >=, ~=).
"""
try:
SpecifierSet(spec_str)
return True
except InvalidSpecifier:
return False
import os
import sys
# Ensure project root is in sys.path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from packaging.version import Version
from src.specifier_rules import can_construct_specifier, matches_requirement
# -----------------------------------------------------------------------------
# 1. Prerelease Upper Bound Trap: '<' vs '<='
# Naive model expectation: If 2.0a1 < 2.0, then '<2.0' with prereleases allowed
# should match 2.0a1.
# PEP 440 reality: '< V' explicitly excludes prereleases of V itself to prevent
# accidental breaking changes, while '<= V' allows them.
# -----------------------------------------------------------------------------
v_pre = Version("2.0a1")
v_final = Version("2.0")
assert v_pre < v_final
assert not matches_requirement("<2.0", "2.0a1", prereleases=True)
assert matches_requirement("<=2.0", "2.0a1", prereleases=True)
assert matches_requirement("<2.0.1", "2.0a1", prereleases=True)
# -----------------------------------------------------------------------------
# 2. Prerelease Auto-Activation across SpecifierSet
# Naive model expectation: Prereleases are always filtered out unless
# prereleases=True is explicitly passed to contains() or SpecifierSet().
# PEP 440 reality: If ANY clause in a SpecifierSet contains a prerelease (e.g. >=1.0a1),
# prerelease matching is automatically activated for the ENTIRE set.
# -----------------------------------------------------------------------------
assert not matches_requirement(">=1.0, <=2.0", "1.5a1")
assert matches_requirement(">=1.0a1, <=2.0", "1.5a1")
# -----------------------------------------------------------------------------
# 3. Epoch Precedence Trap
# Naive model expectation: '1!1.0' has release number 1.0, so 1!1.0 < 2.0.
# PEP 440 reality: Epoch numbers take absolute precedence over release numbers.
# Epoch 1 > Epoch 0, so 1!1.0 is greater than any 0!X.Y version (including 999.0).
# -----------------------------------------------------------------------------
assert Version("1!1.0") > Version("999.0")
assert not matches_requirement("<2.0", "1!1.0")
assert matches_requirement(">=2.0", "1!0.1")
# -----------------------------------------------------------------------------
# 4. Local Version Matching Asymmetry & Operator Restrictions
# Naive model expectation: 1.0+cu118 > 1.0, so ==1.0 won't match 1.0+cu118,
# and '<1.0+cu118' is a valid relational comparison.
# PEP 440 reality:
# - A specifier without a local version label (==1.0) matches ANY local version of 1.0.
# - A specifier with a local version (==1.0+cu118) requires exact local label match.
# - Relational operators (<, <=, >, >=, ~=) with local versions raise InvalidSpecifier.
# -----------------------------------------------------------------------------
assert Version("1.0+cu118") > Version("1.0")
assert matches_requirement("==1.0", "1.0+cu118")
assert not matches_requirement("==1.0+cu118", "1.0")
assert not matches_requirement("==1.0+cu118", "1.0+cu121")
assert not can_construct_specifier("<1.0+cu118")
assert not can_construct_specifier("<=1.0+cu118")
assert not can_construct_specifier(">=1.0+cu118")
assert not can_construct_specifier("~=1.0+cu118")
# -----------------------------------------------------------------------------
# 5. Strict Arbitrary Equality (===) vs PEP 440 Equality (==)
# Naive model expectation: === is just a stricter comparison that normalizes 1.0 to 1.0.0.
# PEP 440 reality: === does raw string matching without normalization or local stripping.
# -----------------------------------------------------------------------------
assert matches_requirement("==1.0", "1.0.0")
assert matches_requirement("==1.0", "1.0+cu118")
assert not matches_requirement("===1.0", "1.0.0")
assert not matches_requirement("===1.0", "1.0+cu118")
assert matches_requirement("===1.0", "1.0")
print("CONTRACT PASS: packaging PEP 440 SpecifierSet edge cases verified")