v440 2.0.0.dev60__tar.gz → 2.0.0.dev62__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.
Files changed (35) hide show
  1. {v440-2.0.0.dev60/src/v440.egg-info → v440-2.0.0.dev62}/PKG-INFO +1 -1
  2. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/pyproject.toml +1 -1
  3. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/BaseList.py +14 -44
  4. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/SlotList.py +12 -5
  5. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/VList.py +95 -1
  6. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/qualparse.py +0 -45
  7. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/utils.py +3 -16
  8. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/Base.py +39 -42
  9. v440-2.0.0.dev62/src/v440/core/Local.py +45 -0
  10. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/Public.py +35 -41
  11. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/Qual.py +44 -19
  12. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/Release.py +7 -17
  13. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/Version.py +34 -40
  14. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/tests/test_testdata.py +5 -4
  15. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/tests/test_version.py +3 -3
  16. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/tests/testdata.toml +7 -3
  17. {v440-2.0.0.dev60 → v440-2.0.0.dev62/src/v440.egg-info}/PKG-INFO +1 -1
  18. v440-2.0.0.dev60/src/v440/core/Local.py +0 -84
  19. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/LICENSE.txt +0 -0
  20. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/MANIFEST.in +0 -0
  21. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/README.rst +0 -0
  22. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/setup.cfg +0 -0
  23. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/__init__.py +0 -0
  24. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/Cfg.py +0 -0
  25. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/Digest.py +0 -0
  26. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/Pattern.py +0 -0
  27. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/__init__.py +0 -0
  28. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/_utils/cfg.toml +0 -0
  29. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/VersionError.py +0 -0
  30. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/core/__init__.py +0 -0
  31. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440/tests/__init__.py +0 -0
  32. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440.egg-info/SOURCES.txt +0 -0
  33. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440.egg-info/dependency_links.txt +0 -0
  34. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440.egg-info/requires.txt +0 -0
  35. {v440-2.0.0.dev60 → v440-2.0.0.dev62}/src/v440.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: v440
3
- Version: 2.0.0.dev60
3
+ Version: 2.0.0.dev62
4
4
  Summary: This project provides mutable version objects in accordance with PEP440.
5
5
  Author-email: Johannes <johannes.programming@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -36,7 +36,7 @@ keywords = []
36
36
  name = "v440"
37
37
  readme = "README.rst"
38
38
  requires-python = ">=3.11"
39
- version = "2.0.0.dev60"
39
+ version = "2.0.0.dev62"
40
40
 
41
41
  [project.license]
42
42
  file = "LICENSE.txt"
@@ -1,18 +1,17 @@
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
 
10
9
  from v440._utils.utils import guard
11
10
  from v440.core.VersionError import VersionError
12
11
 
13
12
 
14
13
  @scaevola.auto
15
- class BaseList(collections.abc.Collection):
14
+ class BaseList(metaclass=ABCMeta):
16
15
  __slots__ = ()
17
16
 
18
17
  string: str
@@ -21,17 +20,13 @@ class BaseList(collections.abc.Collection):
21
20
  @setdoc.basic
22
21
  def __bool__(self: Self) -> bool: ...
23
22
 
24
- @setdoc.basic
25
- def __contains__(self: Self, other: Any) -> bool:
26
- return other in self.data
27
-
28
23
  @setdoc.basic
29
24
  def __eq__(self: Self, other: Any) -> bool:
30
25
  try:
31
26
  alt: Self = type(self)(other)
32
27
  except VersionError:
33
28
  return False
34
- return self.data == alt.data
29
+ return self.string == alt.string
35
30
 
36
31
  @setdoc.basic
37
32
  def __format__(self: Self, format_spec: Any) -> str:
@@ -40,7 +35,7 @@ class BaseList(collections.abc.Collection):
40
35
  except Exception:
41
36
  msg: str = "unsupported format string passed to %s.__format__"
42
37
  msg %= type(self).__name__
43
- raise TypeError(msg) from None
38
+ raise TypeError(msg) # from None
44
39
 
45
40
  @setdoc.basic
46
41
  def __ge__(self: Self, other: Any) -> bool:
@@ -51,10 +46,6 @@ class BaseList(collections.abc.Collection):
51
46
  return NotImplemented
52
47
  return self._cmp() >= alt._cmp()
53
48
 
54
- @setdoc.basic
55
- def __getitem__(self: Self, key: Any) -> Any:
56
- return self.data[key]
57
-
58
49
  @setdoc.basic
59
50
  def __gt__(self: Self, other: Any) -> bool:
60
51
  alt: Self
@@ -66,13 +57,9 @@ class BaseList(collections.abc.Collection):
66
57
 
67
58
  __hash__ = unhash
68
59
 
60
+ @abstractmethod
69
61
  @setdoc.basic
70
- def __init__(self: Self, data: Any = None) -> None:
71
- self.data = data
72
-
73
- @setdoc.basic
74
- def __iter__(self: Self) -> Iterator:
75
- return iter(self.data)
62
+ def __init__(self: Self, string: Any) -> None: ...
76
63
 
77
64
  @setdoc.basic
78
65
  def __le__(self: Self, other: Any) -> bool:
@@ -96,19 +83,9 @@ class BaseList(collections.abc.Collection):
96
83
  def __ne__(self: Self, other: Any) -> bool:
97
84
  return not (self == other)
98
85
 
86
+ @abstractmethod
99
87
  @setdoc.basic
100
- def __repr__(self: Self) -> str:
101
- return datarepr(type(self).__name__, self.data)
102
-
103
- @setdoc.basic
104
- def __reversed__(self: Self) -> reversed:
105
- return reversed(self.data)
106
-
107
- @setdoc.basic
108
- def __setitem__(self: Self, key: Any, value: Any) -> None:
109
- data: list = list(self.data)
110
- data[key] = value
111
- self.data = data
88
+ def __repr__(self: Self) -> str: ...
112
89
 
113
90
  @classmethod
114
91
  def __subclasshook__(cls: type, other: type, /) -> bool:
@@ -125,26 +102,19 @@ class BaseList(collections.abc.Collection):
125
102
  @abstractmethod
126
103
  def _format(self: Self, format_spec: str) -> str: ...
127
104
 
105
+ @abstractmethod
106
+ def _set(self: Self, value: Any) -> None: ...
107
+
128
108
  @abstractmethod
129
109
  def _string_fset(self: Self, value: str) -> None: ...
130
110
 
111
+ @abstractmethod
112
+ def _todict(self: Self) -> dict: ...
113
+
131
114
  @setdoc.basic
132
115
  def copy(self: Self) -> Self:
133
116
  return type(self)(self)
134
117
 
135
- @property
136
- @abstractmethod
137
- @setdoc.basic
138
- def data(self: Self) -> tuple: ...
139
-
140
- def count(self: Self, value: Any) -> int:
141
- "This method counts the occurences of value."
142
- return self.data.count(value)
143
-
144
- def index(self: Self, *args: Any) -> None:
145
- "This method returns the index of the first occurence."
146
- return self.data.index(*args)
147
-
148
118
  @property
149
119
  def string(self: Self) -> str:
150
120
  return self._format("")
@@ -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,16 +13,21 @@ __all__ = ["SlotList"]
11
13
  class SlotList(BaseList):
12
14
  __slots__ = ()
13
15
 
14
- data: tuple
15
16
  string: str
16
17
 
17
- @setdoc.basic
18
- def __bool__(self: Self) -> bool:
19
- return any(self.data)
20
-
21
18
  @setdoc.basic
22
19
  def __len__(self: Self) -> int:
23
20
  return len(type(self).__slots__)
24
21
 
22
+ @setdoc.basic
23
+ def __repr__(self: Self) -> str:
24
+ return datarepr(type(self).__name__, **self._todict())
25
+
25
26
  def _cmp(self: Self) -> tuple:
26
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,14 +1,18 @@
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
@@ -57,6 +61,9 @@ class VList(BaseList):
57
61
  @abstractmethod
58
62
  def _sort(cls: type, value: Any): ...
59
63
 
64
+ def _todict(self: Self) -> dict:
65
+ return dict(data=self.data)
66
+
60
67
  def append(self: Self, value: Self, /) -> None:
61
68
  "This method appends value to self."
62
69
  data: list = list(self.data)
@@ -110,3 +117,90 @@ class VList(BaseList):
110
117
  r: bool = bool(reverse)
111
118
  data.sort(key=k, reverse=r)
112
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: dict = dict()
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
- restore(obj=self, backup=backup)
81
+ setattr(self, old.__name__, backup)
87
82
  raise
88
83
  except Exception:
89
- restore(obj=self, backup=backup)
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,16 +45,42 @@ class Base(SlotList):
70
45
 
71
46
  __slots__ = ("_epoch", "_release")
72
47
 
73
- data: tuple
74
48
  string: str
75
49
  epoch: int
76
50
  release: Release
77
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)
78
71
  @setdoc.basic
79
- def __init__(self: Self, data: Any = None) -> None:
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:
80
82
  self._epoch = 0
81
83
  self._release = Release()
82
- self.data = data
83
84
 
84
85
  def _format(self: Self, format_spec: str) -> str:
85
86
  ans: str = ""
@@ -89,22 +90,18 @@ class Base(SlotList):
89
90
  return ans
90
91
 
91
92
  def _string_fset(self: Self, value: str) -> None:
93
+ v: str = value
94
+ if v.startswith("v"):
95
+ v = v[1:]
92
96
  parsed: Iterable
93
- if "!" in value:
94
- parsed = value.split("!")
97
+ if "!" in v:
98
+ parsed = v.split("!")
95
99
  else:
96
- parsed = 0, value
100
+ parsed = 0, v
97
101
  self.epoch, self.release.string = parsed
98
102
 
99
- @property
100
- @setdoc.basic
101
- def data(self: Self) -> tuple:
102
- return self.epoch, self.release
103
-
104
- @data.setter
105
- @guard
106
- def data(self: Self, value: Any) -> None:
107
- self.epoch, self.release = parse_data(value)
103
+ def _todict(self: Self) -> dict:
104
+ return dict(epoch=self.epoch, release=self.release)
108
105
 
109
106
  @property
110
107
  def epoch(self: Self) -> int:
@@ -124,4 +121,4 @@ class Base(SlotList):
124
121
  @release.setter
125
122
  @guard
126
123
  def release(self: Self, value: Any) -> None:
127
- self._release.data = value
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(".")
@@ -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.Pattern import Pattern
@@ -14,44 +15,46 @@ from v440.core.Qual import Qual
14
15
  __all__ = ["Public"]
15
16
 
16
17
 
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
18
  class Public(SlotList):
42
19
 
43
20
  __slots__ = ("_base", "_qual")
44
21
 
45
- data: tuple
46
22
  string: str
47
23
  base: Base
48
24
  qual: Qual
49
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)
50
39
  @setdoc.basic
51
- def __init__(self: Self, data: Any = None) -> None:
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:
52
56
  self._base = Base()
53
57
  self._qual = Qual()
54
- self.data = data
55
58
 
56
59
  def _format(self: Self, format_spec: str) -> str:
57
60
  return format(self.base, format_spec) + format(self.qual)
@@ -61,25 +64,17 @@ class Public(SlotList):
61
64
  self.base.string = value[: match.end()]
62
65
  self.qual.string = value[match.end() :]
63
66
 
67
+ def _todict(self: Self) -> dict:
68
+ return dict(base=self.base, qual=self.qual)
69
+
64
70
  @property
65
71
  def base(self: Self) -> Base:
66
72
  "This property represents the version base."
67
73
  return self._base
68
74
 
69
75
  @base.setter
70
- @guard
71
76
  def base(self: Self, value: Any) -> None:
72
- self.base.data = value
73
-
74
- @property
75
- @setdoc.basic
76
- def data(self: Self) -> list:
77
- return self.base, self.qual
78
-
79
- @data.setter
80
- @guard
81
- def data(self: Self, value: Any) -> None:
82
- self.base, self.qual = parse_data(value)
77
+ self.base._set(value)
83
78
 
84
79
  @property
85
80
  def qual(self: Self) -> Qual:
@@ -87,6 +82,5 @@ class Public(SlotList):
87
82
  return self._qual
88
83
 
89
84
  @qual.setter
90
- @guard
91
85
  def qual(self: Self, value: Any) -> None:
92
- self.qual.data = value
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,7 +17,6 @@ class Qual(SlotList):
15
17
 
16
18
  __slots__ = ("_prephase", "_presubphase", "_post", "_dev")
17
19
 
18
- data: tuple
19
20
  string: str
20
21
  pre: tuple
21
22
  prephase: Optional[str]
@@ -23,17 +24,42 @@ class Qual(SlotList):
23
24
  post: Optional[int]
24
25
  dev: Optional[int]
25
26
 
26
- @setdoc.basic
27
27
  def __bool__(self: Self) -> bool:
28
- return set(self.data) != {None}
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
29
44
 
45
+ @__init__.overload(False)
30
46
  @setdoc.basic
31
- def __init__(self: Self, data: Any = None) -> None:
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:
32
59
  self._prephase = None
33
60
  self._presubphase = None
34
61
  self._post = None
35
62
  self._dev = None
36
- self.data = data
37
63
 
38
64
  def _cmp(self: Self) -> list:
39
65
  ans: list = list()
@@ -68,31 +94,30 @@ class Qual(SlotList):
68
94
  m: Any
69
95
  x: Any
70
96
  y: Any
97
+ pre: Any = (None, None)
98
+ post: Any = None
99
+ dev: Any = None
71
100
  while v:
72
101
  m = Pattern.QUALIFIERS.leftbound.search(v)
73
102
  v = v[m.end() :]
74
103
  if m.group("N"):
75
- self.post = m.group("N")
104
+ post = m.group("N")
76
105
  continue
77
106
  x = m.group("l")
78
107
  y = m.group("n")
79
108
  if x == "dev":
80
- self.dev = y
109
+ dev = y
81
110
  continue
82
111
  if x in ("post", "r", "rev"):
83
- self.post = y
112
+ post = y
84
113
  continue
85
- self.pre = x, y
114
+ pre = x, y
115
+ self.pre = pre
116
+ self.post = post
117
+ self.dev = dev
86
118
 
87
- @property
88
- @setdoc.basic
89
- def data(self: Self) -> tuple:
90
- return self.prephase, self.presubphase, self.post, self.dev
91
-
92
- @data.setter
93
- @guard
94
- def data(self: Self, value: Any) -> None:
95
- self.pre, self.post, self.dev = qualparse.parse_leg(value)
119
+ def _todict(self: Self) -> dict:
120
+ return dict(pre=self.pre, post=self.post, dev=self.dev)
96
121
 
97
122
  @property
98
123
  def dev(self: Self) -> Optional[int]:
@@ -157,10 +157,6 @@ class Release(VList):
157
157
  ans: list = list(m)
158
158
  return ans
159
159
 
160
- @setdoc.basic
161
- def __init__(self: Any, data: Any = None) -> None:
162
- self.data = data
163
-
164
160
  @Overloadable
165
161
  @setdoc.basic
166
162
  def __setitem__(self: Self, key: Any, value: Any) -> bool:
@@ -178,6 +174,13 @@ class Release(VList):
178
174
  k: range = torange(key, len(self))
179
175
  self._setitem_range(k, value)
180
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
+
181
184
  def _format(self: Self, format_spec: str) -> str:
182
185
  i: Optional[int]
183
186
  if format_spec:
@@ -254,16 +257,3 @@ class Release(VList):
254
257
  self._setitem_int(i, x)
255
258
  if i != -1:
256
259
  self.data = self.data[: i + 1]
257
-
258
- @property
259
- @setdoc.basic
260
- def data(self: Self) -> tuple:
261
- return self._data
262
-
263
- @data.setter
264
- @guard
265
- def data(self: Self, value: Any) -> None:
266
- v: list = tolist(value, slicing="always")
267
- while v and v[-1] == 0:
268
- v.pop()
269
- 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,45 +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
- data: tuple
46
20
  string: str
47
21
  local: Local
48
22
  public: Public
49
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)
50
43
  @setdoc.basic
51
- def __init__(self: Self, data: Any = None) -> None:
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:
52
54
  self._public = Public()
53
55
  self._local = Local()
54
- self.data = data
55
56
 
56
57
  def _format(self: Self, format_spec: str) -> str:
57
58
  ans: str = format(self.public, format_spec)
@@ -67,15 +68,8 @@ class Version(SlotList):
67
68
  parsed = value, ""
68
69
  self.public.string, self.local.string = parsed
69
70
 
70
- @property
71
- @setdoc.basic
72
- def data(self: Self) -> tuple:
73
- return self.public, self.local
74
-
75
- @data.setter
76
- @guard
77
- def data(self: Self, value: Any) -> None:
78
- self.public, self.local = parse_data(value)
71
+ def _todict(self: Self) -> dict:
72
+ return dict(public=self.public, local=self.local)
79
73
 
80
74
  @property
81
75
  def local(self: Self) -> Local:
@@ -85,7 +79,7 @@ class Version(SlotList):
85
79
  @local.setter
86
80
  @guard
87
81
  def local(self: Self, value: Any) -> None:
88
- self.local.data = value
82
+ self.local._set(value)
89
83
 
90
84
  def packaging(self: Self) -> packaging.version.Version:
91
85
  "This method returns an eqivalent packaging.version.Version object."
@@ -99,4 +93,4 @@ class Version(SlotList):
99
93
  @public.setter
100
94
  @guard
101
95
  def public(self: Self, value: Any) -> None:
102
- self.public.data = value
96
+ self.public._set(value)
@@ -167,7 +167,8 @@ class TestSlicingGo(unittest.TestCase):
167
167
  class TestDataProperty(unittest.TestCase):
168
168
  def test_data(self: Self) -> None:
169
169
  for k, v in Util.util.data["data-property"].items():
170
- self.go(**v, key=k)
170
+ with self.subTest(key=k):
171
+ self.go(**v, key=k)
171
172
 
172
173
  def go(
173
174
  self: Self,
@@ -177,7 +178,7 @@ class TestDataProperty(unittest.TestCase):
177
178
  ) -> None:
178
179
  msg: str = "data-property %r" % key
179
180
  version: Version = Version()
180
- version.data = query
181
+ version.string = query
181
182
  self.assertEqual(solution, str(version), msg=msg)
182
183
 
183
184
 
@@ -384,7 +385,7 @@ class TestSlots(unittest.TestCase):
384
385
  clsname: str,
385
386
  attrname: str,
386
387
  attrvalue: Any,
387
- data: Any = None,
388
+ string: Any = None,
388
389
  isimported: Optional[bool] = False,
389
390
  ) -> None:
390
391
  cls: type
@@ -392,7 +393,7 @@ class TestSlots(unittest.TestCase):
392
393
  cls = getattr(core, clsname)
393
394
  else:
394
395
  cls = getattr(getattr(core, clsname), clsname)
395
- obj: Any = cls(data)
396
+ obj: Any = cls(string=string)
396
397
  with self.assertRaises(AttributeError):
397
398
  setattr(obj, attrname, attrvalue)
398
399
 
@@ -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, [None, None, None, None])
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, [None, None, None, None])
91
+ self.assertEqual(str(v.public.qual), "")
92
92
 
93
93
 
94
94
  class TestExample(unittest.TestCase):
@@ -179,7 +179,7 @@ class TestExample(unittest.TestCase):
179
179
  def test_example_7(self: Self) -> None:
180
180
  v: Version = Version("5.0.0")
181
181
  self.assertEqual(str(v), "5") # Original version
182
- v.data = None
182
+ v.string = ""
183
183
  self.assertEqual(str(v), "0") # After reset
184
184
  v.public.base = "4!5.0.1"
185
185
  self.assertEqual(str(v), "4!5.0.1") # Before error
@@ -961,9 +961,6 @@ solution = "9001"
961
961
  query = "1701!4.5.6.rc255+reset"
962
962
  solution = "1701!4.5.6rc255+reset"
963
963
 
964
- [data-property.none]
965
- solution = "0"
966
-
967
964
  [slicingmethod.test_slicing_1]
968
965
  query = "1.2.3.4.5.6.7.8.9.10"
969
966
  start = -8
@@ -1030,36 +1027,43 @@ full = "1.2.3"
1030
1027
  part = 0
1031
1028
 
1032
1029
  [core-non-attributes.test-0000]
1030
+ string = ""
1033
1031
  clsname = "Base"
1034
1032
  attrname = "fdsfvdsff"
1035
1033
  attrvalue = 42
1036
1034
 
1037
1035
  [core-non-attributes.test-0100]
1036
+ string = ""
1038
1037
  clsname = "Local"
1039
1038
  attrname = "fdsfvdsff"
1040
1039
  attrvalue = 42
1041
1040
 
1042
1041
  [core-non-attributes.test-0200]
1042
+ string = ""
1043
1043
  clsname = "Public"
1044
1044
  attrname = "fdsfvdsff"
1045
1045
  attrvalue = 42
1046
1046
 
1047
1047
  [core-non-attributes.test-0300]
1048
+ string = ""
1048
1049
  clsname = "Qual"
1049
1050
  attrname = "fdsfvdsff"
1050
1051
  attrvalue = 42
1051
1052
 
1052
1053
  [core-non-attributes.test-0400]
1054
+ string = ""
1053
1055
  clsname = "Release"
1054
1056
  attrname = "fdsfvdsff"
1055
1057
  attrvalue = 42
1056
1058
 
1057
1059
  [core-non-attributes.test-0500]
1060
+ string = ""
1058
1061
  clsname = "Public"
1059
1062
  attrname = "fdsfvdsff"
1060
1063
  attrvalue = 42
1061
1064
 
1062
1065
  [core-non-attributes.test-0600]
1066
+ string = ""
1063
1067
  clsname = "Version"
1064
1068
  attrname = "fdsfvdsff"
1065
1069
  attrvalue = 42
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: v440
3
- Version: 2.0.0.dev60
3
+ Version: 2.0.0.dev62
4
4
  Summary: This project provides mutable version objects in accordance with PEP440.
5
5
  Author-email: Johannes <johannes.programming@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -1,84 +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
- string: str
54
-
55
- @setdoc.basic
56
- def __init__(self: Any, data: Any = None) -> None:
57
- self.data = data
58
-
59
- def _format(self: Self, format_spec: str) -> str:
60
- if format_spec:
61
- raise ValueError
62
- return ".".join(map(str, self))
63
-
64
- @classmethod
65
- def _sort(cls: type, value: Any) -> tuple[bool, int | str]:
66
- return type(value) is int, value
67
-
68
- def _string_fset(self: Self, value: str) -> None:
69
- v: str = value
70
- if v.startswith("+"):
71
- v = v[1:]
72
- v = v.replace("_", ".")
73
- v = v.replace("-", ".")
74
- self.data = v.split(".")
75
-
76
- @property
77
- @setdoc.basic
78
- def data(self: Self) -> tuple[int | str]:
79
- return self._data
80
-
81
- @data.setter
82
- @guard
83
- def data(self: Self, value: Any) -> None:
84
- self._data = parse_data(value)
File without changes
File without changes
File without changes
File without changes