pythonwrench 0.4.8__tar.gz → 0.4.10__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.
- {pythonwrench-0.4.8/src/pythonwrench.egg-info → pythonwrench-0.4.10}/PKG-INFO +1 -1
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/__init__.py +1 -1
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/disk_cache.py +1 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/semver.py +68 -58
- {pythonwrench-0.4.8 → pythonwrench-0.4.10/src/pythonwrench.egg-info}/PKG-INFO +1 -1
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_semver.py +30 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/LICENSE +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/README.md +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/docs/requirements.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/pyproject.toml +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/setup.cfg +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/setup.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/__main__.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/_core.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/abc.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/argparse.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/cast.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/checksum.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/__init__.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/collections.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/prop.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/reducers.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/concurrent.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/csv.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/dataclasses.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/datetime.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/difflib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/entries.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/enum.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/functools.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/hashlib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/importlib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/inspect.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/json.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/jsonl.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/logging.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/math.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/os.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/pickle.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/random.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/re.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/__init__.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/checks.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/classes.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/warnings.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/SOURCES.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/dependency_links.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/entry_points.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/requires.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/top_level.txt +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_abc.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_argparse.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_cast.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_checksum.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_collections.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_csv.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_dataclasses.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_difflib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_disk_cache.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_entries.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_enum.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_functools.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_hashlib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_importlib.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_inspect.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_json.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_jsonl.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_logging.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_math.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_os.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_random.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_readme.py +0 -0
- {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_typing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pythonwrench
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.10
|
|
4
4
|
Summary: Python library with tools for typing, manipulating collections, and more!
|
|
5
5
|
Author-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
|
|
6
6
|
Maintainer-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
import re
|
|
6
6
|
import sys
|
|
7
7
|
from dataclasses import asdict, dataclass
|
|
8
|
-
from typing import Any,
|
|
8
|
+
from typing import Any, List, Mapping, Tuple, TypedDict, Union, overload
|
|
9
9
|
|
|
10
10
|
from typing_extensions import NotRequired, Self, TypeAlias
|
|
11
11
|
|
|
@@ -40,7 +40,7 @@ VersionTuple: TypeAlias = Union[
|
|
|
40
40
|
]
|
|
41
41
|
|
|
42
42
|
VersionDictLike: TypeAlias = Mapping[str, Union[int, PreRelease, BuildMetadata]]
|
|
43
|
-
VersionTupleLike: TypeAlias =
|
|
43
|
+
VersionTupleLike: TypeAlias = Tuple[Union[int, PreRelease, BuildMetadata], ...]
|
|
44
44
|
VersionLike: TypeAlias = Union["Version", str, VersionDictLike, VersionTupleLike]
|
|
45
45
|
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ class Version:
|
|
|
50
50
|
|
|
51
51
|
Version format is: MAJOR.MINOR.PATCH[-PRERELEASE][+BUILDMETADATA]
|
|
52
52
|
|
|
53
|
-
Based on https://semver.org
|
|
53
|
+
Based on https://semver.org/ version 2.0.0.
|
|
54
54
|
"""
|
|
55
55
|
|
|
56
56
|
major: int
|
|
@@ -266,11 +266,8 @@ class Version:
|
|
|
266
266
|
version_tuple = tuple(self.to_dict(exclude_none).values())
|
|
267
267
|
return version_tuple # type: ignore
|
|
268
268
|
|
|
269
|
-
def
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def __eq__(self, other: Any) -> bool:
|
|
273
|
-
if isinstance(other, (dict, tuple, str)):
|
|
269
|
+
def equals(self, other: VersionLike, *, ignore_buildmetadata: bool = False) -> bool:
|
|
270
|
+
if isinstance(other, (Mapping, tuple, str)):
|
|
274
271
|
other = Version(other)
|
|
275
272
|
# note: use self.__class__ to avoid error cause by 'pytest -v test' collect
|
|
276
273
|
elif not isinstance(other, (Version, self.__class__)):
|
|
@@ -281,67 +278,80 @@ class Version:
|
|
|
281
278
|
and self.minor == other.minor
|
|
282
279
|
and self.patch == other.patch
|
|
283
280
|
and self.prerelease == other.prerelease
|
|
284
|
-
and self.buildmetadata == other.buildmetadata
|
|
281
|
+
and (ignore_buildmetadata or self.buildmetadata == other.buildmetadata)
|
|
285
282
|
)
|
|
286
283
|
|
|
287
|
-
def
|
|
288
|
-
|
|
289
|
-
other = Version(other)
|
|
290
|
-
# note: use self.__class__ to avoid error cause by 'pytest -v test' collect
|
|
291
|
-
elif not isinstance(other, (Version, self.__class__)):
|
|
292
|
-
msg = f"Invalid argument type {type(other)}. (expected an instance of one of {(dict, tuple, str, Version)})"
|
|
293
|
-
raise TypeError(msg)
|
|
294
|
-
|
|
295
|
-
self_tuple = self.to_tuple(exclude_none=False)
|
|
296
|
-
other_tuple = other.to_tuple(exclude_none=False)
|
|
297
|
-
|
|
298
|
-
for self_v, other_v in zip(self_tuple, other_tuple):
|
|
299
|
-
if self_v == other_v:
|
|
300
|
-
continue
|
|
301
|
-
if self_v is None and other_v is not None:
|
|
302
|
-
return False
|
|
303
|
-
if self_v is not None and other_v is None:
|
|
304
|
-
return True
|
|
284
|
+
def __str__(self) -> str:
|
|
285
|
+
return self.to_str()
|
|
305
286
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
elif not isinstance(self_v, list):
|
|
309
|
-
raise TypeError(f"Invalid argument type {type(self_v)}.")
|
|
310
|
-
|
|
311
|
-
if isinstance(other_v, (int, str, NoneType)):
|
|
312
|
-
other_v = [other_v]
|
|
313
|
-
elif not isinstance(other_v, list):
|
|
314
|
-
raise TypeError(f"Invalid argument type {type(other_v)}.")
|
|
315
|
-
|
|
316
|
-
minlen = min(len(self_v), len(other_v))
|
|
317
|
-
if len(self_v) != len(other_v) and self_v[:minlen] == other_v[:minlen]:
|
|
318
|
-
return len(self_v) < len(other_v)
|
|
319
|
-
|
|
320
|
-
for self_vi, other_vi in zip(self_v, other_v):
|
|
321
|
-
if self_vi == other_vi:
|
|
322
|
-
continue
|
|
323
|
-
if isinstance(self_vi, int) and isinstance(other_vi, int):
|
|
324
|
-
return self_vi < other_vi
|
|
325
|
-
if isinstance(self_vi, int) and isinstance(other_vi, str):
|
|
326
|
-
return True
|
|
327
|
-
if isinstance(self_vi, str) and isinstance(other_vi, int):
|
|
328
|
-
return False
|
|
329
|
-
if isinstance(self_vi, str) and isinstance(other_vi, str):
|
|
330
|
-
return self_vi < other_vi
|
|
331
|
-
|
|
332
|
-
msg = f"Invalid attribute type {self_vi=} and {other_vi=}."
|
|
333
|
-
raise TypeError(msg)
|
|
287
|
+
def __eq__(self, other: Any) -> bool:
|
|
288
|
+
return self.equals(other)
|
|
334
289
|
|
|
335
|
-
|
|
290
|
+
def __lt__(self, other: VersionLike) -> bool:
|
|
291
|
+
return _compare_lt(self, other)
|
|
336
292
|
|
|
337
293
|
def __le__(self, other: VersionLike) -> bool:
|
|
338
294
|
return (self == other) or (self < other)
|
|
339
295
|
|
|
340
296
|
def __gt__(self, other: VersionLike) -> bool:
|
|
341
|
-
return (
|
|
297
|
+
return _compare_lt(other, self)
|
|
342
298
|
|
|
343
299
|
def __ge__(self, other: VersionLike) -> bool:
|
|
344
|
-
return
|
|
300
|
+
return (self == other) or (self > other)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _compare_lt(
|
|
304
|
+
x: Union[Version, Mapping, tuple, str], y: Union[Version, Mapping, tuple, str]
|
|
305
|
+
) -> bool:
|
|
306
|
+
if isinstance(x, (Mapping, tuple, str)):
|
|
307
|
+
x = Version(x)
|
|
308
|
+
if isinstance(y, (Mapping, tuple, str)):
|
|
309
|
+
y = Version(y)
|
|
310
|
+
|
|
311
|
+
self_tuple = x.to_tuple(exclude_none=False)
|
|
312
|
+
other_tuple = y.to_tuple(exclude_none=False)
|
|
313
|
+
|
|
314
|
+
self_tuple = self_tuple[:4]
|
|
315
|
+
other_tuple = other_tuple[:4]
|
|
316
|
+
|
|
317
|
+
for self_v, other_v in zip(self_tuple, other_tuple):
|
|
318
|
+
if self_v == other_v:
|
|
319
|
+
continue
|
|
320
|
+
if self_v is None and other_v is not None:
|
|
321
|
+
return False
|
|
322
|
+
if self_v is not None and other_v is None:
|
|
323
|
+
return True
|
|
324
|
+
|
|
325
|
+
if isinstance(self_v, (int, str, NoneType)):
|
|
326
|
+
self_v = [self_v]
|
|
327
|
+
elif not isinstance(self_v, list):
|
|
328
|
+
raise TypeError(f"Invalid argument type {type(self_v)}.")
|
|
329
|
+
|
|
330
|
+
if isinstance(other_v, (int, str, NoneType)):
|
|
331
|
+
other_v = [other_v]
|
|
332
|
+
elif not isinstance(other_v, list):
|
|
333
|
+
raise TypeError(f"Invalid argument type {type(other_v)}.")
|
|
334
|
+
|
|
335
|
+
minlen = min(len(self_v), len(other_v))
|
|
336
|
+
if len(self_v) != len(other_v) and self_v[:minlen] == other_v[:minlen]:
|
|
337
|
+
return len(self_v) < len(other_v)
|
|
338
|
+
|
|
339
|
+
for self_vi, other_vi in zip(self_v, other_v):
|
|
340
|
+
if self_vi == other_vi:
|
|
341
|
+
continue
|
|
342
|
+
if isinstance(self_vi, int) and isinstance(other_vi, int):
|
|
343
|
+
return self_vi < other_vi
|
|
344
|
+
if isinstance(self_vi, int) and isinstance(other_vi, str):
|
|
345
|
+
return True
|
|
346
|
+
if isinstance(self_vi, str) and isinstance(other_vi, int):
|
|
347
|
+
return False
|
|
348
|
+
if isinstance(self_vi, str) and isinstance(other_vi, str):
|
|
349
|
+
return self_vi < other_vi
|
|
350
|
+
|
|
351
|
+
msg = f"Invalid attribute type {self_vi=} and {other_vi=}."
|
|
352
|
+
raise TypeError(msg)
|
|
353
|
+
|
|
354
|
+
return False
|
|
345
355
|
|
|
346
356
|
|
|
347
357
|
def _parse_version_str(version_str: str) -> VersionDict:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pythonwrench
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.10
|
|
4
4
|
Summary: Python library with tools for typing, manipulating collections, and more!
|
|
5
5
|
Author-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
|
|
6
6
|
Maintainer-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
|
|
@@ -63,6 +63,15 @@ class TestVersion(TestCase):
|
|
|
63
63
|
# Check if versions can be parsed
|
|
64
64
|
Version(pw.__version__)
|
|
65
65
|
|
|
66
|
+
# buildmetadata can contains "-" symbol
|
|
67
|
+
v14 = Version("1.0.0+build-info")
|
|
68
|
+
assert v14.to_dict() == {
|
|
69
|
+
"major": 1,
|
|
70
|
+
"minor": 0,
|
|
71
|
+
"patch": 0,
|
|
72
|
+
"buildmetadata": "build-info",
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
def test_parse_invalid(self) -> None:
|
|
67
76
|
with self.assertRaises(ValueError):
|
|
68
77
|
Version() # type: ignore
|
|
@@ -133,6 +142,27 @@ class TestVersion(TestCase):
|
|
|
133
142
|
for version_str in tests:
|
|
134
143
|
_ = Version(version_str)
|
|
135
144
|
|
|
145
|
+
def test_priority(self) -> None:
|
|
146
|
+
v1 = Version("1.0.0")
|
|
147
|
+
v2 = Version("1.0.0-alpha")
|
|
148
|
+
v3 = Version("1.0.0+build")
|
|
149
|
+
v4 = Version("1.0.0-alpha+build")
|
|
150
|
+
|
|
151
|
+
# IMPORTANT: prerelease should have lower precedence than the associated normal version
|
|
152
|
+
assert v1 > v2
|
|
153
|
+
assert not (v1 < v2)
|
|
154
|
+
assert v1 != v2
|
|
155
|
+
|
|
156
|
+
# IMPORTANT: build metadata should not affect version precedence
|
|
157
|
+
assert not (v1 > v3)
|
|
158
|
+
assert not (v1 < v3)
|
|
159
|
+
assert v1 != v3
|
|
160
|
+
|
|
161
|
+
# check both
|
|
162
|
+
assert v1 > v4
|
|
163
|
+
assert not (v1 < v4)
|
|
164
|
+
assert v1 != v4
|
|
165
|
+
|
|
136
166
|
|
|
137
167
|
if __name__ == "__main__":
|
|
138
168
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|