pythonwrench 0.6.4__py3-none-any.whl

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 (52) hide show
  1. pythonwrench/__init__.py +490 -0
  2. pythonwrench/__main__.py +7 -0
  3. pythonwrench/_core.py +192 -0
  4. pythonwrench/abc.py +30 -0
  5. pythonwrench/argparse/__init__.py +81 -0
  6. pythonwrench/argparse/dataclass_.py +284 -0
  7. pythonwrench/argparse/parsers.py +619 -0
  8. pythonwrench/cast.py +247 -0
  9. pythonwrench/checksum.py +427 -0
  10. pythonwrench/collections/__init__.py +104 -0
  11. pythonwrench/collections/collections.py +900 -0
  12. pythonwrench/collections/prop.py +104 -0
  13. pythonwrench/collections/reducers.py +330 -0
  14. pythonwrench/concurrent.py +73 -0
  15. pythonwrench/csv.py +12 -0
  16. pythonwrench/dataclasses.py +117 -0
  17. pythonwrench/datetime.py +17 -0
  18. pythonwrench/difflib.py +39 -0
  19. pythonwrench/disk_cache.py +615 -0
  20. pythonwrench/entrypoints/info.py +44 -0
  21. pythonwrench/entrypoints/safe_rmdir.py +98 -0
  22. pythonwrench/entrypoints/tree.py +113 -0
  23. pythonwrench/enum.py +55 -0
  24. pythonwrench/functools.py +234 -0
  25. pythonwrench/hashlib.py +95 -0
  26. pythonwrench/importlib.py +243 -0
  27. pythonwrench/inspect.py +69 -0
  28. pythonwrench/json.py +12 -0
  29. pythonwrench/jsonl.py +12 -0
  30. pythonwrench/logging.py +252 -0
  31. pythonwrench/math.py +107 -0
  32. pythonwrench/os.py +226 -0
  33. pythonwrench/pickle.py +12 -0
  34. pythonwrench/random.py +60 -0
  35. pythonwrench/re.py +139 -0
  36. pythonwrench/semver.py +406 -0
  37. pythonwrench/serialization/__init__.py +70 -0
  38. pythonwrench/serialization/_core.py +70 -0
  39. pythonwrench/serialization/csv.py +493 -0
  40. pythonwrench/serialization/json.py +178 -0
  41. pythonwrench/serialization/jsonl.py +215 -0
  42. pythonwrench/serialization/pickle.py +186 -0
  43. pythonwrench/time.py +34 -0
  44. pythonwrench/typing/__init__.py +125 -0
  45. pythonwrench/typing/checks.py +551 -0
  46. pythonwrench/typing/classes.py +251 -0
  47. pythonwrench/warnings.py +118 -0
  48. pythonwrench-0.6.4.dist-info/METADATA +242 -0
  49. pythonwrench-0.6.4.dist-info/RECORD +52 -0
  50. pythonwrench-0.6.4.dist-info/WHEEL +4 -0
  51. pythonwrench-0.6.4.dist-info/entry_points.txt +10 -0
  52. pythonwrench-0.6.4.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from io import StringIO, TextIOBase
5
+ from os import PathLike
6
+ from pathlib import Path
7
+ from typing import Union
8
+
9
+ from pythonwrench.cast import as_builtin
10
+ from pythonwrench.functools import function_alias
11
+ from pythonwrench.semver import Version
12
+ from pythonwrench.serialization._core import _setup_output_fpath
13
+ from pythonwrench.serialization.json import (
14
+ _serialize_json,
15
+ dumps_json,
16
+ load_json,
17
+ loads_json,
18
+ )
19
+ from pythonwrench.warnings import warn_once
20
+
21
+ __all__ = [
22
+ "dump_jsonl",
23
+ "dumps_jsonl",
24
+ "save_jsonl",
25
+ "load_jsonl",
26
+ "loads_jsonl",
27
+ "read_jsonl",
28
+ ]
29
+
30
+ # -- Dump / Save / Serialize content to JSONL --
31
+
32
+
33
+ def dump_jsonl(
34
+ data: list,
35
+ file: Union[str, Path, None, TextIOBase] = None,
36
+ /,
37
+ *,
38
+ overwrite: bool = True,
39
+ make_parents: bool = True,
40
+ to_builtins: bool = False,
41
+ # JSON dump kwargs
42
+ ensure_ascii: bool = False,
43
+ **json_dumps_kwds,
44
+ ) -> str:
45
+ r"""Dump content to JSONL format into a string and/or file.
46
+
47
+ Args:
48
+ data: Data to dump to JSONL.
49
+ file: Optional filepath to save dumped data. Not used if None. defaults to None.
50
+ overwrite: If True, overwrite target filepath. defaults to True.
51
+ make_parents: Build intermediate directories to filepath. defaults to True.
52
+ to_builtins: If True, converts data to builtin equivalent before saving. defaults to False.
53
+ ensure_ascii: Ensure only ASCII characters. defaults to False.
54
+ \*\*json_dump_kwds: Other args passed to `json.dumps`.
55
+
56
+ Returns:
57
+ Dumped content as string.
58
+ """
59
+ content = dumps_json(
60
+ data,
61
+ to_builtins=to_builtins,
62
+ ensure_ascii=ensure_ascii,
63
+ **json_dumps_kwds,
64
+ )
65
+
66
+ if isinstance(file, (str, Path, PathLike)):
67
+ file = _setup_output_fpath(file, overwrite=overwrite, make_parents=make_parents)
68
+ with open(file, "w") as opened_file:
69
+ opened_file.write(content)
70
+ elif isinstance(file, TextIOBase):
71
+ file.write(content)
72
+ elif file is None:
73
+ pass
74
+ else:
75
+ msg = f"Invalid argument type {type(file)}. (expected one of str, Path, TextIOBase, None)"
76
+ raise TypeError(msg)
77
+
78
+ return content
79
+
80
+
81
+ def dumps_jsonl(
82
+ data: list,
83
+ /,
84
+ *,
85
+ to_builtins: bool = False,
86
+ # JSON dump kwargs
87
+ ensure_ascii: bool = False,
88
+ **json_dumps_kwds,
89
+ ) -> str:
90
+ """Perform the dumps jsonl operation."""
91
+ with StringIO() as buffer:
92
+ _serialize_jsonl(
93
+ data,
94
+ buffer,
95
+ to_builtins=to_builtins,
96
+ ensure_ascii=ensure_ascii,
97
+ **json_dumps_kwds,
98
+ )
99
+ content = buffer.getvalue()
100
+ return content
101
+
102
+
103
+ def save_jsonl(
104
+ data: list,
105
+ file: Union[str, Path, PathLike, TextIOBase],
106
+ /,
107
+ *,
108
+ overwrite: bool = True,
109
+ make_parents: bool = True,
110
+ to_builtins: bool = False,
111
+ # JSON dump kwargs
112
+ ensure_ascii: bool = False,
113
+ **json_dumps_kwds,
114
+ ) -> None:
115
+ """Save jsonl."""
116
+ if isinstance(file, (str, Path, PathLike)):
117
+ file = _setup_output_fpath(file, overwrite=overwrite, make_parents=make_parents)
118
+ file = open(file, "w")
119
+ close = True
120
+ elif isinstance(file, TextIOBase):
121
+ close = False
122
+ else:
123
+ msg = f"Invalid argument type {type(file)}. (expected one of str, Path, PathLike, TextIOBase)"
124
+ raise TypeError(msg)
125
+
126
+ _serialize_jsonl(
127
+ data,
128
+ file,
129
+ to_builtins=to_builtins,
130
+ ensure_ascii=ensure_ascii,
131
+ **json_dumps_kwds,
132
+ )
133
+
134
+ if close:
135
+ file.close()
136
+
137
+
138
+ def _serialize_jsonl(
139
+ data: list,
140
+ buffer: TextIOBase,
141
+ /,
142
+ *,
143
+ to_builtins: bool = False,
144
+ **json_dumps_kwds,
145
+ ) -> None:
146
+ """Perform the serialize jsonl operation."""
147
+ if to_builtins:
148
+ data = as_builtin(data)
149
+
150
+ indent = json_dumps_kwds.get("indent", None)
151
+ if indent is not None:
152
+ warn_once(f"Invalid argument {indent=}. It will be replaced by indent=None")
153
+ json_dumps_kwds["indent"] = None
154
+
155
+ for data_i in data:
156
+ _serialize_json(data_i, buffer, to_builtins=False, **json_dumps_kwds)
157
+ buffer.write("\n")
158
+
159
+
160
+ # -- Load / Read / Parse JSONL content --
161
+
162
+
163
+ def load_jsonl(
164
+ file: Union[str, Path, PathLike, TextIOBase],
165
+ /,
166
+ **json_loads_kwds,
167
+ ) -> list:
168
+ """Load jsonl."""
169
+ if isinstance(file, (str, Path, PathLike)):
170
+ file = open(file, "r")
171
+ close = True
172
+ else:
173
+ close = False
174
+
175
+ data = _parse_jsonl(file, **json_loads_kwds)
176
+ if close:
177
+ file.close()
178
+ return data
179
+
180
+
181
+ def loads_jsonl(content: str, /, **json_loads_kwds) -> list:
182
+ """Load s jsonl."""
183
+ with StringIO(content) as buffer:
184
+ return _parse_jsonl(buffer, **json_loads_kwds)
185
+
186
+
187
+ @function_alias(load_json)
188
+ def read_jsonl(*args, **kwargs):
189
+ """Read jsonl."""
190
+ ...
191
+
192
+
193
+ def _parse_jsonl(buffer: TextIOBase, **json_loads_kwds) -> list:
194
+ """Parse jsonl."""
195
+ data_lst = []
196
+ while True:
197
+ content = buffer.readline()
198
+ if content == "":
199
+ break
200
+ content = _removesuffix(content, "\n")
201
+ data = loads_json(content, **json_loads_kwds)
202
+ data_lst.append(data)
203
+ return data_lst
204
+
205
+
206
+ def _removesuffix(x: str, suffix: str) -> str:
207
+ """Equivalent to str.removesuffix for python < 3.9.0."""
208
+ if Version.python() >= Version("3.9.0"):
209
+ return x.removesuffix(suffix)
210
+
211
+ size = len(suffix)
212
+ if x[size:] != suffix:
213
+ return x
214
+ else:
215
+ return x[:size]
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import os
5
+ import pickle
6
+ from io import BytesIO
7
+ from os import PathLike
8
+ from pathlib import Path
9
+ from typing import Any, BinaryIO, Union
10
+
11
+ from pythonwrench.cast import as_builtin
12
+ from pythonwrench.functools import function_alias
13
+ from pythonwrench.serialization._core import _setup_output_fpath
14
+
15
+ # -- Dump / Save / Serialize content to PICKLE --
16
+
17
+
18
+ def dump_pickle(
19
+ data: Any,
20
+ file: Union[str, Path, os.PathLike, BinaryIO, None] = None,
21
+ /,
22
+ *,
23
+ overwrite: bool = True,
24
+ make_parents: bool = True,
25
+ to_builtins: bool = False,
26
+ **pkl_dumps_kwds,
27
+ ) -> bytes:
28
+ r"""Dump content to PICKLE format into bytes and/or file.
29
+
30
+ Args:
31
+ data: Data to dump to PICKLE.
32
+ file: Optional filepath to save dumped data. Not used if None. defaults to None.
33
+ overwrite: If True, overwrite target filepath. defaults to True.
34
+ make_parents: Build intermediate directories to filepath. defaults to True.
35
+ to_builtins: If True, converts data to builtin equivalent before saving. defaults to False.
36
+ \*\*pkl_dumps_kwds: Other args passed to `pickle.dumps`.
37
+
38
+ Returns:
39
+ Dumped content as bytes.
40
+ """
41
+ content = dumps_pickle(
42
+ data,
43
+ to_builtins=to_builtins,
44
+ **pkl_dumps_kwds,
45
+ )
46
+
47
+ if isinstance(file, (str, Path, PathLike)):
48
+ file = _setup_output_fpath(file, overwrite=overwrite, make_parents=make_parents)
49
+ with open(file, "wb") as opened_file:
50
+ opened_file.write(content)
51
+ elif isinstance(file, BinaryIO):
52
+ file.write(content)
53
+ elif file is None:
54
+ pass
55
+ else:
56
+ msg = f"Invalid argument type {type(file)}. (expected one of str, Path, TextIOBase, None)"
57
+ raise TypeError(msg)
58
+
59
+ return content
60
+
61
+
62
+ def dumps_pickle(
63
+ data: Any,
64
+ /,
65
+ *,
66
+ to_builtins: bool = False,
67
+ **pkl_dumps_kwds,
68
+ ) -> bytes:
69
+ r"""Dump content to PICKLE format into bytes.
70
+
71
+ Args:
72
+ data: Data to dump to PICKLE.
73
+ to_builtins: If True, converts data to builtin equivalent before saving. defaults to False.
74
+ \*\*pkl_dumps_kwds: Other args passed to `pickle.dumps`.
75
+
76
+ Returns:
77
+ Dumped content as bytes.
78
+ """
79
+ with BytesIO() as buffer:
80
+ _serialize_pickle(
81
+ data,
82
+ buffer,
83
+ to_builtins=to_builtins,
84
+ **pkl_dumps_kwds,
85
+ )
86
+ content = buffer.getvalue()
87
+ return content
88
+
89
+
90
+ def save_pickle(
91
+ data: Any,
92
+ file: Union[str, Path, PathLike, BinaryIO],
93
+ /,
94
+ *,
95
+ overwrite: bool = True,
96
+ make_parents: bool = True,
97
+ to_builtins: bool = False,
98
+ **pkl_dumps_kwds,
99
+ ) -> None:
100
+ r"""Dump content to PICKLE format into file.
101
+
102
+ Args:
103
+ data: Data to dump to PICKLE.
104
+ file: Filepath to save dumped data.
105
+ overwrite: If True, overwrite target filepath. defaults to True.
106
+ make_parents: Build intermediate directories to filepath. defaults to True.
107
+ to_builtins: If True, converts data to builtin equivalent before saving. defaults to False.
108
+ \*\*pkl_dumps_kwds: Other args passed to `pickle.dumps`.
109
+ """
110
+ if isinstance(file, (str, Path, PathLike)):
111
+ file = _setup_output_fpath(file, overwrite=overwrite, make_parents=make_parents)
112
+ file = open(file, "wb")
113
+ close = True
114
+ elif isinstance(file, BinaryIO):
115
+ close = False
116
+ else:
117
+ msg = f"Invalid argument type {type(file)}. (expected one of str, Path, PathLike, TextIOBase)"
118
+ raise TypeError(msg)
119
+
120
+ _serialize_pickle(
121
+ data,
122
+ file,
123
+ to_builtins=to_builtins,
124
+ **pkl_dumps_kwds,
125
+ )
126
+
127
+ if close:
128
+ file.close()
129
+
130
+
131
+ def _serialize_pickle(
132
+ data: Any,
133
+ buffer: BinaryIO,
134
+ /,
135
+ *,
136
+ to_builtins: bool = False,
137
+ **pkl_dump_kwds,
138
+ ) -> None:
139
+ """Perform the serialize pickle operation."""
140
+ if to_builtins:
141
+ data = as_builtin(data)
142
+ return pickle.dump(data, buffer, **pkl_dump_kwds)
143
+
144
+
145
+ # -- Load / Read / Parse PICKLE content --
146
+
147
+
148
+ def load_pickle(file: Union[str, Path, BinaryIO], /, **pkl_loads_kwds) -> Any:
149
+ r"""Load content from PICKLE file.
150
+
151
+ Args:
152
+ file: Filepath file path.
153
+ \*\*pkl_loads_kwds: Other args passed to `pickle.loads`.
154
+ """
155
+ if isinstance(file, (str, Path, PathLike)):
156
+ file = open(file, "rb")
157
+ close = True
158
+ else:
159
+ close = False
160
+
161
+ data = _parse_pickle(file, **pkl_loads_kwds)
162
+ if close:
163
+ file.close()
164
+ return data
165
+
166
+
167
+ def loads_pickle(content: bytes, /, **pkl_loads_kwds) -> Any:
168
+ r"""Load content from raw bytes.
169
+
170
+ Args:
171
+ content: Encoded elements bytes.
172
+ \*\*pkl_loads_kwds: Other args passed to `pickle.loads`.
173
+ """
174
+ with BytesIO(content) as buffer:
175
+ return _parse_pickle(buffer, **pkl_loads_kwds)
176
+
177
+
178
+ @function_alias(load_pickle)
179
+ def read_pickle(*args, **kwargs):
180
+ """Read pickle."""
181
+ ...
182
+
183
+
184
+ def _parse_pickle(buffer: BinaryIO, **pkl_loads_kwds) -> Any:
185
+ """Parse pickle."""
186
+ return pickle.load(buffer, **pkl_loads_kwds)
pythonwrench/time.py ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import time
5
+ from typing import Callable, Optional
6
+
7
+
8
+ class Ticker:
9
+ def __init__(
10
+ self,
11
+ *,
12
+ get_time_fn: Callable[[], float] = time.perf_counter,
13
+ prev_tick: Optional[float] = None,
14
+ ) -> None:
15
+ """Utility class to show time elapsed since last tick."""
16
+ if prev_tick is None:
17
+ prev_tick = get_time_fn()
18
+
19
+ super().__init__()
20
+ self._get_time_fn = get_time_fn
21
+ self._prev_tick = prev_tick
22
+
23
+ def tick(self) -> float:
24
+ """Set tick time and returns duration since last tick."""
25
+ now = self._get_time_fn()
26
+ duration = now - self._prev_tick
27
+ self._prev_tick = now
28
+ return duration
29
+
30
+ def set_prev_tick(self, prev_tick: Optional[float] = None) -> None:
31
+ """Set tick time."""
32
+ if prev_tick is None:
33
+ prev_tick = self._get_time_fn()
34
+ self._prev_tick = prev_tick
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from typing import TYPE_CHECKING
5
+
6
+ try:
7
+ import lazy_loader as lazy # type: ignore
8
+ except ImportError:
9
+ lazy = None
10
+
11
+
12
+ if TYPE_CHECKING or lazy is None:
13
+ from .checks import (
14
+ check_args_types,
15
+ is_builtin_collection,
16
+ is_builtin_number,
17
+ is_builtin_obj,
18
+ is_builtin_scalar,
19
+ is_collection_alias,
20
+ is_dataclass_instance,
21
+ is_dataclass_type,
22
+ is_iterable_bool,
23
+ is_iterable_bytes_or_list,
24
+ is_iterable_float,
25
+ is_iterable_int,
26
+ is_iterable_integral,
27
+ is_iterable_str,
28
+ is_namedtuple_instance,
29
+ is_parameterized,
30
+ is_sequence_str,
31
+ is_special_form,
32
+ is_typed_dict,
33
+ isinstance_generic,
34
+ )
35
+ from .classes import (
36
+ BuiltinCollection,
37
+ BuiltinNumber,
38
+ BuiltinScalar,
39
+ Dataclass,
40
+ DataclassInstance,
41
+ EllipsisType,
42
+ ListOrTuple,
43
+ NamedTupleInstance,
44
+ NoneType,
45
+ SupportsAdd,
46
+ SupportsAnd,
47
+ SupportsBool,
48
+ SupportsDiv,
49
+ SupportsGetitem,
50
+ SupportsGetitem2,
51
+ SupportsGetitemIterLen,
52
+ SupportsGetitemIterLen2,
53
+ SupportsGetitemLen,
54
+ SupportsGetitemLen2,
55
+ SupportsIter,
56
+ SupportsIterLen,
57
+ SupportsLen,
58
+ SupportsMatmul,
59
+ SupportsMul,
60
+ SupportsOr,
61
+ T_BuiltinNumber,
62
+ T_BuiltinScalar,
63
+ )
64
+
65
+ else:
66
+ __getattr__, __dir__, __all__ = lazy.attach(
67
+ __name__,
68
+ submodules=[
69
+ "checks",
70
+ "classes",
71
+ ],
72
+ submod_attrs={
73
+ "checks": [
74
+ "check_args_types",
75
+ "is_builtin_collection",
76
+ "is_builtin_number",
77
+ "is_builtin_obj",
78
+ "is_builtin_scalar",
79
+ "is_collection_alias",
80
+ "is_dataclass_instance",
81
+ "is_dataclass_type",
82
+ "is_iterable_bool",
83
+ "is_iterable_bytes_or_list",
84
+ "is_iterable_float",
85
+ "is_iterable_int",
86
+ "is_iterable_integral",
87
+ "is_iterable_str",
88
+ "is_namedtuple_instance",
89
+ "is_parameterized",
90
+ "is_sequence_str",
91
+ "is_special_form",
92
+ "is_typed_dict",
93
+ "isinstance_generic",
94
+ ],
95
+ "classes": [
96
+ "BuiltinCollection",
97
+ "BuiltinNumber",
98
+ "BuiltinScalar",
99
+ "Dataclass",
100
+ "DataclassInstance",
101
+ "EllipsisType",
102
+ "ListOrTuple",
103
+ "NamedTupleInstance",
104
+ "NoneType",
105
+ "SupportsAdd",
106
+ "SupportsAnd",
107
+ "SupportsBool",
108
+ "SupportsDiv",
109
+ "SupportsGetitem",
110
+ "SupportsGetitem2",
111
+ "SupportsGetitemIterLen",
112
+ "SupportsGetitemIterLen2",
113
+ "SupportsGetitemLen",
114
+ "SupportsGetitemLen2",
115
+ "SupportsIter",
116
+ "SupportsIterLen",
117
+ "SupportsLen",
118
+ "SupportsMatmul",
119
+ "SupportsMul",
120
+ "SupportsOr",
121
+ "T_BuiltinNumber",
122
+ "T_BuiltinScalar",
123
+ ],
124
+ },
125
+ )