Skip to content

Commit 369f5a9

Browse files
authored
make complex marker unions and intersections deterministic (#843)
1 parent 411a7c9 commit 369f5a9

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

src/poetry/core/version/markers.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,13 @@ def union_simplify(self, other: BaseMarker) -> BaseMarker | None:
734734
if not shared_markers:
735735
return None
736736

737-
unique_markers = our_markers - their_markers
738-
other_unique_markers = their_markers - our_markers
737+
# Do not use sets to create MultiMarkers for deterministic order!
738+
unique_markers = [m for m in self.markers if m not in their_markers]
739+
other_unique_markers = [m for m in other.markers if m not in our_markers]
739740
unique_union = MultiMarker(*unique_markers).union(
740741
MultiMarker(*other_unique_markers)
741742
)
742743
if isinstance(unique_union, (SingleMarkerLike, AnyMarker)):
743-
# Use list instead of set for deterministic order.
744744
common_markers = [
745745
marker for marker in self.markers if marker in shared_markers
746746
]
@@ -908,13 +908,13 @@ def intersect_simplify(self, other: BaseMarker) -> BaseMarker | None:
908908
if not shared_markers:
909909
return None
910910

911-
unique_markers = our_markers - their_markers
912-
other_unique_markers = their_markers - our_markers
911+
# Do not use sets to create MarkerUnions for deterministic order!
912+
unique_markers = [m for m in self.markers if m not in their_markers]
913+
other_unique_markers = [m for m in other.markers if m not in our_markers]
913914
unique_intersection = MarkerUnion(*unique_markers).intersect(
914915
MarkerUnion(*other_unique_markers)
915916
)
916917
if isinstance(unique_intersection, (SingleMarkerLike, EmptyMarker)):
917-
# Use list instead of set for deterministic order.
918918
common_markers = [
919919
marker for marker in self.markers if marker in shared_markers
920920
]

tests/version/test_markers.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,35 @@ def test_complex_intersection() -> None:
21542154
)
21552155

21562156

2157+
def test_complex_union_is_deterministic() -> None:
2158+
"""
2159+
This test might fail sporadically if marker operations are not deterministic!
2160+
"""
2161+
m1 = parse_marker(
2162+
'sys_platform != "darwin" and python_version >= "3.12"'
2163+
' and platform_system != "Emscripten" and (python_version < "4.0"'
2164+
' and sys_platform == "linux" and extra == "stretch"'
2165+
' or platform_system == "Windows" or extra == "test"'
2166+
' and sys_platform == "win32")'
2167+
)
2168+
m2 = parse_marker(
2169+
'sys_platform == "linux" and python_version >= "3.12"'
2170+
' and platform_system == "Emscripten" and python_version < "4.0"'
2171+
' and extra == "stretch" or sys_platform == "win32"'
2172+
' and python_version >= "3.12" and platform_system == "Emscripten"'
2173+
' and extra == "test"'
2174+
)
2175+
assert str(m1.union(m2)) == (
2176+
'python_version >= "3.12" and platform_system == "Windows"'
2177+
' and sys_platform != "darwin" or sys_platform == "linux"'
2178+
' and python_version >= "3.12" and python_version < "4.0"'
2179+
' and extra == "stretch" or python_version >= "3.12" and python_version < "4.0"'
2180+
' and extra == "stretch" and extra == "test" and (sys_platform == "linux"'
2181+
' or sys_platform == "win32") or sys_platform == "win32"'
2182+
' and python_version >= "3.12" and extra == "test"'
2183+
)
2184+
2185+
21572186
def test_union_avoids_combinatorial_explosion() -> None:
21582187
"""
21592188
combinatorial explosion without AtomicMultiMarker and AtomicMarkerUnion

0 commit comments

Comments
 (0)