Skip to content

Commit 55d63b0

Browse files
committed
First implementation of #221
* Implement semver.next_version(version, part, *, prerelease_token="rc") * Add test cases * Reformat code with black
1 parent 3f92aa5 commit 55d63b0

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

semver.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,48 @@ def finalize_version(version):
684684
return format_version(verinfo["major"], verinfo["minor"], verinfo["patch"])
685685

686686

687+
def next_version(version, part, *, prerelease_token="rc"):
688+
"""
689+
Determines the next version, takeing prepreleases into account.
690+
691+
The "major", "minor", and "patch" raises the respective parts like
692+
the ``bump_*`` functions. The real difference is using the
693+
"preprelease" part. It gives you the next patch version of the prerelease,
694+
for example:
695+
696+
>>> semver.next_version("0.1.4", "prerelease")
697+
'0.1.5-rc.1'
698+
699+
:param version: a semver version string
700+
:param part: One of "major", "minor", "patch", or "prerelease"
701+
:param prerelease_token: prefix string of prerelease, defaults to 'rc'
702+
:return:
703+
"""
704+
validparts = {
705+
"major",
706+
"minor",
707+
"patch",
708+
"prerelease",
709+
# "build", # ???
710+
}
711+
if part not in validparts:
712+
raise ValueError(
713+
"Invalid part. " f"Expected one of {validparts}, but got {part!r}"
714+
)
715+
version = VersionInfo.parse(version)
716+
if part == "major":
717+
return str(version.bump_major())
718+
elif part == "minor":
719+
return str(version.bump_minor())
720+
elif part == "patch":
721+
return str(version.bump_patch())
722+
elif part == "prerelease":
723+
return str(version.bump_patch().bump_prerelease(token=prerelease_token))
724+
725+
raise RuntimeError(f"Should not happen, got {part}")
726+
727+
728+
# ---- CLI
687729
def cmd_bump(args):
688730
"""
689731
Subcommand: Bumps a version.

test_semver.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
match,
2121
max_ver,
2222
min_ver,
23+
next_version,
2324
parse,
2425
parse_version_info,
2526
process,
@@ -39,6 +40,7 @@
3940
match,
4041
max_ver,
4142
min_ver,
43+
next_version,
4244
parse,
4345
process,
4446
replace,
@@ -827,3 +829,16 @@ def test_replace_raises_ValueError_for_non_numeric_values():
827829
def test_should_versioninfo_isvalid():
828830
assert VersionInfo.isvalid("1.0.0") is True
829831
assert VersionInfo.isvalid("foo") is False
832+
833+
834+
@pytest.mark.parametrize(
835+
"version, part, expected",
836+
[
837+
("1.2.3", "major", "2.0.0"),
838+
("1.3.1", "minor", "1.4.0"),
839+
("1.3.2", "patch", "1.3.3"),
840+
("0.1.4", "prerelease", "0.1.5-rc.1"),
841+
],
842+
)
843+
def test_next_version(version, part, expected):
844+
assert next_version(version, part) == expected

0 commit comments

Comments
 (0)