22
33from semver import Version
44
5- _re_partial_version = re .compile (r"^([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+))?)?$" )
5+ _re_digits_g = "[0-9]+"
6+ def _re_group (inner = "" , numeric = True , delimiter = "." ):
7+ capture = _re_digits_g if numeric else ".*"
8+ return f"(?:{ delimiter } ({ capture } ){ inner } )?"
9+ _re_prerelease = _re_group (numeric = False )
10+ _re_optional = _re_group (_re_group (_re_prerelease ))
11+ _re_partial_version = re .compile (rf"^({ _re_digits_g } ){ _re_optional } $" )
612
713
814def _parse_partial_version (x ):
915 m = _re_partial_version .match (x )
1016 if m is None :
1117 return None , None
12- major , minor , patch = m .groups ()
13- v = Version (major , minor or 0 , patch or 0 )
14- n = 1 if minor is None else 2 if patch is None else 3
18+ major , minor , patch , prerelease = m .groups ()
19+ v = Version (major , minor or 0 , patch or 0 , prerelease )
20+ n = 1 if minor is None else 2 if patch is None else 3 if prerelease is None else 4
1521 return (v , n )
1622
1723
@@ -87,20 +93,26 @@ def caret(cls, v, n):
8793 v .major ,
8894 v .minor if n >= 2 else 0 ,
8995 v .patch if n >= 3 else 0 ,
96+ v .prerelease if n >= 4 else None
9097 )
9198 hi = (
9299 v .bump_major ()
93100 if v .major != 0 or n < 2
94101 else v .bump_minor ()
95102 if v .minor != 0 or n < 3
96103 else v .bump_patch ()
104+ if v .patch != 0 or n < 4
105+ else v .bump_prerelease ()
97106 )
98107 return Range (lo , hi )
99108
100109 @classmethod
101110 def equality (cls , v ):
102111 lo = v
103- hi = v .bump_patch ()
112+ if lo .prerelease is not None :
113+ hi = v .bump_prerelease ()
114+ else :
115+ hi = v .bump_patch ()
104116 return Range (lo , hi )
105117
106118 @classmethod
@@ -120,7 +132,7 @@ def parse(cls, x):
120132 elif x .startswith ("=" ):
121133 # equality specifier
122134 v , n = _parse_partial_version (x [1 :])
123- if v is not None and n = = 3 :
135+ if v is not None and n > = 3 :
124136 return cls .equality (v )
125137 elif " - " in x :
126138 # range specifier
@@ -140,26 +152,40 @@ def __str__(self):
140152 lo = self .lo
141153 hi = self .hi
142154 if self == Range .equality (lo ):
143- return f"={ lo .major } .{ lo .minor } .{ lo .patch } "
155+ prerelease = f"-{ lo .prerelease } " if lo .prerelease else ""
156+ return f"={ lo .major } .{ lo .minor } .{ lo .patch } { prerelease } "
144157 if self == Range .caret (lo , 1 ):
145158 return f"^{ lo .major } "
146159 if self == Range .caret (lo , 2 ):
147160 return f"^{ lo .major } .{ lo .minor } "
148161 if self == Range .caret (lo , 3 ):
149162 return f"^{ lo .major } .{ lo .minor } .{ lo .patch } "
163+ if self == Range .caret (lo , 4 ):
164+ return f"^{ lo .major } .{ lo .minor } .{ lo .patch } -{ lo .prerelease } "
150165 if self == Range .tilde (lo , 1 ):
151166 return f"~{ lo .major } "
152167 if self == Range .tilde (lo , 2 ):
153168 return f"~{ lo .major } .{ lo .minor } "
154169 if self == Range .tilde (lo , 3 ):
155170 return f"~{ lo .major } .{ lo .minor } .{ lo .patch } "
156- lostr = f"{ lo .major } .{ lo .minor } .{ lo .patch } "
171+ if self == Range .tilde (lo , 4 ):
172+ return f"~{ lo .major } .{ lo .minor } .{ lo .patch } -{ lo .prerelease } "
173+ if lo .prerelease is None :
174+ lostr = f"{ lo .major } .{ lo .minor } .{ lo .patch } "
175+ else :
176+ lostr = f"{ lo .major } .{ lo .minor } .{ lo .patch } -{ lo .prerelease } "
177+ hi_str = ""
157178 if hi .major > 0 and hi .minor == 0 and hi .patch == 0 :
158179 return f"{ lostr } - { hi .major - 1 } "
180+ hi_str += f"{ hi .major } "
159181 if hi .minor > 0 and hi .patch == 0 :
160- return f"{ lostr } - { hi .major } .{ hi .minor - 1 } "
161- if hi .patch > 0 :
162- return f"{ lostr } - { hi .major } .{ hi .minor } .{ hi .patch - 1 } "
182+ return f"{ lostr } - { hi_str } .{ hi .minor - 1 } "
183+ hi_str += f".{ hi .minor } "
184+ if hi .patch > 0 and hi .prerelease is None :
185+ return f"{ lostr } - { hi_str } .{ hi .patch - 1 } "
186+ hi_str += f".{ hi .patch } "
187+ if hi .prerelease is not None :
188+ return f"{ lostr } - { hi_str } -{ self ._decrease_string (hi .prerelease )} "
163189 raise ValueError ("invalid range" )
164190
165191 def __repr__ (self ):
@@ -180,3 +206,11 @@ def __eq__(self, other):
180206
181207 def is_empty (self ):
182208 return not (self .lo < self .hi )
209+
210+ def _decrease_string (self , string ):
211+ match = Version ._LAST_NUMBER .search (string )
212+ if match :
213+ prev_ = str (int (match .group (1 )) - 1 )
214+ start , end = match .span (1 )
215+ string = string [: max (end - len (prev_ ), start )] + prev_ + string [end :]
216+ return string
0 commit comments