Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

markers: allow | as value separator for markers with operators in and not in #608

Merged
merged 1 commit into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/poetry/core/packages/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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("*")
Expand Down
5 changes: 3 additions & 2 deletions src/poetry/core/version/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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("*")
Expand All @@ -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:
Expand Down
44 changes: 26 additions & 18 deletions tests/packages/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down
98 changes: 50 additions & 48 deletions tests/version/test_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down