@@ -223,6 +223,41 @@ def from_osv_v1(data, scheme):
223223 """
224224
225225
226+ def get_allof_constraints (cls , clause ):
227+ """
228+ Return a list of VersionConstraint given an AllOf ``clause``.
229+ """
230+ if not isinstance (clause , AllOf ):
231+ raise ValueError (f"Unknown clause type: { clause !r} " )
232+ allof_constraints = []
233+ for constraint in clause .clauses :
234+ comparator = cls .vers_by_native_comparators [constraint .operator ]
235+ version = cls .version_class (str (constraint .target ))
236+ constraint = VersionConstraint (comparator = comparator , version = version )
237+ allof_constraints .append (constraint )
238+ return allof_constraints
239+
240+
241+ def get_npm_version_constraint_for_tilde_and_caret (string , cls ):
242+ """
243+ Return a VersionConstraint for the provided ``string``.
244+ """
245+ spec = semantic_version .NpmSpec (string )
246+ clause = spec .clause .simplify ()
247+ if isinstance (clause , (AnyOf , AllOf )):
248+ anyof_constraints = []
249+ if isinstance (clause , AnyOf ):
250+ for allof_clause in clause .clauses :
251+ anyof_constraints .extend (get_allof_constraints (cls , allof_clause ))
252+ elif isinstance (clause , AllOf ):
253+ alloc = get_allof_constraints (cls , clause )
254+ anyof_constraints .extend (alloc )
255+ else :
256+ raise ValueError (f"Unknown clause type: { spec !r} " )
257+
258+ return anyof_constraints
259+
260+
226261class NpmVersionRange (VersionRange ):
227262 scheme = "npm"
228263 version_class = versions .SemverVersion
@@ -245,35 +280,49 @@ def from_native(cls, string):
245280
246281 # an NpmSpec handles parsing of both the semver versions and node-semver
247282 # ranges at once
248- spec = semantic_version .NpmSpec (string )
249-
250- clause = spec .clause .simplify ()
251- assert isinstance (clause , (AnyOf , AllOf ))
252- anyof_constraints = []
253- if isinstance (clause , AnyOf ):
254- for allof_clause in clause .clauses :
255- anyof_constraints .extend (get_allof_constraints (cls , allof_clause ))
256- elif isinstance (clause , AllOf ):
257- alloc = get_allof_constraints (cls , clause )
258- anyof_constraints .extend (alloc )
259- else :
260- raise ValueError (f"Unknown clause type: { spec !r} " )
261-
262- return cls (constraints = anyof_constraints )
263283
284+ if string == "*" :
285+ return cls (
286+ constraints = [
287+ VersionConstraint .from_string (string = "*" , version_class = cls .version_class )
288+ ]
289+ )
264290
265- def get_allof_constraints (cls , clause ):
266- """
267- Return a list of VersionConstraint given an AllOf ``clause``.
268- """
269- assert isinstance (clause , AllOf )
270- allof_constraints = []
271- for constraint in clause .clauses :
272- comparator = cls .vers_by_native_comparators [constraint .operator ]
273- version = cls .version_class (str (constraint .target ))
274- constraint = VersionConstraint (comparator = comparator , version = version )
275- allof_constraints .append (constraint )
276- return allof_constraints
291+ constraints = []
292+ comparator = ""
293+ vrc = cls .version_class
294+ # A constraint item can be a comparator or a version or a version with comparator
295+ # If it's empty continue
296+ # If it's in `vers_by_native_comparators`, append it with the comparator and continue
297+ # If it's a version, make version constraint from the version and use the comparator from the previous item and make comparator empty
298+ # If it's a version with comparator, use split_req to get version and comparator to form constraint and make comparator empty
299+ for constraint_item in string .split (" " ):
300+ if not constraint_item or constraint_item == "||" :
301+ continue
302+ if "" .join ([comparator , constraint_item ]) in cls .vers_by_native_comparators :
303+ comparator = "" .join ([comparator , constraint_item ])
304+ comparator = cls .vers_by_native_comparators [comparator ]
305+ continue
306+ if comparator :
307+ constraint_item = constraint_item .lstrip ("vV" )
308+ constraints .append (
309+ VersionConstraint (comparator = comparator , version = vrc (constraint_item ))
310+ )
311+ else :
312+ if constraint_item .startswith ("~" ) or constraint_item .startswith ("^" ):
313+ constraints .extend (
314+ get_npm_version_constraint_for_tilde_and_caret (constraint_item , cls )
315+ )
316+ else :
317+ comparator , version_constraint = split_req (
318+ constraint_item , cls .vers_by_native_comparators , default = "="
319+ )
320+ version_constraint = version_constraint .lstrip ("vV" )
321+ constraints .append (
322+ VersionConstraint (comparator = comparator , version = vrc (version_constraint ))
323+ )
324+ comparator = ""
325+ return cls (constraints = constraints )
277326
278327
279328class GemVersionRange (VersionRange ):
0 commit comments