From db2503bfec9f71fdb272e44d2912e4401f09cb79 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 2 Dec 2025 00:41:03 -0500 Subject: [PATCH] fix: restore previous behavior on platform_release Signed-off-by: Henry Schreiner --- src/packaging/markers.py | 8 ++++++-- src/packaging/specifiers.py | 2 +- tests/test_markers.py | 17 +++++++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/packaging/markers.py b/src/packaging/markers.py index f4f6b882..27b729ca 100644 --- a/src/packaging/markers.py +++ b/src/packaging/markers.py @@ -15,6 +15,7 @@ from ._tokenizer import ParserSyntaxError from .specifiers import InvalidSpecifier, Specifier from .utils import canonicalize_name +from .version import Version __all__ = [ "EvaluateContext", @@ -177,13 +178,16 @@ def _format_marker( } -def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool: +def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str], *, key: str) -> bool: + # This is here to avoid a behavior change while the spec is being debated. if isinstance(rhs, str): try: spec = Specifier(f"{op.serialize()}{rhs}") except InvalidSpecifier: pass else: + if key == "platform_release": + Version(lhs) return spec.contains(lhs, prereleases=True) oper: Operator | None = _operators.get(op.serialize()) @@ -236,7 +240,7 @@ def _evaluate_markers( rhs_value = environment[environment_key] assert isinstance(lhs_value, str), "lhs must be a string" lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) - groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + groups[-1].append(_eval_op(lhs_value, op, rhs_value, key=environment_key)) else: assert marker in ["and", "or"] if marker == "or": diff --git a/src/packaging/specifiers.py b/src/packaging/specifiers.py index 3b15703e..97653e0a 100644 --- a/src/packaging/specifiers.py +++ b/src/packaging/specifiers.py @@ -198,7 +198,7 @@ class Specifier(BaseSpecifier): ) | (?: - # All other operators only allow a sub set of what the + # All other operators only allow a subset of what the # (non)equality operators do. Specifically they do not allow # local versions to be specified nor do they allow the prefix # matching wild cards. diff --git a/tests/test_markers.py b/tests/test_markers.py index b4815c52..c95d6712 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -22,6 +22,7 @@ default_environment, format_full_version, ) +from packaging.version import InvalidVersion VARIABLES = [ "extra", @@ -308,6 +309,11 @@ def test_environment_with_extra_none(self) -> None: {"os_name": "other", "python_version": "2.7.4"}, False, ), + ( + "platform_release >= '6'", + {"platform_release": "6.1-foobar"}, + InvalidVersion, + ), ("extra == 'security'", {"extra": "quux"}, False), ("extra == 'security'", {"extra": "security"}, True), ("extra == 'SECURITY'", {"extra": "security"}, True), @@ -321,10 +327,17 @@ def test_environment_with_extra_none(self) -> None: ], ) def test_evaluates( - self, marker_string: str, environment: dict[str, str] | None, expected: bool + self, + marker_string: str, + environment: dict[str, str] | None, + expected: bool | type[Exception], ) -> None: args = () if environment is None else (environment,) - assert Marker(marker_string).evaluate(*args) == expected + if isinstance(expected, bool): + assert Marker(marker_string).evaluate(*args) == expected + else: + with pytest.raises(expected): + Marker(marker_string).evaluate(*args) @pytest.mark.parametrize( "marker_string",