6
6
7
7
8
8
if TYPE_CHECKING :
9
+ from poetry .core .constraints .version .version import Version
9
10
from poetry .core .constraints .version .version_constraint import VersionConstraint
10
11
11
12
12
13
def parse_constraint (constraints : str ) -> VersionConstraint :
14
+ return _parse_constraint (constraints = constraints )
15
+
16
+
17
+ def parse_marker_version_constraint (constraints : str ) -> VersionConstraint :
18
+ return _parse_constraint (constraints = constraints , is_marker_constraint = True )
19
+
20
+
21
+ def _parse_constraint (
22
+ constraints : str , is_marker_constraint : bool = False
23
+ ) -> VersionConstraint :
13
24
if constraints == "*" :
14
25
from poetry .core .constraints .version .version_range import VersionRange
15
26
@@ -28,9 +39,13 @@ def parse_constraint(constraints: str) -> VersionConstraint:
28
39
29
40
if len (and_constraints ) > 1 :
30
41
for constraint in and_constraints :
31
- constraint_objects .append (parse_single_constraint (constraint ))
42
+ constraint_objects .append (
43
+ parse_single_constraint (constraint , is_marker_constraint )
44
+ )
32
45
else :
33
- constraint_objects .append (parse_single_constraint (and_constraints [0 ]))
46
+ constraint_objects .append (
47
+ parse_single_constraint (and_constraints [0 ], is_marker_constraint )
48
+ )
34
49
35
50
if len (constraint_objects ) == 1 :
36
51
constraint = constraint_objects [0 ]
@@ -49,7 +64,9 @@ def parse_constraint(constraints: str) -> VersionConstraint:
49
64
return VersionUnion .of (* or_groups )
50
65
51
66
52
- def parse_single_constraint (constraint : str ) -> VersionConstraint :
67
+ def parse_single_constraint (
68
+ constraint : str , is_marker_constraint : bool = False
69
+ ) -> VersionConstraint :
53
70
from poetry .core .constraints .version .patterns import BASIC_CONSTRAINT
54
71
from poetry .core .constraints .version .patterns import CARET_CONSTRAINT
55
72
from poetry .core .constraints .version .patterns import TILDE_CONSTRAINT
@@ -95,26 +112,15 @@ def parse_single_constraint(constraint: str) -> VersionConstraint:
95
112
m = X_CONSTRAINT .match (constraint )
96
113
if m :
97
114
op = m .group ("op" )
98
- major = int (m .group (2 ))
99
- minor = m .group (3 )
100
115
101
- if minor is not None :
102
- version = Version .from_parts (major , int (minor ), 0 )
103
- result : VersionConstraint = VersionRange (
104
- version , version .next_minor (), include_min = True
116
+ try :
117
+ return _make_x_constraint_range (
118
+ version = Version .parse (m .group ("version" )),
119
+ invert = op == "!=" ,
120
+ is_marker_constraint = is_marker_constraint ,
105
121
)
106
- else :
107
- if major == 0 :
108
- result = VersionRange (max = Version .from_parts (1 , 0 , 0 ))
109
- else :
110
- version = Version .from_parts (major , 0 , 0 )
111
-
112
- result = VersionRange (version , version .next_major (), include_min = True )
113
-
114
- if op == "!=" :
115
- result = VersionRange ().difference (result )
116
-
117
- return result
122
+ except ValueError :
123
+ raise ValueError (f"Could not parse version constraint: { constraint } " )
118
124
119
125
# Basic comparator
120
126
m = BASIC_CONSTRAINT .match (constraint )
@@ -138,10 +144,55 @@ def parse_single_constraint(constraint: str) -> VersionConstraint:
138
144
return VersionRange (min = version )
139
145
if op == ">=" :
140
146
return VersionRange (min = version , include_min = True )
147
+
148
+ if m .group ("wildcard" ) is not None :
149
+ return _make_x_constraint_range (
150
+ version = version ,
151
+ invert = op == "!=" ,
152
+ is_marker_constraint = is_marker_constraint ,
153
+ )
154
+
141
155
if op == "!=" :
142
156
return VersionUnion (VersionRange (max = version ), VersionRange (min = version ))
157
+
143
158
return version
144
159
145
160
from poetry .core .constraints .version .exceptions import ParseConstraintError
146
161
147
162
raise ParseConstraintError (f"Could not parse version constraint: { constraint } " )
163
+
164
+
165
+ def _make_x_constraint_range (
166
+ version : Version , invert : bool = False , is_marker_constraint : bool = False
167
+ ) -> VersionConstraint :
168
+ from poetry .core .constraints .version .version_range import VersionRange
169
+
170
+ _is_zero_major = version .major == 0 and version .precision == 1
171
+
172
+ if version .is_postrelease ():
173
+ _next = version .next_postrelease ()
174
+ _is_zero_major = False
175
+ elif version .is_stable ():
176
+ _next = version .next_stable ()
177
+ elif version .is_prerelease ():
178
+ _next = version .next_prerelease ()
179
+ _is_zero_major = False
180
+ elif version .is_devrelease ():
181
+ _next = version .next_devrelease ()
182
+ _is_zero_major = False
183
+
184
+ if _is_zero_major :
185
+ result = VersionRange (max = _next .with_precision (3 ))
186
+ else :
187
+ _min = version .with_precision (max (version .precision , 3 ))
188
+
189
+ if not is_marker_constraint and not _next .is_unstable ():
190
+ _min = _min .next_devrelease ()
191
+
192
+ _max = _next .with_precision (max (version .precision , 3 ))
193
+ result = VersionRange (_min , _max , include_min = True )
194
+
195
+ if invert :
196
+ return VersionRange ().difference (result )
197
+
198
+ return result
0 commit comments