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.
Files changed (73) hide show
  1. {pythonwrench-0.4.8/src/pythonwrench.egg-info → pythonwrench-0.4.10}/PKG-INFO +1 -1
  2. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/__init__.py +1 -1
  3. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/disk_cache.py +1 -0
  4. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/semver.py +68 -58
  5. {pythonwrench-0.4.8 → pythonwrench-0.4.10/src/pythonwrench.egg-info}/PKG-INFO +1 -1
  6. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_semver.py +30 -0
  7. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/LICENSE +0 -0
  8. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/README.md +0 -0
  9. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/docs/requirements.txt +0 -0
  10. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/pyproject.toml +0 -0
  11. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/setup.cfg +0 -0
  12. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/setup.py +0 -0
  13. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/__main__.py +0 -0
  14. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/_core.py +0 -0
  15. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/abc.py +0 -0
  16. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/argparse.py +0 -0
  17. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/cast.py +0 -0
  18. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/checksum.py +0 -0
  19. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/__init__.py +0 -0
  20. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/collections.py +0 -0
  21. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/prop.py +0 -0
  22. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/collections/reducers.py +0 -0
  23. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/concurrent.py +0 -0
  24. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/csv.py +0 -0
  25. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/dataclasses.py +0 -0
  26. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/datetime.py +0 -0
  27. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/difflib.py +0 -0
  28. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/entries.py +0 -0
  29. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/enum.py +0 -0
  30. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/functools.py +0 -0
  31. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/hashlib.py +0 -0
  32. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/importlib.py +0 -0
  33. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/inspect.py +0 -0
  34. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/json.py +0 -0
  35. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/jsonl.py +0 -0
  36. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/logging.py +0 -0
  37. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/math.py +0 -0
  38. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/os.py +0 -0
  39. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/pickle.py +0 -0
  40. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/random.py +0 -0
  41. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/re.py +0 -0
  42. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/__init__.py +0 -0
  43. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/checks.py +0 -0
  44. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/typing/classes.py +0 -0
  45. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench/warnings.py +0 -0
  46. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/SOURCES.txt +0 -0
  47. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/dependency_links.txt +0 -0
  48. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/entry_points.txt +0 -0
  49. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/requires.txt +0 -0
  50. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/src/pythonwrench.egg-info/top_level.txt +0 -0
  51. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_abc.py +0 -0
  52. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_argparse.py +0 -0
  53. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_cast.py +0 -0
  54. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_checksum.py +0 -0
  55. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_collections.py +0 -0
  56. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_csv.py +0 -0
  57. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_dataclasses.py +0 -0
  58. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_difflib.py +0 -0
  59. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_disk_cache.py +0 -0
  60. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_entries.py +0 -0
  61. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_enum.py +0 -0
  62. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_functools.py +0 -0
  63. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_hashlib.py +0 -0
  64. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_importlib.py +0 -0
  65. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_inspect.py +0 -0
  66. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_json.py +0 -0
  67. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_jsonl.py +0 -0
  68. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_logging.py +0 -0
  69. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_math.py +0 -0
  70. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_os.py +0 -0
  71. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_random.py +0 -0
  72. {pythonwrench-0.4.8 → pythonwrench-0.4.10}/tests/test_readme.py +0 -0
  73. {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.8
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>
@@ -9,7 +9,7 @@ __author_email__ = "labbeti.pub@gmail.com"
9
9
  __license__ = "MIT"
10
10
  __maintainer__ = "Étienne Labbé (Labbeti)"
11
11
  __status__ = "Development"
12
- __version__ = "0.4.8"
12
+ __version__ = "0.4.10"
13
13
 
14
14
 
15
15
  # Re-import for language servers
@@ -441,6 +441,7 @@ def _disk_cache_impl(
441
441
  if cache_fname_fmt_args is None or argname in cache_fname_fmt_args
442
442
  }
443
443
  kwds.update(inputs_kwds)
444
+ kwds.update(kwargs)
444
445
 
445
446
  cache_fname = cache_fname_fmt(**kwds)
446
447
  cache_fpath = cache_fn_dpath.joinpath(cache_fname)
@@ -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, Iterable, List, Mapping, Tuple, TypedDict, Union, overload
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 = Iterable[Union[int, PreRelease, BuildMetadata]]
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 __str__(self) -> str:
270
- return self.to_str()
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 __lt__(self, other: VersionLike) -> bool:
288
- if isinstance(other, (dict, tuple, str)):
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
- if isinstance(self_v, (int, str, NoneType)):
307
- self_v = [self_v]
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
- return False
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 (self != other) and not (self < other)
297
+ return _compare_lt(other, self)
342
298
 
343
299
  def __ge__(self, other: VersionLike) -> bool:
344
- return not (self < other)
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.8
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