@@ -420,7 +420,18 @@ def of(cls, *markers: BaseMarker) -> BaseMarker:
420
420
intersected = True
421
421
break
422
422
423
+ # If we have a MarkerUnion then we can look for the simplifications
424
+ # implemented in intersect_simplify().
425
+ elif isinstance (mark , MarkerUnion ):
426
+ intersection = mark .intersect_simplify (marker )
427
+ if intersection is not None :
428
+ new_markers [i ] = intersection
429
+ intersected = True
430
+ break
431
+
423
432
if intersected :
433
+ # flatten again because intersect_simplify may return a multi
434
+ new_markers = _flatten_markers (new_markers , MultiMarker )
424
435
continue
425
436
426
437
new_markers .append (marker )
@@ -451,6 +462,9 @@ def union_simplify(self, other: BaseMarker) -> BaseMarker | None:
451
462
452
463
- union between two multimarkers where one is contained by the other is just
453
464
the larger of the two
465
+
466
+ - union between two multimarkers where there are some common markers
467
+ and the union of unique markers is a single marker
454
468
"""
455
469
if other in self ._markers :
456
470
return other
@@ -465,6 +479,22 @@ def union_simplify(self, other: BaseMarker) -> BaseMarker | None:
465
479
if their_markers .issubset (our_markers ):
466
480
return other
467
481
482
+ shared_markers = our_markers .intersection (their_markers )
483
+ if not shared_markers :
484
+ return None
485
+
486
+ unique_markers = our_markers - their_markers
487
+ other_unique_markers = their_markers - our_markers
488
+ unique_union = MultiMarker (* unique_markers ).union (
489
+ MultiMarker (* other_unique_markers )
490
+ )
491
+ if isinstance (unique_union , (SingleMarker , AnyMarker )):
492
+ # Use list instead of set for deterministic order.
493
+ common_markers = [
494
+ marker for marker in self .markers if marker in shared_markers
495
+ ]
496
+ return unique_union .intersect (MultiMarker (* common_markers ))
497
+
468
498
return None
469
499
470
500
def validate (self , environment : dict [str , Any ] | None ) -> bool :
@@ -611,6 +641,50 @@ def intersect(self, other: BaseMarker) -> BaseMarker:
611
641
def union (self , other : BaseMarker ) -> BaseMarker :
612
642
return union (self , other )
613
643
644
+ def intersect_simplify (self , other : BaseMarker ) -> BaseMarker | None :
645
+ """
646
+ Finds a couple of easy simplifications for intersection on MarkerUnions:
647
+
648
+ - intersection with any marker that appears as part of the union is just
649
+ that marker
650
+
651
+ - intersection between two markerunions where one is contained by the other
652
+ is just the smaller of the two
653
+
654
+ - intersection between two markerunions where there are some common markers
655
+ and the intersection of unique markers is not a single marker
656
+ """
657
+ if other in self ._markers :
658
+ return other
659
+
660
+ if isinstance (other , MarkerUnion ):
661
+ our_markers = set (self .markers )
662
+ their_markers = set (other .markers )
663
+
664
+ if our_markers .issubset (their_markers ):
665
+ return self
666
+
667
+ if their_markers .issubset (our_markers ):
668
+ return other
669
+
670
+ shared_markers = our_markers .intersection (their_markers )
671
+ if not shared_markers :
672
+ return None
673
+
674
+ unique_markers = our_markers - their_markers
675
+ other_unique_markers = their_markers - our_markers
676
+ unique_intersection = MarkerUnion (* unique_markers ).intersect (
677
+ MarkerUnion (* other_unique_markers )
678
+ )
679
+ if isinstance (unique_intersection , (SingleMarker , EmptyMarker )):
680
+ # Use list instead of set for deterministic order.
681
+ common_markers = [
682
+ marker for marker in self .markers if marker in shared_markers
683
+ ]
684
+ return unique_intersection .union (MarkerUnion (* common_markers ))
685
+
686
+ return None
687
+
614
688
def validate (self , environment : dict [str , Any ] | None ) -> bool :
615
689
return any (m .validate (environment ) for m in self ._markers )
616
690
0 commit comments