22
33import operator
44
5- from typing import Any
65from typing import Callable
76from typing import ClassVar
87
1110from poetry .core .constraints .generic .empty_constraint import EmptyConstraint
1211
1312
14- OperatorType = Callable [[object , object ], Any ]
13+ OperatorType = Callable [[object , object ], bool ]
1514
1615
1716def contains (a : object , b : object , / ) -> bool :
@@ -67,57 +66,22 @@ def operator(self) -> str:
6766 return self ._operator
6867
6968 def allows (self , other : BaseConstraint ) -> bool :
70- """Logic table to help
71-
72- || != | == | in | not in
73- --------||--------|--------|--------|--------
74- != || != | != | not in | not in
75- == || != | == | in | not in
76- in || not in | in | in | not in
77- not in || not in | not in | not in | false
78-
79- """
80-
81- if not isinstance (other , Constraint ) or other .operator not in {
82- "==" ,
83- "in" ,
84- "not in" ,
85- }:
69+ if not isinstance (other , Constraint ) or other .operator != "==" :
8670 raise ValueError (
8771 f"Invalid argument for allows"
8872 f' ("other" must be a constraint with operator "=="): { other } '
8973 )
9074
91- is_equal_op = self ._operator == "=="
92- is_non_equal_op = self ._operator == "!="
93- is_other_equal_op = other .operator == "=="
94- is_other_non_equal_op = other .operator == "!="
95- is_in_op = self ._operator == "in"
96- is_not_in_op = self ._operator == "not in"
97- is_other_in_op = other .operator == "in"
98- is_other_not_in_op = other .operator == "not in"
99-
100- if is_equal_op :
75+ if self ._operator == "==" :
10176 return self ._value == other .value
10277
103- if is_in_op and is_other_in_op or is_in_op and is_other_equal_op :
78+ if self . _operator == "in" :
10479 return bool (self ._trans_op_str ["in" ](other .value , self ._value ))
10580
106- if is_non_equal_op and not ( is_other_in_op or is_other_not_in_op ) :
81+ if self . _operator == "!=" :
10782 return self ._value != other .value
10883
109- if (
110- is_in_op
111- and is_other_non_equal_op
112- or is_in_op
113- and is_other_not_in_op
114- or is_not_in_op
115- and is_other_non_equal_op
116- or is_not_in_op
117- and is_other_equal_op
118- or is_non_equal_op
119- and is_other_not_in_op
120- ):
84+ if self ._operator == "not in" :
12185 return bool (self ._trans_op_str ["not in" ](other .value , self ._value ))
12286
12387 return False
@@ -127,9 +91,22 @@ def allows_all(self, other: BaseConstraint) -> bool:
12791 from poetry .core .constraints .generic import UnionConstraint
12892
12993 if isinstance (other , Constraint ):
130- if other .operator == "==" :
94+ is_in_op = self ._operator == "in"
95+ is_not_in_op = self ._operator == "not in"
96+
97+ is_other_equal_op = other .operator == "=="
98+ is_other_in_op = other .operator == "in"
99+ is_other_not_in_op = other .operator == "not in"
100+
101+ if is_other_equal_op :
131102 return self .allows (other )
132103
104+ if is_other_in_op and is_in_op :
105+ return self ._op (self .value , other .value )
106+
107+ if is_other_not_in_op and not is_not_in_op :
108+ return self ._trans_op_str ["not in" ](other .value , self .value )
109+
133110 return self == other
134111
135112 if isinstance (other , MultiConstraint ):
@@ -146,21 +123,32 @@ def allows_any(self, other: BaseConstraint) -> bool:
146123
147124 is_equal_op = self ._operator == "=="
148125 is_non_equal_op = self ._operator == "!="
126+ is_in_op = self ._operator == "in"
127+ is_not_in_op = self ._operator == "not in"
149128
150129 if is_equal_op :
151130 return other .allows (self )
152131
153132 if isinstance (other , Constraint ):
154133 is_other_equal_op = other .operator == "=="
155134 is_other_non_equal_op = other .operator == "!="
135+ is_other_in_op = other .operator == "in"
136+ is_other_not_in_op = other .operator == "not in"
156137
157138 if is_other_equal_op :
158139 return self .allows (other )
159140
160141 if is_equal_op and is_other_non_equal_op :
161142 return self ._value != other .value
162143
163- return is_non_equal_op and is_other_non_equal_op
144+ return (
145+ is_in_op
146+ and is_other_in_op
147+ or is_not_in_op
148+ and is_other_not_in_op
149+ or is_non_equal_op
150+ and other .operator in {"!=" , "in" , "not in" }
151+ )
164152
165153 elif isinstance (other , MultiConstraint ):
166154 return is_non_equal_op
@@ -188,23 +176,51 @@ def intersect(self, other: BaseConstraint) -> BaseConstraint:
188176 if other == self :
189177 return self
190178
191- if (
192- self .operator in {"!=" , "not in" , "in" }
193- and other .operator in {"==" , "in" , "not in" }
194- and self .allows (other )
195- ):
179+ if self .operator == "!=" and other .operator == "==" and self .allows (other ):
196180 return other
197181
198- if (
199- other .operator in {"!=" , "not in" , "in" }
200- and self .operator in {"==" , "in" , "not in" }
201- and other .allows (self )
202- ):
182+ if other .operator == "!=" and self .operator == "==" and other .allows (self ):
203183 return self
204184
205- if other .operator in {"!=" , "not in" } and self .operator in {"!=" , "not in" }:
185+ if (
186+ other .operator == "!="
187+ and self .operator == "!="
188+ or self .operator == "not in"
189+ and other .operator == "not in"
190+ ):
206191 return MultiConstraint (self , other )
207192
193+ other_in_self = self ._trans_op_str ["in" ](self .value , other .value )
194+ self_in_other = self ._trans_op_str ["in" ](other .value , self .value )
195+ is_in_op = self ._operator == "in"
196+ is_other_in_op = other .operator == "in"
197+
198+ if is_in_op or other .operator == "not in" :
199+ # If self is a subset of other, return self
200+ if is_other_in_op and other_in_self :
201+ return self
202+ # If neither are subsets of each other then its a MC
203+ if (is_other_in_op and not self_in_other ) or (
204+ other .operator == "!=" and self_in_other
205+ ):
206+ return MultiConstraint (self , other )
207+ # if it allows any of other, return other
208+ if self .allows_any (other ):
209+ return other
210+
211+ if is_other_in_op or self .operator == "not in" :
212+ # If other is a subset of self, return other
213+ if is_in_op and self_in_other :
214+ return other
215+ # If neither are subsets of each other then its a MC
216+ if (is_in_op and not other_in_self ) or (
217+ self .operator == "!=" and other_in_self
218+ ):
219+ return MultiConstraint (self , other )
220+ # if other allows any of self, return self
221+ if other .allows_any (self ):
222+ return self
223+
208224 return EmptyConstraint ()
209225
210226 return other .intersect (self )
@@ -216,21 +232,45 @@ def union(self, other: BaseConstraint) -> BaseConstraint:
216232 if other == self :
217233 return self
218234
219- if (
220- self .operator in {"!=" , "not in" , "in" }
221- and other .operator in {"==" , "in" , "not in" }
222- ) and self .allows (other ):
235+ if self .operator == "!=" and other .operator == "==" and self .allows (other ):
223236 return self
224237
225- if (
226- other .operator in {"!=" , "not in" , "in" }
227- and self .operator in {"==" , "in" , "not in" }
228- ) and other .allows (self ):
238+ if other .operator == "!=" and self .operator == "==" and other .allows (self ):
229239 return other
230240
231- if other .operator in {"==" , "in" } and self .operator in {"==" , "in" }:
241+ if (
242+ other .operator == "=="
243+ and self .operator == "=="
244+ or self .operator == "not in"
245+ and other .operator == "not in"
246+ ):
232247 return UnionConstraint (self , other )
233248
249+ other_in_self = self ._trans_op_str ["in" ](self .value , other .value )
250+ self_in_other = self ._trans_op_str ["in" ](other .value , self .value )
251+ is_in_op = self ._operator == "in"
252+ is_other_in_op = other .operator == "in"
253+
254+ if is_in_op or other .operator == "not in" :
255+ if is_other_in_op and self_in_other :
256+ return self
257+ if (is_other_in_op and not other_in_self ) or (
258+ other .operator == "!=" and other_in_self
259+ ):
260+ return UnionConstraint (self , other )
261+ if other .allows_all (self ):
262+ return other
263+
264+ if is_other_in_op or self ._operator == "not in" :
265+ if is_in_op and other_in_self :
266+ return other
267+ if (is_in_op and not self_in_other ) or (
268+ self .operator == "!=" and self_in_other
269+ ):
270+ return UnionConstraint (self , other )
271+ if self .allows_all (other ):
272+ return self
273+
234274 return AnyConstraint ()
235275
236276 # to preserve order (functionally not necessary)
0 commit comments