v440 2.0.0.dev52__tar.gz → 2.0.0.dev54__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 (36) hide show
  1. {v440-2.0.0.dev52/src/v440.egg-info → v440-2.0.0.dev54}/PKG-INFO +3 -2
  2. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/pyproject.toml +3 -2
  3. v440-2.0.0.dev52/src/v440/_utils/SlotList.py → v440-2.0.0.dev54/src/v440/_utils/BaseList.py +37 -47
  4. v440-2.0.0.dev54/src/v440/_utils/SlotList.py +32 -0
  5. v440-2.0.0.dev54/src/v440/_utils/VList.py +112 -0
  6. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/utils.py +0 -31
  7. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Base.py +4 -4
  8. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Local.py +11 -31
  9. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Public.py +2 -2
  10. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Qual.py +4 -3
  11. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Release.py +65 -36
  12. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/Version.py +5 -6
  13. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/tests/test_testdata.py +12 -8
  14. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/tests/test_version.py +2 -2
  15. {v440-2.0.0.dev52 → v440-2.0.0.dev54/src/v440.egg-info}/PKG-INFO +3 -2
  16. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440.egg-info/requires.txt +2 -1
  17. v440-2.0.0.dev52/src/v440/_utils/BaseList.py +0 -15
  18. v440-2.0.0.dev52/src/v440/_utils/VList.py +0 -75
  19. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/LICENSE.txt +0 -0
  20. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/MANIFEST.in +0 -0
  21. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/README.rst +0 -0
  22. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/setup.cfg +0 -0
  23. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/__init__.py +0 -0
  24. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/Cfg.py +0 -0
  25. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/Digest.py +0 -0
  26. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/Pattern.py +0 -0
  27. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/__init__.py +0 -0
  28. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/cfg.toml +0 -0
  29. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/_utils/qualparse.py +0 -0
  30. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/VersionError.py +0 -0
  31. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/core/__init__.py +0 -0
  32. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/tests/__init__.py +0 -0
  33. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440/tests/testdata.toml +0 -0
  34. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440.egg-info/SOURCES.txt +0 -0
  35. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/src/v440.egg-info/dependency_links.txt +0 -0
  36. {v440-2.0.0.dev52 → v440-2.0.0.dev54}/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.dev52
3
+ Version: 2.0.0.dev54
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)
@@ -41,7 +41,7 @@ Requires-Python: >=3.11
41
41
  Description-Content-Type: text/x-rst
42
42
  License-File: LICENSE.txt
43
43
  Requires-Dist: catchlib<2.0,>=1.0
44
- Requires-Dist: datahold<2.0,>=1.1.8
44
+ Requires-Dist: datarepr<2,>=1.0.2
45
45
  Requires-Dist: iterprod<2.0,>=1.0
46
46
  Requires-Dist: keyalias<2.0,>=1.0.3
47
47
  Requires-Dist: overloadable<2.0,>=1.0.5
@@ -49,6 +49,7 @@ Requires-Dist: packaging>=23.2
49
49
  Requires-Dist: scaevola<2.0,>=1.1
50
50
  Requires-Dist: setdoc<2,>=1.2
51
51
  Requires-Dist: tofunc<2,>=1.0.0
52
+ Requires-Dist: unhash<2,>=1.0.1
52
53
  Dynamic: license-file
53
54
 
54
55
  ====
@@ -21,7 +21,7 @@ classifiers = [
21
21
  ]
22
22
  dependencies = [
23
23
  "catchlib>=1.0,<2.0",
24
- "datahold>=1.1.8,<2.0",
24
+ "datarepr>=1.0.2,<2",
25
25
  "iterprod>=1.0,<2.0",
26
26
  "keyalias>=1.0.3,<2.0",
27
27
  "overloadable>=1.0.5,<2.0",
@@ -29,13 +29,14 @@ dependencies = [
29
29
  "scaevola>=1.1,<2.0",
30
30
  "setdoc>=1.2,<2",
31
31
  "tofunc>=1.0.0,<2",
32
+ "unhash>=1.0.1,<2",
32
33
  ]
33
34
  description = "This project provides mutable version objects in accordance with PEP440."
34
35
  keywords = []
35
36
  name = "v440"
36
37
  readme = "README.rst"
37
38
  requires-python = ">=3.11"
38
- version = "2.0.0.dev52"
39
+ version = "2.0.0.dev54"
39
40
 
40
41
  [project.license]
41
42
  file = "LICENSE.txt"
@@ -1,28 +1,22 @@
1
1
  import collections
2
- import sys
3
2
  from abc import abstractmethod
4
3
  from typing import *
5
4
 
6
5
  import scaevola
7
6
  import setdoc
7
+ import unhash
8
8
  from datarepr import datarepr
9
- from unhash import unhash
10
9
 
11
- from v440._utils.BaseList import BaseList
12
10
  from v440.core.VersionError import VersionError
13
11
 
14
- __all__ = ["SlotList"]
15
-
16
12
 
17
13
  @scaevola.auto
18
- class SlotList(collections.abc.Collection, BaseList):
14
+ class BaseList(collections.abc.Sized):
19
15
  __slots__ = ()
20
16
 
21
- data: list
22
-
17
+ @abstractmethod
23
18
  @setdoc.basic
24
- def __bool__(self: Self) -> bool:
25
- return any(self.data)
19
+ def __bool__(self: Self) -> bool: ...
26
20
 
27
21
  @setdoc.basic
28
22
  def __contains__(self: Self, other: Any) -> bool:
@@ -34,8 +28,7 @@ class SlotList(collections.abc.Collection, BaseList):
34
28
  alt: Self = type(self)(other)
35
29
  except VersionError:
36
30
  return False
37
- else:
38
- return self.data == alt.data
31
+ return self.data == alt.data
39
32
 
40
33
  @setdoc.basic
41
34
  def __format__(self: Self, format_spec: Any) -> str:
@@ -47,28 +40,26 @@ class SlotList(collections.abc.Collection, BaseList):
47
40
  raise TypeError(msg) from None
48
41
 
49
42
  @setdoc.basic
50
- def __getitem__(self: Self, key: Any) -> Any:
51
- return self.data[key]
52
-
53
- @setdoc.basic
54
- def __ge__(self: Self, other: Any, /) -> bool:
43
+ def __ge__(self: Self, other: Any) -> bool:
55
44
  alt: Self
56
45
  try:
57
46
  alt = type(self)(other)
58
47
  except VersionError:
59
48
  return NotImplemented
60
- else:
61
- return self._cmp() >= alt._cmp()
49
+ return self._cmp() >= alt._cmp()
62
50
 
63
51
  @setdoc.basic
64
- def __gt__(self: Self, other: Any, /) -> bool:
52
+ def __getitem__(self: Self, key: Any) -> Any:
53
+ return self.data[key]
54
+
55
+ @setdoc.basic
56
+ def __gt__(self: Self, other: Any) -> bool:
65
57
  alt: Self
66
58
  try:
67
59
  alt = type(self)(other)
68
60
  except VersionError:
69
61
  return NotImplemented
70
- else:
71
- return self._cmp() > alt._cmp()
62
+ return self._cmp() > alt._cmp()
72
63
 
73
64
  __hash__ = unhash
74
65
 
@@ -77,32 +68,26 @@ class SlotList(collections.abc.Collection, BaseList):
77
68
  self.data = data
78
69
 
79
70
  @setdoc.basic
80
- def __iter__(self: Self) -> Any:
71
+ def __iter__(self: Self) -> Iterator:
81
72
  return iter(self.data)
82
73
 
83
74
  @setdoc.basic
84
- def __le__(self: Self, other: Any, /) -> bool:
75
+ def __le__(self: Self, other: Any) -> bool:
85
76
  alt: Self
86
77
  try:
87
78
  alt = type(self)(other)
88
79
  except VersionError:
89
80
  return NotImplemented
90
- else:
91
- return self._cmp() <= alt._cmp()
92
-
93
- @setdoc.basic
94
- def __len__(self: Self) -> int:
95
- return len(type(self).__slots__)
81
+ return self._cmp() <= alt._cmp()
96
82
 
97
83
  @setdoc.basic
98
- def __lt__(self: Self, other: Any, /) -> bool:
84
+ def __lt__(self: Self, other: Any) -> bool:
99
85
  alt: Self
100
86
  try:
101
87
  alt = type(self)(other)
102
88
  except VersionError:
103
89
  return NotImplemented
104
- else:
105
- return self._cmp() < alt._cmp()
90
+ return self._cmp() < alt._cmp()
106
91
 
107
92
  @setdoc.basic
108
93
  def __ne__(self: Self, other: Any) -> bool:
@@ -113,38 +98,43 @@ class SlotList(collections.abc.Collection, BaseList):
113
98
  return datarepr(type(self).__name__, self.data)
114
99
 
115
100
  @setdoc.basic
116
- def __reversed__(self: Self) -> Iterable:
101
+ def __reversed__(self: Self) -> reversed:
117
102
  return reversed(self.data)
118
103
 
119
104
  @setdoc.basic
120
105
  def __setitem__(self: Self, key: Any, value: Any) -> None:
121
- data: list = self.data
106
+ data: list = list(self._data)
122
107
  data[key] = value
123
108
  self.data = data
124
109
 
125
- @setdoc.basic
126
- def __str__(self: Self) -> str:
127
- return format(self)
128
-
129
110
  @classmethod
130
111
  def __subclasshook__(cls: type, other: type, /) -> bool:
131
112
  "This magic classmethod can be overwritten for a custom subclass check."
132
113
  return NotImplemented
133
114
 
134
- def _cmp(self: Self) -> Any:
135
- return self.data
115
+ @setdoc.basic
116
+ def __str__(self: Self) -> str:
117
+ return self._format("")
118
+
119
+ @abstractmethod
120
+ def _cmp(self: Self) -> Any: ...
121
+
122
+ @abstractmethod
123
+ def _format(self: Self, format_spec: str) -> str: ...
136
124
 
137
125
  @setdoc.basic
138
126
  def copy(self: Self) -> Self:
139
127
  return type(self)(self)
140
128
 
141
- def count(self: Self, value: Any) -> Any:
142
- return self.data.count(value)
143
-
144
129
  @property
145
130
  @abstractmethod
146
131
  @setdoc.basic
147
- def data(self: Self) -> list: ...
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)
148
137
 
149
- def index(self: Self, value: Any) -> Any:
150
- return self.data.index(value)
138
+ def index(self: Self, *args: Any) -> None:
139
+ "This method returns the index of the first occurence."
140
+ return self.data.index(*args)
@@ -0,0 +1,32 @@
1
+ import collections
2
+ from abc import abstractmethod
3
+ from functools import partial
4
+ from typing import *
5
+
6
+ import scaevola
7
+ import setdoc
8
+ from datarepr import datarepr
9
+
10
+ from v440._utils.BaseList import BaseList
11
+ from v440._utils.utils import guard
12
+ from v440.core.VersionError import VersionError
13
+
14
+ __all__ = ["SlotList"]
15
+
16
+
17
+ @scaevola.auto
18
+ class SlotList(collections.abc.Collection, BaseList):
19
+ __slots__ = ()
20
+
21
+ data: tuple
22
+
23
+ @setdoc.basic
24
+ def __bool__(self: Self) -> bool:
25
+ return any(self.data)
26
+
27
+ @setdoc.basic
28
+ def __len__(self: Self) -> int:
29
+ return len(type(self).__slots__)
30
+
31
+ def _cmp(self: Self) -> tuple:
32
+ return tuple(map(partial(getattr, self), type(self).__slots__))
@@ -0,0 +1,112 @@
1
+ from abc import abstractmethod
2
+ from typing import *
3
+
4
+ import setdoc
5
+
6
+ from v440._utils import utils
7
+ from v440._utils.BaseList import BaseList
8
+
9
+ __all__ = ["VList"]
10
+
11
+
12
+ class VList(BaseList):
13
+
14
+ __slots__ = ("_data",)
15
+ data: tuple
16
+
17
+ @setdoc.basic
18
+ def __add__(self: Self, other: Any) -> Self:
19
+ return type(self)(self.data + tuple(other))
20
+
21
+ @setdoc.basic
22
+ def __bool__(self: Self) -> bool:
23
+ return bool(self.data)
24
+
25
+ @setdoc.basic
26
+ def __delitem__(self: Self, key: Any) -> None:
27
+ data: list = list(self.data)
28
+ del data[key]
29
+ self.data = data
30
+
31
+ @setdoc.basic
32
+ def __iadd__(self: Self, other: Any, /) -> Self:
33
+ self.data = self.data + tuple(other)
34
+ return self
35
+
36
+ @setdoc.basic
37
+ def __imul__(self: Self, other: Any, /) -> Self:
38
+ self.data = self.data * other
39
+ return self
40
+
41
+ @setdoc.basic
42
+ def __len__(self: Self) -> int:
43
+ return len(self.data)
44
+
45
+ @setdoc.basic
46
+ def __mul__(self: Self, other: Any) -> Self:
47
+ return type(self)(self.data * other)
48
+
49
+ @setdoc.basic
50
+ def __rmul__(self: Self, other: Any) -> Self:
51
+ return self * other
52
+
53
+ def _cmp(self: Self) -> tuple:
54
+ return tuple(map(self._sort, self.data))
55
+
56
+ @classmethod
57
+ @abstractmethod
58
+ def _sort(cls: type, value: Any): ...
59
+
60
+ def append(self: Self, value: Self, /) -> None:
61
+ "This method appends value to self."
62
+ data: list = list(self.data)
63
+ data.append(value)
64
+ self.data = data
65
+
66
+ def clear(self: Self, /) -> None:
67
+ "This method clears the data."
68
+ self.data = ()
69
+
70
+ def extend(self: Self, value: Self, /) -> None:
71
+ "This method extends self by value."
72
+ data: list = list(self.data)
73
+ data.extend(value)
74
+ self.data = data
75
+
76
+ def insert(
77
+ self: Self,
78
+ index: SupportsIndex,
79
+ value: Any,
80
+ /,
81
+ ) -> None:
82
+ "This method inserts value at index."
83
+ data: list = list(self.data)
84
+ data.insert(index, value)
85
+ self.data = data
86
+
87
+ def pop(self: Self, index: SupportsIndex = -1, /) -> Any:
88
+ "This method pops an item."
89
+ data: list = list(self.data)
90
+ ans: Any = data.pop(index)
91
+ self.data = data
92
+ return ans
93
+
94
+ def remove(self: Self, value: Any) -> None:
95
+ "This method removes the first occurence of value."
96
+ data: list = list(self.data)
97
+ data.remove(value)
98
+ self.data = data
99
+
100
+ def reverse(self: Self) -> None:
101
+ "This method reverses the order of the data."
102
+ data: list = list(self.data)
103
+ data.reverse()
104
+ self.data = data
105
+
106
+ def sort(self: Self, *, key: Any = None, reverse: Any = False) -> None:
107
+ "This method sorts the data."
108
+ data: list = list(self.data)
109
+ k: Any = self._sort if key is None else key
110
+ r: bool = bool(reverse)
111
+ data.sort(key=k, reverse=r)
112
+ self.data = data
@@ -63,37 +63,6 @@ def _segment(value: Any, /) -> int | str:
63
63
  return int(value)
64
64
 
65
65
 
66
- def torange(key: Any, length: Any) -> range:
67
- start: Any = key.start
68
- stop: Any = key.stop
69
- step: Any = key.step
70
- if step is None:
71
- step = 1
72
- else:
73
- step = operator.index(step)
74
- if step == 0:
75
- raise ValueError
76
- fwd: bool = step > 0
77
- if start is None:
78
- start = 0 if fwd else (length - 1)
79
- else:
80
- start = operator.index(start)
81
- if stop is None:
82
- stop = length if fwd else -1
83
- else:
84
- stop = operator.index(stop)
85
- if start < 0:
86
- start += length
87
- if start < 0:
88
- start = 0 if fwd else -1
89
- if stop < 0:
90
- stop += length
91
- if stop < 0:
92
- stop = 0 if fwd else -1
93
- ans: range = range(start, stop, step)
94
- return ans
95
-
96
-
97
66
  def ishashable(value: Any) -> bool:
98
67
  try:
99
68
  hash(value)
@@ -70,7 +70,7 @@ class Base(SlotList):
70
70
 
71
71
  __slots__ = ("_epoch", "_release")
72
72
 
73
- data: list
73
+ data: tuple
74
74
  epoch: int
75
75
  release: Release
76
76
 
@@ -89,12 +89,12 @@ class Base(SlotList):
89
89
 
90
90
  @property
91
91
  @setdoc.basic
92
- def data(self: Self) -> list:
93
- return [self.epoch, self.release]
92
+ def data(self: Self) -> tuple:
93
+ return self.epoch, self.release
94
94
 
95
95
  @data.setter
96
96
  @guard
97
- def data(self: Self, value: Iterable) -> None:
97
+ def data(self: Self, value: Any) -> None:
98
98
  self.epoch, self.release = parse_data(value)
99
99
 
100
100
  @property
@@ -16,32 +16,32 @@ parse_data: Digest = Digest("parse_data")
16
16
 
17
17
 
18
18
  @parse_data.overload()
19
- def parse_data() -> list:
20
- return list()
19
+ def parse_data() -> tuple:
20
+ return ()
21
21
 
22
22
 
23
23
  @parse_data.overload(int)
24
24
  def parse_data(value: int) -> list:
25
- return [value]
25
+ return (value,)
26
26
 
27
27
 
28
28
  @parse_data.overload(list)
29
29
  def parse_data(value: list) -> list:
30
- ans: list = list(map(utils.segment, value))
30
+ ans: tuple = tuple(map(utils.segment, value))
31
31
  if None in ans:
32
32
  raise ValueError
33
33
  return ans
34
34
 
35
35
 
36
36
  @parse_data.overload(str)
37
- def parse_data(value: str) -> list:
37
+ def parse_data(value: str) -> tuple:
38
38
  v: str = value
39
39
  if v.startswith("+"):
40
40
  v = v[1:]
41
41
  v = v.replace("_", ".")
42
42
  v = v.replace("-", ".")
43
- ans: list = v.split(".")
44
- ans = list(map(utils.segment, ans))
43
+ ans: tuple = v.split(".")
44
+ ans = tuple(map(utils.segment, ans))
45
45
  if None in ans:
46
46
  raise ValueError
47
47
  return ans
@@ -50,47 +50,27 @@ def parse_data(value: str) -> list:
50
50
  class Local(VList):
51
51
  __slots__ = ()
52
52
 
53
- data: list[int | str]
53
+ data: tuple[int | str]
54
54
 
55
55
  @setdoc.basic
56
56
  def __init__(self: Any, data: Any = None) -> None:
57
- self._data = list()
58
57
  self.data = data
59
58
 
60
- @setdoc.basic
61
- def __le__(self: Self, other: Iterable) -> bool:
62
- ans: bool
63
- try:
64
- alt: Self = type(self)(other)
65
- except ValueError:
66
- ans = self.data <= other
67
- else:
68
- ans = self._cmp() <= alt._cmp()
69
- return ans
70
-
71
- def _cmp(self: Self) -> list:
72
- return list(map(self._sortkey, self))
73
-
74
59
  def _format(self: Self, format_spec: str) -> str:
75
60
  if format_spec:
76
61
  raise ValueError
77
62
  return ".".join(map(str, self))
78
63
 
79
- @staticmethod
80
- def _sortkey(value: Any) -> tuple[bool, Any]:
64
+ @classmethod
65
+ def _sort(cls: type, value: Any) -> tuple[bool, Any]:
81
66
  return type(value) is int, value
82
67
 
83
68
  @property
84
69
  @setdoc.basic
85
70
  def data(self: Self) -> list[int | str]:
86
- return list(self._data)
71
+ return self._data
87
72
 
88
73
  @data.setter
89
74
  @guard
90
75
  def data(self: Self, value: Any) -> None:
91
76
  self._data = parse_data(value)
92
-
93
- @functools.wraps(VList.sort)
94
- def sort(self: Self, /, *, key: Any = None, **kwargs: Any) -> None:
95
- k: Any = self._sortkey if key is None else key
96
- self._data.sort(key=k, **kwargs)
@@ -42,7 +42,7 @@ class Public(SlotList):
42
42
 
43
43
  __slots__ = ("_base", "_qual")
44
44
 
45
- data: list
45
+ data: tuple
46
46
  base: Base
47
47
  qual: Qual
48
48
 
@@ -68,7 +68,7 @@ class Public(SlotList):
68
68
  @property
69
69
  @setdoc.basic
70
70
  def data(self: Self) -> list:
71
- return [self.base, self.qual]
71
+ return self.base, self.qual
72
72
 
73
73
  @data.setter
74
74
  @guard
@@ -15,7 +15,7 @@ class Qual(SlotList):
15
15
 
16
16
  __slots__ = ("_prephase", "_presubphase", "_post", "_dev")
17
17
 
18
- data: list
18
+ data: tuple
19
19
  pre: tuple
20
20
  prephase: Optional[str]
21
21
  presubphase: Optional[int]
@@ -64,8 +64,8 @@ class Qual(SlotList):
64
64
 
65
65
  @property
66
66
  @setdoc.basic
67
- def data(self: Self) -> list:
68
- return [self.prephase, self.presubphase, self.post, self.dev]
67
+ def data(self: Self) -> tuple:
68
+ return self.prephase, self.presubphase, self.post, self.dev
69
69
 
70
70
  @data.setter
71
71
  @guard
@@ -74,6 +74,7 @@ class Qual(SlotList):
74
74
 
75
75
  @property
76
76
  def dev(self: Self) -> Optional[int]:
77
+ "This property represents the stage of development."
77
78
  return self._dev
78
79
 
79
80
  @dev.setter
@@ -68,23 +68,47 @@ def tolist(value: Any, *, slicing: Any) -> list:
68
68
  return l
69
69
 
70
70
 
71
+ def torange(key: Any, length: Any) -> range:
72
+ start: Any = key.start
73
+ stop: Any = key.stop
74
+ step: Any = key.step
75
+ if step is None:
76
+ step = 1
77
+ else:
78
+ step = operator.index(step)
79
+ if step == 0:
80
+ raise ValueError
81
+ fwd: bool = step > 0
82
+ if start is None:
83
+ start = 0 if fwd else (length - 1)
84
+ else:
85
+ start = operator.index(start)
86
+ if stop is None:
87
+ stop = length if fwd else -1
88
+ else:
89
+ stop = operator.index(stop)
90
+ if start < 0:
91
+ start += length
92
+ if start < 0:
93
+ start = 0 if fwd else -1
94
+ if stop < 0:
95
+ stop += length
96
+ if stop < 0:
97
+ stop = 0 if fwd else -1
98
+ ans: range = range(start, stop, step)
99
+ return ans
100
+
101
+
71
102
  @keyalias(major=0, minor=1, micro=2, patch=2)
72
103
  class Release(VList):
73
104
  __slots__ = ()
74
105
 
75
- data: list[int]
106
+ data: tuple[int]
76
107
  major: int
77
108
  minor: int
78
109
  micro: int
79
110
  patch: int
80
111
 
81
- @setdoc.basic
82
- def __add__(self: Self, other: Any, /) -> Self:
83
- opp: Self = type(self)(other)
84
- ans: Self = self.copy()
85
- ans._data += opp._data
86
- return ans
87
-
88
112
  @Overloadable
89
113
  @setdoc.basic
90
114
  def __delitem__(self: Self, key: Any) -> bool:
@@ -94,17 +118,23 @@ class Release(VList):
94
118
  @setdoc.basic
95
119
  def __delitem__(self: Self, key: SupportsIndex) -> None:
96
120
  i: int = operator.index(key)
97
- if i < len(self):
98
- del self._data[i]
121
+ if i >= len(self):
122
+ return
123
+ data: list = list(self.data)
124
+ del data[i]
125
+ self.data = data
99
126
 
100
127
  @__delitem__.overload(True)
101
128
  @setdoc.basic
102
129
  def __delitem__(self: Self, key: Any) -> None:
103
- r: range = utils.torange(key, len(self))
130
+ r: range = torange(key, len(self))
131
+ k: Any
104
132
  l: list = [k for k in r if k < len(self)]
105
133
  l.sort(reverse=True)
134
+ data: list = list(self.data)
106
135
  for k in l:
107
- del self._data[k]
136
+ del data[k]
137
+ self.data = data
108
138
 
109
139
  @Overloadable
110
140
  @setdoc.basic
@@ -121,14 +151,13 @@ class Release(VList):
121
151
  @__getitem__.overload(True)
122
152
  @setdoc.basic
123
153
  def __getitem__(self: Self, key: Any) -> list:
124
- r: range = utils.torange(key, len(self))
154
+ r: range = torange(key, len(self))
125
155
  m: map = map(self._getitem_int, r)
126
156
  ans: list = list(m)
127
157
  return ans
128
158
 
129
159
  @setdoc.basic
130
160
  def __init__(self: Any, data: Any = None) -> None:
131
- self._data = list()
132
161
  self.data = data
133
162
 
134
163
  @Overloadable
@@ -145,7 +174,7 @@ class Release(VList):
145
174
  @__setitem__.overload(True)
146
175
  @setdoc.basic
147
176
  def __setitem__(self: Self, key: SupportsIndex, value: Any) -> Any:
148
- k: range = utils.torange(key, len(self))
177
+ k: range = torange(key, len(self))
149
178
  self._setitem_range(k, value)
150
179
 
151
180
  def _format(self: Self, format_spec: str) -> str:
@@ -163,20 +192,21 @@ class Release(VList):
163
192
 
164
193
  def _getitem_int(self: Self, key: int) -> int:
165
194
  if key < len(self):
166
- return self._data[key]
195
+ return self.data[key]
167
196
  else:
168
197
  return 0
169
198
 
170
199
  def _setitem_int(self: Self, key: int, value: Any) -> Any:
171
200
  v: int = utils.numeral(value)
172
- n: int = len(self)
173
- if n > key:
174
- self._data[key] = v
201
+ if key < len(self):
202
+ data = list(self.data)
203
+ data[key] = v
204
+ self.data = data
175
205
  return
176
206
  if v == 0:
177
207
  return
178
- self._data.extend([0] * (key - n))
179
- self._data.append(v)
208
+ self._data += (0,) * (key - len(self))
209
+ self._data += (v,)
180
210
 
181
211
  @Overloadable
182
212
  def _setitem_range(self: Self, key: range, value: Any) -> bool:
@@ -184,32 +214,31 @@ class Release(VList):
184
214
 
185
215
  @_setitem_range.overload(False)
186
216
  def _setitem_range(self: Self, key: range, value: Any) -> Any:
187
- key = list(key)
188
- value = tolist(value, slicing=len(key))
217
+ key: list = list(key)
218
+ value: list = tolist(value, slicing=len(key))
189
219
  if len(key) != len(value):
190
220
  e = "attempt to assign sequence of size %s to extended slice of size %s"
191
221
  e %= (len(value), len(key))
192
222
  raise ValueError(e)
193
- maximum = max(*key)
194
- ext = max(0, maximum + 1 - len(self))
195
- data = self.data
223
+ ext: int = max(0, max(*key) + 1 - len(self))
224
+ data: list = list(self.data)
196
225
  data += [0] * ext
197
226
  for k, v in zip(key, value):
198
227
  data[k] = v
199
- while len(data) and not data[-1]:
200
- data.pop()
201
- self._data = data
228
+ self.data = data
202
229
 
203
230
  @_setitem_range.overload(True)
204
231
  def _setitem_range(self: Self, key: range, value: Any) -> Any:
205
- data: list = self.data
232
+ data: list = list(self.data)
206
233
  ext: int = max(0, key.start - len(data))
207
234
  data += ext * [0]
208
235
  l: list = tolist(value, slicing="always")
209
236
  data = data[: key.start] + l + data[key.stop :]
210
- while len(data) and not data[-1]:
211
- data.pop()
212
- self._data = data
237
+ self.data = data
238
+
239
+ @classmethod
240
+ def _sort(cls: type, value: int) -> int:
241
+ return value
213
242
 
214
243
  def bump(self: Self, index: SupportsIndex = -1, amount: SupportsIndex = 1) -> None:
215
244
  i: int = operator.index(index)
@@ -221,8 +250,8 @@ class Release(VList):
221
250
 
222
251
  @property
223
252
  @setdoc.basic
224
- def data(self: Self) -> list:
225
- return list(self._data)
253
+ def data(self: Self) -> tuple:
254
+ return self._data
226
255
 
227
256
  @data.setter
228
257
  @guard
@@ -230,4 +259,4 @@ class Release(VList):
230
259
  v: list = tolist(value, slicing="always")
231
260
  while v and v[-1] == 0:
232
261
  v.pop()
233
- self._data = v
262
+ self._data = tuple(v)
@@ -42,7 +42,7 @@ def parse_data(value: str) -> tuple:
42
42
  class Version(SlotList):
43
43
  __slots__ = ("_public", "_local")
44
44
 
45
- data: list
45
+ data: tuple
46
46
  local: Local
47
47
  public: Public
48
48
 
@@ -52,9 +52,6 @@ class Version(SlotList):
52
52
  self._local = Local()
53
53
  self.data = data
54
54
 
55
- def __str__(self: Self) -> str:
56
- return format(self)
57
-
58
55
  def _format(self: Self, format_spec: str) -> str:
59
56
  ans: str = format(self.public, format_spec)
60
57
  if self.local:
@@ -63,8 +60,8 @@ class Version(SlotList):
63
60
 
64
61
  @property
65
62
  @setdoc.basic
66
- def data(self: Self) -> list:
67
- return [self.public, self.local]
63
+ def data(self: Self) -> tuple:
64
+ return self.public, self.local
68
65
 
69
66
  @data.setter
70
67
  @guard
@@ -73,6 +70,7 @@ class Version(SlotList):
73
70
 
74
71
  @property
75
72
  def local(self: Self) -> Local:
73
+ "This property represents the local identifier."
76
74
  return self._local
77
75
 
78
76
  @local.setter
@@ -86,6 +84,7 @@ class Version(SlotList):
86
84
 
87
85
  @property
88
86
  def public(self: Self) -> Self:
87
+ "This property represents the public identifier."
89
88
  return self._public
90
89
 
91
90
  @public.setter
@@ -267,18 +267,22 @@ class TestPackagingA(unittest.TestCase):
267
267
 
268
268
  class TestPackagingB(unittest.TestCase):
269
269
  def test_strings_b(self: Self) -> None:
270
+ x: str
271
+ y: list
272
+ for x, y in Util.util.data["strings"]["valid"].items():
273
+ with self.subTest(key=x):
274
+ self.go(y)
275
+
276
+ def go(self: Self, y: list) -> None:
270
277
  a: packaging.version.Version
271
278
  b: packaging.version.Version
272
279
  s: str
273
280
  msg: str
274
- x: str
275
- y: list
276
- for x, y in Util.util.data["strings"]["valid"].items():
277
- for s in y:
278
- a = packaging.version.Version(s)
279
- b = Version(s).packaging()
280
- msg = f"{s} should match packaging.version.Version"
281
- self.assertEqual(a, b, msg=msg)
281
+ for s in y:
282
+ a = packaging.version.Version(s)
283
+ b = Version(s).packaging()
284
+ msg = f"{s} should match packaging.version.Version"
285
+ self.assertEqual(a, b, msg=msg)
282
286
 
283
287
 
284
288
  class TestPackagingC(unittest.TestCase):
@@ -303,7 +303,7 @@ class TestAdditionalVersionRelease(unittest.TestCase):
303
303
  # Test the 'data' property
304
304
  version: Version = Version()
305
305
  version.public.base.release = [1, 2, 3]
306
- self.assertEqual(version.public.base.release.data, [1, 2, 3])
306
+ self.assertEqual(version.public.base.release.data, (1, 2, 3))
307
307
 
308
308
  def test_release_data_setter(self: Self) -> None:
309
309
  # Test setting the 'data' property directly
@@ -381,7 +381,7 @@ class TestVersionLocal(unittest.TestCase):
381
381
  # Test that 'data' property correctly reflects local's internal list
382
382
  version: Version = Version()
383
383
  version.local = [1, "dev", "build"]
384
- self.assertEqual(version.local.data, [1, "dev", "build"])
384
+ self.assertEqual(version.local.data, (1, "dev", "build"))
385
385
 
386
386
  def test_local_data_setter(self: Self) -> None:
387
387
  # Test that 'data' property can be set directly
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: v440
3
- Version: 2.0.0.dev52
3
+ Version: 2.0.0.dev54
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)
@@ -41,7 +41,7 @@ Requires-Python: >=3.11
41
41
  Description-Content-Type: text/x-rst
42
42
  License-File: LICENSE.txt
43
43
  Requires-Dist: catchlib<2.0,>=1.0
44
- Requires-Dist: datahold<2.0,>=1.1.8
44
+ Requires-Dist: datarepr<2,>=1.0.2
45
45
  Requires-Dist: iterprod<2.0,>=1.0
46
46
  Requires-Dist: keyalias<2.0,>=1.0.3
47
47
  Requires-Dist: overloadable<2.0,>=1.0.5
@@ -49,6 +49,7 @@ Requires-Dist: packaging>=23.2
49
49
  Requires-Dist: scaevola<2.0,>=1.1
50
50
  Requires-Dist: setdoc<2,>=1.2
51
51
  Requires-Dist: tofunc<2,>=1.0.0
52
+ Requires-Dist: unhash<2,>=1.0.1
52
53
  Dynamic: license-file
53
54
 
54
55
  ====
@@ -1,5 +1,5 @@
1
1
  catchlib<2.0,>=1.0
2
- datahold<2.0,>=1.1.8
2
+ datarepr<2,>=1.0.2
3
3
  iterprod<2.0,>=1.0
4
4
  keyalias<2.0,>=1.0.3
5
5
  overloadable<2.0,>=1.0.5
@@ -7,3 +7,4 @@ packaging>=23.2
7
7
  scaevola<2.0,>=1.1
8
8
  setdoc<2,>=1.2
9
9
  tofunc<2,>=1.0.0
10
+ unhash<2,>=1.0.1
@@ -1,15 +0,0 @@
1
- from abc import ABCMeta, abstractmethod
2
- from typing import *
3
-
4
- import setdoc
5
-
6
-
7
- class BaseList(metaclass=ABCMeta):
8
- __slots__ = ()
9
-
10
- @abstractmethod
11
- @setdoc.basic
12
- def __bool__(self: Self) -> bool: ...
13
-
14
- @abstractmethod
15
- def _format(self: Self, format_spec: str) -> str: ...
@@ -1,75 +0,0 @@
1
- import builtins
2
- from typing import *
3
-
4
- import setdoc
5
- from datahold import OkayList
6
-
7
- from v440._utils.BaseList import BaseList
8
- from v440.core.VersionError import VersionError
9
-
10
-
11
- class VList(OkayList, BaseList):
12
-
13
- __slots__ = ()
14
-
15
- @setdoc.basic
16
- def __format__(self: Self, format_spec: Any) -> str:
17
- try:
18
- return self._format(str(format_spec))
19
- except Exception:
20
- msg: str = "unsupported format string passed to %s.__format__"
21
- msg %= type(self).__name__
22
- raise TypeError(msg) from None
23
-
24
- @setdoc.basic
25
- def __str__(self: Self) -> str:
26
- return builtins.format(self)
27
-
28
- @setdoc.basic
29
- def __eq__(self: Self, other: Any) -> bool:
30
- ans: bool
31
- try:
32
- alt: Self = type(self)(other)
33
- except VersionError:
34
- ans = False
35
- else:
36
- ans = self._data == alt._data
37
- return ans
38
-
39
- @setdoc.basic
40
- def __ge__(self: Self, other: Any, /) -> bool:
41
- ans: bool
42
- try:
43
- alt: Self = type(self)(other)
44
- except Exception:
45
- ans = self.data >= other
46
- else:
47
- ans = alt <= self
48
- return ans
49
-
50
- @setdoc.basic
51
- def __iadd__(self: Self, other: Any, /) -> Self:
52
- self.data += type(self)(other).data
53
- return self
54
-
55
- @setdoc.basic
56
- def __imul__(self: Self, other: Any, /) -> Self:
57
- self.data = self.data * other
58
- return self
59
-
60
- @setdoc.basic
61
- def __le__(self: Self, other: Any, /) -> bool:
62
- ans: bool
63
- try:
64
- alt: Self = type(self)(other)
65
- except Exception:
66
- ans = self.data <= other
67
- else:
68
- ans = self._data <= alt._data
69
- return ans
70
-
71
- def __sorted__(self: Any, /, **kwargs: Any) -> Self:
72
- "This magic method implements sorted(self, **kwargs)."
73
- ans: Any = self.copy()
74
- ans.sort(**kwargs)
75
- return ans
File without changes
File without changes
File without changes
File without changes