Skip to content

Commit

Permalink
Single marker union simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
radoering committed Feb 28, 2022
1 parent c5f4cda commit b8cf6ec
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 26 deletions.
3 changes: 3 additions & 0 deletions src/poetry/core/semver/empty_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def is_empty(self) -> bool:
def is_any(self) -> bool:
return False

def is_simple(self) -> bool:
return True

def allows(self, version: "Version") -> bool:
return False

Expand Down
3 changes: 3 additions & 0 deletions src/poetry/core/semver/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def is_any(self) -> bool:
def is_empty(self) -> bool:
return False

def is_simple(self) -> bool:
return True

def allows(self, version: "Version") -> bool:
if version is None:
return False
Expand Down
4 changes: 4 additions & 0 deletions src/poetry/core/semver/version_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ def is_empty(self) -> bool:
def is_any(self) -> bool:
raise NotImplementedError()

@abstractmethod
def is_simple(self) -> bool:
raise NotImplementedError()

@abstractmethod
def allows(self, version: "Version") -> bool:
raise NotImplementedError()
Expand Down
3 changes: 3 additions & 0 deletions src/poetry/core/semver/version_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ def is_empty(self) -> bool:
def is_any(self) -> bool:
return self._min is None and self._max is None

def is_simple(self) -> bool:
return self._min is None or self._max is None

def allows(self, other: "Version") -> bool:
if self._min is not None:
if other < self._min:
Expand Down
3 changes: 3 additions & 0 deletions src/poetry/core/semver/version_union.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ def is_empty(self) -> bool:
def is_any(self) -> bool:
return False

def is_simple(self) -> bool:
return self.excludes_single_version()

def allows(self, version: "Version") -> bool:
return any([constraint.allows(version) for constraint in self._ranges])

Expand Down
49 changes: 27 additions & 22 deletions src/poetry/core/version/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
from typing import List
from typing import Union

from poetry.core.semver.version_constraint import VersionConstraint
from poetry.core.version.grammars import GRAMMAR_PEP_508_MARKERS
from poetry.core.version.parser import Parser


if TYPE_CHECKING:
from lark import Tree

from poetry.core.semver.helpers import VersionTypes
from poetry.core.packages.constraints import BaseConstraint

MarkerTypes = Union[
"AnyMarker", "EmptyMarker", "SingleMarker", "MultiMarker", "MarkerUnion"
Expand Down Expand Up @@ -184,7 +185,9 @@ class SingleMarker(BaseMarker):
"platform_release",
}

def __init__(self, name: str, constraint: Union[str, "VersionTypes"]) -> None:
def __init__(
self, name: str, constraint: Union[str, "BaseConstraint", VersionConstraint]
) -> None:
from poetry.core.packages.constraints import (
parse_constraint as parse_generic_constraint,
)
Expand Down Expand Up @@ -247,7 +250,7 @@ def constraint_string(self) -> str:
return self._constraint_string

@property
def constraint(self) -> "VersionTypes":
def constraint(self) -> Union["BaseConstraint", VersionConstraint]:
return self._constraint

@property
Expand Down Expand Up @@ -551,28 +554,30 @@ def of(cls, *markers: BaseMarker) -> MarkerTypes:
if marker in markers:
continue

if (
isinstance(marker, SingleMarker)
and marker.name in PYTHON_VERSION_MARKERS
):
if isinstance(marker, SingleMarker):
included = False
for i, mark in enumerate(markers):
if (
not isinstance(mark, SingleMarker)
or mark.name not in PYTHON_VERSION_MARKERS
if isinstance(mark, SingleMarker) and (
mark.name == marker.name
or (
mark.name in PYTHON_VERSION_MARKERS
and marker.name in PYTHON_VERSION_MARKERS
)
):
continue

union = mark.constraint.union(marker.constraint)
if union == mark.constraint:
included = True
break
elif union == marker.constraint:
markers[i] = marker
included = True
break
elif union.is_any():
return AnyMarker()
union = mark.constraint.union(marker.constraint)
if union == mark.constraint:
included = True
break
elif union == marker.constraint:
markers[i] = marker
included = True
break
elif union.is_any():
return AnyMarker()
elif isinstance(union, VersionConstraint) and union.is_simple():
markers[i] = SingleMarker(mark.name, union)
included = True
break

if included:
continue
Expand Down
42 changes: 38 additions & 4 deletions tests/version/test_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,51 @@ def test_single_marker_union():
union = m.union(parse_marker('implementation_name == "cpython"'))
assert str(union) == 'sys_platform == "darwin" or implementation_name == "cpython"'


def test_single_marker_union_is_any():
m = parse_marker('python_version >= "3.4"')

union = m.union(parse_marker('python_version < "3.6"'))
assert union.is_any()


def test_single_marker_union_compacts_constraints():
m = parse_marker('python_version < "3.6"')
@pytest.mark.parametrize(
("marker1", "marker2", "expected"),
[
(
'python_version < "3.6"',
'python_version < "3.4"',
'python_version < "3.6"',
),
(
'sys_platform == "linux"',
'sys_platform != "win32"',
'sys_platform != "win32"',
),
(
'python_version == "3.6"',
'python_version > "3.6"',
'python_version >= "3.6"',
),
(
'python_version == "3.6"',
'python_version < "3.6"',
'python_version <= "3.6"',
),
(
'python_version < "3.6"',
'python_version > "3.6"',
'python_version != "3.6"',
),
],
)
def test_single_marker_union_is_single_marker(
marker1: str, marker2: str, expected: str
):
m = parse_marker(marker1)

union = m.union(parse_marker('python_version < "3.4"'))
assert str(union) == 'python_version < "3.6"'
union = m.union(parse_marker(marker2))
assert str(union) == expected


def test_single_marker_union_with_multi():
Expand Down

0 comments on commit b8cf6ec

Please sign in to comment.