v440 2.0.0.dev59__tar.gz → 2.0.0.dev61__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {v440-2.0.0.dev59/src/v440.egg-info → v440-2.0.0.dev61}/PKG-INFO +1 -1
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/pyproject.toml +1 -1
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/BaseList.py +29 -41
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/SlotList.py +13 -5
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/VList.py +96 -1
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/qualparse.py +0 -45
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/utils.py +3 -16
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/Base.py +44 -38
- v440-2.0.0.dev61/src/v440/core/Local.py +45 -0
- v440-2.0.0.dev61/src/v440/core/Public.py +86 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/Qual.py +62 -15
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/Release.py +14 -17
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/Version.py +42 -39
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/tests/test_testdata.py +1 -1
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/tests/test_version.py +38 -24
- {v440-2.0.0.dev59 → v440-2.0.0.dev61/src/v440.egg-info}/PKG-INFO +1 -1
- v440-2.0.0.dev59/src/v440/core/Local.py +0 -75
- v440-2.0.0.dev59/src/v440/core/Public.py +0 -86
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/LICENSE.txt +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/MANIFEST.in +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/README.rst +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/setup.cfg +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/__init__.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/Cfg.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/Digest.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/Pattern.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/__init__.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/_utils/cfg.toml +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/VersionError.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/core/__init__.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/tests/__init__.py +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440/tests/testdata.toml +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440.egg-info/SOURCES.txt +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440.egg-info/dependency_links.txt +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440.egg-info/requires.txt +0 -0
- {v440-2.0.0.dev59 → v440-2.0.0.dev61}/src/v440.egg-info/top_level.txt +0 -0
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import collections
|
|
2
|
-
from abc import abstractmethod
|
|
2
|
+
from abc import ABCMeta, abstractmethod
|
|
3
3
|
from typing import *
|
|
4
4
|
|
|
5
5
|
import scaevola
|
|
6
6
|
import setdoc
|
|
7
7
|
import unhash
|
|
8
|
-
from datarepr import datarepr
|
|
9
8
|
|
|
9
|
+
from v440._utils.utils import guard
|
|
10
10
|
from v440.core.VersionError import VersionError
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@scaevola.auto
|
|
14
|
-
class BaseList(
|
|
14
|
+
class BaseList(metaclass=ABCMeta):
|
|
15
15
|
__slots__ = ()
|
|
16
16
|
|
|
17
|
+
string: str
|
|
18
|
+
|
|
17
19
|
@abstractmethod
|
|
18
20
|
@setdoc.basic
|
|
19
21
|
def __bool__(self: Self) -> bool: ...
|
|
20
22
|
|
|
21
|
-
@setdoc.basic
|
|
22
|
-
def __contains__(self: Self, other: Any) -> bool:
|
|
23
|
-
return other in self.data
|
|
24
|
-
|
|
25
23
|
@setdoc.basic
|
|
26
24
|
def __eq__(self: Self, other: Any) -> bool:
|
|
27
25
|
try:
|
|
28
26
|
alt: Self = type(self)(other)
|
|
29
27
|
except VersionError:
|
|
30
28
|
return False
|
|
31
|
-
return self.
|
|
29
|
+
return self.string == alt.string
|
|
32
30
|
|
|
33
31
|
@setdoc.basic
|
|
34
32
|
def __format__(self: Self, format_spec: Any) -> str:
|
|
@@ -37,7 +35,7 @@ class BaseList(collections.abc.Collection):
|
|
|
37
35
|
except Exception:
|
|
38
36
|
msg: str = "unsupported format string passed to %s.__format__"
|
|
39
37
|
msg %= type(self).__name__
|
|
40
|
-
raise TypeError(msg) from None
|
|
38
|
+
raise TypeError(msg) # from None
|
|
41
39
|
|
|
42
40
|
@setdoc.basic
|
|
43
41
|
def __ge__(self: Self, other: Any) -> bool:
|
|
@@ -48,10 +46,6 @@ class BaseList(collections.abc.Collection):
|
|
|
48
46
|
return NotImplemented
|
|
49
47
|
return self._cmp() >= alt._cmp()
|
|
50
48
|
|
|
51
|
-
@setdoc.basic
|
|
52
|
-
def __getitem__(self: Self, key: Any) -> Any:
|
|
53
|
-
return self.data[key]
|
|
54
|
-
|
|
55
49
|
@setdoc.basic
|
|
56
50
|
def __gt__(self: Self, other: Any) -> bool:
|
|
57
51
|
alt: Self
|
|
@@ -63,13 +57,9 @@ class BaseList(collections.abc.Collection):
|
|
|
63
57
|
|
|
64
58
|
__hash__ = unhash
|
|
65
59
|
|
|
60
|
+
@abstractmethod
|
|
66
61
|
@setdoc.basic
|
|
67
|
-
def __init__(self: Self,
|
|
68
|
-
self.data = data
|
|
69
|
-
|
|
70
|
-
@setdoc.basic
|
|
71
|
-
def __iter__(self: Self) -> Iterator:
|
|
72
|
-
return iter(self.data)
|
|
62
|
+
def __init__(self: Self, string: Any) -> None: ...
|
|
73
63
|
|
|
74
64
|
@setdoc.basic
|
|
75
65
|
def __le__(self: Self, other: Any) -> bool:
|
|
@@ -93,19 +83,9 @@ class BaseList(collections.abc.Collection):
|
|
|
93
83
|
def __ne__(self: Self, other: Any) -> bool:
|
|
94
84
|
return not (self == other)
|
|
95
85
|
|
|
86
|
+
@abstractmethod
|
|
96
87
|
@setdoc.basic
|
|
97
|
-
def __repr__(self: Self) -> str:
|
|
98
|
-
return datarepr(type(self).__name__, self.data)
|
|
99
|
-
|
|
100
|
-
@setdoc.basic
|
|
101
|
-
def __reversed__(self: Self) -> reversed:
|
|
102
|
-
return reversed(self.data)
|
|
103
|
-
|
|
104
|
-
@setdoc.basic
|
|
105
|
-
def __setitem__(self: Self, key: Any, value: Any) -> None:
|
|
106
|
-
data: list = list(self.data)
|
|
107
|
-
data[key] = value
|
|
108
|
-
self.data = data
|
|
88
|
+
def __repr__(self: Self) -> str: ...
|
|
109
89
|
|
|
110
90
|
@classmethod
|
|
111
91
|
def __subclasshook__(cls: type, other: type, /) -> bool:
|
|
@@ -122,19 +102,27 @@ class BaseList(collections.abc.Collection):
|
|
|
122
102
|
@abstractmethod
|
|
123
103
|
def _format(self: Self, format_spec: str) -> str: ...
|
|
124
104
|
|
|
105
|
+
@abstractmethod
|
|
106
|
+
def _set(self: Self, value: Any) -> None: ...
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
def _string_fset(self: Self, value: str) -> None: ...
|
|
110
|
+
|
|
111
|
+
@abstractmethod
|
|
112
|
+
def _todict(self: Self) -> dict: ...
|
|
113
|
+
|
|
125
114
|
@setdoc.basic
|
|
126
115
|
def copy(self: Self) -> Self:
|
|
127
116
|
return type(self)(self)
|
|
128
117
|
|
|
129
118
|
@property
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def data(self: Self) -> tuple: ...
|
|
133
|
-
|
|
134
|
-
def count(self: Self, value: Any) -> int:
|
|
135
|
-
"This method counts the occurences of value."
|
|
136
|
-
return self.data.count(value)
|
|
119
|
+
def string(self: Self) -> str:
|
|
120
|
+
return self._format("")
|
|
137
121
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
122
|
+
@string.setter
|
|
123
|
+
@guard
|
|
124
|
+
def string(self: Self, value: Any) -> None:
|
|
125
|
+
if value is None:
|
|
126
|
+
self._string_fset("")
|
|
127
|
+
else:
|
|
128
|
+
self._string_fset(str(value))
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
1
2
|
from functools import partial
|
|
2
3
|
from typing import *
|
|
3
4
|
|
|
4
5
|
import setdoc
|
|
6
|
+
from datarepr import datarepr
|
|
5
7
|
|
|
6
8
|
from v440._utils.BaseList import BaseList
|
|
7
9
|
|
|
@@ -11,15 +13,21 @@ __all__ = ["SlotList"]
|
|
|
11
13
|
class SlotList(BaseList):
|
|
12
14
|
__slots__ = ()
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@setdoc.basic
|
|
17
|
-
def __bool__(self: Self) -> bool:
|
|
18
|
-
return any(self.data)
|
|
16
|
+
string: str
|
|
19
17
|
|
|
20
18
|
@setdoc.basic
|
|
21
19
|
def __len__(self: Self) -> int:
|
|
22
20
|
return len(type(self).__slots__)
|
|
23
21
|
|
|
22
|
+
@setdoc.basic
|
|
23
|
+
def __repr__(self: Self) -> str:
|
|
24
|
+
return datarepr(type(self).__name__, **self._todict())
|
|
25
|
+
|
|
24
26
|
def _cmp(self: Self) -> tuple:
|
|
25
27
|
return tuple(map(partial(getattr, self), type(self).__slots__))
|
|
28
|
+
|
|
29
|
+
def _set(self: Self, value: Any) -> None:
|
|
30
|
+
if value is None:
|
|
31
|
+
self.string = ""
|
|
32
|
+
else:
|
|
33
|
+
self.string = value
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
+
import collections
|
|
1
2
|
from abc import abstractmethod
|
|
2
3
|
from typing import *
|
|
3
4
|
|
|
4
5
|
import setdoc
|
|
6
|
+
from datarepr import datarepr
|
|
7
|
+
from overloadable import Overloadable
|
|
5
8
|
|
|
6
9
|
from v440._utils.BaseList import BaseList
|
|
10
|
+
from v440._utils.utils import guard
|
|
7
11
|
|
|
8
12
|
__all__ = ["VList"]
|
|
9
13
|
|
|
10
14
|
|
|
11
|
-
class VList(BaseList):
|
|
15
|
+
class VList(BaseList, collections.abc.MutableSequence):
|
|
12
16
|
|
|
13
17
|
__slots__ = ("_data",)
|
|
14
18
|
data: tuple
|
|
19
|
+
string: str
|
|
15
20
|
|
|
16
21
|
@setdoc.basic
|
|
17
22
|
def __add__(self: Self, other: Any) -> Self:
|
|
@@ -56,6 +61,9 @@ class VList(BaseList):
|
|
|
56
61
|
@abstractmethod
|
|
57
62
|
def _sort(cls: type, value: Any): ...
|
|
58
63
|
|
|
64
|
+
def _todict(self: Self) -> dict:
|
|
65
|
+
return dict(data=self.data)
|
|
66
|
+
|
|
59
67
|
def append(self: Self, value: Self, /) -> None:
|
|
60
68
|
"This method appends value to self."
|
|
61
69
|
data: list = list(self.data)
|
|
@@ -109,3 +117,90 @@ class VList(BaseList):
|
|
|
109
117
|
r: bool = bool(reverse)
|
|
110
118
|
data.sort(key=k, reverse=r)
|
|
111
119
|
self.data = data
|
|
120
|
+
|
|
121
|
+
# data-associated
|
|
122
|
+
@setdoc.basic
|
|
123
|
+
def __contains__(self: Self, other: Any) -> bool:
|
|
124
|
+
return other in self.data
|
|
125
|
+
|
|
126
|
+
@setdoc.basic
|
|
127
|
+
def __getitem__(self: Self, key: Any) -> Any:
|
|
128
|
+
return self.data[key]
|
|
129
|
+
|
|
130
|
+
@Overloadable
|
|
131
|
+
@setdoc.basic
|
|
132
|
+
def __init__(self: Self, *args: Any, **kwargs: Any) -> bool:
|
|
133
|
+
if len(args) == 0 and "string" in kwargs.keys():
|
|
134
|
+
return True
|
|
135
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
136
|
+
if isinstance(args[0], str):
|
|
137
|
+
return True
|
|
138
|
+
if hasattr(args[0], "__iter__"):
|
|
139
|
+
return False
|
|
140
|
+
return True
|
|
141
|
+
return False
|
|
142
|
+
|
|
143
|
+
@__init__.overload(True)
|
|
144
|
+
@setdoc.basic
|
|
145
|
+
def __init__(self: Self, string: Any) -> None:
|
|
146
|
+
self._init_setup()
|
|
147
|
+
self.string = string
|
|
148
|
+
|
|
149
|
+
@__init__.overload(False)
|
|
150
|
+
@setdoc.basic
|
|
151
|
+
def __init__(self: Self, data: Iterable = ()) -> None:
|
|
152
|
+
self._init_setup()
|
|
153
|
+
self.data = data
|
|
154
|
+
|
|
155
|
+
@setdoc.basic
|
|
156
|
+
def __iter__(self: Self) -> Iterator:
|
|
157
|
+
return iter(self.data)
|
|
158
|
+
|
|
159
|
+
@setdoc.basic
|
|
160
|
+
def __repr__(self: Self) -> str:
|
|
161
|
+
return datarepr(type(self).__name__, *self.data)
|
|
162
|
+
|
|
163
|
+
@setdoc.basic
|
|
164
|
+
def __reversed__(self: Self) -> reversed:
|
|
165
|
+
return reversed(self.data)
|
|
166
|
+
|
|
167
|
+
@setdoc.basic
|
|
168
|
+
def __setitem__(self: Self, key: Any, value: Any) -> None:
|
|
169
|
+
data: list = list(self.data)
|
|
170
|
+
data[key] = value
|
|
171
|
+
self.data = data
|
|
172
|
+
|
|
173
|
+
@classmethod
|
|
174
|
+
@abstractmethod
|
|
175
|
+
def _data_parse(cls: type, value: list) -> Iterable: ...
|
|
176
|
+
|
|
177
|
+
def _init_setup(self: Self) -> None:
|
|
178
|
+
self._data = ()
|
|
179
|
+
|
|
180
|
+
def _set(self: Self, value: Any) -> None:
|
|
181
|
+
if value is None:
|
|
182
|
+
self.data = ()
|
|
183
|
+
elif isinstance(value, str):
|
|
184
|
+
self.string = value
|
|
185
|
+
elif hasattr(value, "__iter__"):
|
|
186
|
+
self.data = value
|
|
187
|
+
else:
|
|
188
|
+
self.string = value
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
@setdoc.basic
|
|
192
|
+
def data(self: Self) -> tuple:
|
|
193
|
+
return self._data
|
|
194
|
+
|
|
195
|
+
@data.setter
|
|
196
|
+
@guard
|
|
197
|
+
def data(self: Self, value: Iterable) -> None:
|
|
198
|
+
self._data = tuple(self._data_parse(list(value)))
|
|
199
|
+
|
|
200
|
+
def count(self: Self, value: Any) -> int:
|
|
201
|
+
"This method counts the occurences of value."
|
|
202
|
+
return self.data.count(value)
|
|
203
|
+
|
|
204
|
+
def index(self: Self, *args: Any) -> None:
|
|
205
|
+
"This method returns the index of the first occurence."
|
|
206
|
+
return self.data.index(*args)
|
|
@@ -7,51 +7,6 @@ from v440._utils.Cfg import Cfg
|
|
|
7
7
|
from v440._utils.Digest import Digest
|
|
8
8
|
from v440._utils.Pattern import Pattern
|
|
9
9
|
|
|
10
|
-
parse_leg: Digest = Digest("parse_leg")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@parse_leg.overload()
|
|
14
|
-
def parse_leg() -> tuple:
|
|
15
|
-
return None, None, None
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@parse_leg.overload(int)
|
|
19
|
-
def parse_leg(value: int) -> tuple:
|
|
20
|
-
return None, abs(value), None
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@parse_leg.overload(list)
|
|
24
|
-
def parse_leg(value: list) -> tuple:
|
|
25
|
-
return tuple([value[:2]] + value[2:])
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@parse_leg.overload(str)
|
|
29
|
-
def parse_leg(value: str) -> tuple:
|
|
30
|
-
v = value
|
|
31
|
-
pre: tuple = None, None
|
|
32
|
-
post: Optional[str] = None
|
|
33
|
-
dev: Optional[str] = None
|
|
34
|
-
m: Any
|
|
35
|
-
x: Any
|
|
36
|
-
y: Any
|
|
37
|
-
while v:
|
|
38
|
-
m = Pattern.QUALIFIERS.leftbound.search(v)
|
|
39
|
-
v = v[m.end() :]
|
|
40
|
-
if m.group("N"):
|
|
41
|
-
post = m.group("N")
|
|
42
|
-
continue
|
|
43
|
-
x = m.group("l")
|
|
44
|
-
y = m.group("n")
|
|
45
|
-
if x == "dev":
|
|
46
|
-
dev = y
|
|
47
|
-
continue
|
|
48
|
-
if x in ("post", "r", "rev"):
|
|
49
|
-
post = y
|
|
50
|
-
continue
|
|
51
|
-
pre = x, y
|
|
52
|
-
return pre, post, dev
|
|
53
|
-
|
|
54
|
-
|
|
55
10
|
parse_dev: Digest = Digest("parse_dev")
|
|
56
11
|
|
|
57
12
|
|
|
@@ -74,30 +74,17 @@ def ishashable(value: Any) -> bool:
|
|
|
74
74
|
def guard(old: Any) -> Any:
|
|
75
75
|
@functools.wraps(old)
|
|
76
76
|
def new(self: Self, value: Any) -> None:
|
|
77
|
-
backup:
|
|
78
|
-
x: Any
|
|
79
|
-
y: Any
|
|
80
|
-
for x in type(self).__slots__:
|
|
81
|
-
y = getattr(self, x)
|
|
82
|
-
backup[x] = y if ishashable(y) else y.copy()
|
|
77
|
+
backup: str = str(getattr(self, old.__name__))
|
|
83
78
|
try:
|
|
84
79
|
old(self, value)
|
|
85
80
|
except VersionError:
|
|
86
|
-
|
|
81
|
+
setattr(self, old.__name__, backup)
|
|
87
82
|
raise
|
|
88
83
|
except Exception:
|
|
89
|
-
|
|
84
|
+
setattr(self, old.__name__, backup)
|
|
90
85
|
msg: str = "%r is an invalid value for %r"
|
|
91
86
|
target: str = type(self).__name__ + "." + old.__name__
|
|
92
87
|
msg %= (value, target)
|
|
93
88
|
raise VersionError(msg)
|
|
94
89
|
|
|
95
90
|
return new
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def restore(obj: Any, backup: dict) -> None:
|
|
99
|
-
for x in type(obj).__slots__:
|
|
100
|
-
if ishashable(backup[x]):
|
|
101
|
-
setattr(obj, x, backup[x])
|
|
102
|
-
else:
|
|
103
|
-
getattr(obj, x).data = backup[x]
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import *
|
|
4
4
|
|
|
5
5
|
import setdoc
|
|
6
|
+
from overloadable import Overloadable
|
|
6
7
|
|
|
7
8
|
from v440._utils.Digest import Digest
|
|
8
9
|
from v440._utils.SlotList import SlotList
|
|
@@ -12,32 +13,6 @@ from v440.core.Release import Release
|
|
|
12
13
|
__all__ = ["Base"]
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
parse_data: Digest = Digest("parse_data")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@parse_data.overload()
|
|
19
|
-
def parse_data() -> tuple:
|
|
20
|
-
return None, None
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@parse_data.overload(int)
|
|
24
|
-
def parse_data(value: int) -> tuple:
|
|
25
|
-
return None, value
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@parse_data.overload(list)
|
|
29
|
-
def parse_data(value: list) -> tuple:
|
|
30
|
-
return tuple(value)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@parse_data.overload(str)
|
|
34
|
-
def parse_data(value: str) -> tuple:
|
|
35
|
-
if "!" in value:
|
|
36
|
-
return tuple(value.split("!"))
|
|
37
|
-
else:
|
|
38
|
-
return 0, value
|
|
39
|
-
|
|
40
|
-
|
|
41
16
|
parse_epoch: Digest = Digest("parse_epoch")
|
|
42
17
|
|
|
43
18
|
|
|
@@ -70,15 +45,42 @@ class Base(SlotList):
|
|
|
70
45
|
|
|
71
46
|
__slots__ = ("_epoch", "_release")
|
|
72
47
|
|
|
73
|
-
|
|
48
|
+
string: str
|
|
74
49
|
epoch: int
|
|
75
50
|
release: Release
|
|
76
51
|
|
|
52
|
+
def __bool__(self: Self) -> bool:
|
|
53
|
+
return bool(self.epoch or self.release)
|
|
54
|
+
|
|
55
|
+
@Overloadable
|
|
56
|
+
@setdoc.basic
|
|
57
|
+
def __init__(self: Self, *args: Any, **kwargs: Any) -> bool:
|
|
58
|
+
if len(args) == 0 and "string" in kwargs.keys():
|
|
59
|
+
return True
|
|
60
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
61
|
+
return True
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
@__init__.overload(True)
|
|
65
|
+
@setdoc.basic
|
|
66
|
+
def __init__(self: Self, string: Any) -> None:
|
|
67
|
+
self._init_setup()
|
|
68
|
+
self.string = string
|
|
69
|
+
|
|
70
|
+
@__init__.overload(False)
|
|
77
71
|
@setdoc.basic
|
|
78
|
-
def __init__(
|
|
72
|
+
def __init__(
|
|
73
|
+
self: Self,
|
|
74
|
+
epoch: Any = "0",
|
|
75
|
+
release: Any = "0",
|
|
76
|
+
) -> None:
|
|
77
|
+
self._init_setup()
|
|
78
|
+
self.epoch = epoch
|
|
79
|
+
self.release = release
|
|
80
|
+
|
|
81
|
+
def _init_setup(self: Self) -> None:
|
|
79
82
|
self._epoch = 0
|
|
80
83
|
self._release = Release()
|
|
81
|
-
self.data = data
|
|
82
84
|
|
|
83
85
|
def _format(self: Self, format_spec: str) -> str:
|
|
84
86
|
ans: str = ""
|
|
@@ -87,15 +89,19 @@ class Base(SlotList):
|
|
|
87
89
|
ans += format(self.release, format_spec)
|
|
88
90
|
return ans
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
93
|
+
v: str = value
|
|
94
|
+
if v.startswith("v"):
|
|
95
|
+
v = v[1:]
|
|
96
|
+
parsed: Iterable
|
|
97
|
+
if "!" in v:
|
|
98
|
+
parsed = v.split("!")
|
|
99
|
+
else:
|
|
100
|
+
parsed = 0, v
|
|
101
|
+
self.epoch, self.release.string = parsed
|
|
94
102
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def data(self: Self, value: Any) -> None:
|
|
98
|
-
self.epoch, self.release = parse_data(value)
|
|
103
|
+
def _todict(self: Self) -> dict:
|
|
104
|
+
return dict(epoch=self.epoch, release=self.release)
|
|
99
105
|
|
|
100
106
|
@property
|
|
101
107
|
def epoch(self: Self) -> int:
|
|
@@ -115,4 +121,4 @@ class Base(SlotList):
|
|
|
115
121
|
@release.setter
|
|
116
122
|
@guard
|
|
117
123
|
def release(self: Self, value: Any) -> None:
|
|
118
|
-
self.
|
|
124
|
+
self.release._set(value)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import *
|
|
4
|
+
|
|
5
|
+
import setdoc
|
|
6
|
+
|
|
7
|
+
from v440._utils import utils
|
|
8
|
+
from v440._utils.Digest import Digest
|
|
9
|
+
from v440._utils.utils import guard
|
|
10
|
+
from v440._utils.VList import VList
|
|
11
|
+
|
|
12
|
+
__all__ = ["Local"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Local(VList):
|
|
16
|
+
__slots__ = ()
|
|
17
|
+
|
|
18
|
+
data: tuple[int | str]
|
|
19
|
+
string: str
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def _data_parse(cls: type, value: list) -> Iterable:
|
|
23
|
+
ans: tuple = tuple(map(utils.segment, value))
|
|
24
|
+
if None in ans:
|
|
25
|
+
raise ValueError
|
|
26
|
+
return ans
|
|
27
|
+
|
|
28
|
+
def _format(self: Self, format_spec: str) -> str:
|
|
29
|
+
if format_spec:
|
|
30
|
+
raise ValueError
|
|
31
|
+
return ".".join(map(str, self))
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def _sort(cls: type, value: Any) -> tuple[bool, int | str]:
|
|
35
|
+
return type(value) is int, value
|
|
36
|
+
|
|
37
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
38
|
+
if value == "":
|
|
39
|
+
return ()
|
|
40
|
+
v: str = value
|
|
41
|
+
if v.startswith("+"):
|
|
42
|
+
v = v[1:]
|
|
43
|
+
v = v.replace("_", ".")
|
|
44
|
+
v = v.replace("-", ".")
|
|
45
|
+
self.data = v.split(".")
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import *
|
|
4
|
+
|
|
5
|
+
import setdoc
|
|
6
|
+
from overloadable import Overloadable
|
|
7
|
+
|
|
8
|
+
from v440._utils.Digest import Digest
|
|
9
|
+
from v440._utils.Pattern import Pattern
|
|
10
|
+
from v440._utils.SlotList import SlotList
|
|
11
|
+
from v440._utils.utils import guard
|
|
12
|
+
from v440.core.Base import Base
|
|
13
|
+
from v440.core.Qual import Qual
|
|
14
|
+
|
|
15
|
+
__all__ = ["Public"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Public(SlotList):
|
|
19
|
+
|
|
20
|
+
__slots__ = ("_base", "_qual")
|
|
21
|
+
|
|
22
|
+
string: str
|
|
23
|
+
base: Base
|
|
24
|
+
qual: Qual
|
|
25
|
+
|
|
26
|
+
def __bool__(self: Self) -> bool:
|
|
27
|
+
return bool(self.base or self.qual)
|
|
28
|
+
|
|
29
|
+
@Overloadable
|
|
30
|
+
@setdoc.basic
|
|
31
|
+
def __init__(self: Self, *args: Any, **kwargs: Any) -> bool:
|
|
32
|
+
if len(args) == 0 and "string" in kwargs.keys():
|
|
33
|
+
return True
|
|
34
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
35
|
+
return True
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
@__init__.overload(True)
|
|
39
|
+
@setdoc.basic
|
|
40
|
+
def __init__(self: Self, string: Any) -> None:
|
|
41
|
+
self._init_setup()
|
|
42
|
+
self.string = string
|
|
43
|
+
|
|
44
|
+
@__init__.overload(False)
|
|
45
|
+
@setdoc.basic
|
|
46
|
+
def __init__(
|
|
47
|
+
self: Self,
|
|
48
|
+
base: Any = "0",
|
|
49
|
+
qual: Any = "",
|
|
50
|
+
) -> None:
|
|
51
|
+
self._init_setup()
|
|
52
|
+
self.base = base
|
|
53
|
+
self.qual = qual
|
|
54
|
+
|
|
55
|
+
def _init_setup(self: Self) -> None:
|
|
56
|
+
self._base = Base()
|
|
57
|
+
self._qual = Qual()
|
|
58
|
+
|
|
59
|
+
def _format(self: Self, format_spec: str) -> str:
|
|
60
|
+
return format(self.base, format_spec) + format(self.qual)
|
|
61
|
+
|
|
62
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
63
|
+
match: Any = Pattern.PUBLIC.leftbound.search(value)
|
|
64
|
+
self.base.string = value[: match.end()]
|
|
65
|
+
self.qual.string = value[match.end() :]
|
|
66
|
+
|
|
67
|
+
def _todict(self: Self) -> dict:
|
|
68
|
+
return dict(base=self.base, qual=self.qual)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def base(self: Self) -> Base:
|
|
72
|
+
"This property represents the version base."
|
|
73
|
+
return self._base
|
|
74
|
+
|
|
75
|
+
@base.setter
|
|
76
|
+
def base(self: Self, value: Any) -> None:
|
|
77
|
+
self.base._set(value)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def qual(self: Self) -> Qual:
|
|
81
|
+
"This property represents the qualification."
|
|
82
|
+
return self._qual
|
|
83
|
+
|
|
84
|
+
@qual.setter
|
|
85
|
+
def qual(self: Self, value: Any) -> None:
|
|
86
|
+
self.qual._set(value)
|
|
@@ -3,8 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import *
|
|
4
4
|
|
|
5
5
|
import setdoc
|
|
6
|
+
from overloadable import Overloadable
|
|
6
7
|
|
|
7
|
-
from v440._utils import qualparse
|
|
8
|
+
from v440._utils import qualparse, utils
|
|
9
|
+
from v440._utils.Pattern import Pattern
|
|
8
10
|
from v440._utils.SlotList import SlotList
|
|
9
11
|
from v440._utils.utils import guard
|
|
10
12
|
|
|
@@ -15,24 +17,49 @@ class Qual(SlotList):
|
|
|
15
17
|
|
|
16
18
|
__slots__ = ("_prephase", "_presubphase", "_post", "_dev")
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
string: str
|
|
19
21
|
pre: tuple
|
|
20
22
|
prephase: Optional[str]
|
|
21
23
|
presubphase: Optional[int]
|
|
22
24
|
post: Optional[int]
|
|
23
25
|
dev: Optional[int]
|
|
24
26
|
|
|
25
|
-
@setdoc.basic
|
|
26
27
|
def __bool__(self: Self) -> bool:
|
|
27
|
-
return
|
|
28
|
+
return self.string == ""
|
|
29
|
+
|
|
30
|
+
@Overloadable
|
|
31
|
+
@setdoc.basic
|
|
32
|
+
def __init__(self: Self, *args: Any, **kwargs: Any) -> bool:
|
|
33
|
+
if len(args) == 0 and "string" in kwargs.keys():
|
|
34
|
+
return True
|
|
35
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
36
|
+
return True
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
@__init__.overload(True)
|
|
40
|
+
@setdoc.basic
|
|
41
|
+
def __init__(self: Self, string: Any) -> None:
|
|
42
|
+
self._init_setup()
|
|
43
|
+
self.string = string
|
|
28
44
|
|
|
45
|
+
@__init__.overload(False)
|
|
29
46
|
@setdoc.basic
|
|
30
|
-
def __init__(
|
|
47
|
+
def __init__(
|
|
48
|
+
self: Self,
|
|
49
|
+
pre: Any = None,
|
|
50
|
+
post: Any = None,
|
|
51
|
+
dev: Any = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
self._init_setup()
|
|
54
|
+
self.pre = pre
|
|
55
|
+
self.post = post
|
|
56
|
+
self.dev = dev
|
|
57
|
+
|
|
58
|
+
def _init_setup(self: Self) -> None:
|
|
31
59
|
self._prephase = None
|
|
32
60
|
self._presubphase = None
|
|
33
61
|
self._post = None
|
|
34
62
|
self._dev = None
|
|
35
|
-
self.data = data
|
|
36
63
|
|
|
37
64
|
def _cmp(self: Self) -> list:
|
|
38
65
|
ans: list = list()
|
|
@@ -62,15 +89,35 @@ class Qual(SlotList):
|
|
|
62
89
|
ans += ".dev%s" % self.dev
|
|
63
90
|
return ans
|
|
64
91
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
92
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
93
|
+
v: str = value
|
|
94
|
+
m: Any
|
|
95
|
+
x: Any
|
|
96
|
+
y: Any
|
|
97
|
+
pre: Any = (None, None)
|
|
98
|
+
post: Any = None
|
|
99
|
+
dev: Any = None
|
|
100
|
+
while v:
|
|
101
|
+
m = Pattern.QUALIFIERS.leftbound.search(v)
|
|
102
|
+
v = v[m.end() :]
|
|
103
|
+
if m.group("N"):
|
|
104
|
+
post = m.group("N")
|
|
105
|
+
continue
|
|
106
|
+
x = m.group("l")
|
|
107
|
+
y = m.group("n")
|
|
108
|
+
if x == "dev":
|
|
109
|
+
dev = y
|
|
110
|
+
continue
|
|
111
|
+
if x in ("post", "r", "rev"):
|
|
112
|
+
post = y
|
|
113
|
+
continue
|
|
114
|
+
pre = x, y
|
|
115
|
+
self.pre = pre
|
|
116
|
+
self.post = post
|
|
117
|
+
self.dev = dev
|
|
118
|
+
|
|
119
|
+
def _todict(self: Self) -> dict:
|
|
120
|
+
return dict(pre=self.pre, post=self.post, dev=self.dev)
|
|
74
121
|
|
|
75
122
|
@property
|
|
76
123
|
def dev(self: Self) -> Optional[int]:
|
|
@@ -104,6 +104,7 @@ class Release(VList):
|
|
|
104
104
|
__slots__ = ()
|
|
105
105
|
|
|
106
106
|
data: tuple[int]
|
|
107
|
+
string: str
|
|
107
108
|
major: int
|
|
108
109
|
minor: int
|
|
109
110
|
micro: int
|
|
@@ -156,10 +157,6 @@ class Release(VList):
|
|
|
156
157
|
ans: list = list(m)
|
|
157
158
|
return ans
|
|
158
159
|
|
|
159
|
-
@setdoc.basic
|
|
160
|
-
def __init__(self: Any, data: Any = None) -> None:
|
|
161
|
-
self.data = data
|
|
162
|
-
|
|
163
160
|
@Overloadable
|
|
164
161
|
@setdoc.basic
|
|
165
162
|
def __setitem__(self: Self, key: Any, value: Any) -> bool:
|
|
@@ -177,6 +174,13 @@ class Release(VList):
|
|
|
177
174
|
k: range = torange(key, len(self))
|
|
178
175
|
self._setitem_range(k, value)
|
|
179
176
|
|
|
177
|
+
@classmethod
|
|
178
|
+
def _data_parse(cls: type, value: list) -> Iterable:
|
|
179
|
+
v: list = tolist(value, slicing="always")
|
|
180
|
+
while v and v[-1] == 0:
|
|
181
|
+
v.pop()
|
|
182
|
+
return v
|
|
183
|
+
|
|
180
184
|
def _format(self: Self, format_spec: str) -> str:
|
|
181
185
|
i: Optional[int]
|
|
182
186
|
if format_spec:
|
|
@@ -240,6 +244,12 @@ class Release(VList):
|
|
|
240
244
|
def _sort(cls: type, value: int) -> int:
|
|
241
245
|
return value
|
|
242
246
|
|
|
247
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
248
|
+
v: str = value
|
|
249
|
+
v = v.replace("_", ".")
|
|
250
|
+
v = v.replace("-", ".")
|
|
251
|
+
self.data = v.split(".")
|
|
252
|
+
|
|
243
253
|
def bump(self: Self, index: SupportsIndex = -1, amount: SupportsIndex = 1) -> None:
|
|
244
254
|
i: int = operator.index(index)
|
|
245
255
|
a: int = operator.index(amount)
|
|
@@ -247,16 +257,3 @@ class Release(VList):
|
|
|
247
257
|
self._setitem_int(i, x)
|
|
248
258
|
if i != -1:
|
|
249
259
|
self.data = self.data[: i + 1]
|
|
250
|
-
|
|
251
|
-
@property
|
|
252
|
-
@setdoc.basic
|
|
253
|
-
def data(self: Self) -> tuple:
|
|
254
|
-
return self._data
|
|
255
|
-
|
|
256
|
-
@data.setter
|
|
257
|
-
@guard
|
|
258
|
-
def data(self: Self, value: Any) -> None:
|
|
259
|
-
v: list = tolist(value, slicing="always")
|
|
260
|
-
while v and v[-1] == 0:
|
|
261
|
-
v.pop()
|
|
262
|
-
self._data = tuple(v)
|
|
@@ -4,8 +4,8 @@ from typing import *
|
|
|
4
4
|
|
|
5
5
|
import packaging.version
|
|
6
6
|
import setdoc
|
|
7
|
+
from overloadable import Overloadable
|
|
7
8
|
|
|
8
|
-
from v440._utils.Digest import Digest
|
|
9
9
|
from v440._utils.SlotList import SlotList
|
|
10
10
|
from v440._utils.utils import guard
|
|
11
11
|
from v440.core.Local import Local
|
|
@@ -13,44 +13,46 @@ from v440.core.Public import Public
|
|
|
13
13
|
|
|
14
14
|
__all__ = ["Version"]
|
|
15
15
|
|
|
16
|
-
parse_data: Digest = Digest("parse_data")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@parse_data.overload()
|
|
20
|
-
def parse_data() -> tuple:
|
|
21
|
-
return None, None
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@parse_data.overload(int)
|
|
25
|
-
def parse_data(value: int) -> tuple:
|
|
26
|
-
return value, None
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@parse_data.overload(list)
|
|
30
|
-
def parse_data(value: list) -> tuple:
|
|
31
|
-
return tuple(value)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@parse_data.overload(str)
|
|
35
|
-
def parse_data(value: str) -> tuple:
|
|
36
|
-
if "+" in value:
|
|
37
|
-
return tuple(value.split("+"))
|
|
38
|
-
else:
|
|
39
|
-
return value, None
|
|
40
|
-
|
|
41
16
|
|
|
42
17
|
class Version(SlotList):
|
|
43
18
|
__slots__ = ("_public", "_local")
|
|
44
19
|
|
|
45
|
-
|
|
20
|
+
string: str
|
|
46
21
|
local: Local
|
|
47
22
|
public: Public
|
|
48
23
|
|
|
24
|
+
def __bool__(self: Self) -> bool:
|
|
25
|
+
return bool(self.local or self.public)
|
|
26
|
+
|
|
27
|
+
@Overloadable
|
|
28
|
+
@setdoc.basic
|
|
29
|
+
def __init__(self: Self, *args: Any, **kwargs: Any) -> bool:
|
|
30
|
+
if len(args) == 0 and "string" in kwargs.keys():
|
|
31
|
+
return True
|
|
32
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
33
|
+
return True
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
@__init__.overload(True)
|
|
37
|
+
@setdoc.basic
|
|
38
|
+
def __init__(self: Self, string: Any) -> None:
|
|
39
|
+
self._init_setup()
|
|
40
|
+
self.string = string
|
|
41
|
+
|
|
42
|
+
@__init__.overload(False)
|
|
49
43
|
@setdoc.basic
|
|
50
|
-
def __init__(
|
|
44
|
+
def __init__(
|
|
45
|
+
self: Self,
|
|
46
|
+
public: Any = "0",
|
|
47
|
+
local: Any = "",
|
|
48
|
+
) -> None:
|
|
49
|
+
self._init_setup()
|
|
50
|
+
self.public = public
|
|
51
|
+
self.local = local
|
|
52
|
+
|
|
53
|
+
def _init_setup(self: Self) -> None:
|
|
51
54
|
self._public = Public()
|
|
52
55
|
self._local = Local()
|
|
53
|
-
self.data = data
|
|
54
56
|
|
|
55
57
|
def _format(self: Self, format_spec: str) -> str:
|
|
56
58
|
ans: str = format(self.public, format_spec)
|
|
@@ -58,15 +60,16 @@ class Version(SlotList):
|
|
|
58
60
|
ans += "+" + format(self.local)
|
|
59
61
|
return ans
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
def _string_fset(self: Self, value: str) -> None:
|
|
64
|
+
parsed: Iterable
|
|
65
|
+
if "+" in value:
|
|
66
|
+
parsed = value.split("+")
|
|
67
|
+
else:
|
|
68
|
+
parsed = value, ""
|
|
69
|
+
self.public.string, self.local.string = parsed
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def data(self: Self, value: Any) -> None:
|
|
69
|
-
self.public, self.local = parse_data(value)
|
|
71
|
+
def _todict(self: Self) -> dict:
|
|
72
|
+
return dict(public=self.public, local=self.local)
|
|
70
73
|
|
|
71
74
|
@property
|
|
72
75
|
def local(self: Self) -> Local:
|
|
@@ -76,7 +79,7 @@ class Version(SlotList):
|
|
|
76
79
|
@local.setter
|
|
77
80
|
@guard
|
|
78
81
|
def local(self: Self, value: Any) -> None:
|
|
79
|
-
self.local.
|
|
82
|
+
self.local._set(value)
|
|
80
83
|
|
|
81
84
|
def packaging(self: Self) -> packaging.version.Version:
|
|
82
85
|
"This method returns an eqivalent packaging.version.Version object."
|
|
@@ -90,4 +93,4 @@ class Version(SlotList):
|
|
|
90
93
|
@public.setter
|
|
91
94
|
@guard
|
|
92
95
|
def public(self: Self, value: Any) -> None:
|
|
93
|
-
self.public.
|
|
96
|
+
self.public._set(value)
|
|
@@ -59,7 +59,7 @@ class TestPre(unittest.TestCase):
|
|
|
59
59
|
|
|
60
60
|
# Initial version, no pre-release version
|
|
61
61
|
self.assertEqual(str(v), "1.2.3")
|
|
62
|
-
self.assertEqual(v.public.qual,
|
|
62
|
+
self.assertEqual(v.public.qual.string, "")
|
|
63
63
|
|
|
64
64
|
# Set pre-release version to "a1"
|
|
65
65
|
v.public.qual = "a1"
|
|
@@ -88,7 +88,7 @@ class TestPre(unittest.TestCase):
|
|
|
88
88
|
# Set pre-release to None
|
|
89
89
|
v.public.qual = None
|
|
90
90
|
self.assertEqual(str(v), "1.2.3")
|
|
91
|
-
self.assertEqual(v.public.qual,
|
|
91
|
+
self.assertEqual(str(v.public.qual), "")
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
class TestExample(unittest.TestCase):
|
|
@@ -105,27 +105,41 @@ class TestExample(unittest.TestCase):
|
|
|
105
105
|
v.public.base.release.micro = 4
|
|
106
106
|
self.assertEqual(str(v), "2.64.4") # Further modified version
|
|
107
107
|
|
|
108
|
-
def
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
108
|
+
def test_example_3a(self: Self) -> None:
|
|
109
|
+
v1: Version = Version("1.6.3")
|
|
110
|
+
v2: str = "1.6.4"
|
|
111
|
+
self.assertEqual(str(v1), "1.6.3") # v1
|
|
112
|
+
self.assertEqual(str(v2), "1.6.4") # v2
|
|
113
|
+
self.assertFalse(v1 == v2) # v1 == v2 gives False
|
|
114
|
+
self.assertTrue(v1 != v2) # v1 != v2 gives True
|
|
115
|
+
self.assertFalse(v1 >= v2) # v1 >= v2 gives False
|
|
116
|
+
self.assertTrue(v1 <= v2) # v1 <= v2 gives True
|
|
117
|
+
self.assertFalse(v1 > v2) # v1 > v2 gives False
|
|
118
|
+
self.assertTrue(v1 < v2) # v1 < v2 gives True
|
|
119
|
+
|
|
120
|
+
def test_example_3b(self: Self) -> None:
|
|
121
|
+
v1: str = "1.6.3"
|
|
122
|
+
v2: Version = Version("1.6.4")
|
|
123
|
+
self.assertEqual(str(v1), "1.6.3") # v1
|
|
124
|
+
self.assertEqual(str(v2), "1.6.4") # v2
|
|
125
|
+
self.assertFalse(v1 == v2) # v1 == v2 gives False
|
|
126
|
+
self.assertTrue(v1 != v2) # v1 != v2 gives True
|
|
127
|
+
self.assertFalse(v1 >= v2) # v1 >= v2 gives False
|
|
128
|
+
self.assertTrue(v1 <= v2) # v1 <= v2 gives True
|
|
129
|
+
self.assertFalse(v1 > v2) # v1 > v2 gives False
|
|
130
|
+
self.assertTrue(v1 < v2) # v1 < v2 gives True
|
|
131
|
+
|
|
132
|
+
def test_example_3c(self: Self) -> None:
|
|
133
|
+
v1: Version = Version("1.6.3")
|
|
134
|
+
v2: Version = Version("1.6.4")
|
|
135
|
+
self.assertEqual(str(v1), "1.6.3") # v1
|
|
136
|
+
self.assertEqual(str(v2), "1.6.4") # v2
|
|
137
|
+
self.assertFalse(v1 == v2) # v1 == v2 gives False
|
|
138
|
+
self.assertTrue(v1 != v2) # v1 != v2 gives True
|
|
139
|
+
self.assertFalse(v1 >= v2) # v1 >= v2 gives False
|
|
140
|
+
self.assertTrue(v1 <= v2) # v1 <= v2 gives True
|
|
141
|
+
self.assertFalse(v1 > v2) # v1 > v2 gives False
|
|
142
|
+
self.assertTrue(v1 < v2) # v1 < v2 gives True
|
|
129
143
|
|
|
130
144
|
def test_example_4(self: Self) -> None:
|
|
131
145
|
v: Version = Version("2.5.3.9")
|
|
@@ -165,7 +179,7 @@ class TestExample(unittest.TestCase):
|
|
|
165
179
|
def test_example_7(self: Self) -> None:
|
|
166
180
|
v: Version = Version("5.0.0")
|
|
167
181
|
self.assertEqual(str(v), "5") # Original version
|
|
168
|
-
v.
|
|
182
|
+
v.string = ""
|
|
169
183
|
self.assertEqual(str(v), "0") # After reset
|
|
170
184
|
v.public.base = "4!5.0.1"
|
|
171
185
|
self.assertEqual(str(v), "4!5.0.1") # Before error
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import *
|
|
4
|
-
|
|
5
|
-
import setdoc
|
|
6
|
-
|
|
7
|
-
from v440._utils import utils
|
|
8
|
-
from v440._utils.Digest import Digest
|
|
9
|
-
from v440._utils.utils import guard
|
|
10
|
-
from v440._utils.VList import VList
|
|
11
|
-
|
|
12
|
-
__all__ = ["Local"]
|
|
13
|
-
|
|
14
|
-
parse_data: Digest = Digest("parse_data")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@parse_data.overload()
|
|
18
|
-
def parse_data() -> tuple:
|
|
19
|
-
return ()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@parse_data.overload(int)
|
|
23
|
-
def parse_data(value: int) -> list:
|
|
24
|
-
return (value,)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@parse_data.overload(list)
|
|
28
|
-
def parse_data(value: list) -> list:
|
|
29
|
-
ans: tuple = tuple(map(utils.segment, value))
|
|
30
|
-
if None in ans:
|
|
31
|
-
raise ValueError
|
|
32
|
-
return ans
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@parse_data.overload(str)
|
|
36
|
-
def parse_data(value: str) -> tuple:
|
|
37
|
-
v: str = value
|
|
38
|
-
if v.startswith("+"):
|
|
39
|
-
v = v[1:]
|
|
40
|
-
v = v.replace("_", ".")
|
|
41
|
-
v = v.replace("-", ".")
|
|
42
|
-
ans: tuple = v.split(".")
|
|
43
|
-
ans = tuple(map(utils.segment, ans))
|
|
44
|
-
if None in ans:
|
|
45
|
-
raise ValueError
|
|
46
|
-
return ans
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class Local(VList):
|
|
50
|
-
__slots__ = ()
|
|
51
|
-
|
|
52
|
-
data: tuple[int | str]
|
|
53
|
-
|
|
54
|
-
@setdoc.basic
|
|
55
|
-
def __init__(self: Any, data: Any = None) -> None:
|
|
56
|
-
self.data = data
|
|
57
|
-
|
|
58
|
-
def _format(self: Self, format_spec: str) -> str:
|
|
59
|
-
if format_spec:
|
|
60
|
-
raise ValueError
|
|
61
|
-
return ".".join(map(str, self))
|
|
62
|
-
|
|
63
|
-
@classmethod
|
|
64
|
-
def _sort(cls: type, value: Any) -> tuple[bool, int | str]:
|
|
65
|
-
return type(value) is int, value
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
@setdoc.basic
|
|
69
|
-
def data(self: Self) -> tuple[int | str]:
|
|
70
|
-
return self._data
|
|
71
|
-
|
|
72
|
-
@data.setter
|
|
73
|
-
@guard
|
|
74
|
-
def data(self: Self, value: Any) -> None:
|
|
75
|
-
self._data = parse_data(value)
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import *
|
|
4
|
-
|
|
5
|
-
import setdoc
|
|
6
|
-
|
|
7
|
-
from v440._utils.Digest import Digest
|
|
8
|
-
from v440._utils.Pattern import Pattern
|
|
9
|
-
from v440._utils.SlotList import SlotList
|
|
10
|
-
from v440._utils.utils import guard
|
|
11
|
-
from v440.core.Base import Base
|
|
12
|
-
from v440.core.Qual import Qual
|
|
13
|
-
|
|
14
|
-
__all__ = ["Public"]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
parse_data: Digest = Digest("parse_data")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@parse_data.overload()
|
|
21
|
-
def parse_data() -> tuple:
|
|
22
|
-
return None, None
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@parse_data.overload(int)
|
|
26
|
-
def parse_data(value: int) -> tuple:
|
|
27
|
-
return value, None
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@parse_data.overload(list)
|
|
31
|
-
def parse_data(value: list) -> tuple:
|
|
32
|
-
return tuple(value)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@parse_data.overload(str)
|
|
36
|
-
def parse_data(value: str) -> tuple:
|
|
37
|
-
match: Any = Pattern.PUBLIC.leftbound.search(value)
|
|
38
|
-
return value[: match.end()], value[match.end() :]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class Public(SlotList):
|
|
42
|
-
|
|
43
|
-
__slots__ = ("_base", "_qual")
|
|
44
|
-
|
|
45
|
-
data: tuple
|
|
46
|
-
base: Base
|
|
47
|
-
qual: Qual
|
|
48
|
-
|
|
49
|
-
@setdoc.basic
|
|
50
|
-
def __init__(self: Self, data: Any = None) -> None:
|
|
51
|
-
self._base = Base()
|
|
52
|
-
self._qual = Qual()
|
|
53
|
-
self.data = data
|
|
54
|
-
|
|
55
|
-
def _format(self: Self, format_spec: str) -> str:
|
|
56
|
-
return format(self.base, format_spec) + format(self.qual)
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def base(self: Self) -> Base:
|
|
60
|
-
"This property represents the version base."
|
|
61
|
-
return self._base
|
|
62
|
-
|
|
63
|
-
@base.setter
|
|
64
|
-
@guard
|
|
65
|
-
def base(self: Self, value: Any) -> None:
|
|
66
|
-
self.base.data = value
|
|
67
|
-
|
|
68
|
-
@property
|
|
69
|
-
@setdoc.basic
|
|
70
|
-
def data(self: Self) -> list:
|
|
71
|
-
return self.base, self.qual
|
|
72
|
-
|
|
73
|
-
@data.setter
|
|
74
|
-
@guard
|
|
75
|
-
def data(self: Self, value: Any) -> None:
|
|
76
|
-
self.base, self.qual = parse_data(value)
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def qual(self: Self) -> Qual:
|
|
80
|
-
"This property represents the qualification."
|
|
81
|
-
return self._qual
|
|
82
|
-
|
|
83
|
-
@qual.setter
|
|
84
|
-
@guard
|
|
85
|
-
def qual(self: Self, value: Any) -> None:
|
|
86
|
-
self.qual.data = value
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|