From b25aa07740a456f9e3d988489fe5579dd93f6af2 Mon Sep 17 00:00:00 2001 From: Tom Schraitle Date: Sun, 18 Oct 2020 19:25:00 +0200 Subject: [PATCH] Fix #291: Disallow negative numbers in VersionInfo Disallow negative numbers in major, minor, and patch in semver.VersionInfo. Reason: a version can only contain positive numbers --- CHANGELOG.rst | 30 ++++++++++++++++++++++++++++++ docs/usage.rst | 8 ++++++++ semver.py | 21 ++++++++++++++++++--- test_semver.py | 14 ++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 46a94ee3..2fdfa8dd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,36 @@ Change Log All notable changes to this code base will be documented in this file, in every released version. +Version 2.12.0 +============== + +:Released: +:Maintainer: Tom Schraitle + +Features +-------- + +n/a + + +Bug Fixes +--------- + +* :gh:`291` (:pr:`292`): Disallow negative numbers of + major, minor, and patch for ``semver.VersionInfo`` + + +Additions +--------- + +n/a + + +Deprecations +------------ + +n/a + Version 2.11.0 ============== diff --git a/docs/usage.rst b/docs/usage.rst index 010f1c0b..05d45082 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -63,6 +63,14 @@ A :class:`semver.VersionInfo` instance can be created in different ways: >>> semver.VersionInfo(**d) VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + Keep in mind, the ``major``, ``minor``, ``patch`` parts has to + be positive. + + >>> semver.VersionInfo(-1) + Traceback (most recent call last): + ... + ValueError: 'major' is negative. A version can only be positive. + As a minimum requirement, your dictionary needs at least the ``major`` key, others can be omitted. You get a ``TypeError`` if your dictionary contains invalid keys. diff --git a/semver.py b/semver.py index 1e15a08d..bd298824 100644 --- a/semver.py +++ b/semver.py @@ -243,9 +243,24 @@ class VersionInfo(object): ) def __init__(self, major, minor=0, patch=0, prerelease=None, build=None): - self._major = int(major) - self._minor = int(minor) - self._patch = int(patch) + # Build a dictionary of the arguments except prerelease and build + version_parts = { + "major": major, + "minor": minor, + "patch": patch, + } + + for name, value in version_parts.items(): + value = int(value) + version_parts[name] = value + if value < 0: + raise ValueError( + "{!r} is negative. A version can only be positive.".format(name) + ) + + self._major = version_parts["major"] + self._minor = version_parts["minor"] + self._patch = version_parts["patch"] self._prerelease = None if prerelease is None else str(prerelease) self._build = None if build is None else str(build) diff --git a/test_semver.py b/test_semver.py index 0aeedbdb..36379821 100644 --- a/test_semver.py +++ b/test_semver.py @@ -73,6 +73,20 @@ def test_fordocstrings(func): assert func.__doc__, "Need a docstring for function %r" % func.__name +@pytest.mark.parametrize( + "ver", + [ + {"major": -1}, + {"major": 1, "minor": -2}, + {"major": 1, "minor": 2, "patch": -3}, + {"major": 1, "minor": -2, "patch": 3}, + ], +) +def test_should_not_allow_negative_numbers(ver): + with pytest.raises(ValueError, match=".* is negative. .*"): + VersionInfo(**ver) + + @pytest.mark.parametrize( "version,expected", [