From 95058699b9d2fe0a744da18377915e5db2d078b3 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 12 May 2022 14:23:09 -0700 Subject: [PATCH 1/2] Normalize extra comparison in markers for output This guarantees that getting the string representation of a marker is always normalized for extras. Part of #526 --- packaging/markers.py | 34 ++++++++++++++++++++++++++++++---- tests/test_markers.py | 9 +++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packaging/markers.py b/packaging/markers.py index 03d8cdef..1f889693 100644 --- a/packaging/markers.py +++ b/packaging/markers.py @@ -6,7 +6,7 @@ import os import platform import sys -from typing import Any, Callable, Dict, List, Optional, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, overload from pyparsing import ( # noqa: N817 Forward, @@ -139,11 +139,37 @@ def serialize(self) -> str: MARKER = stringStart + MARKER_EXPR + stringEnd -def _coerce_parse_result(results: Union[ParseResults, List[Any]]) -> List[Any]: +_T = TypeVar("_T") + + +@overload +def _coerce_parse_result(results: ParseResults) -> List[Any]: + ... + + +@overload +def _coerce_parse_result(results: _T) -> _T: + ... + + +def _coerce_parse_result(results): + """ + Flatten the parse results into a list of results. + + Also normalize extra values. + """ if isinstance(results, ParseResults): return [_coerce_parse_result(i) for i in results] - else: - return results + elif isinstance(results, tuple): + lhs, op, rhs = results + if isinstance(lhs, Variable) and lhs.value == "extra": + normalized_extra = canonicalize_name(rhs.value) + rhs = Value(normalized_extra) + elif isinstance(rhs, Variable) and rhs.value == "extra": + normalized_extra = canonicalize_name(lhs.value) + lhs = Value(normalized_extra) + results = lhs, op, rhs + return results def _format_marker( diff --git a/tests/test_markers.py b/tests/test_markers.py index b1ccf63c..28f71c64 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -362,3 +362,12 @@ def test_evaluate_setuptools_legacy_markers(self): marker_string = "python_implementation=='Jython'" args = [{"platform_python_implementation": "CPython"}] assert Marker(marker_string).evaluate(*args) is False + + def test_extra_str_normalization(self): + raw_name = "S_P__A_M" + normalized_name = "s-p-a-m" + lhs = f"{raw_name!r} == extra" + rhs = f"extra == {raw_name!r}" + + assert str(Marker(lhs)) == f'"{normalized_name}" == extra' + assert str(Marker(rhs)) == f'extra == "{normalized_name}"' From 274bf7ea09986c5259d036981e0c5800da67e447 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 13 May 2022 12:45:18 -0700 Subject: [PATCH 2/2] Make mypy happy --- packaging/markers.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/packaging/markers.py b/packaging/markers.py index 1f889693..6c58c16f 100644 --- a/packaging/markers.py +++ b/packaging/markers.py @@ -6,7 +6,7 @@ import os import platform import sys -from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, overload +from typing import Any, Callable, Dict, List, Optional, Tuple, Union from pyparsing import ( # noqa: N817 Forward, @@ -139,20 +139,7 @@ def serialize(self) -> str: MARKER = stringStart + MARKER_EXPR + stringEnd -_T = TypeVar("_T") - - -@overload -def _coerce_parse_result(results: ParseResults) -> List[Any]: - ... - - -@overload -def _coerce_parse_result(results: _T) -> _T: - ... - - -def _coerce_parse_result(results): +def _coerce_parse_result(results: Any) -> Any: """ Flatten the parse results into a list of results.