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