Skip to content

v0.2.0 — conformance release

Choose a tag to compare

@jonyoder jonyoder released this 03 Aug 16:22
· 32 commits to main since this release
3dfc5dc

Conformance release. requirement/, version/, and the PEP 508 grammar are now tested against tables ported from pypa/packaging's tests/test_requirements.py (upstream SHA 4eb0753), plus property-based tests adapted from its Hypothesis suite. The divergences those tests revealed are fixed.

This release changes behavior. It is a minor rather than a patch bump because a consumer pinning ^0.1 would otherwise pick up the narrowing and the ordering change silently. See CHANGELOG.md for the full list.

Breaking

  • Requirement.String() renders the marker separator as "; " when the requirement has no URL — it previously always rendered " ; ". The " ; " form is kept when a URL is present, since a bare ; after a URL is ambiguous. Consumers that compare, hash, cache, or persist rendered requirement strings will see different bytes for the same input.
  • Local version labels normalize - and _ to ., as PEP 440 requires. This changes String() output, equality, and ordering. Previously a label was compared as a single alphabetic segment, so 1.0+ubuntu-2 sorted above 1.0+ubuntu-10; it now sorts below, matching upstream.
  • Arbitrary equality (===) accepts exactly one token. === lolwat is valid; ===any string here is now rejected.
  • A .* prefix match is rejected on a post-release (e.g. ==1.2.3.post4.*).
  • A trailing line break (\n, \r, \r\n) is rejected. A trailing space or tab is still accepted.
  • Malformed quoted strings in environment markers are rejected: a trailing unpaired backslash and a truncated \x. Valid Python escapes still parse.

Added

  • name() — an empty parenthesized specifier group — is valid, meaning "no version constraint".
  • A vertical tab is accepted as surrounding whitespace, matching upstream (Go's \s omits \v where Python's includes it).
  • Conformance tables and property tests ported from pypa/packaging. The property-test dependency (pgregory.net/rapid, MPL-2.0) is test-only and does not enter this module's non-test import graph.

Fixed

  • The PEP 440 operator alternation is built in a deterministic, longest-first order. It was previously assembled by ranging a Go map, so the compiled pattern varied per process — and because Go's regexp is leftmost-first, an operator that is a prefix of another could win.

Note on comparing against pip install packaging

The trailing-line-break rule matches upstream's current source, not the released packaging 26.2. Upstream changed its end-of-input rule from $ to \Z after 26.2, and Python's $ matches before a trailing newline — so 26.2 still accepts "name>=1\n". A difference seen there is upstream's version skew, not a divergence here.