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.
- pythonwrench/__init__.py +490 -0
- pythonwrench/__main__.py +7 -0
- pythonwrench/_core.py +192 -0
- pythonwrench/abc.py +30 -0
- pythonwrench/argparse/__init__.py +81 -0
- pythonwrench/argparse/dataclass_.py +284 -0
- pythonwrench/argparse/parsers.py +619 -0
- pythonwrench/cast.py +247 -0
- pythonwrench/checksum.py +427 -0
- pythonwrench/collections/__init__.py +104 -0
- pythonwrench/collections/collections.py +900 -0
- pythonwrench/collections/prop.py +104 -0
- pythonwrench/collections/reducers.py +330 -0
- pythonwrench/concurrent.py +73 -0
- pythonwrench/csv.py +12 -0
- pythonwrench/dataclasses.py +117 -0
- pythonwrench/datetime.py +17 -0
- pythonwrench/difflib.py +39 -0
- pythonwrench/disk_cache.py +615 -0
- pythonwrench/entrypoints/info.py +44 -0
- pythonwrench/entrypoints/safe_rmdir.py +98 -0
- pythonwrench/entrypoints/tree.py +113 -0
- pythonwrench/enum.py +55 -0
- pythonwrench/functools.py +234 -0
- pythonwrench/hashlib.py +95 -0
- pythonwrench/importlib.py +243 -0
- pythonwrench/inspect.py +69 -0
- pythonwrench/json.py +12 -0
- pythonwrench/jsonl.py +12 -0
- pythonwrench/logging.py +252 -0
- pythonwrench/math.py +107 -0
- pythonwrench/os.py +226 -0
- pythonwrench/pickle.py +12 -0
- pythonwrench/random.py +60 -0
- pythonwrench/re.py +139 -0
- pythonwrench/semver.py +406 -0
- pythonwrench/serialization/__init__.py +70 -0
- pythonwrench/serialization/_core.py +70 -0
- pythonwrench/serialization/csv.py +493 -0
- pythonwrench/serialization/json.py +178 -0
- pythonwrench/serialization/jsonl.py +215 -0
- pythonwrench/serialization/pickle.py +186 -0
- pythonwrench/time.py +34 -0
- pythonwrench/typing/__init__.py +125 -0
- pythonwrench/typing/checks.py +551 -0
- pythonwrench/typing/classes.py +251 -0
- pythonwrench/warnings.py +118 -0
- pythonwrench-0.6.4.dist-info/METADATA +242 -0
- pythonwrench-0.6.4.dist-info/RECORD +52 -0
- pythonwrench-0.6.4.dist-info/WHEEL +4 -0
- pythonwrench-0.6.4.dist-info/entry_points.txt +10 -0
- pythonwrench-0.6.4.dist-info/licenses/LICENSE +21 -0
pythonwrench/__init__.py
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""Python library with tools for typing, manipulating collections, and more!"""
|
|
5
|
+
|
|
6
|
+
__name__ = "pythonwrench"
|
|
7
|
+
__author__ = "Étienne Labbé (Labbeti)"
|
|
8
|
+
__author_email__ = "labbeti.pub@gmail.com"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
__maintainer__ = "Étienne Labbé (Labbeti)"
|
|
11
|
+
__status__ = "Development"
|
|
12
|
+
__version__ = "0.6.4"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import lazy_loader as lazy # type: ignore
|
|
19
|
+
except ImportError:
|
|
20
|
+
lazy = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING or lazy is None:
|
|
24
|
+
# Re-import for language servers
|
|
25
|
+
from . import abc as abc
|
|
26
|
+
from . import argparse as argparse
|
|
27
|
+
from . import cast as cast
|
|
28
|
+
from . import checksum as checksum
|
|
29
|
+
from . import collections as collections
|
|
30
|
+
from . import concurrent as concurrent
|
|
31
|
+
from . import dataclasses as dataclasses
|
|
32
|
+
from . import datetime as datetime
|
|
33
|
+
from . import difflib as difflib
|
|
34
|
+
from . import disk_cache as disk_cache
|
|
35
|
+
from . import entrypoints as entrypoints
|
|
36
|
+
from . import enum as enum
|
|
37
|
+
from . import functools as functools
|
|
38
|
+
from . import hashlib as hashlib
|
|
39
|
+
from . import importlib as importlib
|
|
40
|
+
from . import inspect as inspect
|
|
41
|
+
from . import logging as logging
|
|
42
|
+
from . import math as math
|
|
43
|
+
from . import os as os
|
|
44
|
+
from . import random as random
|
|
45
|
+
from . import re as re
|
|
46
|
+
from . import semver as semver
|
|
47
|
+
from . import serialization as serialization
|
|
48
|
+
from . import time as time
|
|
49
|
+
from . import warnings as warnings
|
|
50
|
+
|
|
51
|
+
# Global library imports
|
|
52
|
+
from .abc import Singleton
|
|
53
|
+
from .argparse import (
|
|
54
|
+
add_dataclass_fields_to_parser,
|
|
55
|
+
get_parse_fn,
|
|
56
|
+
new_parser_from_dataclass,
|
|
57
|
+
parse_args_using_dataclass,
|
|
58
|
+
parse_to,
|
|
59
|
+
parse_to_bool,
|
|
60
|
+
parse_to_float,
|
|
61
|
+
parse_to_int,
|
|
62
|
+
parse_to_none,
|
|
63
|
+
parse_to_optional_bool,
|
|
64
|
+
parse_to_optional_float,
|
|
65
|
+
parse_to_optional_int,
|
|
66
|
+
parse_to_optional_str,
|
|
67
|
+
parse_to_type,
|
|
68
|
+
register_parser_fn,
|
|
69
|
+
str_to_bool,
|
|
70
|
+
str_to_float,
|
|
71
|
+
str_to_int,
|
|
72
|
+
str_to_none,
|
|
73
|
+
str_to_optional_bool,
|
|
74
|
+
str_to_optional_float,
|
|
75
|
+
str_to_optional_int,
|
|
76
|
+
str_to_optional_str,
|
|
77
|
+
str_to_type,
|
|
78
|
+
)
|
|
79
|
+
from .cast import as_builtin, register_as_builtin_fn
|
|
80
|
+
from .checksum import checksum_any, checksum_object, register_checksum_fn
|
|
81
|
+
from .collections import (
|
|
82
|
+
SizedGenerator,
|
|
83
|
+
all_eq,
|
|
84
|
+
all_ne,
|
|
85
|
+
contained,
|
|
86
|
+
dict_list_to_list_dict,
|
|
87
|
+
dump_dict,
|
|
88
|
+
duplicate_list,
|
|
89
|
+
filter_iterable,
|
|
90
|
+
find,
|
|
91
|
+
flat_dict_of_dict,
|
|
92
|
+
flat_list_of_list,
|
|
93
|
+
flatten,
|
|
94
|
+
intersect,
|
|
95
|
+
intersect_lists,
|
|
96
|
+
is_full,
|
|
97
|
+
is_sorted,
|
|
98
|
+
is_unique,
|
|
99
|
+
list_dict_to_dict_list,
|
|
100
|
+
prod,
|
|
101
|
+
recursive_generator,
|
|
102
|
+
reduce_add,
|
|
103
|
+
reduce_and,
|
|
104
|
+
reduce_matmul,
|
|
105
|
+
reduce_mul,
|
|
106
|
+
reduce_or,
|
|
107
|
+
shuffled,
|
|
108
|
+
sorted_dict,
|
|
109
|
+
sum,
|
|
110
|
+
unflat_dict_of_dict,
|
|
111
|
+
unflat_list_of_list,
|
|
112
|
+
union,
|
|
113
|
+
union_dicts,
|
|
114
|
+
union_lists,
|
|
115
|
+
unzip,
|
|
116
|
+
)
|
|
117
|
+
from .dataclasses import add_dict_methods, dataclassdict, get_defaults_values
|
|
118
|
+
from .datetime import get_now, get_now_iso8601
|
|
119
|
+
from .difflib import find_closest_in_list, sequence_matcher_ratio
|
|
120
|
+
from .disk_cache import disk_cache_call, disk_cache_decorator
|
|
121
|
+
from .enum import StrEnum
|
|
122
|
+
from .functools import (
|
|
123
|
+
Compose,
|
|
124
|
+
compose,
|
|
125
|
+
filter_and_call,
|
|
126
|
+
function_alias,
|
|
127
|
+
identity,
|
|
128
|
+
repeat_fn,
|
|
129
|
+
)
|
|
130
|
+
from .hashlib import hash_file
|
|
131
|
+
from .importlib import (
|
|
132
|
+
ModulePlaceholder,
|
|
133
|
+
Placeholder,
|
|
134
|
+
import_if_available,
|
|
135
|
+
is_available_package,
|
|
136
|
+
is_editable_package,
|
|
137
|
+
reload_editable_packages,
|
|
138
|
+
reload_submodules,
|
|
139
|
+
requires_packages,
|
|
140
|
+
search_submodules,
|
|
141
|
+
)
|
|
142
|
+
from .inspect import get_argnames, get_current_fn_name, get_fullname
|
|
143
|
+
from .logging import (
|
|
144
|
+
VERBOSE_DEBUG,
|
|
145
|
+
VERBOSE_ERROR,
|
|
146
|
+
VERBOSE_INFO,
|
|
147
|
+
VERBOSE_WARNING,
|
|
148
|
+
MkdirFileHandler,
|
|
149
|
+
get_current_file_logger,
|
|
150
|
+
get_ipython_name,
|
|
151
|
+
get_null_logger,
|
|
152
|
+
log_once,
|
|
153
|
+
running_on_interpreter,
|
|
154
|
+
running_on_notebook,
|
|
155
|
+
running_on_terminal,
|
|
156
|
+
setup_logging_level,
|
|
157
|
+
setup_logging_verbose,
|
|
158
|
+
)
|
|
159
|
+
from .math import argmax, argmin, argsort, clamp, clip
|
|
160
|
+
from .os import get_num_cpus_available, safe_rmdir, tree_iter
|
|
161
|
+
from .random import randstr
|
|
162
|
+
from .re import (
|
|
163
|
+
PatternLike,
|
|
164
|
+
PatternListLike,
|
|
165
|
+
compile_patterns,
|
|
166
|
+
filter_with_patterns,
|
|
167
|
+
find_patterns,
|
|
168
|
+
get_key_fn,
|
|
169
|
+
match_patterns,
|
|
170
|
+
sort_with_patterns,
|
|
171
|
+
)
|
|
172
|
+
from .semver import Version
|
|
173
|
+
from .serialization import (
|
|
174
|
+
dump_csv,
|
|
175
|
+
dump_json,
|
|
176
|
+
dump_jsonl,
|
|
177
|
+
dump_pickle,
|
|
178
|
+
dumps_csv,
|
|
179
|
+
dumps_json,
|
|
180
|
+
dumps_jsonl,
|
|
181
|
+
dumps_pickle,
|
|
182
|
+
load_csv,
|
|
183
|
+
load_json,
|
|
184
|
+
load_jsonl,
|
|
185
|
+
load_pickle,
|
|
186
|
+
loads_csv,
|
|
187
|
+
loads_json,
|
|
188
|
+
loads_jsonl,
|
|
189
|
+
loads_pickle,
|
|
190
|
+
read_csv,
|
|
191
|
+
read_json,
|
|
192
|
+
read_jsonl,
|
|
193
|
+
read_pickle,
|
|
194
|
+
save_csv,
|
|
195
|
+
save_json,
|
|
196
|
+
save_jsonl,
|
|
197
|
+
save_pickle,
|
|
198
|
+
)
|
|
199
|
+
from .time import Ticker
|
|
200
|
+
from .typing import (
|
|
201
|
+
BuiltinCollection,
|
|
202
|
+
BuiltinNumber,
|
|
203
|
+
BuiltinScalar,
|
|
204
|
+
Dataclass,
|
|
205
|
+
DataclassInstance,
|
|
206
|
+
EllipsisType,
|
|
207
|
+
ListOrTuple,
|
|
208
|
+
NamedTupleInstance,
|
|
209
|
+
NoneType,
|
|
210
|
+
SupportsAdd,
|
|
211
|
+
SupportsAnd,
|
|
212
|
+
SupportsBool,
|
|
213
|
+
SupportsDiv,
|
|
214
|
+
SupportsGetitem,
|
|
215
|
+
SupportsGetitem2,
|
|
216
|
+
SupportsGetitemIterLen,
|
|
217
|
+
SupportsGetitemIterLen2,
|
|
218
|
+
SupportsGetitemLen,
|
|
219
|
+
SupportsGetitemLen2,
|
|
220
|
+
SupportsIter,
|
|
221
|
+
SupportsIterLen,
|
|
222
|
+
SupportsLen,
|
|
223
|
+
SupportsMatmul,
|
|
224
|
+
SupportsMul,
|
|
225
|
+
SupportsOr,
|
|
226
|
+
T_BuiltinNumber,
|
|
227
|
+
T_BuiltinScalar,
|
|
228
|
+
check_args_types,
|
|
229
|
+
is_builtin_collection,
|
|
230
|
+
is_builtin_number,
|
|
231
|
+
is_builtin_obj,
|
|
232
|
+
is_builtin_scalar,
|
|
233
|
+
is_collection_alias,
|
|
234
|
+
is_dataclass_instance,
|
|
235
|
+
is_dataclass_type,
|
|
236
|
+
is_iterable_bool,
|
|
237
|
+
is_iterable_bytes_or_list,
|
|
238
|
+
is_iterable_float,
|
|
239
|
+
is_iterable_int,
|
|
240
|
+
is_iterable_integral,
|
|
241
|
+
is_iterable_str,
|
|
242
|
+
is_namedtuple_instance,
|
|
243
|
+
is_parameterized,
|
|
244
|
+
is_sequence_str,
|
|
245
|
+
is_special_form,
|
|
246
|
+
is_typed_dict,
|
|
247
|
+
isinstance_generic,
|
|
248
|
+
)
|
|
249
|
+
from .warnings import deprecated_alias, deprecated_function, warn_once
|
|
250
|
+
|
|
251
|
+
else:
|
|
252
|
+
__getattr__, __dir__, __all__ = lazy.attach(
|
|
253
|
+
__name__,
|
|
254
|
+
submodules=[
|
|
255
|
+
"abc",
|
|
256
|
+
"argparse",
|
|
257
|
+
"cast",
|
|
258
|
+
"checksum",
|
|
259
|
+
"collections",
|
|
260
|
+
"concurrent",
|
|
261
|
+
"dataclasses",
|
|
262
|
+
"datetime",
|
|
263
|
+
"difflib",
|
|
264
|
+
"disk_cache",
|
|
265
|
+
"entrypoints",
|
|
266
|
+
"enum",
|
|
267
|
+
"functools",
|
|
268
|
+
"hashlib",
|
|
269
|
+
"importlib",
|
|
270
|
+
"inspect",
|
|
271
|
+
"logging",
|
|
272
|
+
"math",
|
|
273
|
+
"os",
|
|
274
|
+
"random",
|
|
275
|
+
"re",
|
|
276
|
+
"semver",
|
|
277
|
+
"serialization",
|
|
278
|
+
"time",
|
|
279
|
+
"typing",
|
|
280
|
+
"warnings",
|
|
281
|
+
],
|
|
282
|
+
submod_attrs={
|
|
283
|
+
"argparse": [
|
|
284
|
+
"add_dataclass_fields_to_parser",
|
|
285
|
+
"get_parse_fn",
|
|
286
|
+
"new_parser_from_dataclass",
|
|
287
|
+
"parse_args_using_dataclass",
|
|
288
|
+
"parse_to",
|
|
289
|
+
"parse_to_bool",
|
|
290
|
+
"parse_to_float",
|
|
291
|
+
"parse_to_int",
|
|
292
|
+
"parse_to_none",
|
|
293
|
+
"parse_to_optional_bool",
|
|
294
|
+
"parse_to_optional_float",
|
|
295
|
+
"parse_to_optional_int",
|
|
296
|
+
"parse_to_optional_str",
|
|
297
|
+
"parse_to_type",
|
|
298
|
+
"register_parser_fn",
|
|
299
|
+
"str_to_bool",
|
|
300
|
+
"str_to_float",
|
|
301
|
+
"str_to_int",
|
|
302
|
+
"str_to_none",
|
|
303
|
+
"str_to_optional_bool",
|
|
304
|
+
"str_to_optional_float",
|
|
305
|
+
"str_to_optional_int",
|
|
306
|
+
"str_to_optional_str",
|
|
307
|
+
"str_to_type",
|
|
308
|
+
],
|
|
309
|
+
"abc": ["Singleton"],
|
|
310
|
+
"cast": ["as_builtin", "register_as_builtin_fn"],
|
|
311
|
+
"checksum": ["checksum_any", "checksum_object", "register_checksum_fn"],
|
|
312
|
+
"collections": [
|
|
313
|
+
"SizedGenerator",
|
|
314
|
+
"all_eq",
|
|
315
|
+
"all_ne",
|
|
316
|
+
"contained",
|
|
317
|
+
"dict_list_to_list_dict",
|
|
318
|
+
"dump_dict",
|
|
319
|
+
"duplicate_list",
|
|
320
|
+
"filter_iterable",
|
|
321
|
+
"find",
|
|
322
|
+
"flat_dict_of_dict",
|
|
323
|
+
"flat_list_of_list",
|
|
324
|
+
"flatten",
|
|
325
|
+
"intersect",
|
|
326
|
+
"intersect_lists",
|
|
327
|
+
"is_full",
|
|
328
|
+
"is_sorted",
|
|
329
|
+
"is_unique",
|
|
330
|
+
"list_dict_to_dict_list",
|
|
331
|
+
"prod",
|
|
332
|
+
"recursive_generator",
|
|
333
|
+
"reduce_add",
|
|
334
|
+
"reduce_and",
|
|
335
|
+
"reduce_matmul",
|
|
336
|
+
"reduce_mul",
|
|
337
|
+
"reduce_or",
|
|
338
|
+
"shuffled",
|
|
339
|
+
"sorted_dict",
|
|
340
|
+
"sum",
|
|
341
|
+
"unflat_dict_of_dict",
|
|
342
|
+
"unflat_list_of_list",
|
|
343
|
+
"union",
|
|
344
|
+
"union_dicts",
|
|
345
|
+
"union_lists",
|
|
346
|
+
"unzip",
|
|
347
|
+
],
|
|
348
|
+
"serialization": [
|
|
349
|
+
"dump_csv",
|
|
350
|
+
"dump_json",
|
|
351
|
+
"dump_jsonl",
|
|
352
|
+
"dump_pickle",
|
|
353
|
+
"dumps_csv",
|
|
354
|
+
"dumps_json",
|
|
355
|
+
"dumps_jsonl",
|
|
356
|
+
"dumps_pickle",
|
|
357
|
+
"load_csv",
|
|
358
|
+
"load_json",
|
|
359
|
+
"load_jsonl",
|
|
360
|
+
"load_pickle",
|
|
361
|
+
"loads_csv",
|
|
362
|
+
"loads_json",
|
|
363
|
+
"loads_jsonl",
|
|
364
|
+
"loads_pickle",
|
|
365
|
+
"read_csv",
|
|
366
|
+
"read_json",
|
|
367
|
+
"read_jsonl",
|
|
368
|
+
"read_pickle",
|
|
369
|
+
"save_csv",
|
|
370
|
+
"save_json",
|
|
371
|
+
"save_jsonl",
|
|
372
|
+
"save_pickle",
|
|
373
|
+
],
|
|
374
|
+
"dataclasses": ["add_dict_methods", "dataclassdict", "get_defaults_values"],
|
|
375
|
+
"datetime": ["get_now", "get_now_iso8601"],
|
|
376
|
+
"difflib": ["find_closest_in_list", "sequence_matcher_ratio"],
|
|
377
|
+
"disk_cache": ["disk_cache_call", "disk_cache_decorator"],
|
|
378
|
+
"enum": ["StrEnum"],
|
|
379
|
+
"functools": [
|
|
380
|
+
"Compose",
|
|
381
|
+
"compose",
|
|
382
|
+
"filter_and_call",
|
|
383
|
+
"function_alias",
|
|
384
|
+
"identity",
|
|
385
|
+
"repeat_fn",
|
|
386
|
+
],
|
|
387
|
+
"hashlib": ["hash_file"],
|
|
388
|
+
"importlib": [
|
|
389
|
+
"import_if_available",
|
|
390
|
+
"ModulePlaceholder",
|
|
391
|
+
"is_available_package",
|
|
392
|
+
"is_editable_package",
|
|
393
|
+
"reload_editable_packages",
|
|
394
|
+
"reload_submodules",
|
|
395
|
+
"requires_packages",
|
|
396
|
+
"search_submodules",
|
|
397
|
+
"Placeholder",
|
|
398
|
+
],
|
|
399
|
+
"inspect": ["get_argnames", "get_current_fn_name", "get_fullname"],
|
|
400
|
+
"logging": [
|
|
401
|
+
"VERBOSE_DEBUG",
|
|
402
|
+
"VERBOSE_ERROR",
|
|
403
|
+
"VERBOSE_INFO",
|
|
404
|
+
"VERBOSE_WARNING",
|
|
405
|
+
"MkdirFileHandler",
|
|
406
|
+
"get_current_file_logger",
|
|
407
|
+
"get_ipython_name",
|
|
408
|
+
"get_null_logger",
|
|
409
|
+
"log_once",
|
|
410
|
+
"running_on_interpreter",
|
|
411
|
+
"running_on_notebook",
|
|
412
|
+
"running_on_terminal",
|
|
413
|
+
"setup_logging_level",
|
|
414
|
+
"setup_logging_verbose",
|
|
415
|
+
],
|
|
416
|
+
"math": ["argmax", "argmin", "argsort", "clamp", "clip"],
|
|
417
|
+
"os": ["get_num_cpus_available", "safe_rmdir", "tree_iter"],
|
|
418
|
+
"random": ["randstr"],
|
|
419
|
+
"re": [
|
|
420
|
+
"PatternLike",
|
|
421
|
+
"PatternListLike",
|
|
422
|
+
"compile_patterns",
|
|
423
|
+
"filter_with_patterns",
|
|
424
|
+
"find_patterns",
|
|
425
|
+
"get_key_fn",
|
|
426
|
+
"match_patterns",
|
|
427
|
+
"sort_with_patterns",
|
|
428
|
+
],
|
|
429
|
+
"semver": ["Version"],
|
|
430
|
+
"time": ["Ticker"],
|
|
431
|
+
"typing": [
|
|
432
|
+
"BuiltinCollection",
|
|
433
|
+
"BuiltinNumber",
|
|
434
|
+
"BuiltinScalar",
|
|
435
|
+
"Dataclass",
|
|
436
|
+
"DataclassInstance",
|
|
437
|
+
"EllipsisType",
|
|
438
|
+
"ListOrTuple",
|
|
439
|
+
"NamedTupleInstance",
|
|
440
|
+
"NoneType",
|
|
441
|
+
"SupportsAdd",
|
|
442
|
+
"SupportsAnd",
|
|
443
|
+
"SupportsBool",
|
|
444
|
+
"SupportsDiv",
|
|
445
|
+
"SupportsGetitem",
|
|
446
|
+
"SupportsGetitem2",
|
|
447
|
+
"SupportsGetitemIterLen",
|
|
448
|
+
"SupportsGetitemIterLen2",
|
|
449
|
+
"SupportsGetitemLen",
|
|
450
|
+
"SupportsGetitemLen2",
|
|
451
|
+
"SupportsIter",
|
|
452
|
+
"SupportsIterLen",
|
|
453
|
+
"SupportsLen",
|
|
454
|
+
"SupportsMatmul",
|
|
455
|
+
"SupportsMul",
|
|
456
|
+
"SupportsOr",
|
|
457
|
+
"T_BuiltinNumber",
|
|
458
|
+
"T_BuiltinScalar",
|
|
459
|
+
"check_args_types",
|
|
460
|
+
"is_builtin_collection",
|
|
461
|
+
"is_builtin_number",
|
|
462
|
+
"is_builtin_obj",
|
|
463
|
+
"is_builtin_scalar",
|
|
464
|
+
"is_collection_alias",
|
|
465
|
+
"is_dataclass_instance",
|
|
466
|
+
"is_dataclass_type",
|
|
467
|
+
"is_iterable_bool",
|
|
468
|
+
"is_iterable_bytes_or_list",
|
|
469
|
+
"is_iterable_float",
|
|
470
|
+
"is_iterable_int",
|
|
471
|
+
"is_iterable_integral",
|
|
472
|
+
"is_iterable_str",
|
|
473
|
+
"is_namedtuple_instance",
|
|
474
|
+
"is_parameterized",
|
|
475
|
+
"is_sequence_str",
|
|
476
|
+
"is_special_form",
|
|
477
|
+
"is_typed_dict",
|
|
478
|
+
"isinstance_generic",
|
|
479
|
+
],
|
|
480
|
+
"warnings": ["deprecated_alias", "deprecated_function", "warn_once"],
|
|
481
|
+
},
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
Version = __getattr__("Version")
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
version = __version__
|
|
488
|
+
version_info = Version(__version__)
|
|
489
|
+
|
|
490
|
+
del TYPE_CHECKING, lazy
|
pythonwrench/__main__.py
ADDED
pythonwrench/_core.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from functools import wraps
|
|
5
|
+
from typing import (
|
|
6
|
+
Any,
|
|
7
|
+
Callable,
|
|
8
|
+
Dict,
|
|
9
|
+
Generic,
|
|
10
|
+
Literal,
|
|
11
|
+
Optional,
|
|
12
|
+
Protocol,
|
|
13
|
+
Tuple,
|
|
14
|
+
Union,
|
|
15
|
+
get_args,
|
|
16
|
+
runtime_checkable,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from typing_extensions import ParamSpec, TypeVar
|
|
20
|
+
|
|
21
|
+
P = ParamSpec("P")
|
|
22
|
+
T = TypeVar("T", covariant=True)
|
|
23
|
+
U = TypeVar("U", covariant=True)
|
|
24
|
+
T_Output = TypeVar("T_Output", default=Any)
|
|
25
|
+
T_PredicateArg = TypeVar("T_PredicateArg", contravariant=True, default=Any)
|
|
26
|
+
T_Function = TypeVar("T_Function", bound=Callable[..., Any])
|
|
27
|
+
|
|
28
|
+
UnkMode = Literal["identity", "error"]
|
|
29
|
+
ClassOrTuple = Union[type, Tuple[type, ...]]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@runtime_checkable
|
|
33
|
+
class Predicate(Protocol[T_PredicateArg]):
|
|
34
|
+
def __call__(self, /, x: T_PredicateArg) -> bool:
|
|
35
|
+
"""Call the instance."""
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def return_none(*args, **kwargs) -> None:
|
|
40
|
+
"""Return None function placeholder."""
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _decorator_factory(
|
|
45
|
+
inner_fn: Optional[T_Function],
|
|
46
|
+
*,
|
|
47
|
+
pre_fn: Optional[Callable[..., Any]] = None,
|
|
48
|
+
post_fn: Optional[Callable[..., Any]] = None,
|
|
49
|
+
) -> Callable[[T_Function], T_Function]:
|
|
50
|
+
"""Decorator for function aliases."""
|
|
51
|
+
if pre_fn is None:
|
|
52
|
+
pre_fn = return_none
|
|
53
|
+
if post_fn is None:
|
|
54
|
+
post_fn = return_none
|
|
55
|
+
|
|
56
|
+
def wrapper_factory(fn: T_Function) -> T_Function:
|
|
57
|
+
"""Perform the wrapper factory operation."""
|
|
58
|
+
if inner_fn is None:
|
|
59
|
+
_inner_fn = fn
|
|
60
|
+
else:
|
|
61
|
+
_inner_fn = inner_fn
|
|
62
|
+
|
|
63
|
+
@wraps(_inner_fn)
|
|
64
|
+
def wrapped(*args, **kwargs):
|
|
65
|
+
"""Perform the wrapped operation."""
|
|
66
|
+
pre_fn(fn, *args, **kwargs)
|
|
67
|
+
result = _inner_fn(*args, **kwargs)
|
|
68
|
+
post_fn(fn, *args, **kwargs)
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
return wrapped # type: ignore
|
|
72
|
+
|
|
73
|
+
return wrapper_factory
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class _FunctionRegistry(Generic[T_Output]):
|
|
77
|
+
def __init__(self) -> None:
|
|
78
|
+
"""Initialize the instance."""
|
|
79
|
+
fns: Dict[
|
|
80
|
+
Callable[..., T_Output],
|
|
81
|
+
Tuple[Optional[ClassOrTuple], Optional[Predicate], int],
|
|
82
|
+
] = {}
|
|
83
|
+
|
|
84
|
+
super().__init__()
|
|
85
|
+
self.fns = fns
|
|
86
|
+
|
|
87
|
+
def register(
|
|
88
|
+
self,
|
|
89
|
+
fn: Callable[[T], T_Output],
|
|
90
|
+
class_or_tuple: Optional[ClassOrTuple] = None,
|
|
91
|
+
*,
|
|
92
|
+
custom_predicate: Optional[Predicate] = None,
|
|
93
|
+
priority: int = 0,
|
|
94
|
+
) -> Callable[[T], T_Output]:
|
|
95
|
+
"""Perform the register operation."""
|
|
96
|
+
return self.register_decorator(
|
|
97
|
+
class_or_tuple,
|
|
98
|
+
custom_predicate=custom_predicate,
|
|
99
|
+
priority=priority,
|
|
100
|
+
)(fn)
|
|
101
|
+
|
|
102
|
+
def register_decorator(
|
|
103
|
+
self,
|
|
104
|
+
class_or_tuple: Optional[ClassOrTuple] = None,
|
|
105
|
+
*,
|
|
106
|
+
custom_predicate: Optional[Predicate] = None,
|
|
107
|
+
priority: int = 0,
|
|
108
|
+
) -> Callable:
|
|
109
|
+
"""Perform the register decorator operation."""
|
|
110
|
+
if (class_or_tuple is None) == (custom_predicate is None):
|
|
111
|
+
msg = f"Invalid combinaison of arguments: {class_or_tuple=} and {custom_predicate=}. (only one of them must be None)"
|
|
112
|
+
raise ValueError(msg)
|
|
113
|
+
|
|
114
|
+
def _impl(new_fn: Callable[[T], T_Output]) -> Callable[[T], T_Output]:
|
|
115
|
+
"""Perform the impl operation."""
|
|
116
|
+
new_value = (class_or_tuple, custom_predicate, priority)
|
|
117
|
+
self.fns = _insert_in_dict(
|
|
118
|
+
self.fns,
|
|
119
|
+
new_fn,
|
|
120
|
+
new_value,
|
|
121
|
+
priority,
|
|
122
|
+
priority_key=2,
|
|
123
|
+
)
|
|
124
|
+
return new_fn
|
|
125
|
+
|
|
126
|
+
return _impl
|
|
127
|
+
|
|
128
|
+
def apply(
|
|
129
|
+
self,
|
|
130
|
+
x: Any,
|
|
131
|
+
*,
|
|
132
|
+
isinstance_fn: Callable[[Any, Union[type, tuple]], bool] = isinstance,
|
|
133
|
+
unk_mode: UnkMode = "error",
|
|
134
|
+
**kwargs,
|
|
135
|
+
) -> T_Output:
|
|
136
|
+
"""Perform the apply operation."""
|
|
137
|
+
for fn, (class_or_tuple, custom_predicate, _) in self.fns.items():
|
|
138
|
+
if custom_predicate is not None:
|
|
139
|
+
predicate = custom_predicate
|
|
140
|
+
|
|
141
|
+
elif class_or_tuple is not None:
|
|
142
|
+
|
|
143
|
+
def target_isinstance_fn_wrap(x: Any) -> bool:
|
|
144
|
+
"""Perform the target isinstance fn wrap operation."""
|
|
145
|
+
return isinstance_fn(x, class_or_tuple) # type: ignore
|
|
146
|
+
|
|
147
|
+
predicate = target_isinstance_fn_wrap
|
|
148
|
+
else:
|
|
149
|
+
msg = f"Invalid function registered. (found {class_or_tuple=} and {custom_predicate=})"
|
|
150
|
+
raise TypeError(msg)
|
|
151
|
+
|
|
152
|
+
if predicate(x):
|
|
153
|
+
return fn(x, **kwargs)
|
|
154
|
+
|
|
155
|
+
if unk_mode == "identity":
|
|
156
|
+
return x
|
|
157
|
+
elif unk_mode == "error":
|
|
158
|
+
valid_types = [
|
|
159
|
+
class_or_tuple
|
|
160
|
+
for class_or_tuple, _, _ in self.fns.values()
|
|
161
|
+
if class_or_tuple is not None
|
|
162
|
+
]
|
|
163
|
+
msg = f"Invalid argument type {type(x)}. (expected one of {tuple(valid_types)})"
|
|
164
|
+
raise TypeError(msg)
|
|
165
|
+
else:
|
|
166
|
+
msg = f"Invalid argument {unk_mode=}. (expected one of {get_args(UnkMode)})"
|
|
167
|
+
raise ValueError(msg)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _insert_in_dict(
|
|
171
|
+
dic: Dict,
|
|
172
|
+
key: Any,
|
|
173
|
+
value: Any,
|
|
174
|
+
priority: int,
|
|
175
|
+
priority_key: int,
|
|
176
|
+
) -> Dict:
|
|
177
|
+
"""Perform the insert in dict operation."""
|
|
178
|
+
if key in dic:
|
|
179
|
+
return dic
|
|
180
|
+
insert_index = _get_insertion_index(list(dic.values()), priority, priority_key)
|
|
181
|
+
items = list(dic.items())
|
|
182
|
+
items.insert(insert_index, (key, value))
|
|
183
|
+
return dict(items)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _get_insertion_index(lst: list, priority: int, priority_key: int) -> int:
|
|
187
|
+
"""Perform the get insertion index operation."""
|
|
188
|
+
for i, item in enumerate(lst):
|
|
189
|
+
other_priority = item[priority_key]
|
|
190
|
+
if priority >= other_priority:
|
|
191
|
+
return i
|
|
192
|
+
return len(lst)
|