Skip to content

Commit

Permalink
markers: union of adjacent ranges should collapse (#390)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Jun 4, 2022
1 parent 07c6c0d commit c23dffd
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/poetry/core/version/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,9 @@ def union_simplify(self, other: BaseMarker) -> BaseMarker | None:
):
return other

if not any(isinstance(m, MarkerUnion) for m in new_markers):
return self.of(*new_markers)

elif isinstance(other, MultiMarker):
common_markers = [
marker for marker in self.markers if marker in other.markers
Expand All @@ -525,6 +528,23 @@ def union_simplify(self, other: BaseMarker) -> BaseMarker | None:
if not isinstance(unique_union, MarkerUnion):
return self.of(*common_markers).intersect(unique_union)

else:
# Usually this operation just complicates things, but the special case
# where it doesn't allows the collapse of adjacent ranges eg
#
# 'python_version >= "3.6" and python_version < "3.6.2"' union
# 'python_version >= "3.6.2" and python_version < "3.7"' ->
#
# 'python_version >= "3.6" and python_version < "3.7"'.
unions = [
m1.union(m2) for m2 in other_unique_markers for m1 in unique_markers
]
conjunction = self.of(*unions)
if not isinstance(conjunction, MultiMarker) or not any(
isinstance(m, MarkerUnion) for m in conjunction.markers
):
return conjunction

return None

def validate(self, environment: dict[str, Any] | None) -> bool:
Expand Down
88 changes: 86 additions & 2 deletions tests/version/test_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,90 @@ def test_multi_marker_union_multi_is_multi(
assert str(m2.union(m1)) == expected


@pytest.mark.parametrize(
"marker1, marker2, expected",
[
# Ranges with same start
(
'python_version >= "3.6" and python_full_version < "3.6.2"',
'python_version >= "3.6" and python_version < "3.7"',
'python_version >= "3.6" and python_version < "3.7"',
),
(
'python_version > "3.6" and python_full_version < "3.6.2"',
'python_version > "3.6" and python_version < "3.7"',
'python_version > "3.6" and python_version < "3.7"',
),
# Ranges meet exactly
(
'python_version >= "3.6" and python_full_version < "3.6.2"',
'python_full_version >= "3.6.2" and python_version < "3.7"',
'python_version >= "3.6" and python_version < "3.7"',
),
(
'python_version >= "3.6" and python_full_version <= "3.6.2"',
'python_full_version > "3.6.2" and python_version < "3.7"',
'python_version >= "3.6" and python_version < "3.7"',
),
# Ranges overlap
(
'python_version >= "3.6" and python_full_version <= "3.6.8"',
'python_full_version >= "3.6.2" and python_version < "3.7"',
'python_version >= "3.6" and python_version < "3.7"',
),
# Ranges with same end. Ideally the union would give the lower version first.
(
'python_version >= "3.6" and python_version < "3.7"',
'python_full_version >= "3.6.2" and python_version < "3.7"',
'python_version < "3.7" and python_version >= "3.6"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_full_version >= "3.6.2" and python_version <= "3.7"',
'python_version <= "3.7" and python_version >= "3.6"',
),
# A range covers an exact marker.
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_version == "3.6"',
'python_version >= "3.6" and python_version <= "3.7"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_version == "3.6" and implementation_name == "cpython"',
'python_version >= "3.6" and python_version <= "3.7"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_full_version == "3.6.2"',
'python_version >= "3.6" and python_version <= "3.7"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_full_version == "3.6.2" and implementation_name == "cpython"',
'python_version >= "3.6" and python_version <= "3.7"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_version == "3.7"',
'python_version >= "3.6" and python_version <= "3.7"',
),
(
'python_version >= "3.6" and python_version <= "3.7"',
'python_version == "3.7" and implementation_name == "cpython"',
'python_version >= "3.6" and python_version <= "3.7"',
),
],
)
def test_version_ranges_collapse_on_union(
marker1: str, marker2: str, expected: str
) -> None:
m1 = parse_marker(marker1)
m2 = parse_marker(marker2)
assert str(m1.union(m2)) == expected
assert str(m2.union(m1)) == expected


def test_multi_marker_union_with_union() -> None:
m = parse_marker('sys_platform == "darwin" and implementation_name == "cpython"')

Expand Down Expand Up @@ -964,8 +1048,8 @@ def test_union_of_multi_with_a_containing_single() -> None:
'python_version < "3.6" or python_version >= "4.0"',
),
(
'python_version ~= "3.6.3"',
'python_version < "3.6.3" or python_version >= "3.7.0"',
'python_full_version ~= "3.6.3"',
'python_full_version < "3.6.3" or python_full_version >= "3.7.0"',
),
],
)
Expand Down

0 comments on commit c23dffd

Please sign in to comment.