4141
4242Increment : TypeAlias = Literal ["MAJOR" , "MINOR" , "PATCH" ]
4343Prerelease : TypeAlias = Literal ["alpha" , "beta" , "rc" ]
44- DEFAULT_VERSION_PARSER = r"v?(?P<version>([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.]+)?(\w+)?)"
44+ _DEFAULT_VERSION_PARSER = re .compile (
45+ r"v?(?P<version>([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.]+)?(\w+)?)"
46+ )
4547
4648
4749@runtime_checkable
@@ -156,7 +158,7 @@ class BaseVersion(_BaseVersion):
156158 A base class implementing the `VersionProtocol` for PEP440-like versions.
157159 """
158160
159- parser : ClassVar [re .Pattern ] = re . compile ( DEFAULT_VERSION_PARSER )
161+ parser : ClassVar [re .Pattern ] = _DEFAULT_VERSION_PARSER
160162 """Regex capturing this version scheme into a `version` group"""
161163
162164 @property
@@ -186,20 +188,16 @@ def generate_prerelease(
186188 if not prerelease :
187189 return ""
188190
191+ new_prerelease_number = offset
189192 # prevent down-bumping the pre-release phase, e.g. from 'b1' to 'a2'
190193 # https://packaging.python.org/en/latest/specifications/version-specifiers/#pre-releases
191194 # https://semver.org/#spec-item-11
192195 if self .is_prerelease and self .pre :
193196 prerelease = max (prerelease , self .pre [0 ])
197+ if prerelease .startswith (self .pre [0 ]):
198+ new_prerelease_number = self .pre [1 ] + 1
194199
195- # version.pre is needed for mypy check
196- if self .is_prerelease and self .pre and prerelease .startswith (self .pre [0 ]):
197- prev_prerelease : int = self .pre [1 ]
198- new_prerelease_number = prev_prerelease + 1
199- else :
200- new_prerelease_number = offset
201- pre_version = f"{ prerelease } { new_prerelease_number } "
202- return pre_version
200+ return f"{ prerelease } { new_prerelease_number } "
203201
204202 def generate_devrelease (self , devrelease : int | None ) -> str :
205203 """Generate devrelease
@@ -265,39 +263,35 @@ def bump(
265263 if self .local and is_local_version :
266264 local_version = self .scheme (self .local ).bump (increment )
267265 return self .scheme (f"{ self .public } +{ local_version } " ) # type: ignore
268- else :
269- if not self .is_prerelease :
270- base = self .increment_base (increment )
271- elif exact_increment :
272- base = self .increment_base (increment )
273- else :
274- base = f"{ self .major } .{ self .minor } .{ self .micro } "
275- if increment == PATCH :
276- pass
277- elif increment == MINOR :
278- if self .micro != 0 :
279- base = self .increment_base (increment )
280- elif increment == MAJOR :
281- if self .minor != 0 or self .micro != 0 :
282- base = self .increment_base (increment )
283- dev_version = self .generate_devrelease (devrelease )
284-
285- release = list (self .release )
286- if len (release ) < 3 :
287- release += [0 ] * (3 - len (release ))
288- current_base = "." .join (str (part ) for part in release )
289- if base == current_base :
290- pre_version = self .generate_prerelease (
291- prerelease , offset = prerelease_offset
292- )
293- else :
294- base_version = cast (BaseVersion , self .scheme (base ))
295- pre_version = base_version .generate_prerelease (
296- prerelease , offset = prerelease_offset
297- )
298- build_metadata = self .generate_build_metadata (build_metadata )
299- # TODO: post version
300- return self .scheme (f"{ base } { pre_version } { dev_version } { build_metadata } " ) # type: ignore
266+
267+ base = self ._get_increment_base (increment , exact_increment )
268+ dev_version = self .generate_devrelease (devrelease )
269+
270+ release = list (self .release )
271+ if len (release ) < 3 :
272+ release += [0 ] * (3 - len (release ))
273+ current_base = "." .join (str (part ) for part in release )
274+
275+ pre_version = (
276+ self if base == current_base else cast (BaseVersion , self .scheme (base ))
277+ ).generate_prerelease (prerelease , offset = prerelease_offset )
278+
279+ # TODO: post version
280+ return self .scheme (
281+ f"{ base } { pre_version } { dev_version } { self .generate_build_metadata (build_metadata )} "
282+ ) # type: ignore
283+
284+ def _get_increment_base (
285+ self , increment : Increment | None , exact_increment : bool
286+ ) -> str :
287+ if (
288+ not self .is_prerelease
289+ or exact_increment
290+ or (increment == MINOR and self .micro != 0 )
291+ or (increment == MAJOR and (self .minor != 0 or self .micro != 0 ))
292+ ):
293+ return self .increment_base (increment )
294+ return f"{ self .major } .{ self .minor } .{ self .micro } "
301295
302296
303297class Pep440 (BaseVersion ):
@@ -316,7 +310,7 @@ class SemVer(BaseVersion):
316310 """
317311
318312 def __str__ (self ) -> str :
319- parts = []
313+ parts : list [ str ] = []
320314
321315 # Epoch
322316 if self .epoch != 0 :
@@ -364,7 +358,7 @@ def prerelease(self) -> str | None:
364358 return None
365359
366360 def __str__ (self ) -> str :
367- parts = []
361+ parts : list [ str ] = []
368362
369363 # Epoch
370364 if self .epoch != 0 :
@@ -373,9 +367,19 @@ def __str__(self) -> str:
373367 # Release segment
374368 parts .append ("." .join (str (x ) for x in self .release ))
375369
370+ if prerelease := self ._get_prerelease ():
371+ parts .append (f"-{ prerelease } " )
372+
373+ # Local version segment
374+ if self .local :
375+ parts .append (f"+{ self .local } " )
376+
377+ return "" .join (parts )
378+
379+ def _get_prerelease (self ) -> str :
376380 # Pre-release identifiers
377381 # See: https://semver.org/spec/v2.0.0.html#spec-item-9
378- prerelease_parts = []
382+ prerelease_parts : list [ str ] = []
379383 if self .prerelease :
380384 prerelease_parts .append (f"{ self .prerelease } " )
381385
@@ -387,15 +391,7 @@ def __str__(self) -> str:
387391 if self .dev is not None :
388392 prerelease_parts .append (f"dev.{ self .dev } " )
389393
390- if prerelease_parts :
391- parts .append ("-" )
392- parts .append ("." .join (prerelease_parts ))
393-
394- # Local version segment
395- if self .local :
396- parts .append (f"+{ self .local } " )
397-
398- return "" .join (parts )
394+ return "." .join (prerelease_parts )
399395
400396
401397DEFAULT_SCHEME : VersionScheme = Pep440
0 commit comments