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
@@ -265,39 +267,35 @@ def bump(
265267 if self .local and is_local_version :
266268 local_version = self .scheme (self .local ).bump (increment )
267269 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
270+
271+ base = self ._get_increment_base (increment , exact_increment )
272+ dev_version = self .generate_devrelease (devrelease )
273+
274+ release = list (self .release )
275+ if len (release ) < 3 :
276+ release += [0 ] * (3 - len (release ))
277+ current_base = "." .join (str (part ) for part in release )
278+
279+ pre_version = (
280+ self if base == current_base else cast (BaseVersion , self .scheme (base ))
281+ ).generate_prerelease (prerelease , offset = prerelease_offset )
282+
283+ # TODO: post version
284+ return self .scheme (
285+ f"{ base } { pre_version } { dev_version } { self .generate_build_metadata (build_metadata )} "
286+ ) # type: ignore
287+
288+ def _get_increment_base (
289+ self , increment : Increment | None , exact_increment : bool
290+ ) -> str :
291+ if (
292+ not self .is_prerelease
293+ or exact_increment
294+ or (increment == MINOR and self .micro != 0 )
295+ or (increment == MAJOR and (self .minor != 0 or self .micro != 0 ))
296+ ):
297+ return self .increment_base (increment )
298+ return f"{ self .major } .{ self .minor } .{ self .micro } "
301299
302300
303301class Pep440 (BaseVersion ):
@@ -316,7 +314,7 @@ class SemVer(BaseVersion):
316314 """
317315
318316 def __str__ (self ) -> str :
319- parts = []
317+ parts : list [ str ] = []
320318
321319 # Epoch
322320 if self .epoch != 0 :
@@ -364,7 +362,7 @@ def prerelease(self) -> str | None:
364362 return None
365363
366364 def __str__ (self ) -> str :
367- parts = []
365+ parts : list [ str ] = []
368366
369367 # Epoch
370368 if self .epoch != 0 :
@@ -373,9 +371,19 @@ def __str__(self) -> str:
373371 # Release segment
374372 parts .append ("." .join (str (x ) for x in self .release ))
375373
374+ if prerelease := self ._get_prerelease ():
375+ parts .append (f"-{ prerelease } " )
376+
377+ # Local version segment
378+ if self .local :
379+ parts .append (f"+{ self .local } " )
380+
381+ return "" .join (parts )
382+
383+ def _get_prerelease (self ) -> str :
376384 # Pre-release identifiers
377385 # See: https://semver.org/spec/v2.0.0.html#spec-item-9
378- prerelease_parts = []
386+ prerelease_parts : list [ str ] = []
379387 if self .prerelease :
380388 prerelease_parts .append (f"{ self .prerelease } " )
381389
@@ -387,15 +395,7 @@ def __str__(self) -> str:
387395 if self .dev is not None :
388396 prerelease_parts .append (f"dev.{ self .dev } " )
389397
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 )
398+ return "." .join (prerelease_parts )
399399
400400
401401DEFAULT_SCHEME : VersionScheme = Pep440
0 commit comments