Skip to content

Commit edf0a58

Browse files
committed
Implemented the namedtuple interface in Version
1 parent 7a4ba5f commit edf0a58

File tree

2 files changed

+86
-16
lines changed

2 files changed

+86
-16
lines changed

doc-source/api/versions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
.. automodule:: domdf_python_tools.versions
66
:undoc-members:
77
:special-members:
8+
:private-members:

domdf_python_tools/versions.py

Lines changed: 85 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,50 +25,77 @@
2525

2626
# stdlib
2727
import re
28-
from typing import Generator, Sequence, Tuple, Union
28+
from typing import Dict, Generator, Iterable, Sequence, Tuple, Union
29+
30+
# 3rd party
31+
from typing_extensions import final
2932

3033
__all__ = ["Version"]
3134

3235

36+
@final
3337
class Version(Tuple[int, int, int]):
3438
"""
3539
NamedTuple-like class to represent a version number.
3640
37-
:param major: The major version number.
38-
:type major: :class:`int`
39-
:param minor: The minor version number.
40-
:type minor: :class:`int`
41-
:param patch: The patch version number.
42-
:type patch: :class:`int`
41+
:param major:
4342
4443
.. versionadded:: 0.4.4
44+
45+
.. versionchanged:: 1.4.0 Implemented the same interface as a :func:`collections.namedtuple`.
4546
"""
4647

48+
__slots__ = ()
49+
50+
#: The major version number.
4751
major: int
48-
"The major version number."
4952

53+
#: The minor version number.
5054
minor: int
51-
"The minor version number."
5255

56+
#: The patch version number.
5357
patch: int
54-
"The patch number."
58+
59+
_fields: Tuple[str, str, str] = ("major", "minor", "patch")
60+
"""
61+
Tuple of strings listing the field names.
62+
63+
Useful for introspection and for creating new named tuple types from existing named tuples.
64+
65+
.. versionadded:: 1.4.0
66+
"""
67+
68+
_field_defaults: Dict[str, int] = {"major": 0, "minor": 0, "patch": 0}
69+
"""
70+
Dictionary mapping field names to default values.
71+
72+
.. versionadded:: 1.4.0
73+
"""
74+
75+
@property # type: ignore
76+
def major(self):
77+
return self[0]
78+
79+
@property # type: ignore
80+
def minor(self):
81+
return self[1]
82+
83+
@property # type: ignore
84+
def patch(self):
85+
return self[2]
5586

5687
def __new__(cls, major=0, minor=0, patch=0) -> "Version":
5788
t: "Version" = super().__new__(cls, (int(major), int(minor), int(patch))) # type: ignore
5889

59-
t.__dict__["major"] = int(major)
60-
t.__dict__["minor"] = int(minor)
61-
t.__dict__["patch"] = int(patch)
62-
6390
return t
6491

6592
def __repr__(self) -> str:
6693
"""
6794
Return the representation of the version.
6895
"""
6996

70-
field_names = self.__annotations__.keys()
71-
repr_fmt = '(' + ", ".join(f"{name}=%r" for name in field_names) + ')'
97+
repr_fmt = '(' + ", ".join(f"{name}=%r" for name in self._fields) + ')'
98+
print(repr_fmt)
7299
return self.__class__.__name__ + repr_fmt % self
73100

74101
def __str__(self) -> str:
@@ -211,6 +238,48 @@ def from_float(cls, version_float: float) -> "Version":
211238

212239
return cls.from_str(str(version_float))
213240

241+
def _asdict(self) -> Dict[str, int]:
242+
"""
243+
Return a new dict which maps field names to their corresponding values.
244+
245+
:rtype:
246+
247+
.. versionadded:: 1.4.0
248+
"""
249+
250+
return {
251+
"major": self.major,
252+
"minor": self.minor,
253+
"patch": self.patch,
254+
}
255+
256+
def _replace(self, **kwargs) -> "Version":
257+
"""
258+
Return a new instance of the named tuple replacing specified fields with new values:
259+
260+
:param kwargs:
261+
262+
:rtype:
263+
264+
.. versionadded:: 1.4.0
265+
"""
266+
267+
return self.__class__(**{**self._asdict(), **kwargs})
268+
269+
@classmethod
270+
def _make(cls, iterable: Iterable[Union[str, int]]) -> "Version":
271+
"""
272+
Class method that makes a new instance from an existing sequence or iterable.
273+
274+
:param iterable:
275+
276+
:rtype:
277+
278+
.. versionadded:: 1.4.0
279+
"""
280+
281+
return cls(*(int(x) for x in tuple(iterable)[:3]))
282+
214283

215284
def _iter_string(version_string: str) -> Generator[int, None, None]:
216285
"""

0 commit comments

Comments
 (0)