1# SPDX-License-Identifier: MIT

2

3

4 from functools import total_ordering

5

6 from ._funcs import astuple

7 from ._make import attrib, attrs

8

9

10@total_ordering

11@attrs(eq=False, order=False, slots=True, frozen=True)

12 class VersionInfo:

13 """

14 A version object that can be compared to tuple of length 1--4:

15

16 >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2)

17 True

18 >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1)

19 True

20 >>> vi = attr.VersionInfo(19, 2, 0, "final")

21 >>> vi < (19, 1, 1)

22 False

23 >>> vi < (19,)

24 False

25 >>> vi == (19, 2,)

26 True

27 >>> vi == (19, 2, 1)

28 False

29

30 .. versionadded:: 19.2

31 """

32

33 year = attrib(type=int)

34 minor = attrib(type=int)

35 micro = attrib(type=int)

36 releaselevel = attrib(type=str)

37

38 @classmethod

39 def _from_version_string(cls, s):

40 """

41 Parse *s* and return a _VersionInfo.

42 """

43 v = s.split(".")

44 if len(v) == 3:

45 v.append("final")

46

47 return cls(

48 year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3]

49 )

50

51 def _ensure_tuple(self, other):

52 """

53 Ensure *other* is a tuple of a valid length.

54

55 Returns a possibly transformed *other* and ourselves as a tuple of

56 the same length as *other*.

57 """

58

59 if self.__class__ is other.__class__:

60 other = astuple(other)

61

62 if not isinstance(other, tuple):

63 raise NotImplementedError

64

65 if not (1 <= len(other) <= 4):

66 raise NotImplementedError

67

68 return astuple(self)[: len(other)], other

69

70 def __eq__(self, other):

71 try:

72 us, them = self._ensure_tuple(other)

73 except NotImplementedError:

74 return NotImplemented

75

76 return us == them

77

78 def __lt__(self, other):

79 try:

80 us, them = self._ensure_tuple(other)

81 except NotImplementedError:

82 return NotImplemented

83

84 # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't

85 # have to do anything special with releaselevel for now.

86 return us < them