diff --git a/semver.py b/semver.py index 85811fec..f6e5bffc 100644 --- a/semver.py +++ b/semver.py @@ -637,8 +637,8 @@ def match(self, match_expr): return cmp_res in possibilities - @staticmethod - def parse(version): + @classmethod + def parse(cls, version): """ Parse version string to a VersionInfo instance. @@ -651,7 +651,7 @@ def parse(version): VersionInfo(major=3, minor=4, patch=5, \ prerelease='pre.2', build='build.4') """ - match = VersionInfo._REGEX.match(version) + match = cls._REGEX.match(version) if match is None: raise ValueError("%s is not valid SemVer string" % version) @@ -661,7 +661,7 @@ def parse(version): version_parts["minor"] = int(version_parts["minor"]) version_parts["patch"] = int(version_parts["patch"]) - return VersionInfo(**version_parts) + return cls(**version_parts) def replace(self, **parts): """ diff --git a/test_semver.py b/test_semver.py index b23576d5..0aeedbdb 100644 --- a/test_semver.py +++ b/test_semver.py @@ -1128,3 +1128,21 @@ def test_next_version_with_versioninfo(version, part, expected): ) def test_repr(version, expected): assert repr(version) == expected + + +def test_subclass_from_versioninfo(): + class SemVerWithVPrefix(VersionInfo): + @classmethod + def parse(cls, version): + if not version.startswith("v"): + raise ValueError( + "{v}: not a valid semantic version tag".format(v=version) + ) + return super(SemVerWithVPrefix, cls).parse(version[1:]) + + def __str__(self): + # Reconstruct the tag. + return "v" + super(SemVerWithVPrefix, self).__str__() + + v = SemVerWithVPrefix.parse("v1.2.3") + assert str(v) == "v1.2.3"