Skip to content

Commit f8a182f

Browse files
committed
Fix #344 Allow empty string for bump methods
The methods .bump_prerelease() and .bump_build() allow now different types for the token argument: * A string. This was already allowed and default was "rc". If the string is empty, we get only the raised number (without the "rc" part). The number starts from 1. * None. Is the same as calling the method without any argument.
1 parent bee273e commit f8a182f

File tree

5 files changed

+116
-11
lines changed

5 files changed

+116
-11
lines changed

changelog.d/344.bugfix.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Allow empty string, a string with a prefix, or ``None``
2+
as token in
3+
:meth:`Version.bump_build <semver.Version.bump_build>` and
4+
:meth:`Version.bump_prerelease <semver.Version.bump_prerelease>`.
5+

docs/usage/increase-parts-of-a-version_prereleases.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.. _increase-parts-of-a-version:
12
Increasing Parts of a Version Taking into Account Prereleases
23
=============================================================
34

docs/usage/raise-parts-of-a-version.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
Raising Parts of a Version
22
==========================
33

4+
.. note::
5+
6+
Keep in mind, "raising" the pre-release only will make your
7+
complete version *lower* than before.
8+
9+
For example, having version ``1.0.0`` and raising the pre-release
10+
will lead to ``1.0.0-rc.1``, but ``1.0.0-rc.1`` is smaller than ``1.0.0``.
11+
12+
If you search for a way to take into account this behavior, look for the
13+
method :meth:`Version.next_version <semver.version.Version.next_version>`
14+
in section :ref:`increase-parts-of-a-version`.
15+
16+
417
The ``semver`` module contains the following functions to raise parts of
518
a version:
619

@@ -14,6 +27,7 @@ a version:
1427
``build`` to ``None``.
1528
* :func:`Version.bump_build <semver.version.Version.bump_build>`: raises the build part.
1629

30+
1731
.. code-block:: python
1832
1933
>>> str(Version.parse("3.4.5-pre.2+build.4").bump_major())
@@ -28,3 +42,29 @@ a version:
2842
'3.4.5-pre.2+build.5'
2943
3044
Likewise the module level functions :func:`semver.bump_major`.
45+
46+
For the methods :meth:`Version.bump_prerelease <semver.version.Version.bump_prerelease>`
47+
and :meth:`Version.bump_build <semver.version.Version.bump_build>` it's possible to pass an empty string or ``None``.
48+
However, it gives different results::
49+
50+
.. code-block:: python
51+
52+
>>> str(Version.parse("3.4.5").bump_prerelease(''))
53+
'3.4.5-1'
54+
>>> str(Version.parse("3.4.5").bump_prerelease(None))
55+
'3.4.5-rc.1'
56+
57+
An empty string removes any prefix whereas ``None`` is the same as calling
58+
the method without any argument.
59+
60+
If you already have a prerelease, the argument for the method
61+
is not taken into account:
62+
63+
.. code-block:: python
64+
65+
>>> str(Version.parse("3.4.5-rc.1").bump_prerelease(None))
66+
'3.4.5-rc.2'
67+
>>> str(Version.parse("3.4.5-rc.1").bump_prerelease(''))
68+
'3.4.5-rc.2'
69+
70+

src/semver/version.py

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -305,38 +305,73 @@ def bump_patch(self) -> "Version":
305305
cls = type(self)
306306
return cls(self._major, self._minor, self._patch + 1)
307307

308-
def bump_prerelease(self, token: str = "rc") -> "Version":
308+
def bump_prerelease(self, token: Optional[str] = "rc") -> "Version":
309309
"""
310310
Raise the prerelease part of the version, return a new object but leave
311311
self untouched.
312312
313-
:param token: defaults to ``rc``
314-
:return: new object with the raised prerelease part
313+
:param token: defaults to ``'rc'``
314+
:return: new :class:`Version` object with the raised prerelease part.
315+
The original object is not modified.
315316
316317
>>> ver = semver.parse("3.4.5")
317-
>>> ver.bump_prerelease()
318-
Version(major=3, minor=4, patch=5, prerelease='rc.2', \
319-
build=None)
318+
>>> ver.bump_prerelease().prerelease
319+
'rc.2'
320+
>>> ver.bump_prerelease('').prerelease
321+
'1'
322+
>>> ver.bump_prerelease(None).prerelease
323+
'rc.1'
320324
"""
321325
cls = type(self)
322-
prerelease = cls._increment_string(self._prerelease or (token or "rc") + ".0")
326+
if self._prerelease is not None:
327+
prerelease = self._prerelease
328+
elif token == "":
329+
prerelease = "0"
330+
elif token is None:
331+
prerelease = "rc.0"
332+
else:
333+
prerelease = str(token) + ".0"
334+
335+
prerelease = cls._increment_string(prerelease)
323336
return cls(self._major, self._minor, self._patch, prerelease)
324337

325-
def bump_build(self, token: str = "build") -> "Version":
338+
def bump_build(self, token: Optional[str] = "build") -> "Version":
326339
"""
327340
Raise the build part of the version, return a new object but leave self
328341
untouched.
329342
330-
:param token: defaults to ``build``
331-
:return: new object with the raised build part
343+
:param token: defaults to ``'build'``
344+
:return: new :class:`Version` object with the raised build part.
345+
The original object is not modified.
332346
333347
>>> ver = semver.parse("3.4.5-rc.1+build.9")
334348
>>> ver.bump_build()
335349
Version(major=3, minor=4, patch=5, prerelease='rc.1', \
336350
build='build.10')
337351
"""
338352
cls = type(self)
339-
build = cls._increment_string(self._build or (token or "build") + ".0")
353+
if self._build is not None:
354+
build = self._build
355+
elif token == "":
356+
build = "0"
357+
elif token is None:
358+
build = "build.0"
359+
else:
360+
build = str(token) + ".0"
361+
362+
# self._build or (token or "build") + ".0"
363+
build = cls._increment_string(build)
364+
if self._build is not None:
365+
build = self._build
366+
elif token == "":
367+
build = "0"
368+
elif token is None:
369+
build = "build.0"
370+
else:
371+
build = str(token) + ".0"
372+
373+
# self._build or (token or "build") + ".0"
374+
build = cls._increment_string(build)
340375
return cls(self._major, self._minor, self._patch, self._prerelease, build)
341376

342377
def compare(self, other: Comparable) -> int:

tests/test_bump.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,30 @@ def test_should_versioninfo_bump_multiple():
6666
assert v.bump_prerelease().bump_build().bump_build().bump_prerelease() == expected
6767

6868

69+
def test_should_versioninfo_bump_prerelease_with_empty_str():
70+
v = parse_version_info("3.4.5")
71+
expected = parse_version_info("3.4.5-1")
72+
assert v.bump_prerelease("") == expected
73+
74+
75+
def test_should_versioninfo_bump_prerelease_with_none():
76+
v = parse_version_info("3.4.5")
77+
expected = parse_version_info("3.4.5-rc.1")
78+
assert v.bump_prerelease(None) == expected
79+
80+
81+
def test_should_versioninfo_bump_build_with_empty_str():
82+
v = parse_version_info("3.4.5")
83+
expected = parse_version_info("3.4.5+1")
84+
assert v.bump_build("") == expected
85+
86+
87+
def test_should_versioninfo_bump_build_with_none():
88+
v = parse_version_info("3.4.5")
89+
expected = parse_version_info("3.4.5+build.1")
90+
assert v.bump_build(None) == expected
91+
92+
6993
def test_should_ignore_extensions_for_bump():
7094
assert bump_patch("3.4.5-rc1+build4") == "3.4.6"
7195

0 commit comments

Comments
 (0)