diff --git a/changelog.d/344.bugfix.rst b/changelog.d/344.bugfix.rst new file mode 100644 index 00000000..9daa9e73 --- /dev/null +++ b/changelog.d/344.bugfix.rst @@ -0,0 +1,5 @@ +Allow empty string, a string with a prefix, or ``None`` +as token in +:meth:`Version.bump_build ` and +:meth:`Version.bump_prerelease `. + diff --git a/docs/usage/increase-parts-of-a-version_prereleases.rst b/docs/usage/increase-parts-of-a-version_prereleases.rst index 98283937..87685b76 100644 --- a/docs/usage/increase-parts-of-a-version_prereleases.rst +++ b/docs/usage/increase-parts-of-a-version_prereleases.rst @@ -1,3 +1,4 @@ +.. _increase-parts-of-a-version: Increasing Parts of a Version Taking into Account Prereleases ============================================================= diff --git a/docs/usage/raise-parts-of-a-version.rst b/docs/usage/raise-parts-of-a-version.rst index cc62fffb..d369c575 100644 --- a/docs/usage/raise-parts-of-a-version.rst +++ b/docs/usage/raise-parts-of-a-version.rst @@ -1,6 +1,19 @@ Raising Parts of a Version ========================== +.. note:: + + Keep in mind, "raising" the pre-release only will make your + complete version *lower* than before. + + For example, having version ``1.0.0`` and raising the pre-release + will lead to ``1.0.0-rc.1``, but ``1.0.0-rc.1`` is smaller than ``1.0.0``. + + If you search for a way to take into account this behavior, look for the + method :meth:`Version.next_version ` + in section :ref:`increase-parts-of-a-version`. + + The ``semver`` module contains the following functions to raise parts of a version: @@ -14,6 +27,7 @@ a version: ``build`` to ``None``. * :func:`Version.bump_build `: raises the build part. + .. code-block:: python >>> str(Version.parse("3.4.5-pre.2+build.4").bump_major()) @@ -28,3 +42,29 @@ a version: '3.4.5-pre.2+build.5' Likewise the module level functions :func:`semver.bump_major`. + +For the methods :meth:`Version.bump_prerelease ` +and :meth:`Version.bump_build ` it's possible to pass an empty string or ``None``. +However, it gives different results:: + +.. code-block:: python + + >>> str(Version.parse("3.4.5").bump_prerelease('')) + '3.4.5-1' + >>> str(Version.parse("3.4.5").bump_prerelease(None)) + '3.4.5-rc.1' + +An empty string removes any prefix whereas ``None`` is the same as calling +the method without any argument. + +If you already have a prerelease, the argument for the method +is not taken into account: + +.. code-block:: python + + >>> str(Version.parse("3.4.5-rc.1").bump_prerelease(None)) + '3.4.5-rc.2' + >>> str(Version.parse("3.4.5-rc.1").bump_prerelease('')) + '3.4.5-rc.2' + + diff --git a/src/semver/version.py b/src/semver/version.py index bf949bb4..bfce8101 100644 --- a/src/semver/version.py +++ b/src/semver/version.py @@ -305,30 +305,44 @@ def bump_patch(self) -> "Version": cls = type(self) return cls(self._major, self._minor, self._patch + 1) - def bump_prerelease(self, token: str = "rc") -> "Version": + def bump_prerelease(self, token: Optional[str] = "rc") -> "Version": """ Raise the prerelease part of the version, return a new object but leave self untouched. - :param token: defaults to ``rc`` - :return: new object with the raised prerelease part + :param token: defaults to ``'rc'`` + :return: new :class:`Version` object with the raised prerelease part. + The original object is not modified. >>> ver = semver.parse("3.4.5") - >>> ver.bump_prerelease() - Version(major=3, minor=4, patch=5, prerelease='rc.2', \ -build=None) + >>> ver.bump_prerelease().prerelease + 'rc.2' + >>> ver.bump_prerelease('').prerelease + '1' + >>> ver.bump_prerelease(None).prerelease + 'rc.1' """ cls = type(self) - prerelease = cls._increment_string(self._prerelease or (token or "rc") + ".0") + if self._prerelease is not None: + prerelease = self._prerelease + elif token == "": + prerelease = "0" + elif token is None: + prerelease = "rc.0" + else: + prerelease = str(token) + ".0" + + prerelease = cls._increment_string(prerelease) return cls(self._major, self._minor, self._patch, prerelease) - def bump_build(self, token: str = "build") -> "Version": + def bump_build(self, token: Optional[str] = "build") -> "Version": """ Raise the build part of the version, return a new object but leave self untouched. - :param token: defaults to ``build`` - :return: new object with the raised build part + :param token: defaults to ``'build'`` + :return: new :class:`Version` object with the raised build part. + The original object is not modified. >>> ver = semver.parse("3.4.5-rc.1+build.9") >>> ver.bump_build() @@ -336,7 +350,28 @@ def bump_build(self, token: str = "build") -> "Version": build='build.10') """ cls = type(self) - build = cls._increment_string(self._build or (token or "build") + ".0") + if self._build is not None: + build = self._build + elif token == "": + build = "0" + elif token is None: + build = "build.0" + else: + build = str(token) + ".0" + + # self._build or (token or "build") + ".0" + build = cls._increment_string(build) + if self._build is not None: + build = self._build + elif token == "": + build = "0" + elif token is None: + build = "build.0" + else: + build = str(token) + ".0" + + # self._build or (token or "build") + ".0" + build = cls._increment_string(build) return cls(self._major, self._minor, self._patch, self._prerelease, build) def compare(self, other: Comparable) -> int: diff --git a/tests/test_bump.py b/tests/test_bump.py index c28e1905..34e0b2ac 100644 --- a/tests/test_bump.py +++ b/tests/test_bump.py @@ -66,6 +66,30 @@ def test_should_versioninfo_bump_multiple(): assert v.bump_prerelease().bump_build().bump_build().bump_prerelease() == expected +def test_should_versioninfo_bump_prerelease_with_empty_str(): + v = parse_version_info("3.4.5") + expected = parse_version_info("3.4.5-1") + assert v.bump_prerelease("") == expected + + +def test_should_versioninfo_bump_prerelease_with_none(): + v = parse_version_info("3.4.5") + expected = parse_version_info("3.4.5-rc.1") + assert v.bump_prerelease(None) == expected + + +def test_should_versioninfo_bump_build_with_empty_str(): + v = parse_version_info("3.4.5") + expected = parse_version_info("3.4.5+1") + assert v.bump_build("") == expected + + +def test_should_versioninfo_bump_build_with_none(): + v = parse_version_info("3.4.5") + expected = parse_version_info("3.4.5+build.1") + assert v.bump_build(None) == expected + + def test_should_ignore_extensions_for_bump(): assert bump_patch("3.4.5-rc1+build4") == "3.4.6"