5.2. Creating Subclasses from Version

If you do not like creating functions to modify the behavior of semver (as shown in section Dealing with Invalid Versions), you can also create a subclass of the Version class.

For example, if you want to output a “v” prefix before a version, but the other behavior is the same, use the following code:

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__()

The derived class SemVerWithVPrefix can be used like the original class. Additionally, you can pass “incomplete” version strings like v2.3:

>>> v1 = SemVerWithVPrefix.parse("v1.2.3")
>>> assert str(v1) == "v1.2.3"
>>> print(v1)
v1.2.3
>>> v2 = SemVerWithVPrefix.parse("v2.3")
>>> v2 > v1
True
>>> bad = SemVerWithVPrefix.parse("1.2.4")
Traceback (most recent call last):
...
ValueError: '1.2.4': not a valid semantic version tag. Must start with 'v' or 'V'