Skip to content

Commit dee4dff

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

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

semver.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,43 @@ 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 = {"major", "minor", "patch", "prerelease",
705+
# "build", # ???
706+
}
707+
if part not in validparts:
708+
raise ValueError("Invalid part. "
709+
f"Expected one of {validparts}, but got {part!r}")
710+
version = VersionInfo.parse(version)
711+
if part == "major":
712+
return str(version.bump_major())
713+
elif part == "minor":
714+
return str(version.bump_minor())
715+
elif part == "patch":
716+
return str(version.bump_patch())
717+
elif part == "prerelease":
718+
return str(version.bump_patch().bump_prerelease(token=prerelease_token))
719+
720+
raise RuntimeError(f"Should not happen, got {part}")
721+
722+
723+
# ---- CLI
687724
def cmd_bump(args):
688725
"""
689726
Subcommand: Bumps a version.

test_semver.py

Lines changed: 14 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,15 @@ 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+
@pytest.mark.parametrize(
834+
"version, part, expected",
835+
[
836+
("1.2.3", "major", "2.0.0"),
837+
("1.3.1", "minor", "1.4.0"),
838+
("1.3.2", "patch", "1.3.3"),
839+
("0.1.4", "prerelease", "0.1.5-rc.1"),
840+
]
841+
)
842+
def test_next_version(version, part, expected):
843+
assert next_version(version, part) == expected

0 commit comments

Comments
 (0)