@@ -422,6 +422,51 @@ def compare(self, other):
422
422
423
423
return rccmp
424
424
425
+ def next_version (self , part , prerelease_token = "rc" ):
426
+ """
427
+ Determines next version, preserving natural order.
428
+
429
+ This function is taking prereleases into account.
430
+ The "major", "minor", and "patch" raises the respective parts like
431
+ the ``bump_*`` functions. The real difference is using the
432
+ "preprelease" part. It gives you the next patch version of the prerelease,
433
+ for example:
434
+
435
+ >>> str(semver.VersionInfo.parse("0.1.4").next_version("prerelease"))
436
+ '0.1.5-rc.1'
437
+
438
+ :param part: One of "major", "minor", "patch", or "prerelease"
439
+ :param prerelease_token: prefix string of prerelease, defaults to 'rc'
440
+ :return:
441
+ """
442
+ validparts = {
443
+ "major" ,
444
+ "minor" ,
445
+ "patch" ,
446
+ "prerelease" ,
447
+ # "build", # currently not used
448
+ }
449
+ if part not in validparts :
450
+ raise ValueError (
451
+ "Invalid part. Expected one of {validparts}, but got {part!r}" .format (
452
+ validparts = validparts , part = part
453
+ )
454
+ )
455
+ version = self
456
+ if (version .prerelease or version .build ) and (
457
+ part == "patch"
458
+ or (part == "minor" and version .patch == 0 )
459
+ or (part == "major" and version .minor == version .patch == 0 )
460
+ ):
461
+ return version .replace (prerelease = None , build = None )
462
+
463
+ if part in ("major" , "minor" , "patch" ):
464
+ return str (getattr (version , "bump_" + part )())
465
+
466
+ if not version .prerelease :
467
+ version = version .bump_patch ()
468
+ return version .bump_prerelease (prerelease_token )
469
+
425
470
@comparator
426
471
def __eq__ (self , other ):
427
472
return self .compare (other ) == 0
@@ -898,6 +943,7 @@ def replace(version, **parts):
898
943
return str (VersionInfo .parse (version ).replace (** parts ))
899
944
900
945
946
+ # ---- CLI
901
947
def cmd_bump (args ):
902
948
"""
903
949
Subcommand: Bumps a version.
@@ -953,6 +999,19 @@ def cmd_compare(args):
953
999
return str (compare (args .version1 , args .version2 ))
954
1000
955
1001
1002
+ def cmd_nextver (args ):
1003
+ """
1004
+ Subcommand: Determines the next version, taking prereleases into account.
1005
+
1006
+ Synopsis: nextver <VERSION> <PART>
1007
+
1008
+ :param args: The parsed arguments
1009
+ :type args: :class:`argparse.Namespace`
1010
+ """
1011
+ version = VersionInfo .parse (args .version )
1012
+ return str (version .next_version (args .part ))
1013
+
1014
+
956
1015
def createparser ():
957
1016
"""
958
1017
Create an :class:`argparse.ArgumentParser` instance.
@@ -995,6 +1054,15 @@ def createparser():
995
1054
parser_check .set_defaults (func = cmd_check )
996
1055
parser_check .add_argument ("version" , help = "Version to check" )
997
1056
1057
+ # Create the nextver subcommand
1058
+ parser_nextver = s .add_parser (
1059
+ "nextver" , help = "Determines the next version, taking prereleases into account."
1060
+ )
1061
+ parser_nextver .set_defaults (func = cmd_nextver )
1062
+ parser_nextver .add_argument ("version" , help = "Version to raise" )
1063
+ parser_nextver .add_argument (
1064
+ "part" , help = "One of 'major', 'minor', 'patch', or 'prerelease'"
1065
+ )
998
1066
return parser
999
1067
1000
1068
0 commit comments