v440 2.0.0.dev196__tar.gz → 2.0.0.dev200__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 (58) hide show
  1. {v440-2.0.0.dev196/src/v440.egg-info → v440-2.0.0.dev200}/PKG-INFO +5 -6
  2. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/pyproject.toml +6 -7
  3. {v440-2.0.0.dev196/src/v440/core → v440-2.0.0.dev200/src/v440}/__init__.py +1 -0
  4. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/BaseStringer.py +40 -6
  5. v440-2.0.0.dev200/src/v440/_utils/Cfg.py +41 -0
  6. v440-2.0.0.dev200/src/v440/_utils/Clue.py +114 -0
  7. v440-2.0.0.dev200/src/v440/_utils/ListStringer.py +90 -0
  8. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/QualStringer.py +27 -31
  9. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/SlotStringer.py +3 -0
  10. v440-2.0.0.dev200/src/v440/_utils/cfg.toml +51 -0
  11. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/guarding.py +7 -4
  12. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/releaseparse/getting.py +2 -2
  13. v440-2.0.0.dev200/src/v440/core/Base.py +130 -0
  14. v440-2.0.0.dev200/src/v440/core/Dev.py +79 -0
  15. v440-2.0.0.dev200/src/v440/core/Local.py +208 -0
  16. v440-2.0.0.dev200/src/v440/core/Post.py +78 -0
  17. v440-2.0.0.dev200/src/v440/core/Pre.py +106 -0
  18. v440-2.0.0.dev200/src/v440/core/Public.py +93 -0
  19. v440-2.0.0.dev200/src/v440/core/Qual.py +150 -0
  20. v440-2.0.0.dev200/src/v440/core/Release.py +153 -0
  21. v440-2.0.0.dev200/src/v440/core/Version.py +105 -0
  22. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/core/VersionError.py +3 -0
  23. v440-2.0.0.dev200/src/v440/core/__init__.py +0 -0
  24. v440-2.0.0.dev200/src/v440/tests/test_testdata.py +471 -0
  25. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/tests/test_version.py +8 -28
  26. v440-2.0.0.dev200/src/v440/tests/testdata.toml +2600 -0
  27. {v440-2.0.0.dev196 → v440-2.0.0.dev200/src/v440.egg-info}/PKG-INFO +5 -6
  28. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440.egg-info/SOURCES.txt +1 -1
  29. v440-2.0.0.dev200/src/v440.egg-info/requires.txt +9 -0
  30. v440-2.0.0.dev196/src/v440/__init__.py +0 -2
  31. v440-2.0.0.dev196/src/v440/_utils/Cfg.py +0 -18
  32. v440-2.0.0.dev196/src/v440/_utils/ListStringer.py +0 -183
  33. v440-2.0.0.dev196/src/v440/_utils/Pattern.py +0 -33
  34. v440-2.0.0.dev196/src/v440/_utils/cfg.toml +0 -9
  35. v440-2.0.0.dev196/src/v440/core/Base.py +0 -70
  36. v440-2.0.0.dev196/src/v440/core/Dev.py +0 -31
  37. v440-2.0.0.dev196/src/v440/core/Local.py +0 -63
  38. v440-2.0.0.dev196/src/v440/core/Post.py +0 -32
  39. v440-2.0.0.dev196/src/v440/core/Pre.py +0 -28
  40. v440-2.0.0.dev196/src/v440/core/Public.py +0 -51
  41. v440-2.0.0.dev196/src/v440/core/Qual.py +0 -93
  42. v440-2.0.0.dev196/src/v440/core/Release.py +0 -122
  43. v440-2.0.0.dev196/src/v440/core/Version.py +0 -62
  44. v440-2.0.0.dev196/src/v440/tests/test_testdata.py +0 -422
  45. v440-2.0.0.dev196/src/v440/tests/testdata.toml +0 -967
  46. v440-2.0.0.dev196/src/v440.egg-info/requires.txt +0 -10
  47. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/LICENSE.txt +0 -0
  48. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/MANIFEST.in +0 -0
  49. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/README.rst +0 -0
  50. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/setup.cfg +0 -0
  51. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/__init__.py +0 -0
  52. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/releaseparse/__init__.py +0 -0
  53. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/releaseparse/deleting.py +0 -0
  54. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/releaseparse/ranging.py +0 -0
  55. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/_utils/releaseparse/setting.py +0 -0
  56. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440/tests/__init__.py +0 -0
  57. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/src/v440.egg-info/dependency_links.txt +0 -0
  58. {v440-2.0.0.dev196 → v440-2.0.0.dev200}/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.dev196
3
+ Version: 2.0.0.dev200
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)
@@ -40,15 +40,14 @@ Classifier: Typing :: Typed
40
40
  Requires-Python: >=3.11
41
41
  Description-Content-Type: text/x-rst
42
42
  License-File: LICENSE.txt
43
- Requires-Dist: catchlib<2.0,>=1.0
44
- Requires-Dist: datarepr<2,>=1.0.2
43
+ Requires-Dist: datahold<3,>=2.0
44
+ Requires-Dist: datarepr<2,>=1.1
45
+ Requires-Dist: iterflat<2,>=0.1.3
45
46
  Requires-Dist: iterprod<2.0,>=1.0
46
47
  Requires-Dist: keyalias<2.0,>=1.0.3
47
- Requires-Dist: packaging>=23.2
48
- Requires-Dist: scaevola<2.0,>=1.1
48
+ Requires-Dist: packaging<26,>=25.0
49
49
  Requires-Dist: setdoc<2,>=1.2.6
50
50
  Requires-Dist: setsig<2,>=1.0
51
- Requires-Dist: tofunc<2,>=1.0.0
52
51
  Requires-Dist: unhash<2,>=1.0.1
53
52
  Dynamic: license-file
54
53
 
@@ -1,7 +1,7 @@
1
1
  [build-system]
2
2
  build-backend = "setuptools.build_meta"
3
3
  requires = [
4
- "setuptools>=61.0",
4
+ "setuptools>=64.0",
5
5
  ]
6
6
 
7
7
  [project]
@@ -20,15 +20,14 @@ classifiers = [
20
20
  "Typing :: Typed",
21
21
  ]
22
22
  dependencies = [
23
- "catchlib>=1.0,<2.0",
24
- "datarepr>=1.0.2,<2",
23
+ "datahold>=2.0,<3",
24
+ "datarepr>=1.1,<2",
25
+ "iterflat>=0.1.3,<2",
25
26
  "iterprod>=1.0,<2.0",
26
27
  "keyalias>=1.0.3,<2.0",
27
- "packaging>=23.2",
28
- "scaevola>=1.1,<2.0",
28
+ "packaging>=25.0,<26",
29
29
  "setdoc>=1.2.6,<2",
30
30
  "setsig>=1.0,<2",
31
- "tofunc>=1.0.0,<2",
32
31
  "unhash>=1.0.1,<2",
33
32
  ]
34
33
  description = "This project provides mutable version objects in accordance with PEP440."
@@ -36,7 +35,7 @@ keywords = []
36
35
  name = "v440"
37
36
  readme = "README.rst"
38
37
  requires-python = ">=3.11"
39
- version = "2.0.0.dev196"
38
+ version = "2.0.0.dev200"
40
39
 
41
40
  [project.license]
42
41
  file = "LICENSE.txt"
@@ -1,2 +1,3 @@
1
1
  from v440.core.Version import Version
2
2
  from v440.core.VersionError import VersionError
3
+ from v440.tests import *
@@ -3,8 +3,11 @@ from typing import *
3
3
 
4
4
  import setdoc
5
5
  import unhash
6
+ from datarepr import oxford
6
7
 
8
+ from v440._utils.Cfg import Cfg
7
9
  from v440._utils.guarding import guard
10
+ from v440.core.VersionError import VersionError
8
11
 
9
12
  __all__ = ["BaseStringer"]
10
13
 
@@ -13,6 +16,7 @@ class BaseStringer(metaclass=ABCMeta):
13
16
  __slots__ = ()
14
17
 
15
18
  string: str
19
+ packaging: Any
16
20
 
17
21
  @abstractmethod
18
22
  @setdoc.basic
@@ -27,12 +31,17 @@ class BaseStringer(metaclass=ABCMeta):
27
31
 
28
32
  @setdoc.basic
29
33
  def __format__(self: Self, format_spec: Any) -> str:
34
+ parsed: dict
35
+ ans: str
36
+ msg: str
30
37
  try:
31
- return self._format(str(format_spec))
38
+ parsed = self._format_parse(str(format_spec))
32
39
  except Exception:
33
- msg: str = "Invalid format specifier %r for object of type %r"
40
+ msg = Cfg.cfg.data["consts"]["errors"]["format"]
34
41
  msg %= (format_spec, type(self).__name__)
35
- raise TypeError(msg) from None
42
+ raise VersionError(msg) # from None
43
+ ans = str(self._format_parsed(**parsed))
44
+ return ans
36
45
 
37
46
  @setdoc.basic
38
47
  def __ge__(self: Self, other: Any) -> bool:
@@ -83,13 +92,21 @@ class BaseStringer(metaclass=ABCMeta):
83
92
 
84
93
  @setdoc.basic
85
94
  def __str__(self: Self) -> str:
86
- return self._format("")
95
+ return format(self, "")
87
96
 
88
97
  @abstractmethod
89
98
  def _cmp(self: Self) -> Any: ...
90
99
 
100
+ @classmethod
101
+ @abstractmethod
102
+ def _deformat(cls: type, info: dict[str, Self], /) -> Any: ...
103
+
104
+ @classmethod
91
105
  @abstractmethod
92
- def _format(self: Self, format_spec: str) -> str: ...
106
+ def _format_parse(self: Self, spec: str, /) -> dict: ...
107
+
108
+ @abstractmethod
109
+ def _format_parsed(self: Self, **kwargs: Any) -> Any: ...
93
110
 
94
111
  @abstractmethod
95
112
  def _string_fset(self: Self, value: str) -> None: ...
@@ -98,10 +115,27 @@ class BaseStringer(metaclass=ABCMeta):
98
115
  def copy(self: Self) -> Self:
99
116
  return type(self)(self)
100
117
 
118
+ @classmethod
119
+ def deformat(cls: type, *strings: Any) -> str:
120
+ keys: tuple = tuple(map(str, strings))
121
+ values: tuple = tuple(map(cls, keys))
122
+ info: dict = dict(zip(keys, values))
123
+ try:
124
+ ans: str = cls._deformat(info)
125
+ except Exception:
126
+ msg: str = Cfg.cfg.data["consts"]["errors"]["deformat"]
127
+ msg %= oxford(*strings)
128
+ raise TypeError(msg)
129
+ return ans
130
+
131
+ @property
132
+ @abstractmethod
133
+ def packaging(self: Self) -> Any: ...
134
+
101
135
  @property
102
136
  def string(self: Self) -> str:
103
137
  "This property represents self as str."
104
- return self._format("")
138
+ return format(self, "")
105
139
 
106
140
  @string.setter
107
141
  @guard
@@ -0,0 +1,41 @@
1
+ import enum
2
+ import functools
3
+ import re
4
+ import tomllib
5
+ from importlib import resources
6
+ from typing import *
7
+
8
+ __all__ = ["Cfg"]
9
+
10
+
11
+ class Cfg(enum.Enum):
12
+ cfg = None
13
+
14
+ @functools.cached_property
15
+ def data(self: Self) -> dict:
16
+ "This cached property holds the cfg data."
17
+ text: str = resources.read_text("v440._utils", "cfg.toml")
18
+ ans: dict = tomllib.loads(text)
19
+ return ans
20
+
21
+ @classmethod
22
+ def fullmatches(cls: type, key: str, value: str) -> dict[str, str]:
23
+ ans: dict = cls.cfg.patterns[key].fullmatch(value).groupdict()
24
+ x: str
25
+ for x in ans.keys():
26
+ if ans[x] is None:
27
+ ans[x] = ""
28
+ return ans
29
+
30
+ @functools.cached_property
31
+ def patterns(self: Self) -> dict[str, re.Pattern]:
32
+ ans: dict = dict()
33
+ parts: dict = dict()
34
+ x: str
35
+ y: str
36
+ z: str
37
+ for x, y in self.data["patterns"].items():
38
+ z = y.format(**parts)
39
+ parts[x] = f"(?P<{x}>{z})"
40
+ ans[x] = re.compile(z, re.IGNORECASE | re.VERBOSE)
41
+ return ans
@@ -0,0 +1,114 @@
1
+ import string as string_
2
+ from typing import *
3
+
4
+ from v440._utils.Cfg import Cfg
5
+
6
+
7
+ class Clue(NamedTuple):
8
+ head: str = ""
9
+ sep: str = "?"
10
+ mag: int = 0
11
+
12
+ def __and__(self: Self, other: Self) -> Self:
13
+ s: str
14
+ m: int
15
+ if self.head == "":
16
+ return other
17
+ if other.head == "":
18
+ return self
19
+ if self.head != other.head:
20
+ raise ValueError
21
+ if self.sep == "?":
22
+ s = other.sep
23
+ elif other.sep == "?":
24
+ s = self.sep
25
+ elif self.sep == other.sep:
26
+ s = self.sep
27
+ else:
28
+ raise ValueError
29
+ if self.mag < 0 and other.mag < 0:
30
+ m = max(self.mag, other.mag)
31
+ elif self.mag < 0 or other.mag < 0:
32
+ if 0 < self.mag + other.mag:
33
+ raise ValueError
34
+ m = max(self.mag, other.mag)
35
+ else:
36
+ if self.mag != other.mag:
37
+ raise ValueError
38
+ m = self.mag
39
+ return type(self)(self.head, s, m)
40
+
41
+ @classmethod
42
+ def by_example(cls: type, value: str, /) -> Self:
43
+ sep: str
44
+ mag: int
45
+ matches: dict[str, str]
46
+ if value == "-0":
47
+ return cls("-", "", -1)
48
+ matches = Cfg.fullmatches("clue", value)
49
+ if matches["sep"] or matches["num"]:
50
+ sep = matches["sep"]
51
+ else:
52
+ sep = "?"
53
+ if matches["num"].startswith("0"):
54
+ mag = len(matches["num"])
55
+ else:
56
+ mag = -len(matches["num"])
57
+ return cls(matches["head"], sep, mag)
58
+
59
+ @classmethod
60
+ def by_examples(cls: type, *values: str) -> Self:
61
+ ans: Self = cls()
62
+ s: str
63
+ for s in values:
64
+ ans &= cls.by_string(s)
65
+ return ans
66
+
67
+ @classmethod
68
+ def by_spec(cls: type, value: str, /) -> Self:
69
+ matches: dict[str, str]
70
+ matches = Cfg.fullmatches("clue_f", value)
71
+ return cls(matches["head_f"], matches["sep_f"], len(matches["num_f"]))
72
+
73
+ def seal(self: Self) -> Self:
74
+ mag: int
75
+ mag = self.mag if self.mag >= -1 else -1
76
+ return type(self)(self.head, self.sep, mag)
77
+
78
+ def solo(self: Self, hollow: str) -> str:
79
+ sep: str
80
+ mag: int
81
+ if self.head == "":
82
+ return ""
83
+ mag = self.mag if self.mag >= -1 else -1
84
+ sep = self.sep.replace("?", "")
85
+ if self.head == hollow and sep == "" and mag in (-1, 1):
86
+ return ""
87
+ return self.head + sep + max(0, mag) * "#"
88
+
89
+ def possible(self: Self, *, hollow: str, short: str) -> set:
90
+ s: str
91
+ n: str
92
+ seps: set[str]
93
+ nums: set[str]
94
+ ans: set
95
+ ans = set()
96
+ if self.head == "":
97
+ ans.add("")
98
+ ans.add(short + "#")
99
+ return ans
100
+ if self.sep != "?":
101
+ seps = {self.sep}
102
+ else:
103
+ seps = {"", "."}
104
+ if self.mag < 0:
105
+ nums = {"", "#"}
106
+ else:
107
+ nums = {"#" * self.mag}
108
+ ans = set()
109
+ for s in seps:
110
+ for n in nums:
111
+ ans.add(self.head + s + n)
112
+ if (hollow + "#") in ans:
113
+ ans.add("")
114
+ return ans
@@ -0,0 +1,90 @@
1
+ from abc import abstractmethod
2
+ from typing import *
3
+
4
+ import setdoc
5
+ from datahold import OkayList
6
+ from datarepr import datarepr
7
+
8
+ from v440._utils.BaseStringer import BaseStringer
9
+ from v440._utils.guarding import guard
10
+
11
+ __all__ = ["ListStringer"]
12
+
13
+
14
+ class ListStringer(BaseStringer, OkayList):
15
+
16
+ __slots__ = ()
17
+ string: str
18
+ packaging: Any
19
+ data: tuple
20
+
21
+ @setdoc.basic
22
+ def __add__(self: Self, other: Any) -> Self:
23
+ alt: tuple
24
+ ans: Self
25
+ try:
26
+ alt = tuple(other)
27
+ except Exception:
28
+ return NotImplemented
29
+ ans = type(self)()
30
+ ans.data = self.data + alt
31
+ return ans
32
+
33
+ @setdoc.basic
34
+ def __bool__(self: Self) -> bool:
35
+ return bool(self.data)
36
+
37
+ @setdoc.basic
38
+ def __mul__(self: Self, other: Any) -> Self:
39
+ ans: Self
40
+ ans = type(self)()
41
+ ans.data = self.data * other
42
+ return ans
43
+
44
+ @setdoc.basic
45
+ def __radd__(self: Self, other: Any) -> Self:
46
+ alt: tuple
47
+ ans: Self
48
+ try:
49
+ alt = tuple(other)
50
+ except Exception:
51
+ return NotImplemented
52
+ ans = type(self)()
53
+ ans.data = alt + self.data
54
+ return ans
55
+
56
+ @setdoc.basic
57
+ def __repr__(self: Self) -> str:
58
+ return datarepr(type(self).__name__, list(self))
59
+
60
+ def _cmp(self: Self) -> tuple:
61
+ return tuple(map(self._sort, self.data))
62
+
63
+ @classmethod
64
+ @abstractmethod
65
+ def _data_parse(cls: type, value: list) -> Iterable: ...
66
+
67
+ @classmethod
68
+ @abstractmethod
69
+ def _sort(cls: type, value: Any): ...
70
+
71
+ @property
72
+ @setdoc.basic
73
+ def data(self: Self) -> tuple:
74
+ return self._data
75
+
76
+ @data.setter
77
+ @guard
78
+ def data(self: Self, value: Iterable) -> None:
79
+ self._data = tuple(self._data_parse(list(value)))
80
+
81
+ def sort(self: Self, *, key: Any = None, reverse: Any = False) -> None:
82
+ "This method sorts the data."
83
+ data: list
84
+ k: Any
85
+ r: bool
86
+ data = list(self.data)
87
+ k = self._sort if key is None else key
88
+ r = bool(reverse)
89
+ data.sort(key=k, reverse=r)
90
+ self.data = data
@@ -15,12 +15,13 @@ class QualStringer(BaseStringer):
15
15
  __slots__ = ("_lit", "_num")
16
16
 
17
17
  string: str
18
+ packaging: Any
18
19
  lit: str
19
20
  num: int
20
21
 
21
22
  @setdoc.basic
22
23
  def __bool__(self: Self) -> bool:
23
- return self.lit != ""
24
+ return bool(self.lit)
24
25
 
25
26
  @setdoc.basic
26
27
  def __init__(self: Self, string: Any = "") -> None:
@@ -36,29 +37,25 @@ class QualStringer(BaseStringer):
36
37
  num=self.num,
37
38
  )
38
39
 
39
- def _format(self: Self, format_spec: str) -> str:
40
- if format_spec:
41
- raise ValueError
42
- if self.lit:
43
- return self.lit + str(self.num)
44
- else:
45
- return ""
46
-
47
40
  @classmethod
48
41
  @abstractmethod
49
42
  def _lit_parse(cls: type, value: str) -> str: ...
50
43
 
51
44
  def _string_fset(self: Self, value: str) -> None:
45
+ x: str
46
+ y: str
52
47
  if value == "":
53
48
  self._lit = ""
54
49
  self._num = 0
55
50
  return
56
- x: str = value.rstrip("0123456789")
57
- y: str = value[len(x) :]
51
+ x = value.rstrip("0123456789")
52
+ y = value[len(x) :]
58
53
  if x == "-":
59
- self._string_fset_minus(y)
54
+ if not y:
55
+ raise ValueError
56
+ self._lit = self._lit_parse("-")
57
+ self._num = int(y)
60
58
  return
61
- x = x.lower()
62
59
  x = x.replace("-", ".")
63
60
  x = x.replace("_", ".")
64
61
  if x.endswith("."):
@@ -72,8 +69,21 @@ class QualStringer(BaseStringer):
72
69
  self._lit = self._lit_parse(x)
73
70
  self._num = int("0" + y)
74
71
 
75
- @abstractmethod
76
- def _string_fset_minus(self: Self, value: str) -> None: ...
72
+ @property
73
+ def lit(self: Self) -> str:
74
+ return self._lit
75
+
76
+ @lit.setter
77
+ @guard
78
+ def lit(self: Self, value: Any) -> None:
79
+ x: str
80
+ x = str(value).lower()
81
+ if x:
82
+ self._lit = self._lit_parse(x)
83
+ elif self.num:
84
+ self.string = self.num
85
+ else:
86
+ self._lit = ""
77
87
 
78
88
  @property
79
89
  def num(self: Self) -> int:
@@ -82,25 +92,11 @@ class QualStringer(BaseStringer):
82
92
  @num.setter
83
93
  @guard
84
94
  def num(self: Self, value: SupportsIndex) -> None:
85
- y: int = operator.index(value)
95
+ y: int
96
+ y = operator.index(value)
86
97
  if y < 0:
87
98
  raise ValueError
88
99
  if y and not self.lit:
89
100
  self.string = y
90
101
  else:
91
102
  self._num = y
92
-
93
- @property
94
- def lit(self: Self) -> str:
95
- return self._lit
96
-
97
- @lit.setter
98
- @guard
99
- def lit(self: Self, value: Any) -> None:
100
- x: str = str(value).lower()
101
- if x:
102
- self._lit = self._lit_parse(x)
103
- elif self.num:
104
- self.string = self.num
105
- else:
106
- self._lit = ""
@@ -13,6 +13,7 @@ class SlotStringer(BaseStringer):
13
13
  __slots__ = ()
14
14
 
15
15
  string: str
16
+ packaging: str
16
17
 
17
18
  @setdoc.basic
18
19
  def __bool__(self: Self) -> bool:
@@ -24,3 +25,5 @@ class SlotStringer(BaseStringer):
24
25
 
25
26
  @abstractmethod
26
27
  def _todict(self: Self) -> dict: ...
28
+
29
+ packaging = BaseStringer.string
@@ -0,0 +1,51 @@
1
+ [consts.errors]
2
+ deformat = "No common format specifier for %s."
3
+ format = "Invalid format specifier %r for object of type %r."
4
+
5
+ [consts.phases]
6
+ alpha = "a"
7
+ a = "a"
8
+ beta = "b"
9
+ b = "b"
10
+ preview = "rc"
11
+ pre = "rc"
12
+ c = "rc"
13
+ rc = "rc"
14
+
15
+ [patterns]
16
+ basev_f = "V?"
17
+ epoch_f = "\\#*"
18
+ release_f = "[\\#\\.]*"
19
+ base_f = "{basev_f}({epoch_f}!)?{release_f}"
20
+ a_f = "[-_\\.]?(ALPHA|A)[-_\\.]?\\#*"
21
+ b_f = "[-_\\.]?(BETA|B)[-_\\.]?\\#*"
22
+ rc_f = "[-_\\.]?(PREVIEW|PRE|C|RC)[-_\\.]?\\#*"
23
+ pre_f = "{a_f}?{b_f}?{rc_f}?"
24
+ post_hyphen_f = "-"
25
+ post_head_f = "[-_\\.]?(POST|REV|R)"
26
+ post_sep_f = "[-_\\.]?"
27
+ post_lit_f = "({post_hyphen_f}|({post_head_f}{post_sep_f}))"
28
+ post_num_f = "\\#*"
29
+ post_f = "({post_lit_f}{post_num_f})?"
30
+ dev_head_f = "[-_\\.]?DEV"
31
+ dev_sep_f = "[-_\\.]?"
32
+ dev_num_f = "\\#*"
33
+ dev_f = "({dev_head_f}{dev_sep_f}{dev_num_f})?"
34
+ qual_f = "{pre_f}{post_f}{dev_f}"
35
+ basev = "V"
36
+ epoch = "[0-9]+"
37
+ release = "[0-9]+(\\.[0-9]+)*"
38
+ base = "{basev}?({epoch}!)?{release}"
39
+ pre = "[-_\\.]?(ALPHA|A|BETA|B|PREVIEW|PRE|C|RC)([-_\\.]?[0-9]+)?"
40
+ post = "(-([0-9]+))|(([-_\\.]?(POST|REV|R))([-_\\.]?([0-9]+))?)"
41
+ dev = "[-_\\.]?DEV([-_\\.]?[0-9]+)?"
42
+ qual = "{pre}?{post}?{dev}?"
43
+ local_splitter = "([-_\\.])"
44
+ head = "[-_\\.]?[A-Z]*"
45
+ sep = "[-_\\.]?"
46
+ num = "[0-9]*"
47
+ clue = "{head}?{sep}?{num}?"
48
+ head_f = "[-_\\.]?[A-Z]*"
49
+ sep_f = "[-_\\.]?"
50
+ num_f = "\\#*"
51
+ clue_f = "{head_f}?{sep_f}?{num_f}?"
@@ -11,16 +11,19 @@ __all__ = ["guard"]
11
11
  def guard(old: Any) -> Any:
12
12
  @functools.wraps(old)
13
13
  def new(self: Self, value: Any) -> None:
14
- backup: str = str(self)
14
+ backup: str
15
+ msg: str
16
+ target: str
17
+ backup = str(self)
15
18
  try:
16
19
  old(self, value)
17
20
  except VersionError:
18
21
  self.string = backup
19
22
  raise
20
23
  except Exception:
21
- self.string = backup
22
- msg: str = "%r is an invalid value for %r"
23
- target: str = type(self).__name__ + "." + old.__name__
24
+ self._string_fset(backup.lower())
25
+ msg = "%r is an invalid value for %r"
26
+ target = type(self).__name__ + "." + old.__name__
24
27
  msg %= (value, target)
25
28
  raise VersionError(msg)
26
29
 
@@ -7,8 +7,8 @@ from typing import *
7
7
  from v440._utils.releaseparse import ranging
8
8
 
9
9
 
10
- def getitem(data: tuple, key: SupportsIndex | slice) -> list:
11
- ans: int | tuple
10
+ def getitem(data: tuple, key: SupportsIndex | slice) -> int | list:
11
+ ans: int | list
12
12
  if type(key) is slice:
13
13
  r: range = ranging.torange(key, len(data))
14
14
  f: partial = partial(getitem_int, data)