Breakwater

Sandboxes / #1082

perf: Add fast path for parsing simple versions (digits and dots only)

pypa/packaging#1082 · merged 2026-02-11 · base 59f183fe90 → head ee13ba2c1c · ran on Sandboxes

REVIEW

A valid input family runs 2.91× the instructions of the old code.

Known regressions in this PR

Counterexamples · 1 class: 1 intended

P2

Exception behaviour changed

known regression: oversized-int-exception
inputVersion("100000000000000000000000000000000000000000…000000.0.1" (4,305 chars))
baseraises ValueError
headraises InvalidVersion

Packaging.version.InvalidVersion is a subclass of builtins.ValueError.

Intendedvotes: 3 intended

The PR adds a fast‑path for versions that contain only digits and dots. In that path it explicitly catches a `ValueError` from `int()` conversion and re‑raises it as `packaging.version.InvalidVersion`. This makes the exception type more specific and matches the library’s own error hierarchy, so the new behavior is deliberate.

if _SIMPLE_VERSION_INDICATORS.issuperset(version):
self._release = tuple(map(int, version.split('.')))

Found by: hostile mutation · also caught by: Mutations of the PR's own test strings

ran onToken Factory Sandboxes · image cdd80561-4ef0-4ca1-b645-b13306e326c6

No regression test: adjudicated intended: no test pins the old behaviour.

Performance · Version

Worst family with mostly valid inputs: 2.91× the instructions of base (Leading zeros in first segment).

head slowerhead faster1×1.2×1.4×1.7×2×2.4×2.8×1001,00010,000100,000input size (characters)R4.1R4.1: 1.05× at ~17 charsR4.1: 1.10× at ~35 charsR4.1: 1.47× at ~318 charsR4.1: 2.23× at ~4,350 charsR4.1: 2.36× at ~66,715 charsR4R4: 1.05× at ~17 charsR4: 1.10× at ~35 charsR4: 1.47× at ~311 charsR4: 2.32× at ~4,295 charsR4: 2.91× at ~66,311 charsR4.2R4.2: 1.04× at ~13 charsR4.2: 1.07× at ~24 charsR4.2: 1.30× at ~174 charsR4.2: 1.95× at ~2,214 charsR4.2: 2.61× at ~33,414 charsR4.2: 2.66× at ~526,854 charsR4.3R4.3: 1.03× at ~18 charsR4.3: 1.05× at ~25 charsR4.3: 1.17× at ~109 charsR4.3: 1.63× at ~1,188 charsR4.3: 2.33× at ~17,057 charsR4.3: 2.59× at ~265,121 chars
  • R4.1
  • R4
  • R4.2
  • R4.3
Head/base cachegrind instructions per call, by input size (log-log). Each line is one input family Nemotron proposed; points above 1× are where the "faster" code does more work.
FamilyInputsRatio range Slope base → headVerdict
R4.1Trailing zerossuspected slowdown · expand:R41.05× – 2.36×0.60 → 0.71slower
R4Leading zeros in first segmentsuspected slowdown · archive1.05× – 2.91×0.56 → 0.70slower
R4.2Mixed leading/trailingsuspected slowdown · expand:R41.04× – 2.66×0.65 → 0.75slower
R4.3Increasing common prefixsuspected slowdown · expand:R41.03× – 2.59×0.64 → 0.74slower

Receipt

TargetBackendImageRun AuditAdjudication
packaging.version:VersionToken Factory Sandboxescdd80561-4ef0-4ca1-b645-b13306e326c6bt-1082-4a405a$0.17$0.018

Nemotron cost on Nebius Token Factory. Backend: where the untrusted code ran. Token Factory Sandboxes (a microVM branched from a kept image, cited by its UUID). Every image is content-addressed (repo at each commit + harness), so every card re-runs from the image and seed 0. Raw data: audit, adjudication.