Skip to content

Commit 232d8e8

Browse files
committed
Fix #426: call subclass when deriving from Version
When using the replace method, an instance of the Version class is created and not the respective subclass.
1 parent 757ada6 commit 232d8e8

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

changelog.d/426.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`~semver.version.Version.replace` method to use the derived class
2+
of an instance instead of :class:`~semver.version.Version` class.

src/semver/version.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,8 @@ def parse(
655655

656656
def replace(self, **parts: Union[int, Optional[str]]) -> "Version":
657657
"""
658-
Replace one or more parts of a version and return a new
659-
:class:`Version` object, but leave self untouched
658+
Replace one or more parts of a version and return a new :class:`Version`
659+
object, but leave self untouched.
660660
661661
.. versionadded:: 2.9.0
662662
Added :func:`Version.replace`
@@ -670,7 +670,7 @@ def replace(self, **parts: Union[int, Optional[str]]) -> "Version":
670670
version = self.to_dict()
671671
version.update(parts)
672672
try:
673-
return Version(**version) # type: ignore
673+
return type(self)(**version) # type: ignore
674674
except TypeError:
675675
unknownkeys = set(parts) - set(self.to_dict())
676676
error = "replace() got %d unexpected keyword argument(s): %s" % (

tests/test_subclass.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,37 @@ def __str__(self):
1717

1818
v = SemVerWithVPrefix.parse("v1.2.3")
1919
assert str(v) == "v1.2.3"
20+
21+
22+
def test_replace_from_subclass():
23+
# Issue#426
24+
# Taken from the example "Creating Subclasses from Version"
25+
class SemVerWithVPrefix(Version):
26+
"""
27+
A subclass of Version which allows a "v" prefix
28+
"""
29+
30+
@classmethod
31+
def parse(cls, version: str) -> "SemVerWithVPrefix":
32+
"""
33+
Parse version string to a Version instance.
34+
35+
:param version: version string with "v" or "V" prefix
36+
:raises ValueError: when version does not start with "v" or "V"
37+
:return: a new instance
38+
"""
39+
if not version[0] in ("v", "V"):
40+
raise ValueError(
41+
f"{version!r}: not a valid semantic version tag. "
42+
"Must start with 'v' or 'V'"
43+
)
44+
return super().parse(version[1:], optional_minor_and_patch=True)
45+
46+
def __str__(self) -> str:
47+
# Reconstruct the tag
48+
return "v" + super().__str__()
49+
50+
version = SemVerWithVPrefix.parse("v1.1.0")
51+
dev_version = version.replace(prerelease="dev.0")
52+
53+
assert str(dev_version) == "v1.1.0-dev.0"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy