pythonwrench 0.4.0__tar.gz → 0.4.1__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 (72) hide show
  1. {pythonwrench-0.4.0/src/pythonwrench.egg-info → pythonwrench-0.4.1}/PKG-INFO +2 -3
  2. pythonwrench-0.4.1/docs/requirements.txt +3 -0
  3. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/__init__.py +6 -1
  4. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/_core.py +7 -3
  5. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/argparse.py +9 -9
  6. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/checksum.py +3 -1
  7. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/importlib.py +7 -3
  8. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/random.py +12 -1
  9. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/typing/__init__.py +1 -0
  10. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/typing/classes.py +27 -18
  11. {pythonwrench-0.4.0 → pythonwrench-0.4.1/src/pythonwrench.egg-info}/PKG-INFO +2 -3
  12. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench.egg-info/SOURCES.txt +1 -0
  13. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_checksum.py +6 -0
  14. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/LICENSE +0 -0
  15. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/README.md +0 -0
  16. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/pyproject.toml +0 -0
  17. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/setup.cfg +0 -0
  18. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/setup.py +0 -0
  19. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/__main__.py +0 -0
  20. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/abc.py +0 -0
  21. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/cast.py +0 -0
  22. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/collections/__init__.py +0 -0
  23. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/collections/collections.py +6 -6
  24. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/collections/prop.py +0 -0
  25. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/collections/reducers.py +0 -0
  26. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/csv.py +0 -0
  27. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/dataclasses.py +0 -0
  28. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/datetime.py +0 -0
  29. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/difflib.py +0 -0
  30. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/disk_cache.py +0 -0
  31. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/entries.py +0 -0
  32. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/enum.py +0 -0
  33. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/functools.py +0 -0
  34. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/hashlib.py +0 -0
  35. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/inspect.py +0 -0
  36. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/io.py +0 -0
  37. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/json.py +0 -0
  38. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/jsonl.py +0 -0
  39. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/logging.py +0 -0
  40. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/math.py +0 -0
  41. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/os.py +0 -0
  42. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/pickle.py +0 -0
  43. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/re.py +0 -0
  44. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/semver.py +0 -0
  45. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/typing/checks.py +0 -0
  46. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench/warnings.py +0 -0
  47. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench.egg-info/dependency_links.txt +0 -0
  48. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench.egg-info/entry_points.txt +0 -0
  49. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench.egg-info/requires.txt +0 -0
  50. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/src/pythonwrench.egg-info/top_level.txt +0 -0
  51. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_abc.py +0 -0
  52. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_argparse.py +0 -0
  53. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_cast.py +0 -0
  54. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_collections.py +0 -0
  55. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_csv.py +0 -0
  56. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_dataclasses.py +0 -0
  57. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_difflib.py +0 -0
  58. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_entries.py +0 -0
  59. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_enum.py +0 -0
  60. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_functools.py +0 -0
  61. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_hashlib.py +0 -0
  62. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_importlib.py +0 -0
  63. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_inspect.py +0 -0
  64. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_json.py +0 -0
  65. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_jsonl.py +0 -0
  66. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_logging.py +0 -0
  67. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_math.py +0 -0
  68. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_os.py +0 -0
  69. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_random.py +0 -0
  70. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_readme.py +0 -0
  71. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_semver.py +0 -0
  72. {pythonwrench-0.4.0 → pythonwrench-0.4.1}/tests/test_typing.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.1
2
2
  Name: pythonwrench
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Set of tools for Python that could be in the standard library.
5
5
  Author-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
6
6
  Maintainer-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
@@ -47,7 +47,6 @@ Requires-Python: >=3.8
47
47
  Description-Content-Type: text/markdown
48
48
  License-File: LICENSE
49
49
  Requires-Dist: typing-extensions>=4.10.0
50
- Dynamic: license-file
51
50
 
52
51
  # pythonwrench
53
52
 
@@ -0,0 +1,3 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ sphinx-press-theme>=0.8.0
@@ -9,17 +9,20 @@ __author_email__ = "labbeti.pub@gmail.com"
9
9
  __license__ = "MIT"
10
10
  __maintainer__ = "Étienne Labbé (Labbeti)"
11
11
  __status__ = "Development"
12
- __version__ = "0.4.0"
12
+ __version__ = "0.4.1"
13
13
 
14
14
 
15
15
  # Re-import for language servers
16
16
  from . import abc as abc
17
17
  from . import argparse as argparse
18
+ from . import cast as cast
19
+ from . import checksum as checksum
18
20
  from . import collections as collections
19
21
  from . import csv as csv
20
22
  from . import dataclasses as dataclasses
21
23
  from . import datetime as datetime
22
24
  from . import difflib as difflib
25
+ from . import disk_cache as disk_cache
23
26
  from . import entries as entries
24
27
  from . import enum as enum
25
28
  from . import functools as functools
@@ -28,6 +31,7 @@ from . import importlib as importlib
28
31
  from . import inspect as inspect
29
32
  from . import io as io
30
33
  from . import json as json
34
+ from . import jsonl as jsonl
31
35
  from . import logging as logging
32
36
  from . import math as math
33
37
  from . import os as os
@@ -166,6 +170,7 @@ from .typing import (
166
170
  SupportsAnd,
167
171
  SupportsBool,
168
172
  SupportsDiv,
173
+ SupportsGetitem,
169
174
  SupportsGetitemIterLen,
170
175
  SupportsGetitemLen,
171
176
  SupportsIterLen,
@@ -9,22 +9,26 @@ from typing import (
9
9
  Generic,
10
10
  Literal,
11
11
  Optional,
12
+ Protocol,
12
13
  Tuple,
13
- TypeVar,
14
14
  Union,
15
15
  get_args,
16
16
  )
17
17
 
18
- from typing_extensions import ParamSpec
18
+ from typing_extensions import ParamSpec, TypeVar
19
19
 
20
20
  P = ParamSpec("P")
21
21
  T = TypeVar("T")
22
22
  U = TypeVar("U")
23
23
  T_Output = TypeVar("T_Output")
24
+ T_Any = TypeVar("T_Any", contravariant=True, default=Any)
24
25
 
25
26
  UnkMode = Literal["identity", "error"]
26
27
  ClassOrTuple = Union[type, Tuple[type, ...]]
27
- Predicate = Callable[[Any], bool]
28
+
29
+
30
+ class Predicate(Protocol[T_Any]):
31
+ def __call__(self, x: T_Any) -> bool: ...
28
32
 
29
33
 
30
34
  def return_none(*args, **kwargs) -> None:
@@ -35,7 +35,7 @@ def parse_to(
35
35
  ) -> Callable[[str], T]:
36
36
  """Returns a callable that convert string value to target type safely.
37
37
 
38
- Intended for argparse boolean arguments.
38
+ Intended for argparse arguments.
39
39
  """
40
40
  return partial(
41
41
  str_to_type,
@@ -56,7 +56,7 @@ def str_to_type(
56
56
  false_values: Union[str, Iterable[str]] = DEFAULT_FALSE_VALUES,
57
57
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
58
58
  ) -> T:
59
- """Convert string values to target type safely. Intended for argparse boolean arguments.
59
+ """Convert string values to target type safely. Intended for argparse arguments.
60
60
 
61
61
  - True values: 'True', 'T', 'yes', 'y', '1'.
62
62
  - False values: 'False', 'F', 'no', 'n', '0'.
@@ -84,7 +84,7 @@ def str_to_bool(
84
84
  true_values: Union[str, Iterable[str]] = DEFAULT_TRUE_VALUES,
85
85
  false_values: Union[str, Iterable[str]] = DEFAULT_FALSE_VALUES,
86
86
  ) -> bool:
87
- """Convert string values to bool safely. Intended for argparse boolean arguments.
87
+ """Convert string values to bool safely. Intended for argparse arguments.
88
88
 
89
89
  - True values: 'True', 'T', 'yes', 'y', '1'.
90
90
  - False values: 'False', 'F', 'no', 'n', '0'.
@@ -105,7 +105,7 @@ def str_to_none(
105
105
  case_sensitive: bool = False,
106
106
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
107
107
  ) -> None:
108
- """Convert string values to None safely. Intended for argparse boolean arguments.
108
+ """Convert string values to None safely. Intended for argparse arguments.
109
109
 
110
110
  - None values: 'None', 'null'
111
111
  - Other raises ValueError.
@@ -123,7 +123,7 @@ def str_to_optional_bool(
123
123
  false_values: Union[str, Iterable[str]] = DEFAULT_FALSE_VALUES,
124
124
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
125
125
  ) -> Optional[bool]:
126
- """Convert string values to optional bool safely. Intended for argparse boolean arguments.
126
+ """Convert string values to optional bool safely. Intended for argparse arguments.
127
127
 
128
128
  - True values: 'True', 'T', 'yes', 'y', '1'.
129
129
  - False values: 'False', 'F', 'no', 'n', '0'.
@@ -141,7 +141,7 @@ def str_to_optional_float(
141
141
  case_sensitive: bool = False,
142
142
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
143
143
  ) -> Optional[float]:
144
- """Convert string values to optional float safely. Intended for argparse boolean arguments."""
144
+ """Convert string values to optional float safely. Intended for argparse arguments."""
145
145
  return str_to_type(
146
146
  x, Optional[float], case_sensitive=case_sensitive, none_values=none_values
147
147
  )
@@ -153,7 +153,7 @@ def str_to_optional_int(
153
153
  case_sensitive: bool = False,
154
154
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
155
155
  ) -> Optional[int]:
156
- """Convert string values to optional int safely. Intended for argparse boolean arguments."""
156
+ """Convert string values to optional int safely. Intended for argparse arguments."""
157
157
  return str_to_type(
158
158
  x, Optional[int], case_sensitive=case_sensitive, none_values=none_values
159
159
  )
@@ -165,7 +165,7 @@ def str_to_optional_str(
165
165
  case_sensitive: bool = False,
166
166
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
167
167
  ) -> Optional[str]:
168
- """Convert string values to optional str safely. Intended for argparse boolean arguments."""
168
+ """Convert string values to optional str safely. Intended for argparse arguments."""
169
169
  return str_to_type(
170
170
  x, Optional[str], case_sensitive=case_sensitive, none_values=none_values
171
171
  )
@@ -284,7 +284,7 @@ def _str_to_none_impl(
284
284
  case_sensitive: bool = False,
285
285
  none_values: Union[str, Iterable[str]] = DEFAULT_NONE_VALUES,
286
286
  ) -> Union[None, Exception]:
287
- """Convert string values to None safely. Intended for argparse boolean arguments.
287
+ """Convert string values to None safely. Intended for argparse arguments.
288
288
 
289
289
  - None values: 'None', 'null'
290
290
  - Other raises ValueError.
@@ -196,7 +196,9 @@ def checksum_set(x: Union[set, frozenset], **kwargs) -> int:
196
196
  kwargs["accumulator"] = kwargs.get("accumulator", 0) + _cached_checksum_str(
197
197
  get_fullname(x)
198
198
  )
199
- return _checksum_iterable(sorted(x), **kwargs)
199
+ # Simply use sum here, order does not matter
200
+ csum = sum(checksum_any(xi, **kwargs) for xi in x)
201
+ return csum
200
202
 
201
203
 
202
204
  @register_checksum_fn(range)
@@ -107,14 +107,12 @@ def search_submodules(
107
107
 
108
108
 
109
109
  def reload_submodules(
110
- module: ModuleType,
111
- *others: ModuleType,
110
+ *modules: ModuleType,
112
111
  verbose: int = 0,
113
112
  only_editable: bool = True,
114
113
  only_loaded: bool = False,
115
114
  ) -> List[ModuleType]:
116
115
  """Reload all submodule recursively."""
117
- modules = (module,) + others
118
116
  candidates: Dict[ModuleType, None] = {}
119
117
  for module in modules:
120
118
  submodules = search_submodules(
@@ -169,6 +167,12 @@ class Placeholder:
169
167
  def __getitem__(self, *args, **kwargs) -> Any:
170
168
  return self
171
169
 
170
+ def __eq__(self, other) -> Any:
171
+ return self == other
172
+
173
+ def __ne__(self, other) -> Any:
174
+ return self != other
175
+
172
176
 
173
177
  def requires_packages(
174
178
  arg0: Union[Iterable[str], str],
@@ -13,6 +13,7 @@ def randstr(
13
13
  /,
14
14
  *,
15
15
  letters: Iterable[str] = string.ascii_letters,
16
+ seed: Optional[int] = None,
16
17
  ) -> str: ...
17
18
 
18
19
 
@@ -23,6 +24,7 @@ def randstr(
23
24
  /,
24
25
  *,
25
26
  letters: Iterable[str] = string.ascii_letters,
27
+ seed: Optional[int] = None,
26
28
  ) -> str: ...
27
29
 
28
30
 
@@ -32,14 +34,23 @@ def randstr(
32
34
  /,
33
35
  *,
34
36
  letters: Iterable[str] = string.ascii_letters,
37
+ seed: Optional[int] = None,
35
38
  ) -> str:
36
39
  """Returns a randomly generated string of a random range length."""
37
40
  assert low_or_size >= 0
41
+
42
+ initial_state = random.getstate()
38
43
  if high is None:
39
44
  size = low_or_size
45
+ random.seed(seed)
40
46
  else:
41
47
  assert low_or_size < high
48
+ random.seed(seed)
42
49
  size = random.randint(low_or_size, high - 1)
43
50
 
44
51
  letters = list(letters)
45
- return "".join(random.choice(letters) for _ in range(size))
52
+ result = "".join(random.choice(letters) for _ in range(size))
53
+
54
+ if seed is not None:
55
+ random.setstate(initial_state)
56
+ return result
@@ -31,6 +31,7 @@ from .classes import (
31
31
  SupportsAnd,
32
32
  SupportsBool,
33
33
  SupportsDiv,
34
+ SupportsGetitem,
34
35
  SupportsGetitemIterLen,
35
36
  SupportsGetitemLen,
36
37
  SupportsIterLen,
@@ -21,7 +21,10 @@ BuiltinCollection: TypeAlias = Union[list, tuple, dict, set, frozenset]
21
21
  BuiltinNumber: TypeAlias = Union[bool, int, float, complex]
22
22
  BuiltinScalar: TypeAlias = Union[bool, int, float, complex, NoneType, str, bytes]
23
23
 
24
- T = TypeVar("T", covariant=True)
24
+ _T_Item = TypeVar("_T_Item", covariant=True)
25
+ _T_Index = TypeVar("_T_Index", contravariant=True, default=int)
26
+ _T_Other = TypeVar("_T_Other", contravariant=True, default=Any)
27
+
25
28
  T_BuiltinNumber = TypeVar(
26
29
  "T_BuiltinNumber",
27
30
  bound=BuiltinNumber,
@@ -59,14 +62,14 @@ class NamedTupleInstance(Protocol):
59
62
 
60
63
 
61
64
  @runtime_checkable
62
- class SupportsAdd(Protocol):
63
- def __add__(self, other, /):
65
+ class SupportsAdd(Protocol[_T_Other]):
66
+ def __add__(self, other: _T_Other, /):
64
67
  raise NotImplementedError
65
68
 
66
69
 
67
70
  @runtime_checkable
68
- class SupportsAnd(Protocol):
69
- def __and__(self, other, /):
71
+ class SupportsAnd(Protocol[_T_Other]):
72
+ def __and__(self, other: _T_Other, /):
70
73
  raise NotImplementedError
71
74
 
72
75
 
@@ -77,14 +80,20 @@ class SupportsBool(Protocol):
77
80
 
78
81
 
79
82
  @runtime_checkable
80
- class SupportsDiv(Protocol):
81
- def __div__(self, other, /):
83
+ class SupportsDiv(Protocol[_T_Other]):
84
+ def __div__(self, other: _T_Other, /):
85
+ raise NotImplementedError
86
+
87
+
88
+ @runtime_checkable
89
+ class SupportsGetitem(Protocol[_T_Item, _T_Index]):
90
+ def __getitem__(self, idx: _T_Index, /) -> _T_Item:
82
91
  raise NotImplementedError
83
92
 
84
93
 
85
94
  @runtime_checkable
86
- class SupportsGetitemLen(Protocol[T]):
87
- def __getitem__(self, idx, /) -> T:
95
+ class SupportsGetitemLen(Protocol[_T_Item, _T_Index]):
96
+ def __getitem__(self, idx: _T_Index, /) -> _T_Item:
88
97
  raise NotImplementedError
89
98
 
90
99
  def __len__(self) -> int:
@@ -92,11 +101,11 @@ class SupportsGetitemLen(Protocol[T]):
92
101
 
93
102
 
94
103
  @runtime_checkable
95
- class SupportsGetitemIterLen(Protocol[T]):
96
- def __getitem__(self, idx, /) -> T:
104
+ class SupportsGetitemIterLen(Protocol[_T_Item, _T_Index]):
105
+ def __getitem__(self, idx: _T_Index, /) -> _T_Item:
97
106
  raise NotImplementedError
98
107
 
99
- def __iter__(self) -> Iterator[T]:
108
+ def __iter__(self) -> Iterator[_T_Item]:
100
109
  raise NotImplementedError
101
110
 
102
111
  def __len__(self) -> int:
@@ -104,8 +113,8 @@ class SupportsGetitemIterLen(Protocol[T]):
104
113
 
105
114
 
106
115
  @runtime_checkable
107
- class SupportsIterLen(Protocol[T]):
108
- def __iter__(self) -> Iterator[T]:
116
+ class SupportsIterLen(Protocol[_T_Item]):
117
+ def __iter__(self) -> Iterator[_T_Item]:
109
118
  raise NotImplementedError
110
119
 
111
120
  def __len__(self) -> int:
@@ -119,12 +128,12 @@ class SupportsLen(Protocol):
119
128
 
120
129
 
121
130
  @runtime_checkable
122
- class SupportsMul(Protocol):
123
- def __mul__(self, other, /):
131
+ class SupportsMul(Protocol[_T_Other]):
132
+ def __mul__(self, other: _T_Other, /):
124
133
  raise NotImplementedError
125
134
 
126
135
 
127
136
  @runtime_checkable
128
- class SupportsOr(Protocol):
129
- def __or__(self, other, /):
137
+ class SupportsOr(Protocol[_T_Other]):
138
+ def __or__(self, other: _T_Other, /):
130
139
  raise NotImplementedError
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.1
2
2
  Name: pythonwrench
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Set of tools for Python that could be in the standard library.
5
5
  Author-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
6
6
  Maintainer-email: "Étienne Labbé (Labbeti)" <labbeti.pub@gmail.com>
@@ -47,7 +47,6 @@ Requires-Python: >=3.8
47
47
  Description-Content-Type: text/markdown
48
48
  License-File: LICENSE
49
49
  Requires-Dist: typing-extensions>=4.10.0
50
- Dynamic: license-file
51
50
 
52
51
  # pythonwrench
53
52
 
@@ -2,6 +2,7 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  setup.py
5
+ docs/requirements.txt
5
6
  src/pythonwrench/__init__.py
6
7
  src/pythonwrench/__main__.py
7
8
  src/pythonwrench/_core.py
@@ -51,6 +51,12 @@ class TestChecksum(TestCase):
51
51
  assert x0 != x1
52
52
  assert checksum_any(x0) != checksum_any(x1)
53
53
 
54
+ def test_sets(self) -> None:
55
+ s1 = {1, 2}
56
+ s2 = {2, 1}
57
+ assert s1 == s2
58
+ assert checksum_any(s1) == checksum_any(s2)
59
+
54
60
 
55
61
  if __name__ == "__main__":
56
62
  unittest.main()
File without changes
File without changes
File without changes
File without changes
@@ -74,17 +74,17 @@ def contained(
74
74
  @overload
75
75
  def dict_list_to_list_dict(
76
76
  dic: Mapping[T, Iterable[U]],
77
- key_mode: Literal["same", "intersect"],
78
- default_val: Any = None,
79
- ) -> List[Dict[T, U]]: ...
77
+ key_mode: Literal["union"] = "union",
78
+ default_val: W = None,
79
+ ) -> List[Dict[T, Union[U, W]]]: ...
80
80
 
81
81
 
82
82
  @overload
83
83
  def dict_list_to_list_dict(
84
84
  dic: Mapping[T, Iterable[U]],
85
- key_mode: Literal["union"] = "union",
86
- default_val: W = None,
87
- ) -> List[Dict[T, Union[U, W]]]: ...
85
+ key_mode: Literal["same", "intersect"],
86
+ default_val: Any = None,
87
+ ) -> List[Dict[T, U]]: ...
88
88
 
89
89
 
90
90
  def dict_list_to_list_dict(