v440 0.2.0__3-none-any.whl
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/__init__.py +1 -0
- v440/_core/Local.py +118 -0
- v440/_core/Pre.py +138 -0
- v440/_core/Release.py +251 -0
- v440/_core/Version.py +264 -0
- v440/_core/__init__.py +2 -0
- v440/_core/utils.py +196 -0
- v440-0.2.0.dist-info/LICENSE.txt +21 -0
- v440-0.2.0.dist-info/METADATA +74 -0
- v440-0.2.0.dist-info/RECORD +12 -0
- v440-0.2.0.dist-info/WHEEL +5 -0
- v440-0.2.0.dist-info/top_level.txt +1 -0
v440/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from v440._core import *
|
v440/_core/Local.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import types
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
import scaevola
|
|
7
|
+
|
|
8
|
+
from . import utils
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@utils.compclass(list)
|
|
12
|
+
class Local(scaevola.Scaevola):
|
|
13
|
+
def __add__(self, other, /):
|
|
14
|
+
return self._new(self._data + self._todata(other))
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def __class_getitem__(cls, key, /):
|
|
18
|
+
return types.GenericAlias(cls, key)
|
|
19
|
+
|
|
20
|
+
def __eq__(self, other):
|
|
21
|
+
if type(self) != type(other):
|
|
22
|
+
return False
|
|
23
|
+
return self._data == other._data
|
|
24
|
+
|
|
25
|
+
def __getitem__(self, key, /):
|
|
26
|
+
if type(key) is not slice:
|
|
27
|
+
return self._data[key]
|
|
28
|
+
return self._new(self._data[key])
|
|
29
|
+
|
|
30
|
+
def __hash__(self):
|
|
31
|
+
raise TypeError("unhashable type: %r" % type(self).__name__)
|
|
32
|
+
|
|
33
|
+
def __iadd__(self, other, /):
|
|
34
|
+
self._data += self._todata(other)
|
|
35
|
+
|
|
36
|
+
def __imul__(self, other, /):
|
|
37
|
+
self._data *= other
|
|
38
|
+
|
|
39
|
+
def __init__(self, data=[]):
|
|
40
|
+
self.data = data
|
|
41
|
+
|
|
42
|
+
def __le__(self, other):
|
|
43
|
+
other = type(self)(other)
|
|
44
|
+
return self._cmpkey() <= other._cmpkey()
|
|
45
|
+
|
|
46
|
+
def __lt__(self, other):
|
|
47
|
+
other = type(self)(other)
|
|
48
|
+
return self._cmpkey() < other._cmpkey()
|
|
49
|
+
|
|
50
|
+
def __mul__(self, other, /):
|
|
51
|
+
return self._new(self._data * other)
|
|
52
|
+
|
|
53
|
+
def __repr__(self) -> str:
|
|
54
|
+
return "%s(%r)" % (type(self).__name__, str(self))
|
|
55
|
+
|
|
56
|
+
def __reversed__(self, /):
|
|
57
|
+
ans = self[:]
|
|
58
|
+
ans._data.reverse()
|
|
59
|
+
return ans
|
|
60
|
+
|
|
61
|
+
def __rmul__(self, other, /):
|
|
62
|
+
return self.__mul__(other)
|
|
63
|
+
|
|
64
|
+
def __setitem__(self, key, value, /):
|
|
65
|
+
if type(key) is not slice:
|
|
66
|
+
self._data[key] = utils.segment(value)
|
|
67
|
+
else:
|
|
68
|
+
self._data[key] = self._todata(value._data)
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
return ".".join(str(x) for x in self)
|
|
72
|
+
|
|
73
|
+
def _cmpkey(self):
|
|
74
|
+
return [self._sortkey(x) for x in self]
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def _new(cls, data, /):
|
|
78
|
+
ans = object.__new__(cls)
|
|
79
|
+
ans._data = data
|
|
80
|
+
return ans
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def _sortkey(value):
|
|
84
|
+
return type(value) is int, value
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _todata(data, /):
|
|
88
|
+
return utils.todata(data, "+")
|
|
89
|
+
|
|
90
|
+
def append(self, elem, /):
|
|
91
|
+
self._data.append(utils.segment(elem))
|
|
92
|
+
|
|
93
|
+
def copy(self):
|
|
94
|
+
return self._new(self.data)
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def data(self, /):
|
|
98
|
+
return list(self._data)
|
|
99
|
+
|
|
100
|
+
@data.setter
|
|
101
|
+
@utils.setterdeco
|
|
102
|
+
def data(self, data, /):
|
|
103
|
+
self._data = self._todata(data)
|
|
104
|
+
|
|
105
|
+
@data.deleter
|
|
106
|
+
def data(self):
|
|
107
|
+
self._data = []
|
|
108
|
+
|
|
109
|
+
def extend(self, data, /):
|
|
110
|
+
self.__iadd__(data)
|
|
111
|
+
|
|
112
|
+
def insert(self, index, elem, /):
|
|
113
|
+
self._data.insert(index, utils.segment(elem))
|
|
114
|
+
|
|
115
|
+
def sort(self, *, key=None, reverse=False):
|
|
116
|
+
if key is None:
|
|
117
|
+
key = self._sortkey
|
|
118
|
+
self._data.sort(key=key, reverse=reverse)
|
v440/_core/Pre.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
import scaevola
|
|
6
|
+
|
|
7
|
+
from . import utils
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Pre:
|
|
11
|
+
_PHASEDICT = dict(
|
|
12
|
+
alpha="a",
|
|
13
|
+
a="a",
|
|
14
|
+
beta="b",
|
|
15
|
+
b="b",
|
|
16
|
+
preview="rc",
|
|
17
|
+
pre="rc",
|
|
18
|
+
c="rc",
|
|
19
|
+
rc="rc",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def __bool__(self):
|
|
23
|
+
return bool(self.phase)
|
|
24
|
+
|
|
25
|
+
def __eq__(self, other):
|
|
26
|
+
if type(other) is not type(self):
|
|
27
|
+
return False
|
|
28
|
+
return self.data == other.data
|
|
29
|
+
|
|
30
|
+
def __hash__(self) -> int:
|
|
31
|
+
return hash((self.phase, self.subphase))
|
|
32
|
+
|
|
33
|
+
@typing.overload
|
|
34
|
+
def __init__(self, data=None) -> None: ...
|
|
35
|
+
@typing.overload
|
|
36
|
+
def __init__(self, phase, subphase=0): ...
|
|
37
|
+
|
|
38
|
+
def __init__(self, *args, **kwargs):
|
|
39
|
+
self._init(*args, **kwargs)(*args, **kwargs)
|
|
40
|
+
|
|
41
|
+
def __repr__(self) -> str:
|
|
42
|
+
return "%s(%r)" % (type(self).__name__, str(self))
|
|
43
|
+
|
|
44
|
+
def __str__(self) -> str:
|
|
45
|
+
if self:
|
|
46
|
+
return self.phase + str(self.subphase)
|
|
47
|
+
else:
|
|
48
|
+
return ""
|
|
49
|
+
|
|
50
|
+
def _init(self, *args, **kwargs):
|
|
51
|
+
if "data" in kwargs.keys():
|
|
52
|
+
return self._init_data
|
|
53
|
+
if kwargs:
|
|
54
|
+
return self._init_items
|
|
55
|
+
if len(args) > 1:
|
|
56
|
+
return self._init_items
|
|
57
|
+
return self._init_data
|
|
58
|
+
|
|
59
|
+
def _init_data(self, data=None):
|
|
60
|
+
self.data = data
|
|
61
|
+
|
|
62
|
+
def _init_items(self, phase, subphase=0):
|
|
63
|
+
self.phase = phase
|
|
64
|
+
self.subphase = subphase
|
|
65
|
+
|
|
66
|
+
def copy(self):
|
|
67
|
+
return type(self)(self)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def data(self):
|
|
71
|
+
if not self.phase:
|
|
72
|
+
return None
|
|
73
|
+
return self.phase, self.subphase
|
|
74
|
+
|
|
75
|
+
@data.setter
|
|
76
|
+
@utils.setterdeco
|
|
77
|
+
def data(self, value, /):
|
|
78
|
+
value = utils.todata(value, ".")
|
|
79
|
+
if len(value) == 0:
|
|
80
|
+
del self.data
|
|
81
|
+
return
|
|
82
|
+
if len(value) > 1:
|
|
83
|
+
self.phase, self.subphase = value
|
|
84
|
+
return
|
|
85
|
+
value = value[0]
|
|
86
|
+
if type(value) is int:
|
|
87
|
+
raise TypeError
|
|
88
|
+
for long, short in type(self)._PHASEDICT.items():
|
|
89
|
+
p, value = utils.lsplit(value, long, "")
|
|
90
|
+
if p == "":
|
|
91
|
+
continue
|
|
92
|
+
self.phase = short
|
|
93
|
+
self.subphase = value[len(long) :]
|
|
94
|
+
return
|
|
95
|
+
raise ValueError
|
|
96
|
+
|
|
97
|
+
@data.deleter
|
|
98
|
+
def data(self):
|
|
99
|
+
del self.phase
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def phase(self):
|
|
103
|
+
return self._phase
|
|
104
|
+
|
|
105
|
+
@phase.setter
|
|
106
|
+
@utils.setterdeco
|
|
107
|
+
def phase(self, value):
|
|
108
|
+
if not value:
|
|
109
|
+
del self.phase
|
|
110
|
+
return
|
|
111
|
+
value = utils.literal(value)
|
|
112
|
+
value = type(self)._PHASEDICT[value]
|
|
113
|
+
self._phase = value
|
|
114
|
+
|
|
115
|
+
@phase.deleter
|
|
116
|
+
def phase(self):
|
|
117
|
+
self._phase = None
|
|
118
|
+
self._subphase = 0
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def subphase(self):
|
|
122
|
+
return self._subphase
|
|
123
|
+
|
|
124
|
+
@subphase.setter
|
|
125
|
+
@utils.setterdeco
|
|
126
|
+
def subphase(self, value):
|
|
127
|
+
value = utils.numeral(value)
|
|
128
|
+
if value == 0:
|
|
129
|
+
del self.subphase
|
|
130
|
+
return
|
|
131
|
+
if self.phase:
|
|
132
|
+
self._subphase = value
|
|
133
|
+
return
|
|
134
|
+
raise utils.VersionError("no subphase allowed without a phase")
|
|
135
|
+
|
|
136
|
+
@subphase.deleter
|
|
137
|
+
def subphase(self):
|
|
138
|
+
self._subphase = 0
|
v440/_core/Release.py
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import types
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
import scaevola
|
|
7
|
+
|
|
8
|
+
from . import utils
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@utils.compclass(list)
|
|
12
|
+
class Release(scaevola.Scaevola):
|
|
13
|
+
def __add__(self, other):
|
|
14
|
+
return type(self)(self._data + list(other))
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def __class_getitem__(cls, key, /):
|
|
18
|
+
return types.GenericAlias(cls, key)
|
|
19
|
+
|
|
20
|
+
def __delitem__(self, index, /) -> None:
|
|
21
|
+
del self._data[index]
|
|
22
|
+
self._rstrip()
|
|
23
|
+
|
|
24
|
+
def __eq__(self, other):
|
|
25
|
+
if type(self) != type(other):
|
|
26
|
+
return False
|
|
27
|
+
return self._data == other._data
|
|
28
|
+
|
|
29
|
+
def __format__(self, cutoff=None):
|
|
30
|
+
return self.format(cutoff=cutoff)
|
|
31
|
+
|
|
32
|
+
def __getitem__(self, key):
|
|
33
|
+
if type(key) is slice:
|
|
34
|
+
return self._getitem_slice(key)
|
|
35
|
+
else:
|
|
36
|
+
return self._getitem_index(key)
|
|
37
|
+
|
|
38
|
+
def __hash__(self):
|
|
39
|
+
raise TypeError("unhashable type: %r" % type(self).__name__)
|
|
40
|
+
|
|
41
|
+
def __iadd__(self, other, /):
|
|
42
|
+
self._data += self._todata(other)
|
|
43
|
+
self._rstrip()
|
|
44
|
+
|
|
45
|
+
def __init__(self, data=[], /):
|
|
46
|
+
self.data = data
|
|
47
|
+
|
|
48
|
+
def __le__(self, other):
|
|
49
|
+
other = type(self)(other)
|
|
50
|
+
return self._data <= other._data
|
|
51
|
+
|
|
52
|
+
def __lt__(self, other):
|
|
53
|
+
other = type(self)(other)
|
|
54
|
+
return self._data < other._data
|
|
55
|
+
|
|
56
|
+
def __mul__(self, other):
|
|
57
|
+
return self._new(self._data * other)
|
|
58
|
+
|
|
59
|
+
def __repr__(self) -> str:
|
|
60
|
+
return "%s(%r)" % (type(self).__name__, str(self))
|
|
61
|
+
|
|
62
|
+
def __reversed__(self):
|
|
63
|
+
return type(self)(reversed(self._data))
|
|
64
|
+
|
|
65
|
+
def __rmul__(self, other):
|
|
66
|
+
return self.__mul__(other)
|
|
67
|
+
|
|
68
|
+
def __setitem__(self, key, value):
|
|
69
|
+
if type(key) is slice:
|
|
70
|
+
self._setitem_slice(key, value)
|
|
71
|
+
else:
|
|
72
|
+
self._setitem_index(key, value)
|
|
73
|
+
|
|
74
|
+
def __str__(self) -> str:
|
|
75
|
+
return ".".join(str(x) for x in self)
|
|
76
|
+
|
|
77
|
+
def _getitem_index(self, key):
|
|
78
|
+
key = utils.toindex(key)
|
|
79
|
+
if len(self) <= key:
|
|
80
|
+
return 0
|
|
81
|
+
return self._data[key]
|
|
82
|
+
|
|
83
|
+
def _getitem_slice(self, key):
|
|
84
|
+
ans = self._range(key)
|
|
85
|
+
ans = [self._getitem_index(i) for i in ans]
|
|
86
|
+
return ans
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def _new(cls, data, /):
|
|
90
|
+
ans = object.__new__(cls)
|
|
91
|
+
ans._data = data
|
|
92
|
+
return ans
|
|
93
|
+
|
|
94
|
+
def _range(self, key):
|
|
95
|
+
start = key.start
|
|
96
|
+
stop = key.stop
|
|
97
|
+
step = key.step
|
|
98
|
+
if step is None:
|
|
99
|
+
step = 1
|
|
100
|
+
else:
|
|
101
|
+
step = utils.toindex(step)
|
|
102
|
+
if step == 0:
|
|
103
|
+
raise ValueError
|
|
104
|
+
fwd = step > 0
|
|
105
|
+
if start is None:
|
|
106
|
+
start = 0 if fwd else len(self) - 1
|
|
107
|
+
else:
|
|
108
|
+
start = utils.toindex(start)
|
|
109
|
+
if stop is None:
|
|
110
|
+
stop = len(self) if fwd else -1
|
|
111
|
+
else:
|
|
112
|
+
stop = utils.toindex(stop)
|
|
113
|
+
if start < 0:
|
|
114
|
+
start += len(self)
|
|
115
|
+
if start < 0:
|
|
116
|
+
start = 0 if fwd else -1
|
|
117
|
+
if stop < 0:
|
|
118
|
+
stop += len(self)
|
|
119
|
+
if stop < 0:
|
|
120
|
+
stop = 0 if fwd else -1
|
|
121
|
+
return range(start, stop, step)
|
|
122
|
+
|
|
123
|
+
def _rstrip(self):
|
|
124
|
+
if not self._data:
|
|
125
|
+
return
|
|
126
|
+
while self._data[-1] == 0:
|
|
127
|
+
self._data.pop(0)
|
|
128
|
+
|
|
129
|
+
def _setitem_index(self, key, value):
|
|
130
|
+
key = utils.toindex(key)
|
|
131
|
+
value = utils.numeral(value)
|
|
132
|
+
if len(self) > key:
|
|
133
|
+
self._data[key] = value
|
|
134
|
+
self._rstrip()
|
|
135
|
+
return
|
|
136
|
+
if value == 0:
|
|
137
|
+
return
|
|
138
|
+
self._data.extend([0] * (key - len(self)))
|
|
139
|
+
self._data.append(value)
|
|
140
|
+
|
|
141
|
+
def _setitem_slice(self, key, value):
|
|
142
|
+
key = list(self._range(key))
|
|
143
|
+
value = self._todata(value)
|
|
144
|
+
if len(key) != len(value):
|
|
145
|
+
e = "attempt to assign sequence of size %s to extended slice of size %s"
|
|
146
|
+
e %= (len(value), len(key))
|
|
147
|
+
raise ValueError(e)
|
|
148
|
+
for k, v in zip(key, value):
|
|
149
|
+
self._setitem_index(k, v)
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def _todata(value):
|
|
153
|
+
return [utils.numeral(x) for x in utils.tolist(value, "v")]
|
|
154
|
+
|
|
155
|
+
def append(self, element):
|
|
156
|
+
element = utils.numeral(element)
|
|
157
|
+
if element:
|
|
158
|
+
self._data.append(element)
|
|
159
|
+
|
|
160
|
+
def bump(self, index=-1, amount=1):
|
|
161
|
+
x = self._getitem_index(index) + amount
|
|
162
|
+
self._setitem_index(index, x)
|
|
163
|
+
if index != -1:
|
|
164
|
+
self._data = self._data[: index + 1]
|
|
165
|
+
self._rstrip()
|
|
166
|
+
|
|
167
|
+
def copy(self):
|
|
168
|
+
return self.__mul__(1)
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def data(self):
|
|
172
|
+
return list(self._data)
|
|
173
|
+
|
|
174
|
+
@data.setter
|
|
175
|
+
@utils.setterdeco
|
|
176
|
+
def data(self, v):
|
|
177
|
+
del self.data
|
|
178
|
+
self.extend(v)
|
|
179
|
+
|
|
180
|
+
@data.deleter
|
|
181
|
+
def data(self):
|
|
182
|
+
self._data = []
|
|
183
|
+
|
|
184
|
+
def extend(self, data, /):
|
|
185
|
+
self._data.extend(self._todata(data))
|
|
186
|
+
self._rstrip()
|
|
187
|
+
|
|
188
|
+
def format(self, cutoff=None):
|
|
189
|
+
ans = self[:cutoff]
|
|
190
|
+
ans = [str(x) for x in ans]
|
|
191
|
+
ans = ".".join(ans)
|
|
192
|
+
return ans
|
|
193
|
+
|
|
194
|
+
def insert(self, index, elem, /):
|
|
195
|
+
self[index:index] = [elem]
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def major(self) -> int:
|
|
199
|
+
return self[0]
|
|
200
|
+
|
|
201
|
+
@major.setter
|
|
202
|
+
@utils.setterdeco
|
|
203
|
+
def major(self, value: typing.Any):
|
|
204
|
+
self[0] = value
|
|
205
|
+
|
|
206
|
+
@major.deleter
|
|
207
|
+
def major(self):
|
|
208
|
+
del self[0]
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def micro(self) -> int:
|
|
212
|
+
return self[2]
|
|
213
|
+
|
|
214
|
+
@micro.setter
|
|
215
|
+
@utils.setterdeco
|
|
216
|
+
def micro(self, value: typing.Any):
|
|
217
|
+
self[2] = value
|
|
218
|
+
|
|
219
|
+
@micro.deleter
|
|
220
|
+
def micro(self):
|
|
221
|
+
del self[2]
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def minor(self) -> int:
|
|
225
|
+
return self[1]
|
|
226
|
+
|
|
227
|
+
@minor.setter
|
|
228
|
+
@utils.setterdeco
|
|
229
|
+
def minor(self, value: typing.Any):
|
|
230
|
+
self[1] = value
|
|
231
|
+
|
|
232
|
+
@minor.deleter
|
|
233
|
+
def minor(self):
|
|
234
|
+
del self[1]
|
|
235
|
+
|
|
236
|
+
def pop(self, index=-1, /):
|
|
237
|
+
ans = self._data.pop(index)
|
|
238
|
+
self._rstrip()
|
|
239
|
+
return ans
|
|
240
|
+
|
|
241
|
+
def remove(self, elem, /) -> None:
|
|
242
|
+
self._data.remove(elem)
|
|
243
|
+
self._rstrip()
|
|
244
|
+
|
|
245
|
+
def reverse(self):
|
|
246
|
+
self._data.reverse()
|
|
247
|
+
self._rstrip()
|
|
248
|
+
|
|
249
|
+
def sort(self, *, key=None, reverse=False):
|
|
250
|
+
self._data.sort(key=key, reverse=reverse)
|
|
251
|
+
self._rstrip()
|
v440/_core/Version.py
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
import packaging.version
|
|
6
|
+
import scaevola
|
|
7
|
+
|
|
8
|
+
from v440._core.Local import Local
|
|
9
|
+
from v440._core.Pre import Pre
|
|
10
|
+
from v440._core.Release import Release
|
|
11
|
+
|
|
12
|
+
from . import utils
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Version(scaevola.Scaevola):
|
|
16
|
+
def __bool__(self):
|
|
17
|
+
return self != type(self)()
|
|
18
|
+
|
|
19
|
+
def __eq__(self, other) -> bool:
|
|
20
|
+
other = type(self)(other)
|
|
21
|
+
return self._cmpkey() == other._cmpkey()
|
|
22
|
+
|
|
23
|
+
def __hash__(self) -> int:
|
|
24
|
+
return hash(self._cmpkey())
|
|
25
|
+
|
|
26
|
+
def __init__(self, data="0", /, **kwargs) -> None:
|
|
27
|
+
self.data = data
|
|
28
|
+
self.update(**kwargs)
|
|
29
|
+
|
|
30
|
+
def __le__(self, other) -> bool:
|
|
31
|
+
other = type(self)(other)
|
|
32
|
+
return self._cmpkey() <= other._cmpkey()
|
|
33
|
+
|
|
34
|
+
def __lt__(self, other) -> bool:
|
|
35
|
+
other = type(self)(other)
|
|
36
|
+
return self._cmpkey() < other._cmpkey()
|
|
37
|
+
|
|
38
|
+
def __repr__(self) -> str:
|
|
39
|
+
return "%s(%r)" % (type(self).__name__, str(self))
|
|
40
|
+
|
|
41
|
+
def __str__(self) -> str:
|
|
42
|
+
return self.data
|
|
43
|
+
|
|
44
|
+
def _aux(self) -> str:
|
|
45
|
+
ans = str(self.pre)
|
|
46
|
+
if self.post is not None:
|
|
47
|
+
ans += ".post%s" % self.post
|
|
48
|
+
if self.dev is not None:
|
|
49
|
+
ans += ".dev%s" % self.dev
|
|
50
|
+
return ans
|
|
51
|
+
|
|
52
|
+
def _cmpkey(self) -> tuple:
|
|
53
|
+
if self.pre:
|
|
54
|
+
pre = self.pre.data
|
|
55
|
+
elif self.post is None and self.dev is not None:
|
|
56
|
+
pre = "", -1
|
|
57
|
+
else:
|
|
58
|
+
pre = "z", float("inf")
|
|
59
|
+
post = -1 if self.post is None else self.post
|
|
60
|
+
dev = float("inf") if self.dev is None else self.dev
|
|
61
|
+
return self.epoch, self.release, pre, post, dev, self.local
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def base(self) -> str:
|
|
65
|
+
if self.epoch:
|
|
66
|
+
return "%s!%s" % (self.epoch, self.release)
|
|
67
|
+
else:
|
|
68
|
+
return str(self.release)
|
|
69
|
+
|
|
70
|
+
@base.setter
|
|
71
|
+
@utils.setterdeco
|
|
72
|
+
def base(self, v):
|
|
73
|
+
v = str(v)
|
|
74
|
+
if "!" in v:
|
|
75
|
+
self.epoch, self.release = v.split("!")
|
|
76
|
+
else:
|
|
77
|
+
self.epoch, self.release = 0, v
|
|
78
|
+
|
|
79
|
+
@base.deleter
|
|
80
|
+
def base(self):
|
|
81
|
+
del self.epoch
|
|
82
|
+
del self.release
|
|
83
|
+
|
|
84
|
+
def clear(self):
|
|
85
|
+
del self.public
|
|
86
|
+
del self.local
|
|
87
|
+
|
|
88
|
+
def copy(self):
|
|
89
|
+
return type(self)(self)
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def data(self):
|
|
93
|
+
return self.format()
|
|
94
|
+
|
|
95
|
+
@data.setter
|
|
96
|
+
@utils.setterdeco
|
|
97
|
+
def data(self, x):
|
|
98
|
+
x = str(x)
|
|
99
|
+
if "+" in x:
|
|
100
|
+
self.public, self.local = x.split("+")
|
|
101
|
+
else:
|
|
102
|
+
self.public, self.local = x, None
|
|
103
|
+
|
|
104
|
+
@data.deleter
|
|
105
|
+
def data(self):
|
|
106
|
+
del self.public
|
|
107
|
+
del self.local
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def dev(self):
|
|
111
|
+
return self._dev
|
|
112
|
+
|
|
113
|
+
@dev.setter
|
|
114
|
+
@utils.setterdeco
|
|
115
|
+
def dev(self, v):
|
|
116
|
+
v = utils.tolist(v, ".")
|
|
117
|
+
if len(v) > 2:
|
|
118
|
+
raise ValueError
|
|
119
|
+
if len(v) == 0:
|
|
120
|
+
del self.dev
|
|
121
|
+
return
|
|
122
|
+
if len(v) == 1:
|
|
123
|
+
v = v[0]
|
|
124
|
+
v = utils.lsplit(v, "dev", "")
|
|
125
|
+
if v[0] != "dev":
|
|
126
|
+
raise ValueError
|
|
127
|
+
v = utils.numeral(v[1])
|
|
128
|
+
self._dev = v
|
|
129
|
+
|
|
130
|
+
@dev.deleter
|
|
131
|
+
def dev(self):
|
|
132
|
+
self._dev = None
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def epoch(self):
|
|
136
|
+
return self._epoch
|
|
137
|
+
|
|
138
|
+
@epoch.setter
|
|
139
|
+
@utils.setterdeco
|
|
140
|
+
def epoch(self, v):
|
|
141
|
+
v = str(v)
|
|
142
|
+
v = utils.lsplit(v, "v", "")[1]
|
|
143
|
+
if v.endswith("!"):
|
|
144
|
+
v = v[:-1]
|
|
145
|
+
v = utils.numeral(v)
|
|
146
|
+
return v
|
|
147
|
+
|
|
148
|
+
@epoch.deleter
|
|
149
|
+
def epoch(self):
|
|
150
|
+
self._epoch = 0
|
|
151
|
+
|
|
152
|
+
def format(self, cutoff=None) -> str:
|
|
153
|
+
ans = ""
|
|
154
|
+
if self.epoch:
|
|
155
|
+
ans += "%s!" % self.epoch
|
|
156
|
+
ans += self.release.format(cutoff=cutoff)
|
|
157
|
+
ans += self._aux()
|
|
158
|
+
if self.local:
|
|
159
|
+
ans += "+%s" % self.local
|
|
160
|
+
return ans
|
|
161
|
+
|
|
162
|
+
def is_prerelease(self) -> bool:
|
|
163
|
+
return self.dev is not None or self.pre is not None
|
|
164
|
+
|
|
165
|
+
def is_postrelease(self) -> bool:
|
|
166
|
+
return self.post is not None
|
|
167
|
+
|
|
168
|
+
def is_devrelease(self) -> bool:
|
|
169
|
+
return self.dev is not None
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def local(self) -> str:
|
|
173
|
+
return self._local
|
|
174
|
+
|
|
175
|
+
@local.setter
|
|
176
|
+
@utils.setterdeco
|
|
177
|
+
def local(self, v):
|
|
178
|
+
self._local = Local(v)
|
|
179
|
+
|
|
180
|
+
@local.deleter
|
|
181
|
+
def local(self):
|
|
182
|
+
self._local = Local()
|
|
183
|
+
|
|
184
|
+
def packaging(self):
|
|
185
|
+
return packaging.version.Version(self.data)
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def post(self):
|
|
189
|
+
return self._post
|
|
190
|
+
|
|
191
|
+
@post.setter
|
|
192
|
+
@utils.setterdeco
|
|
193
|
+
def post(self, v):
|
|
194
|
+
v = utils.tolist(v, ".")
|
|
195
|
+
if len(v) > 2:
|
|
196
|
+
raise ValueError
|
|
197
|
+
if len(v) == 0:
|
|
198
|
+
del self.post
|
|
199
|
+
return
|
|
200
|
+
prefices = "post", "rev", "r", ""
|
|
201
|
+
if len(v) == 1:
|
|
202
|
+
v = utils.lsplit(v[0], *prefices)
|
|
203
|
+
elif v[0] not in prefices:
|
|
204
|
+
raise ValueError
|
|
205
|
+
v = utils.numeral(v[1])
|
|
206
|
+
self._post = v
|
|
207
|
+
|
|
208
|
+
@post.deleter
|
|
209
|
+
def post(self):
|
|
210
|
+
self._post = None
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def pre(self):
|
|
214
|
+
return self._pre
|
|
215
|
+
|
|
216
|
+
@pre.setter
|
|
217
|
+
@utils.setterdeco
|
|
218
|
+
def pre(self, data, /):
|
|
219
|
+
self._pre = Pre(data)
|
|
220
|
+
|
|
221
|
+
@pre.deleter
|
|
222
|
+
def pre(self):
|
|
223
|
+
self._pre = Pre()
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def public(self) -> str:
|
|
227
|
+
return self.base + self._aux()
|
|
228
|
+
|
|
229
|
+
@public.setter
|
|
230
|
+
@utils.setterdeco
|
|
231
|
+
def public(self, v):
|
|
232
|
+
v = str(v).lower().strip()
|
|
233
|
+
d = utils.Pattern.PUBLIC.regex.search(v).groupdict()
|
|
234
|
+
names = "epoch release pre post dev".split()
|
|
235
|
+
for n in names:
|
|
236
|
+
setattr(self, n, d[n])
|
|
237
|
+
|
|
238
|
+
@public.deleter
|
|
239
|
+
def public(self):
|
|
240
|
+
self.public = "0"
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def release(self) -> Release:
|
|
244
|
+
return self._release
|
|
245
|
+
|
|
246
|
+
@release.setter
|
|
247
|
+
@utils.setterdeco
|
|
248
|
+
def release(self, v):
|
|
249
|
+
self._release = Release(v)
|
|
250
|
+
|
|
251
|
+
@release.deleter
|
|
252
|
+
def release(self):
|
|
253
|
+
self._release = Release()
|
|
254
|
+
|
|
255
|
+
def update(self, **kwargs):
|
|
256
|
+
for k, v in kwargs.items():
|
|
257
|
+
attr = getattr(type(self), k)
|
|
258
|
+
if isinstance(attr, property):
|
|
259
|
+
setattr(self, k, v)
|
|
260
|
+
continue
|
|
261
|
+
e = "%r is not a property"
|
|
262
|
+
e %= k
|
|
263
|
+
e = AttributeError(e)
|
|
264
|
+
raise e
|
v440/_core/__init__.py
ADDED
v440/_core/utils.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
import functools
|
|
5
|
+
import inspect
|
|
6
|
+
import re
|
|
7
|
+
import string
|
|
8
|
+
import typing
|
|
9
|
+
|
|
10
|
+
SEGCHARS = string.ascii_lowercase + string.digits
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EMPTY: ...
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def compclass(innerclass):
|
|
17
|
+
return functools.partial(compclass_core, innerclass)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def compclass_core(innerclass, outerclass):
|
|
21
|
+
for n in dir(innerclass):
|
|
22
|
+
if not (isnunder(n) or ismagic(n)):
|
|
23
|
+
continue
|
|
24
|
+
i = getattr(innerclass, n)
|
|
25
|
+
if type(i) is type:
|
|
26
|
+
continue
|
|
27
|
+
if not callable(i):
|
|
28
|
+
continue
|
|
29
|
+
o = getattr(outerclass, n, EMPTY)
|
|
30
|
+
o = compclass_outerfunc(n, o)
|
|
31
|
+
if isnunder(n):
|
|
32
|
+
o = functools.wraps(i)(o)
|
|
33
|
+
setattr(outerclass, n, o)
|
|
34
|
+
return outerclass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def compclass_outerfunc(n, gotten, /):
|
|
38
|
+
if gotten is not EMPTY:
|
|
39
|
+
return gotten
|
|
40
|
+
|
|
41
|
+
def o(self, *args, **kwargs):
|
|
42
|
+
f = getattr(self._data, n)
|
|
43
|
+
y = f(*args, **kwargs)
|
|
44
|
+
return y
|
|
45
|
+
|
|
46
|
+
return o
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def ismagic(name):
|
|
50
|
+
name = str(name)
|
|
51
|
+
if len(name) < 5:
|
|
52
|
+
return False
|
|
53
|
+
if not name.startswith("__"):
|
|
54
|
+
return False
|
|
55
|
+
if not name.endswith("__"):
|
|
56
|
+
return False
|
|
57
|
+
if name.startswith("___"):
|
|
58
|
+
return False
|
|
59
|
+
if name.endswith("___"):
|
|
60
|
+
return False
|
|
61
|
+
return True
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def isnunder(name):
|
|
65
|
+
name = str(name)
|
|
66
|
+
return not name.startswith("_")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def literal(value, /):
|
|
70
|
+
e = "%r is not a valid literal segment"
|
|
71
|
+
e = VersionError(e % value)
|
|
72
|
+
try:
|
|
73
|
+
x = segment(value)
|
|
74
|
+
except:
|
|
75
|
+
raise e
|
|
76
|
+
if type(x) is str:
|
|
77
|
+
return x
|
|
78
|
+
raise e
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def lsplit(value: str, *prefices):
|
|
82
|
+
for p in prefices:
|
|
83
|
+
if value.startswith(p):
|
|
84
|
+
return p, value[len(p) :]
|
|
85
|
+
raise ValueError
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def numeral(value, /):
|
|
89
|
+
e = "%r is not a valid numeral segment"
|
|
90
|
+
e = VersionError(e % value)
|
|
91
|
+
try:
|
|
92
|
+
x = segment(value)
|
|
93
|
+
except:
|
|
94
|
+
raise e
|
|
95
|
+
if type(x) is int:
|
|
96
|
+
return x
|
|
97
|
+
if x == "":
|
|
98
|
+
return 0
|
|
99
|
+
raise e
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def segment(value, /):
|
|
103
|
+
e = "%r is not a valid segment"
|
|
104
|
+
e = VersionError(e % value)
|
|
105
|
+
try:
|
|
106
|
+
x = str(value).lower().strip()
|
|
107
|
+
except:
|
|
108
|
+
raise e
|
|
109
|
+
if x.strip(SEGCHARS):
|
|
110
|
+
raise e
|
|
111
|
+
try:
|
|
112
|
+
return int(x)
|
|
113
|
+
except:
|
|
114
|
+
return x
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def setterdeco(old, /):
|
|
118
|
+
@functools.wraps(old)
|
|
119
|
+
def new(self, value, /):
|
|
120
|
+
if value is None:
|
|
121
|
+
delattr(self, old.__name__)
|
|
122
|
+
return
|
|
123
|
+
try:
|
|
124
|
+
old(self, value)
|
|
125
|
+
except VersionError:
|
|
126
|
+
raise
|
|
127
|
+
except:
|
|
128
|
+
e = "%r is an invalid value for %r"
|
|
129
|
+
e %= (value, old.__name__)
|
|
130
|
+
raise VersionError(e)
|
|
131
|
+
|
|
132
|
+
return new
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def todata(value, *args):
|
|
136
|
+
try:
|
|
137
|
+
return tolist(value, *args)
|
|
138
|
+
except VersionError:
|
|
139
|
+
raise
|
|
140
|
+
except:
|
|
141
|
+
e = "%r is an invalid value for %r"
|
|
142
|
+
e %= (value, "data")
|
|
143
|
+
raise VersionError(e)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def toindex(value, /):
|
|
147
|
+
ans = value.__index__()
|
|
148
|
+
if type(ans) is not int:
|
|
149
|
+
raise TypeError("__index__ returned non-int (type %s)" % type(ans).__name__)
|
|
150
|
+
return ans
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def tolist(value, prefix):
|
|
154
|
+
if value is None:
|
|
155
|
+
return
|
|
156
|
+
if not issubclass(type(value), str) and hasattr(value, "__iter__"):
|
|
157
|
+
return list(value)
|
|
158
|
+
value = str(value).lower()
|
|
159
|
+
value = value.replace("-", ".")
|
|
160
|
+
value = value.replace("_", ".")
|
|
161
|
+
value = lsplit(value, prefix, "")[1]
|
|
162
|
+
if value == "":
|
|
163
|
+
return []
|
|
164
|
+
value = value.split(".")
|
|
165
|
+
return value
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class Pattern(enum.StrEnum):
|
|
169
|
+
EPOCH = r"(?:(?P<epoch>[0-9]+)!)?"
|
|
170
|
+
RELEASE = r"(?P<release>[0-9]+(?:\.[0-9]+)*)"
|
|
171
|
+
PRE = r"""
|
|
172
|
+
(?P<pre>
|
|
173
|
+
[-_\.]?
|
|
174
|
+
(?P<pre_l>alpha|a|beta|b|preview|pre|c|rc)
|
|
175
|
+
[-_\.]?
|
|
176
|
+
(?P<pre_n>[0-9]+)?
|
|
177
|
+
)?"""
|
|
178
|
+
POST = r"""
|
|
179
|
+
(?P<post>
|
|
180
|
+
(?:-(?:[0-9]+))
|
|
181
|
+
|
|
|
182
|
+
(?: [-_\.]? (?:post|rev|r) [-_\.]? (?:[0-9]+)? )
|
|
183
|
+
)?"""
|
|
184
|
+
DEV = r"""(?P<dev> [-_\.]? dev [-_\.]? (?:[0-9]+)? )?"""
|
|
185
|
+
LOCAL = r"""(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?"""
|
|
186
|
+
PUBLIC = f"v? {EPOCH} {RELEASE} {PRE} {POST} {DEV}"
|
|
187
|
+
|
|
188
|
+
@functools.cached_property
|
|
189
|
+
def regex(self):
|
|
190
|
+
p = self.value
|
|
191
|
+
p = r"^" + p + r"$"
|
|
192
|
+
ans = re.compile(p, re.VERBOSE)
|
|
193
|
+
return ans
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class VersionError(ValueError): ...
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Johannes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: v440
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: mutable version objects
|
|
5
|
+
Author-email: Johannes <johannes-programming@mailfence.com>
|
|
6
|
+
License: The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Johannes
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Project-URL: Download, https://pypi.org/project/v440/#files
|
|
28
|
+
Project-URL: Source, https://github.com/johannes-programming/v440
|
|
29
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
30
|
+
Classifier: Programming Language :: Python
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
33
|
+
Requires-Python: >=3.12
|
|
34
|
+
Description-Content-Type: text/x-rst
|
|
35
|
+
License-File: LICENSE.txt
|
|
36
|
+
Requires-Dist: packaging >=23.2
|
|
37
|
+
Requires-Dist: scaevola >=1.0.5
|
|
38
|
+
|
|
39
|
+
====
|
|
40
|
+
v440
|
|
41
|
+
====
|
|
42
|
+
|
|
43
|
+
Overview
|
|
44
|
+
--------
|
|
45
|
+
|
|
46
|
+
mutable version objects in accordance with PEP440
|
|
47
|
+
|
|
48
|
+
Installation
|
|
49
|
+
------------
|
|
50
|
+
|
|
51
|
+
To install v440, you can use `pip`. Open your terminal and run:
|
|
52
|
+
|
|
53
|
+
.. code-block:: bash
|
|
54
|
+
|
|
55
|
+
pip install v440
|
|
56
|
+
|
|
57
|
+
License
|
|
58
|
+
-------
|
|
59
|
+
|
|
60
|
+
This project is licensed under the MIT License.
|
|
61
|
+
|
|
62
|
+
Links
|
|
63
|
+
-----
|
|
64
|
+
|
|
65
|
+
* `Download <https://pypi.org/project/v440/#files>`_
|
|
66
|
+
* `Source <https://github.com/johannes-programming/v440>`_
|
|
67
|
+
|
|
68
|
+
Credits
|
|
69
|
+
-------
|
|
70
|
+
|
|
71
|
+
- Author: Johannes
|
|
72
|
+
- Email: johannes-programming@mailfence.com
|
|
73
|
+
|
|
74
|
+
Thank you for using v440!
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
v440/__init__.py,sha256=MQrVNWvZoxumw3SE5XBnGWje_gQ7V_DvfDLv29UX0SE,25
|
|
2
|
+
v440/_core/Local.py,sha256=P_r3ZYlN_Ifn3Qp15wYa24y0bPvgksVHgrwwx4lyuY8,2820
|
|
3
|
+
v440/_core/Pre.py,sha256=yOA2bst5PdFwjcJhBHHC_a9XwdmvOnlwJhauXEYS0CI,3195
|
|
4
|
+
v440/_core/Release.py,sha256=-tEpa1uTQqK9vAt2WdOMKapvH0kT50_LSXUYOGjaPJo,6106
|
|
5
|
+
v440/_core/Version.py,sha256=BcnxNQvoA5CGg-3uBhg6BjcfHbU94_tIy6CSqAK_ETU,6114
|
|
6
|
+
v440/_core/__init__.py,sha256=uYjdaudy0Sc4ys1eoI8c7-WvW5394p5UNw2BI_thrRA,81
|
|
7
|
+
v440/_core/utils.py,sha256=q2sgR4nKSEuwjVgIk5kVdVBkoZ-zmGOEynGdspFwIpQ,4369
|
|
8
|
+
v440-0.2.0.dist-info/LICENSE.txt,sha256=QwqYepQwTN5xG57cngKt6xxYD9z9hw9d3lcI8zSLiNg,1074
|
|
9
|
+
v440-0.2.0.dist-info/METADATA,sha256=E0zZRIJP5VRvmTqKiCIJJ_9k_qW3lhxtpFR5NBULG94,2382
|
|
10
|
+
v440-0.2.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
11
|
+
v440-0.2.0.dist-info/top_level.txt,sha256=0KhvBmvlzcE4QlmK9pkVo1pXR2q-YDKG5Bj5yIXmWTE,5
|
|
12
|
+
v440-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v440
|