From 4b03f867a3deaecb07240f471fed9bf9c9072629 Mon Sep 17 00:00:00 2001 From: Tom Schraitle Date: Thu, 28 Sep 2023 14:31:42 +0200 Subject: [PATCH 1/2] 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. Co-authored-by: Danny Staple --- changelog.d/426.bugfix.rst | 2 ++ src/semver/version.py | 6 +++--- tests/test_subclass.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelog.d/426.bugfix.rst diff --git a/changelog.d/426.bugfix.rst b/changelog.d/426.bugfix.rst new file mode 100644 index 00000000..2c2d0eac --- /dev/null +++ b/changelog.d/426.bugfix.rst @@ -0,0 +1,2 @@ +Fix :meth:`~semver.version.Version.replace` method to use the derived class +of an instance instead of :class:`~semver.version.Version` class. diff --git a/src/semver/version.py b/src/semver/version.py index 9a7a4ffc..29309ab4 100644 --- a/src/semver/version.py +++ b/src/semver/version.py @@ -655,8 +655,8 @@ def parse( def replace(self, **parts: Union[int, Optional[str]]) -> "Version": """ - Replace one or more parts of a version and return a new - :class:`Version` object, but leave self untouched + Replace one or more parts of a version and return a new :class:`Version` + object, but leave self untouched. .. versionadded:: 2.9.0 Added :func:`Version.replace` @@ -670,7 +670,7 @@ def replace(self, **parts: Union[int, Optional[str]]) -> "Version": version = self.to_dict() version.update(parts) try: - return Version(**version) # type: ignore + return type(self)(**version) # type: ignore except TypeError: unknownkeys = set(parts) - set(self.to_dict()) error = "replace() got %d unexpected keyword argument(s): %s" % ( diff --git a/tests/test_subclass.py b/tests/test_subclass.py index cbf9d271..b33f4969 100644 --- a/tests/test_subclass.py +++ b/tests/test_subclass.py @@ -17,3 +17,37 @@ def __str__(self): v = SemVerWithVPrefix.parse("v1.2.3") assert str(v) == "v1.2.3" + + +def test_replace_from_subclass(): + # Issue#426 + # Taken from the example "Creating Subclasses from Version" + class SemVerWithVPrefix(Version): + """ + A subclass of Version which allows a "v" prefix + """ + + @classmethod + def parse(cls, version: str) -> "SemVerWithVPrefix": + """ + Parse version string to a Version instance. + + :param version: version string with "v" or "V" prefix + :raises ValueError: when version does not start with "v" or "V" + :return: a new instance + """ + if not version[0] in ("v", "V"): + raise ValueError( + f"{version!r}: not a valid semantic version tag. " + "Must start with 'v' or 'V'" + ) + return super().parse(version[1:], optional_minor_and_patch=True) + + def __str__(self) -> str: + # Reconstruct the tag + return "v" + super().__str__() + + version = SemVerWithVPrefix.parse("v1.1.0") + dev_version = version.replace(prerelease="dev.0") + + assert str(dev_version) == "v1.1.0-dev.0" From 2dda51c0b3d0956187533210927533af50bf6175 Mon Sep 17 00:00:00 2001 From: Tom Schraitle Date: Fri, 29 Sep 2023 14:34:57 +0200 Subject: [PATCH 2/2] GHA: Require setuptool>60 and setuptools-scm>60 --- .github/workflows/python-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-testing.yml b/.github/workflows/python-testing.yml index f6decc03..adb06d4a 100644 --- a/.github/workflows/python-testing.yml +++ b/.github/workflows/python-testing.yml @@ -60,7 +60,7 @@ jobs: cache: 'pip' - name: Install dependencies run: | - python3 -m pip install --upgrade pip setuptools setuptools-scm + python3 -m pip install --upgrade pip setuptools>60 setuptools-scm>=60 pip install tox tox-gh-actions - name: Check run: | 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