diff --git a/src/packaging/markers.py b/src/packaging/markers.py index a5bf35c6..68369c98 100644 --- a/src/packaging/markers.py +++ b/src/packaging/markers.py @@ -237,5 +237,9 @@ def evaluate(self, environment: Optional[Dict[str, str]] = None) -> bool: current_environment["extra"] = "" if environment is not None: current_environment.update(environment) + # The API used to allow setting extra to None. We need to handle this + # case for backwards compatibility. + if current_environment["extra"] is None: + current_environment["extra"] = "" return _evaluate_markers(self._markers, current_environment) diff --git a/tests/test_markers.py b/tests/test_markers.py index 41bda762..f199c977 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -7,6 +7,7 @@ import os import platform import sys +from typing import cast import pytest @@ -256,6 +257,20 @@ def test_compare_markers_to_other_objects(self): def test_environment_assumes_empty_extra(self): assert Marker('extra == "im_valid"').evaluate() is False + def test_environment_with_extra_none(self): + # GIVEN + marker_str = 'extra == "im_valid"' + + # Pretend that this is dict[str, str], even though it's not. This is a + # test for being bug-for-bug compatible with the older implementation. + environment = cast("dict[str, str]", {"extra": None}) + + # WHEN + marker = Marker(marker_str) + + # THEN + assert marker.evaluate(environment) is False + @pytest.mark.parametrize( ("marker_string", "environment", "expected"), [