diff --git a/dep_freshness/tests/test_versions.py b/dep_freshness/tests/test_versions.py index 969e3a8..70f5204 100644 --- a/dep_freshness/tests/test_versions.py +++ b/dep_freshness/tests/test_versions.py @@ -34,7 +34,10 @@ def test_newest_stable_ignores_unparseable_entries(): @pytest.mark.parametrize("raw,expected", [ ("1.6.0", "1.6.0"), ("==1.6.0", "1.6.0"), ("v2.0.0", "2.0.0"), - (" 1.0.0 ", "1.0.0"), + (" 1.0.0 ", "1.0.0"), ("1.9", "1.9"), ("3", "3"), + # PyPI stub packages date-stamp a fourth component. Capping the regex at + # three reported this exact pin as unpinned *against its own value*. + ("==2.33.0.20260712", "2.33.0.20260712"), ]) def test_exact_pins_are_recognised(raw, expected): assert exact_pin(raw) == expected diff --git a/dep_freshness/versions.py b/dep_freshness/versions.py index 0a63e2e..1929424 100644 --- a/dep_freshness/versions.py +++ b/dep_freshness/versions.py @@ -74,7 +74,10 @@ def behind(pinned: str, latest: str) -> bool: return left < right -EXACT = re.compile(r"^\s*(?:==\s*)?v?\d+(?:\.\d+){0,2}(?:[-+][0-9A-Za-z.-]+)?\s*$") +# Any number of numeric release components, not three: PyPI stub packages +# date-stamp a fourth (`types-requests==2.33.0.20260712`), and capping at +# three reported an exact pin as unpinned against itself. +EXACT = re.compile(r"^\s*(?:==\s*)?v?\d+(?:\.\d+)*(?:[-+][0-9A-Za-z.-]+)?\s*$") def exact_pin(constraint: str) -> str | None: