P2Exception behaviour changed
known regression: inner-whitespaceknown regression: unicode-digits
inputVersion("1 .2")
baseraises InvalidVersion
headreturns normally
Likely bugvotes: 3 likely-bug
The fast path accepts spaces in the version string (e.g., '1 .2') because `strip()` removes leading/trailing spaces and `int()` ignores spaces around digits, whereas the regex rejects spaces. This is an unintended relaxation of the version syntax.
if _NON_SIMPLE_VERSION_INDICATORS.isdisjoint(version):
self._release = tuple(map(int, version.strip().split('.')))
Found by: Ultra's planned example, hostile mutation · also caught by: Mutations of the PR's own test strings, Nemotron plan only
ran onToken Factory Sandboxes · image 62d98fe8-9c1e-42e6-b250-ab6f630d8680
Regression test verified passes on base, fails on head
def test_1082_61967cca_p2_outcome_2():
"""Breakwater P2: base behaviour pinned (found by differential testing; label: likely-bug)."""
import pytest
from packaging.version import InvalidVersion, Version
with pytest.raises(InvalidVersion) as excinfo:
Version('1 .2')
assert type(excinfo.value) is InvalidVersion # exact type: a subclass would be a behaviour change
Reproduce
uv run breakwater probe --repo https://github.com/pypa/packaging --base 59f183fe90da --head 61967cca278d --target packaging.version:Version --backend contree --input "1 .2"
1 near-duplicate class same behaviour, inputs with extra traits
Version("١ .2") base raises InvalidVersion · head returns normallyunicode-digitsinner-whitespace test verified (also under another group)
P2Exception behaviour changed
known regression: unicode-digitsknown regression: inner-whitespace
inputVersion("٠")
baseraises InvalidVersion
headreturns normally
Likely bugvotes: 3 likely-bug
The fast path accepts Unicode digits (e.g., Arabic-Indic '٠') because `int()` supports them, while the original regex only matches ASCII `[0-9]`. This expands accepted input beyond PEP 440 without documentation or tests.
_NON_SIMPLE_VERSION_INDICATORS = frozenset('!+-ABCDEHILOPRSTVW_abcdehiloprstvw')
if _NON_SIMPLE_VERSION_INDICATORS.isdisjoint(version):
Found by: Nemotron strategy search, Ultra's planned example, hostile mutation, search sample · also caught by: Nemotron plan only
ran onToken Factory Sandboxes · image 62d98fe8-9c1e-42e6-b250-ab6f630d8680
Regression test verified passes on base, fails on head
def test_1082_61967cca_p2_outcome_0():
"""Breakwater P2: base behaviour pinned (found by differential testing; label: likely-bug)."""
import pytest
from packaging.version import InvalidVersion, Version
with pytest.raises(InvalidVersion) as excinfo:
Version('٠')
assert type(excinfo.value) is InvalidVersion # exact type: a subclass would be a behaviour change
Reproduce
uv run breakwater probe --repo https://github.com/pypa/packaging --base 59f183fe90da --head 61967cca278d --target packaging.version:Version --backend contree --input "٠"
1 near-duplicate class same behaviour, inputs with extra traits
Version("١ .2") base raises InvalidVersion · head returns normallyunicode-digitsinner-whitespace test verified (also under another group)
P2Exception behaviour changed
inputVersion(["..0"])
baseraises TypeError
headraises AttributeError
Neither exception type subclasses the other.
Likely bugvotes: 3 likely-bug
For non-string input (a list), the fast path bypasses the regex and calls `.strip()` on the list, raising `AttributeError` instead of the original `TypeError`. The PR does not intend to change error types for invalid input types.
if _NON_SIMPLE_VERSION_INDICATORS.isdisjoint(version):
self._release = tuple(map(int, version.strip().split('.')))
Found by: Nemotron strategy search · no baseline found it
ran onToken Factory Sandboxes · image 62d98fe8-9c1e-42e6-b250-ab6f630d8680
Regression test verified passes on base, errors on head
def test_1082_61967cca_p2_outcome_1():
"""Breakwater P2: base behaviour pinned (found by differential testing; label: likely-bug)."""
import pytest
from packaging.version import Version
with pytest.raises(TypeError) as excinfo:
Version(['..0'])
assert type(excinfo.value) is TypeError # exact type: a subclass would be a behaviour change
P2Exception behaviour changed
known regression: inner-whitespaceknown regression: oversized-int-exception
inputVersion("100000000000000000000000000000000000000000…0000000 .2" (4,303 chars))
baseraises InvalidVersion
headreturns normally
Needs a humanvotes: 1 intended, 1 likely-bug, 1 needs-human (no majority)
The fast path accepts extremely long numbers that the regex rejects (likely due to regex engine limits). The PR is a perf refactor; no intent to change valid version set. PEP 440 doesn't forbid long numbers but the original behavior was to reject them.
Found by: hostile mutation · no baseline found it
ran onToken Factory Sandboxes · image 62d98fe8-9c1e-42e6-b250-ab6f630d8680
Regression test verified passes on base, fails on head
def test_1082_61967cca_p2_outcome_4():
"""Breakwater P2: base behaviour pinned (found by differential testing; label: needs-human)."""
import pytest
from packaging.version import InvalidVersion, Version
with pytest.raises(InvalidVersion) as excinfo:
Version('1' + '0' * 4299 + ' ' + '.' + '2')
assert type(excinfo.value) is InvalidVersion # exact type: a subclass would be a behaviour change
P2Exception 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.
Needs a humanvotes: 1 intended, 1 likely-bug, 1 needs-human (no majority)
Both error but with different exception types (ValueError vs InvalidVersion) for a very long number. The fast path catches ValueError and wraps in InvalidVersion; the base path lets ValueError propagate. The PR is a perf refactor; no intent to change exception types.
Found by: hostile mutation · also caught by: Mutations of the PR's own test strings
ran onToken Factory Sandboxes · image 62d98fe8-9c1e-42e6-b250-ab6f630d8680
Regression test verified passes on base, fails on head
def test_1082_61967cca_p2_outcome_5():
"""Breakwater P2: base behaviour pinned (found by differential testing; label: needs-human)."""
import pytest
from packaging.version import Version
with pytest.raises(ValueError) as excinfo:
Version('1' + '0' * 4300 + '.' + '0' + '.' + '1')
assert type(excinfo.value) is ValueError # exact type: a subclass would be a behaviour change