From 6ece3ca79c9e7bf5e7a077b644f6e0482065d306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Mon, 19 Jun 2023 17:16:56 +0200 Subject: [PATCH] markers: allow `|` as value separator for markers with operators `in` and `not in` --- src/poetry/core/packages/utils/utils.py | 3 +- src/poetry/core/version/markers.py | 5 +- tests/packages/test_main.py | 44 ++++++----- tests/version/test_markers.py | 98 +++++++++++++------------ 4 files changed, 81 insertions(+), 69 deletions(-) diff --git a/src/poetry/core/packages/utils/utils.py b/src/poetry/core/packages/utils/utils.py index f8ea8b527..97229517b 100644 --- a/src/poetry/core/packages/utils/utils.py +++ b/src/poetry/core/packages/utils/utils.py @@ -19,6 +19,7 @@ from poetry.core.constraints.version import VersionRange from poetry.core.constraints.version import parse_marker_version_constraint from poetry.core.pyproject.toml import PyProjectTOML +from poetry.core.version.markers import SingleMarker from poetry.core.version.markers import SingleMarkerLike from poetry.core.version.markers import dnf @@ -374,7 +375,7 @@ def normalize_python_version_markers( # NOSONAR elif op in ("in", "not in"): versions = [] - for v in re.split("[ ,]+", version): + for v in SingleMarker.VALUE_SEPARATOR_RE.split(version): split = v.split(".") if len(split) in (1, 2): split.append("*") diff --git a/src/poetry/core/version/markers.py b/src/poetry/core/version/markers.py index 4fccf3736..b05059fca 100644 --- a/src/poetry/core/version/markers.py +++ b/src/poetry/core/version/markers.py @@ -291,6 +291,7 @@ def __hash__(self) -> int: class SingleMarker(SingleMarkerLike[Union[BaseConstraint, VersionConstraint]]): _CONSTRAINT_RE = re.compile(r"(?i)^(~=|!=|>=?|<=?|==?=?|in|not in)?\s*(.+)$") + VALUE_SEPARATOR_RE = re.compile("[ ,|]+") _VERSION_LIKE_MARKER_NAME = { "python_version", "python_full_version", @@ -326,7 +327,7 @@ def __init__( if self._operator in {"in", "not in"}: versions = [] - for v in re.split("[ ,]+", self._value): + for v in self.VALUE_SEPARATOR_RE.split(self._value): split = v.split(".") if len(split) in (1, 2): split.append("*") @@ -346,7 +347,7 @@ def __init__( # into a union/multi-constraint of single constraint if self._operator in {"in", "not in"}: op, glue = ("==", " || ") if self._operator == "in" else ("!=", ", ") - values = re.split("[ ,]+", self._value) + values = self.VALUE_SEPARATOR_RE.split(self._value) constraint_string = glue.join(f"{op} {value}" for value in values) try: diff --git a/tests/packages/test_main.py b/tests/packages/test_main.py index b102065a7..f208905e3 100644 --- a/tests/packages/test_main.py +++ b/tests/packages/test_main.py @@ -3,6 +3,8 @@ from typing import TYPE_CHECKING from typing import cast +import pytest + from poetry.core.constraints.version import Version from poetry.core.packages.dependency import Dependency @@ -108,33 +110,39 @@ def test_dependency_from_pep_508_complex() -> None: ) -def test_dependency_python_version_in() -> None: - name = "requests (==2.18.0); python_version in '3.3 3.4 3.5'" - dep = Dependency.create_from_pep_508(name) - - assert dep.name == "requests" - assert str(dep.constraint) == "2.18.0" - assert dep.python_versions == "3.3.* || 3.4.* || 3.5.*" - assert str(dep.marker) == 'python_version in "3.3 3.4 3.5"' - - -def test_dependency_python_version_in_comma() -> None: - name = "requests (==2.18.0); python_version in '3.3, 3.4, 3.5'" +@pytest.mark.parametrize( + "marker_value", + [ + "3.3 3.4 3.5", # space + "3.3, 3.4, 3.5", # comma + "3.3|3.4|3.5", # pipe + ], +) +def test_dependency_python_version_in_(marker_value: str) -> None: + name = f"requests (==2.18.0); python_version in '{marker_value}'" dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.python_versions == "3.3.* || 3.4.* || 3.5.*" - assert str(dep.marker) == 'python_version in "3.3, 3.4, 3.5"' - - -def test_dependency_platform_in() -> None: - name = "requests (==2.18.0); sys_platform in 'win32 darwin'" + assert str(dep.marker) == f'python_version in "{marker_value}"' + + +@pytest.mark.parametrize( + "marker_value", + [ + "win32 darwin", # space + "win32, darwin", # comma + "win32|darwin", # pipe + ], +) +def test_dependency_platform_in(marker_value: str) -> None: + name = f"requests (==2.18.0); sys_platform in '{marker_value}'" dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" - assert str(dep.marker) == 'sys_platform in "win32 darwin"' + assert str(dep.marker) == f'sys_platform in "{marker_value}"' def test_dependency_with_extra() -> None: diff --git a/tests/version/test_markers.py b/tests/version/test_markers.py index d5db34513..f6c5738c3 100644 --- a/tests/version/test_markers.py +++ b/tests/version/test_markers.py @@ -55,56 +55,58 @@ def test_parse_marker(marker: str) -> None: assert str(parse_marker(marker)) == marker -def test_single_marker() -> None: - m = parse_marker('sys_platform == "darwin"') - - assert isinstance(m, SingleMarker) - assert m.name == "sys_platform" - assert str(m.constraint) == "darwin" - - m = parse_marker('python_version in "2.7, 3.0, 3.1"') - - assert isinstance(m, SingleMarker) - assert m.name == "python_version" - assert str(m.constraint) == ">=2.7,<2.8 || >=3.0,<3.2" - - m = parse_marker('"2.7" in python_version') - - assert isinstance(m, SingleMarker) - assert m.name == "python_version" - assert str(m.constraint) == ">=2.7,<2.8" - - m = parse_marker('python_version not in "2.7, 3.0, 3.1"') - - assert isinstance(m, SingleMarker) - assert m.name == "python_version" - assert str(m.constraint) == "<2.7 || >=2.8,<3.0 || >=3.2" - - m = parse_marker( - "platform_machine in 'x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64" - " win32 WIN32'" - ) - - assert isinstance(m, SingleMarker) - assert m.name == "platform_machine" - assert ( - str(m.constraint) - == "x86_64 || X86_64 || aarch64 || AARCH64 || ppc64le || PPC64LE || amd64 ||" - " AMD64 || win32 || WIN32" - ) - - m = parse_marker( - "platform_machine not in 'x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64" - " AMD64 win32 WIN32'" - ) +@pytest.mark.parametrize( + ("marker", "expected_name", "expected_constraint"), + [ + ('sys_platform == "darwin"', "sys_platform", "darwin"), + ( + 'python_version in "2.7, 3.0, 3.1"', + "python_version", + ">=2.7,<2.8 || >=3.0,<3.2", + ), + ('"2.7" in python_version', "python_version", ">=2.7,<2.8"), + ( + 'python_version not in "2.7, 3.0, 3.1"', + "python_version", + "<2.7 || >=2.8,<3.0 || >=3.2", + ), + ( + ( + "platform_machine in 'x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE" + " amd64 AMD64 win32 WIN32'" + ), + "platform_machine", + ( + "x86_64 || X86_64 || aarch64 || AARCH64 || ppc64le || PPC64LE || amd64" + " || AMD64 || win32 || WIN32" + ), + ), + ( + ( + "platform_machine not in 'x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE" + " amd64 AMD64 win32 WIN32'" + ), + "platform_machine", + ( + "!=x86_64, !=X86_64, !=aarch64, !=AARCH64, !=ppc64le, !=PPC64LE," + " !=amd64, !=AMD64, !=win32, !=WIN32" + ), + ), + ( + 'platform_machine not in "aarch64|loongarch64"', + "platform_machine", + "!=aarch64, !=loongarch64", + ), + ], +) +def test_parse_single_marker( + marker: str, expected_name: str, expected_constraint: str +) -> None: + m = parse_marker(marker) assert isinstance(m, SingleMarker) - assert m.name == "platform_machine" - assert ( - str(m.constraint) - == "!=x86_64, !=X86_64, !=aarch64, !=AARCH64, !=ppc64le, !=PPC64LE, !=amd64," - " !=AMD64, !=win32, !=WIN32" - ) + assert m.name == expected_name + assert str(m.constraint) == expected_constraint def test_single_marker_normalisation() -> None: