44#
55# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download.
66
7- import functools
8- from functools import total_ordering
9-
107import attr
118import semantic_version
129from packaging import version as packaging_version
@@ -59,7 +56,7 @@ def is_valid_alpine_version(s):
5956 return str (i ) == left
6057
6158
62- @attr .s (frozen = True , order = False , hash = True )
59+ @attr .s (frozen = True , order = True , eq = True , hash = True )
6360class Version :
6461 """
6562 Base version mixin to subclass for each version syntax implementation.
@@ -73,14 +70,16 @@ class Version:
7370 """
7471
7572 # the original string used to build this Version
76- string = attr .ib (type = str )
73+ string = attr .ib (type = str , eq = False , order = False , hash = False )
7774
7875 # the normalized string for this Version, stored without spaces and
7976 # lowercased. Any leading v is removed too.
80- normalized_string = attr .ib (type = str , default = None , repr = False )
77+ normalized_string = attr .ib (
78+ type = str , default = None , repr = False , eq = False , order = False , hash = False
79+ )
8180
8281 # a comparable scheme-specific version object constructed from the version string
83- value = attr .ib (default = None , repr = False )
82+ value = attr .ib (default = None , repr = False , eq = True , order = True , hash = True )
8483
8584 def __attrs_post_init__ (self ):
8685 normalized_string = self .normalize (self .string )
@@ -110,7 +109,7 @@ def normalize(cls, string):
110109 Return a normalized version string from ``string ``. Subclass can override.
111110 """
112111 # FIXME: Is removing spaces and strip v the right thing to do?
113- return remove_spaces (string ).rstrip ( "v " ). strip ( )
112+ return remove_spaces (string ).lstrip ( "vV" )
114113
115114 @classmethod
116115 def build_value (self , string ):
@@ -133,33 +132,7 @@ def satisfies(self, constraint):
133132 def __str__ (self ):
134133 return str (self .value )
135134
136- def __eq__ (self , other ):
137- if not isinstance (other , self .__class__ ):
138- return NotImplemented
139- return self .value .__eq__ (other .value )
140-
141- def __lt__ (self , other ):
142- if not isinstance (other , self .__class__ ):
143- return NotImplemented
144- return self .value .__lt__ (other .value )
145-
146- def __gt__ (self , other ):
147- if not isinstance (other , self .__class__ ):
148- return NotImplemented
149- return self .value .__gt__ (other .value )
150135
151- def __le__ (self , other ):
152- if not isinstance (other , self .__class__ ):
153- return NotImplemented
154- return self .value .__le__ (other .value )
155-
156- def __ge__ (self , other ):
157- if not isinstance (other , self .__class__ ):
158- return NotImplemented
159- return self .value .__ge__ (other .value )
160-
161-
162- @attr .s (frozen = True , order = False , hash = True )
163136class GenericVersion (Version ):
164137 @classmethod
165138 def is_valid (cls , string ):
@@ -174,13 +147,13 @@ def is_valid(cls, string):
174147 return super (GenericVersion , cls ).is_valid (string )
175148
176149
177- @attr .s (frozen = True , order = False , eq = False , hash = True )
178150class PypiVersion (Version ):
179151 """
180152 Python PEP 440 version as implemented in packaging with fallback to "legacy"
181153 """
182154
183155 # TODO: ensure we deal with triple equal
156+ # TODO: use packvers and handle legacy versions
184157
185158 @classmethod
186159 def build_value (cls , string ):
@@ -199,18 +172,22 @@ def is_valid(cls, string):
199172 except packaging_version .InvalidVersion :
200173 return False
201174
202- return False
175+
176+ class EnhancedSemanticVersion (semantic_version .Version ):
177+ @property
178+ def precedence_key (self ):
179+ key = super (EnhancedSemanticVersion , self ).precedence_key
180+ return key + (self .build or ())
203181
204182
205- @attr .s (frozen = True , order = False , eq = False , hash = True )
206183class SemverVersion (Version ):
207184 """
208185 Strict semver v2.0 with 3 segments.
209186 """
210187
211188 @classmethod
212189 def build_value (cls , string ):
213- return semantic_version . Version .coerce (string )
190+ return EnhancedSemanticVersion .coerce (string )
214191
215192 @classmethod
216193 def is_valid (cls , string ):
@@ -265,7 +242,6 @@ def is_even(s):
265242 return (int (s ) % 2 ) == 0
266243
267244
268- @attr .s (frozen = True , order = False , eq = False , hash = True )
269245class NginxVersion (SemverVersion ):
270246 """
271247 Semver with 3 segments and extra attribute for stable vs. unstable branches
@@ -279,7 +255,6 @@ def is_stable(self):
279255 return is_even (self .minor )
280256
281257
282- @attr .s (frozen = True , order = False , eq = False , hash = True )
283258class RubygemsVersion (Version ):
284259 """
285260 Rubygems encourages semver version but does not enforce it.
@@ -296,7 +271,6 @@ def is_valid(cls, string):
296271 return gem .GemVersion .is_correct (string )
297272
298273
299- @attr .s (frozen = True , order = False , eq = False , hash = True )
300274class ArchLinuxVersion (Version ):
301275 def __eq__ (self , other ):
302276 if not isinstance (other , self .__class__ ):
@@ -324,7 +298,6 @@ def __ge__(self, other):
324298 return arch .vercmp (self .value , other .value ) >= 0
325299
326300
327- @attr .s (frozen = True , order = False , eq = False , hash = True )
328301class DebianVersion (Version ):
329302 @classmethod
330303 def build_value (cls , string ):
@@ -335,7 +308,6 @@ def is_valid(cls, string):
335308 return debian .Version .is_valid (string )
336309
337310
338- @attr .s (frozen = True , order = False , eq = False , hash = True )
339311class MavenVersion (Version ):
340312 # See https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
341313 # https://github.com/apache/maven/tree/master/maven-artifact/src/main/java/org/apache/maven/artifact/versioning
@@ -346,8 +318,6 @@ def build_value(cls, string):
346318
347319
348320# We will use total ordering to sort the versions, since these versions also consider prereleases.
349- @attr .s (frozen = True , order = False , eq = False , hash = True )
350- @functools .total_ordering
351321class NugetVersion (Version ):
352322 # See https://docs.microsoft.com/en-us/nuget/concepts/package-versioning
353323
@@ -363,33 +333,17 @@ def is_valid(cls, string):
363333 except ValueError :
364334 return False
365335
366- def __str__ (self ):
367- return str (self .string )
368336
369- def __lt__ (self , other ):
370- return nuget .Version .from_string (self .string ) < nuget .Version .from_string (other .string )
371-
372- def __eq__ (self , other ):
373- return nuget .Version .from_string (self .string ) == nuget .Version .from_string (other .string )
374-
375-
376- @attr .s (frozen = True , order = False , eq = False , hash = True )
377337class RpmVersion (Version ):
378338 """
379339 Represent an RPM version.
380-
381- For example::
382-
383- # 1:1.1.4|>=2.8.16|<=2.8.16-z
384340 """
385341
386342 @classmethod
387343 def build_value (cls , string ):
388344 return rpm .RpmVersion .from_string (string )
389345
390346
391- @total_ordering
392- @attr .s (frozen = True , order = False , eq = False , hash = True )
393347class GentooVersion (Version ):
394348 @classmethod
395349 def is_valid (cls , string ):
@@ -405,44 +359,30 @@ def __lt__(self, other):
405359 return NotImplemented
406360 return gentoo .vercmp (self .value , other .value ) == - 1
407361
408-
409- @attr .s (frozen = True , order = False , eq = False , hash = True )
410- class AlpineLinuxVersion (Version ):
411- @classmethod
412- def is_valid (cls , string ):
413- return is_valid_alpine_version (string ) and gentoo .is_valid (string )
414-
415- def __eq__ (self , other ):
362+ def __gt__ (self , other ):
416363 if not isinstance (other , self .__class__ ):
417364 return NotImplemented
418- return gentoo .vercmp (self .value , other .value ) == 0
365+ return gentoo .vercmp (self .value , other .value ) == 1
419366
420- def __lt__ (self , other ):
421- if not isinstance (other , self .__class__ ):
422- return NotImplemented
423- return gentoo .vercmp (self .value , other .value ) < 0
424367
425- def __gt__ ( self , other ):
426- if not isinstance ( other , self . __class__ ):
427- return NotImplemented
428- return gentoo . vercmp ( self . value , other . value ) > 0
368+ class AlpineLinuxVersion ( GentooVersion ):
369+ @ classmethod
370+ def is_valid ( cls , string ):
371+ return is_valid_alpine_version ( string ) and gentoo . is_valid ( string )
429372
430373
431- @attr .s (frozen = True , order = False , eq = False , hash = True )
432374class ComposerVersion (SemverVersion ):
433375 @classmethod
434376 def build_value (cls , string ):
435- return semantic_version . Version . coerce (string .lstrip ("vV" ))
377+ return super (). build_value (string .lstrip ("vV" ))
436378
437379
438- @attr .s (frozen = True , order = False , eq = False , hash = True )
439380class GolangVersion (SemverVersion ):
440381 @classmethod
441382 def build_value (cls , string ):
442- return semantic_version . Version . coerce (string .lstrip ("vV" ))
383+ return super (). build_value (string .lstrip ("vV" ))
443384
444385
445- @attr .s (frozen = True , order = False , eq = False , hash = True )
446386class LegacyOpensslVersion (Version ):
447387 """
448388 Represent an Legacy Openssl Version.
@@ -558,7 +498,6 @@ def is_prerelease(self):
558498 return self .patch .startswith (("-beta" , "-alpha" ))
559499
560500
561- @attr .s (frozen = True , order = False , eq = False , hash = True )
562501class OpensslVersion (Version ):
563502 """
564503 Internally tracks two types of openssl versions
@@ -654,7 +593,6 @@ def __ge__(self, other):
654593
655594
656595@attr .s (frozen = True , order = False , eq = False , hash = True )
657- @total_ordering
658596class ConanVersion (Version ):
659597 @classmethod
660598 def build_value (cls , string ):
@@ -775,3 +713,22 @@ def __ge__(self, other):
775713 if not isinstance (other , ConanVersion ):
776714 other = ConanVersion (str (other ))
777715 return self .value >= other .value
716+
717+
718+ AVAILABLE_VERSIONS = [
719+ SemverVersion ,
720+ GolangVersion ,
721+ PypiVersion ,
722+ GenericVersion ,
723+ ComposerVersion ,
724+ NginxVersion ,
725+ ArchLinuxVersion ,
726+ DebianVersion ,
727+ RpmVersion ,
728+ MavenVersion ,
729+ NugetVersion ,
730+ GentooVersion ,
731+ OpensslVersion ,
732+ LegacyOpensslVersion ,
733+ AlpineLinuxVersion ,
734+ ]
0 commit comments