Skip to content

Rethinking __init__ of VersionInfo class? #303

Open
@tomschr

Description

@tomschr

Situation

Originally posted by @tomschr in #258 (comment)

From the above discussion, I thought it would be worth to decouple the compare discussion from the initializer discussion. Both are somewhat related, but can live independently.

With a more "advanced" initializer/constructor we get the following benefits:

  • more "pythonic": it's one, obvious way to get an instance.
  • avoids the longer function call Version.parse(...).
  • more readable

With such an (overloaded?) initializer, we could cover the following use cases:

>>> from semver import Version
>>> Version(1)
Version(major=1, minor=0, patch=0, prerelease=None, build=None)
>>> Version(1, "4", b"5")
Version(major=1, minor=4, patch=5, prerelease=None, build=None)
>>> Version(1, patch=2)
Version(major=1, minor=0, patch=2, prerelease=None, build=None)
>>> Version("1.2.3")
Version(major=1, minor=2, patch=3, prerelease=None, build=None)
>>> Version(b"1.2.3")
Version(major=1, minor=2, patch=3, prerelease=None, build=None)
>>> v = Version(b"2.3.4")
>>> Version(v)
Version(major=2, minor=3, patch=4, prerelease=None, build=None)
>>> t = (1, 2, 3)
>>> Version(*t)                                             
Version(major=1, minor=2, patch=3, prerelease=None, build=None)
>>> d = {'major': 3, 'minor': 4, 'patch': 5,  'prerelease': 'pre.2', 'build': 'build.4'}
>>> Version(**d)
Version(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')

Discussions and Possible Solutions

To implement a somewhat more advanced constructor/initializer, we have these options:

  1. Program it manually with isinstance and if...else constructs
  2. Use the typing.overload function (suggested by @tlaferriere)
  3. Use functools.singledispatch

However, all three comes at a cost or an issue:

  1. Maybe not impossible, but the code would look probably ugly.
  2. "The @overload decorator is purely for type hints, you can only specify one function body and it has to distinguish the different types using isinstance.` (Originally posted by @tlaferriere in Consider keeping compare module level function #258 (comment))
  3. Is not possible with an __init__ method. The singledispatch works only for functions(!), not methods. For methods we would need functools.singledispatchmethod which is only available from Python >= 3.8.

Another idea goes into a completely different direction. Maybe we shouldn't change the Version class much, but offer a much shorter variant: semver.v.

from functools import singledispatch

# ...
@singledispatch
def ver(major, minor=0, patch=0, prerelease=None, build=None) -> "Version":
    return Version(major, minor, patch, prerelease, build)
    
@ver.register(bytes)
@ver.register(str)
def _(ver: str) -> "Version":
    if isinstance(ver, bytes):
       ver = str(ver, "utf-8")
    if "." in ver:
        return Version.parse(ver)
    return Version(int(ver))

@ver.register(Version)
def _(ver: "Version") -> "Version":
    return ver

Which means, we could just use semver.v as a much shorter variant:

>>> import semver
>>> semver.v("1.2.3")
Version(major=1, minor=2, patch=3, prerelease=None, build=None)

One drawback could be that v is quite short. Maybe too short? Especially if you import it with from semver import v it could be easily overwritten by other, local variables.
That could be a bit avoided to use capital V or ver. Or we use the much longer name semver.version.

Thoughts? Any other ideas? Would that be worth the effort?

@tlaferriere @gsakkis @ppkt

Metadata

Metadata

Assignees

No one assigned

    Labels

    DesignIdeas, suggestions, musings about design questionsEnhancementNot a bug, but increases or improves in value, quality, desirability, or attractivenessQuestionUnclear or open issue subject for debateRelease_3.x.yOnly for the major release 3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      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