faster-eth-utils 5.3.8__cp313-cp313-win_amd64.whl → 5.3.23__cp313-cp313-win_amd64.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.
- faster_eth_utils/abi.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/abi.py +95 -70
- faster_eth_utils/address.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/address.py +7 -14
- faster_eth_utils/applicators.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/applicators.py +73 -56
- faster_eth_utils/conversions.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/conversions.py +18 -20
- faster_eth_utils/crypto.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/crypto.py +3 -8
- faster_eth_utils/currency.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/currency.py +11 -8
- faster_eth_utils/curried/__init__.py +62 -65
- faster_eth_utils/debug.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/decorators.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/decorators.py +65 -29
- faster_eth_utils/encoding.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/encoding.py +1 -1
- faster_eth_utils/exceptions.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/exceptions.py +8 -1
- faster_eth_utils/functional.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/functional.py +10 -12
- faster_eth_utils/hexadecimal.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/hexadecimal.py +8 -12
- faster_eth_utils/humanize.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/humanize.py +16 -16
- faster_eth_utils/logging.py +51 -44
- faster_eth_utils/module_loading.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/network.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/network.py +2 -3
- faster_eth_utils/numeric.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/pydantic.py +5 -7
- faster_eth_utils/toolz.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/types.cp313-win_amd64.pyd +0 -0
- faster_eth_utils/types.py +7 -10
- faster_eth_utils/units.cp313-win_amd64.pyd +0 -0
- {faster_eth_utils-5.3.8.dist-info → faster_eth_utils-5.3.23.dist-info}/METADATA +39 -19
- faster_eth_utils-5.3.23.dist-info/RECORD +53 -0
- faster_eth_utils-5.3.23.dist-info/top_level.txt +3 -0
- faster_eth_utils__mypyc.cp313-win_amd64.pyd +0 -0
- 99c07adba6ff961eaf3e__mypyc.cp313-win_amd64.pyd +0 -0
- faster_eth_utils-5.3.8.dist-info/RECORD +0 -53
- faster_eth_utils-5.3.8.dist-info/top_level.txt +0 -3
- {faster_eth_utils-5.3.8.dist-info → faster_eth_utils-5.3.23.dist-info}/WHEEL +0 -0
- {faster_eth_utils-5.3.8.dist-info → faster_eth_utils-5.3.23.dist-info}/licenses/LICENSE +0 -0
|
Binary file
|
faster_eth_utils/abi.py
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
from collections import (
|
|
2
|
-
abc,
|
|
3
|
-
)
|
|
4
1
|
import copy
|
|
5
2
|
import itertools
|
|
6
3
|
import re
|
|
7
|
-
from
|
|
8
|
-
Any,
|
|
9
|
-
Dict,
|
|
4
|
+
from collections.abc import (
|
|
10
5
|
Iterable,
|
|
11
|
-
List,
|
|
12
|
-
Literal,
|
|
13
6
|
Mapping,
|
|
14
|
-
Optional,
|
|
15
7
|
Sequence,
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
)
|
|
9
|
+
from typing import (
|
|
10
|
+
Any,
|
|
11
|
+
Final,
|
|
12
|
+
Generic,
|
|
13
|
+
Literal,
|
|
14
|
+
TypeVar,
|
|
18
15
|
cast,
|
|
19
16
|
overload,
|
|
20
17
|
)
|
|
@@ -30,6 +27,9 @@ from eth_typing import (
|
|
|
30
27
|
ABIFunction,
|
|
31
28
|
ABIReceive,
|
|
32
29
|
)
|
|
30
|
+
from typing_extensions import (
|
|
31
|
+
Self,
|
|
32
|
+
)
|
|
33
33
|
|
|
34
34
|
from faster_eth_utils.types import (
|
|
35
35
|
is_list_like,
|
|
@@ -40,9 +40,37 @@ from .crypto import (
|
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
T = TypeVar("T")
|
|
44
|
+
|
|
45
|
+
ABIType = Literal["function", "constructor", "fallback", "receive", "event", "error"]
|
|
46
|
+
|
|
47
|
+
_TUPLE_TYPE_STR_RE: Final = re.compile("^(tuple)((\\[([1-9]\\d*\\b)?])*)??$")
|
|
48
|
+
|
|
49
|
+
_chain: Final = itertools.chain
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class _repeat(Generic[T]):
|
|
53
|
+
|
|
54
|
+
def __init__(self, value: T, times: int | None = None) -> None:
|
|
55
|
+
self._value: Final[T] = value
|
|
56
|
+
self._times: Final[int | None] = times
|
|
57
|
+
self._index = 0
|
|
58
|
+
|
|
59
|
+
def __iter__(self) -> Self:
|
|
60
|
+
return self
|
|
61
|
+
|
|
62
|
+
def __next__(self) -> T:
|
|
63
|
+
if self._times is None:
|
|
64
|
+
return self._value
|
|
65
|
+
if self._index >= self._times:
|
|
66
|
+
raise StopIteration
|
|
67
|
+
self._index += 1
|
|
68
|
+
return self._value
|
|
69
|
+
|
|
70
|
+
|
|
43
71
|
def _align_abi_input(
|
|
44
72
|
arg_abi: ABIComponent, normalized_arg: Any
|
|
45
|
-
) ->
|
|
73
|
+
) -> Any | tuple[Any, ...]:
|
|
46
74
|
"""
|
|
47
75
|
Aligns the values of any mapping at any level of nesting in ``normalized_arg``
|
|
48
76
|
according to the layout of the corresponding abi spec.
|
|
@@ -66,37 +94,38 @@ def _align_abi_input(
|
|
|
66
94
|
new_abi = copy.copy(arg_abi)
|
|
67
95
|
new_abi["type"] = tuple_prefix + "[]" * (num_dims - 1)
|
|
68
96
|
|
|
69
|
-
sub_abis =
|
|
97
|
+
sub_abis = _repeat(new_abi)
|
|
70
98
|
|
|
71
99
|
aligned_arg: Any
|
|
72
|
-
if isinstance(normalized_arg,
|
|
100
|
+
if isinstance(normalized_arg, Mapping):
|
|
73
101
|
# normalized_arg is mapping. Align values according to abi order.
|
|
74
102
|
aligned_arg = tuple(normalized_arg[abi["name"]] for abi in sub_abis)
|
|
75
103
|
else:
|
|
76
104
|
aligned_arg = normalized_arg
|
|
77
105
|
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
)
|
|
106
|
+
# We can generate more optimized C code if we branch by arg type
|
|
107
|
+
if isinstance(aligned_arg, tuple):
|
|
108
|
+
# convert NamedTuple to regular tuple
|
|
109
|
+
return tuple(map(_align_abi_input, sub_abis, aligned_arg))
|
|
83
110
|
|
|
84
|
-
|
|
85
|
-
|
|
111
|
+
elif type(aligned_arg) is list:
|
|
112
|
+
return list(map(_align_abi_input, sub_abis, aligned_arg))
|
|
86
113
|
|
|
87
|
-
|
|
88
|
-
_align_abi_input
|
|
89
|
-
|
|
114
|
+
elif is_list_like(aligned_arg):
|
|
115
|
+
return type(aligned_arg)(map(_align_abi_input, sub_abis, aligned_arg)) # type: ignore [call-arg]
|
|
116
|
+
|
|
117
|
+
raise TypeError(
|
|
118
|
+
f'Expected non-string sequence for "{arg_abi.get("type")}" '
|
|
119
|
+
f"component type: got {aligned_arg}"
|
|
90
120
|
)
|
|
91
121
|
|
|
92
122
|
|
|
93
|
-
def _get_tuple_type_str_and_dims(s: str) ->
|
|
123
|
+
def _get_tuple_type_str_and_dims(s: str) -> tuple[str, str | None] | None:
|
|
94
124
|
"""
|
|
95
125
|
Takes a JSON ABI type string. For tuple type strings, returns the separated
|
|
96
126
|
prefix and array dimension parts. For all other strings, returns ``None``.
|
|
97
127
|
"""
|
|
98
|
-
|
|
99
|
-
match = re.compile(tuple_type_str_re).match(s)
|
|
128
|
+
match = _TUPLE_TYPE_STR_RE.match(s)
|
|
100
129
|
|
|
101
130
|
return None if match is None else (match[1], match[2])
|
|
102
131
|
|
|
@@ -119,7 +148,7 @@ def _raise_if_fallback_or_receive_abi(abi_element: ABIElement) -> None:
|
|
|
119
148
|
)
|
|
120
149
|
|
|
121
150
|
|
|
122
|
-
def collapse_if_tuple(abi:
|
|
151
|
+
def collapse_if_tuple(abi: ABIComponent | dict[str, Any] | str) -> str:
|
|
123
152
|
"""
|
|
124
153
|
Extract argument types from a function or event ABI parameter.
|
|
125
154
|
|
|
@@ -278,11 +307,21 @@ def filter_abi_by_name(abi_name: str, contract_abi: ABI) -> Sequence[ABIElement]
|
|
|
278
307
|
]
|
|
279
308
|
|
|
280
309
|
|
|
310
|
+
__ABI_TYPE_LITERALS: Final = {
|
|
311
|
+
Literal["function"]: "function",
|
|
312
|
+
Literal["constructor"]: "constructor",
|
|
313
|
+
Literal["fallback"]: "fallback",
|
|
314
|
+
Literal["receive"]: "receive",
|
|
315
|
+
Literal["event"]: "event",
|
|
316
|
+
Literal["error"]: "error",
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
281
320
|
@overload
|
|
282
321
|
def filter_abi_by_type(
|
|
283
322
|
abi_type: Literal["function"],
|
|
284
323
|
contract_abi: ABI,
|
|
285
|
-
) ->
|
|
324
|
+
) -> list[ABIFunction]:
|
|
286
325
|
pass
|
|
287
326
|
|
|
288
327
|
|
|
@@ -290,7 +329,7 @@ def filter_abi_by_type(
|
|
|
290
329
|
def filter_abi_by_type(
|
|
291
330
|
abi_type: Literal["constructor"],
|
|
292
331
|
contract_abi: ABI,
|
|
293
|
-
) ->
|
|
332
|
+
) -> list[ABIConstructor]:
|
|
294
333
|
pass
|
|
295
334
|
|
|
296
335
|
|
|
@@ -298,7 +337,7 @@ def filter_abi_by_type(
|
|
|
298
337
|
def filter_abi_by_type(
|
|
299
338
|
abi_type: Literal["fallback"],
|
|
300
339
|
contract_abi: ABI,
|
|
301
|
-
) ->
|
|
340
|
+
) -> list[ABIFallback]:
|
|
302
341
|
pass
|
|
303
342
|
|
|
304
343
|
|
|
@@ -306,7 +345,7 @@ def filter_abi_by_type(
|
|
|
306
345
|
def filter_abi_by_type(
|
|
307
346
|
abi_type: Literal["receive"],
|
|
308
347
|
contract_abi: ABI,
|
|
309
|
-
) ->
|
|
348
|
+
) -> list[ABIReceive]:
|
|
310
349
|
pass
|
|
311
350
|
|
|
312
351
|
|
|
@@ -314,7 +353,7 @@ def filter_abi_by_type(
|
|
|
314
353
|
def filter_abi_by_type(
|
|
315
354
|
abi_type: Literal["event"],
|
|
316
355
|
contract_abi: ABI,
|
|
317
|
-
) ->
|
|
356
|
+
) -> list[ABIEvent]:
|
|
318
357
|
pass
|
|
319
358
|
|
|
320
359
|
|
|
@@ -322,18 +361,16 @@ def filter_abi_by_type(
|
|
|
322
361
|
def filter_abi_by_type(
|
|
323
362
|
abi_type: Literal["error"],
|
|
324
363
|
contract_abi: ABI,
|
|
325
|
-
) ->
|
|
364
|
+
) -> list[ABIError]:
|
|
326
365
|
pass
|
|
327
366
|
|
|
328
367
|
|
|
329
368
|
def filter_abi_by_type(
|
|
330
|
-
abi_type:
|
|
331
|
-
"function", "constructor", "fallback", "receive", "event", "error"
|
|
332
|
-
],
|
|
369
|
+
abi_type: ABIType,
|
|
333
370
|
contract_abi: ABI,
|
|
334
|
-
) ->
|
|
335
|
-
|
|
336
|
-
|
|
371
|
+
) -> (
|
|
372
|
+
list[ABIFunction] | list[ABIConstructor] | list[ABIFallback] | list[ABIReceive] | list[ABIEvent] | list[ABIError]
|
|
373
|
+
):
|
|
337
374
|
"""
|
|
338
375
|
Return a list of each ``ABIElement`` that is of type ``abi_type``.
|
|
339
376
|
|
|
@@ -361,20 +398,12 @@ ABIEvent, ABIError]]`
|
|
|
361
398
|
[{'type': 'function', 'name': 'myFunction', 'inputs': [], 'outputs': []}, \
|
|
362
399
|
{'type': 'function', 'name': 'myFunction2', 'inputs': [], 'outputs': []}]
|
|
363
400
|
"""
|
|
364
|
-
if abi_type
|
|
365
|
-
return [abi for abi in contract_abi if abi["type"] ==
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
elif abi_type == Literal["fallback"] or abi_type == "fallback":
|
|
369
|
-
return [abi for abi in contract_abi if abi["type"] == "fallback"]
|
|
370
|
-
elif abi_type == Literal["receive"] or abi_type == "receive":
|
|
371
|
-
return [abi for abi in contract_abi if abi["type"] == "receive"]
|
|
372
|
-
elif abi_type == Literal["event"] or abi_type == "event":
|
|
373
|
-
return [abi for abi in contract_abi if abi["type"] == "event"]
|
|
374
|
-
elif abi_type == Literal["error"] or abi_type == "error":
|
|
375
|
-
return [abi for abi in contract_abi if abi["type"] == "error"]
|
|
376
|
-
else:
|
|
401
|
+
if abi_type in ("function", "constructor", "fallback", "receive", "event", "error"):
|
|
402
|
+
return [abi for abi in contract_abi if abi["type"] == abi_type] # type: ignore [return-value]
|
|
403
|
+
abi_type_string: ABIType | None = __ABI_TYPE_LITERALS.get(abi_type) # type: ignore [call-overload]
|
|
404
|
+
if abi_type_string is None:
|
|
377
405
|
raise ValueError(f"Unsupported ABI type: {abi_type}")
|
|
406
|
+
return [abi for abi in contract_abi if abi["type"] == abi_type_string] # type: ignore [return-value]
|
|
378
407
|
|
|
379
408
|
|
|
380
409
|
def get_all_function_abis(contract_abi: ABI) -> Sequence[ABIFunction]:
|
|
@@ -428,7 +457,7 @@ def get_normalized_abi_inputs(
|
|
|
428
457
|
abi_element: ABIElement,
|
|
429
458
|
*args: Any,
|
|
430
459
|
**kwargs: Any,
|
|
431
|
-
) ->
|
|
460
|
+
) -> tuple[Any, ...]:
|
|
432
461
|
r"""
|
|
433
462
|
Flattens positional args (``args``) and keyword args (``kwargs``) into a Tuple and
|
|
434
463
|
uses the ``abi_element`` for validation.
|
|
@@ -496,6 +525,7 @@ def get_normalized_abi_inputs(
|
|
|
496
525
|
|
|
497
526
|
kwarg_names = set(kwargs.keys())
|
|
498
527
|
sorted_arg_names = tuple(arg_abi["name"] for arg_abi in function_inputs)
|
|
528
|
+
arg_positions = {name: index for index, name in enumerate(sorted_arg_names)}
|
|
499
529
|
args_as_kwargs = dict(zip(sorted_arg_names, args))
|
|
500
530
|
|
|
501
531
|
# Check for duplicate args
|
|
@@ -521,22 +551,17 @@ def get_normalized_abi_inputs(
|
|
|
521
551
|
|
|
522
552
|
# Sort args according to their position in the ABI and unzip them from their
|
|
523
553
|
# names
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
itertools.chain(kwargs.items(), args_as_kwargs.items()),
|
|
528
|
-
key=lambda kv: sorted_arg_names.index(kv[0]),
|
|
529
|
-
)
|
|
530
|
-
)
|
|
554
|
+
sorted_items = sorted(
|
|
555
|
+
_chain(kwargs.items(), args_as_kwargs.items()),
|
|
556
|
+
key=lambda kv: arg_positions[kv[0]],
|
|
531
557
|
)
|
|
532
|
-
|
|
533
|
-
return tuple(sorted_args[1]) if sorted_args else ()
|
|
558
|
+
return tuple(val for _, val in sorted_items)
|
|
534
559
|
|
|
535
560
|
|
|
536
561
|
def get_aligned_abi_inputs(
|
|
537
562
|
abi_element: ABIElement,
|
|
538
|
-
normalized_args:
|
|
539
|
-
) ->
|
|
563
|
+
normalized_args: tuple[Any, ...] | Mapping[Any, Any],
|
|
564
|
+
) -> tuple[tuple[str, ...], tuple[Any, ...]]:
|
|
540
565
|
"""
|
|
541
566
|
Returns a pair of nested Tuples containing a list of types and a list of input
|
|
542
567
|
values sorted by the order specified by the ``abi``.
|
|
@@ -579,7 +604,7 @@ def get_aligned_abi_inputs(
|
|
|
579
604
|
_raise_if_fallback_or_receive_abi(abi_element)
|
|
580
605
|
|
|
581
606
|
abi_element_inputs = cast(Sequence[ABIComponent], abi_element.get("inputs", []))
|
|
582
|
-
if isinstance(normalized_args,
|
|
607
|
+
if isinstance(normalized_args, Mapping):
|
|
583
608
|
# `args` is mapping. Align values according to abi order.
|
|
584
609
|
normalized_args = tuple(
|
|
585
610
|
normalized_args[abi["name"]] for abi in abi_element_inputs
|
|
@@ -594,7 +619,7 @@ def get_aligned_abi_inputs(
|
|
|
594
619
|
)
|
|
595
620
|
|
|
596
621
|
|
|
597
|
-
def get_abi_input_names(abi_element: ABIElement) ->
|
|
622
|
+
def get_abi_input_names(abi_element: ABIElement) -> list[str | None]:
|
|
598
623
|
"""
|
|
599
624
|
Return names for each input from the function or event ABI.
|
|
600
625
|
|
|
@@ -630,7 +655,7 @@ def get_abi_input_names(abi_element: ABIElement) -> List[Optional[str]]:
|
|
|
630
655
|
]
|
|
631
656
|
|
|
632
657
|
|
|
633
|
-
def get_abi_input_types(abi_element: ABIElement) ->
|
|
658
|
+
def get_abi_input_types(abi_element: ABIElement) -> list[str]:
|
|
634
659
|
"""
|
|
635
660
|
Return types for each input from the function or event ABI.
|
|
636
661
|
|
|
@@ -666,7 +691,7 @@ def get_abi_input_types(abi_element: ABIElement) -> List[str]:
|
|
|
666
691
|
]
|
|
667
692
|
|
|
668
693
|
|
|
669
|
-
def get_abi_output_names(abi_element: ABIElement) ->
|
|
694
|
+
def get_abi_output_names(abi_element: ABIElement) -> list[str | None]:
|
|
670
695
|
"""
|
|
671
696
|
Return names for each output from the ABI element.
|
|
672
697
|
|
|
@@ -711,7 +736,7 @@ def get_abi_output_names(abi_element: ABIElement) -> List[Optional[str]]:
|
|
|
711
736
|
]
|
|
712
737
|
|
|
713
738
|
|
|
714
|
-
def get_abi_output_types(abi_element: ABIElement) ->
|
|
739
|
+
def get_abi_output_types(abi_element: ABIElement) -> list[str]:
|
|
715
740
|
"""
|
|
716
741
|
Return types for each output from the function ABI.
|
|
717
742
|
|
|
Binary file
|
faster_eth_utils/address.py
CHANGED
|
@@ -2,7 +2,7 @@ import re
|
|
|
2
2
|
from typing import (
|
|
3
3
|
Any,
|
|
4
4
|
Final,
|
|
5
|
-
|
|
5
|
+
TypeGuard,
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
import cchecksum
|
|
@@ -13,21 +13,13 @@ from eth_typing import (
|
|
|
13
13
|
HexAddress,
|
|
14
14
|
HexStr,
|
|
15
15
|
)
|
|
16
|
-
from typing_extensions import (
|
|
17
|
-
TypeGuard,
|
|
18
|
-
)
|
|
19
16
|
|
|
20
17
|
from .conversions import (
|
|
21
18
|
hexstr_if_str,
|
|
22
19
|
to_hex,
|
|
23
20
|
)
|
|
24
|
-
from .crypto import (
|
|
25
|
-
keccak,
|
|
26
|
-
)
|
|
27
21
|
from .hexadecimal import (
|
|
28
|
-
add_0x_prefix,
|
|
29
22
|
decode_hex,
|
|
30
|
-
encode_hex,
|
|
31
23
|
remove_0x_prefix,
|
|
32
24
|
)
|
|
33
25
|
from .types import (
|
|
@@ -76,7 +68,7 @@ def is_address(value: Any) -> bool:
|
|
|
76
68
|
return False
|
|
77
69
|
|
|
78
70
|
|
|
79
|
-
def to_normalized_address(value:
|
|
71
|
+
def to_normalized_address(value: AnyAddress | str | bytes) -> HexAddress:
|
|
80
72
|
"""
|
|
81
73
|
Converts an address to its normalized hexadecimal representation.
|
|
82
74
|
"""
|
|
@@ -100,7 +92,7 @@ def is_normalized_address(value: Any) -> TypeGuard[HexAddress]:
|
|
|
100
92
|
return is_address(value) and value == to_normalized_address(value)
|
|
101
93
|
|
|
102
94
|
|
|
103
|
-
def to_canonical_address(address:
|
|
95
|
+
def to_canonical_address(address: AnyAddress | str | bytes) -> Address:
|
|
104
96
|
"""
|
|
105
97
|
Convert a valid address to its canonical form (20-length bytes).
|
|
106
98
|
"""
|
|
@@ -115,15 +107,16 @@ def is_canonical_address(address: Any) -> TypeGuard[Address]:
|
|
|
115
107
|
8
|
|
116
108
|
|
|
117
109
|
def is_same_address(
|
|
118
|
-
left:
|
|
110
|
+
left: AnyAddress | str | bytes, right: AnyAddress | str | bytes
|
|
119
111
|
) -> bool:
|
|
120
112
|
"""
|
|
121
113
|
Checks if both addresses are same or not.
|
|
122
114
|
"""
|
|
123
115
|
if not is_address(left) or not is_address(right):
|
|
124
116
|
raise ValueError("Both values must be valid addresses")
|
|
125
|
-
|
|
126
|
-
return
|
|
117
|
+
if left == right:
|
|
118
|
+
return True
|
|
119
|
+
return to_normalized_address(left) == to_normalized_address(right)
|
|
127
120
|
|
|
128
121
|
|
|
129
122
|
def is_checksum_address(value: Any) -> TypeGuard[ChecksumAddress]:
|
|
Binary file
|
faster_eth_utils/applicators.py
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
|
+
from collections.abc import Callable, Generator, Mapping, Sequence
|
|
1
2
|
from typing import (
|
|
3
|
+
TYPE_CHECKING,
|
|
2
4
|
Any,
|
|
3
|
-
|
|
4
|
-
Dict,
|
|
5
|
-
Generator,
|
|
6
|
-
List,
|
|
7
|
-
Sequence,
|
|
8
|
-
Tuple,
|
|
5
|
+
TypeGuard,
|
|
9
6
|
TypeVar,
|
|
10
|
-
Union,
|
|
11
7
|
cast,
|
|
8
|
+
overload,
|
|
12
9
|
)
|
|
10
|
+
|
|
13
11
|
import warnings
|
|
14
12
|
|
|
15
13
|
from .decorators import (
|
|
16
14
|
return_arg_type,
|
|
17
15
|
)
|
|
18
|
-
from .functional import (
|
|
19
|
-
to_dict,
|
|
20
|
-
)
|
|
21
16
|
from .pydantic import (
|
|
22
17
|
CamelModel,
|
|
23
18
|
)
|
|
@@ -26,17 +21,23 @@ from .toolz import (
|
|
|
26
21
|
curry,
|
|
27
22
|
)
|
|
28
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from _typeshed import SupportsBool
|
|
26
|
+
# We have to sacrifice a little bit of specificity on dinosaur Python3.8
|
|
27
|
+
|
|
29
28
|
TArg = TypeVar("TArg")
|
|
30
29
|
TReturn = TypeVar("TReturn")
|
|
31
30
|
TOther = TypeVar("TOther")
|
|
32
31
|
|
|
33
|
-
Formatters = Callable[[
|
|
32
|
+
Formatters = Callable[[list[Any]], list[Any]]
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
@return_arg_type(2)
|
|
37
36
|
def apply_formatter_at_index(
|
|
38
|
-
formatter: Callable[[TArg], TReturn],
|
|
39
|
-
|
|
37
|
+
formatter: Callable[[TArg], TReturn],
|
|
38
|
+
at_index: int,
|
|
39
|
+
value: Sequence[TArg | TOther],
|
|
40
|
+
) -> Generator[TOther | TReturn, None, None]:
|
|
40
41
|
try:
|
|
41
42
|
item = value[at_index]
|
|
42
43
|
except IndexError:
|
|
@@ -45,9 +46,9 @@ def apply_formatter_at_index(
|
|
|
45
46
|
f"Need: {at_index + 1}"
|
|
46
47
|
) from None
|
|
47
48
|
|
|
48
|
-
yield from value[:at_index]
|
|
49
|
+
yield from cast(Sequence[TOther], value[:at_index])
|
|
49
50
|
yield formatter(cast(TArg, item))
|
|
50
|
-
yield from value[at_index + 1 :]
|
|
51
|
+
yield from cast(Sequence[TOther], value[at_index + 1 :])
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
@@ -63,7 +64,7 @@ def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
|
63
64
|
)
|
|
64
65
|
|
|
65
66
|
_formatter_at_index = curry(apply_formatter_at_index)
|
|
66
|
-
return compose( # type: ignore
|
|
67
|
+
return compose( # type: ignore [no-any-return]
|
|
67
68
|
*(
|
|
68
69
|
_formatter_at_index(formatter, index)
|
|
69
70
|
for index, formatter in enumerate(formatters)
|
|
@@ -73,38 +74,55 @@ def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
|
73
74
|
|
|
74
75
|
@return_arg_type(1)
|
|
75
76
|
def apply_formatters_to_sequence(
|
|
76
|
-
formatters:
|
|
77
|
+
formatters: list[Callable[[Any], TReturn]], sequence: Sequence[Any]
|
|
77
78
|
) -> Generator[TReturn, None, None]:
|
|
78
|
-
|
|
79
|
+
num_formatters = len(formatters)
|
|
80
|
+
num_items = len(sequence)
|
|
81
|
+
if num_formatters == num_items:
|
|
79
82
|
for formatter, item in zip(formatters, sequence):
|
|
80
83
|
yield formatter(item)
|
|
81
|
-
elif
|
|
84
|
+
elif num_formatters > num_items:
|
|
82
85
|
raise IndexError(
|
|
83
|
-
f"Too many formatters for sequence: {
|
|
84
|
-
f"{
|
|
86
|
+
f"Too many formatters for sequence: {num_formatters} formatters for "
|
|
87
|
+
f"{sequence!r}"
|
|
85
88
|
)
|
|
86
89
|
else:
|
|
87
90
|
raise IndexError(
|
|
88
|
-
f"Too few formatters for sequence: {
|
|
89
|
-
f"{
|
|
91
|
+
f"Too few formatters for sequence: {num_formatters} formatters for "
|
|
92
|
+
f"{sequence!r}"
|
|
90
93
|
)
|
|
91
94
|
|
|
92
95
|
|
|
96
|
+
@overload
|
|
97
|
+
def apply_formatter_if(
|
|
98
|
+
condition: Callable[[TArg], TypeGuard[TOther]],
|
|
99
|
+
formatter: Callable[[TOther], TReturn],
|
|
100
|
+
value: TArg,
|
|
101
|
+
) -> TArg | TReturn: ...
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@overload
|
|
93
105
|
def apply_formatter_if(
|
|
94
106
|
condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
|
|
95
|
-
) ->
|
|
107
|
+
) -> TArg | TReturn: ...
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def apply_formatter_if( # type: ignore [misc]
|
|
111
|
+
condition: Callable[[TArg], TypeGuard[TOther]] | Callable[[TArg], bool],
|
|
112
|
+
formatter: Callable[[TOther], TReturn] | Callable[[TArg], TReturn],
|
|
113
|
+
value: TArg,
|
|
114
|
+
) -> TArg | TReturn:
|
|
96
115
|
if condition(value):
|
|
97
|
-
return formatter(value)
|
|
116
|
+
return formatter(value) # type: ignore [arg-type]
|
|
98
117
|
else:
|
|
99
118
|
return value
|
|
100
119
|
|
|
101
120
|
|
|
102
|
-
@to_dict
|
|
103
121
|
def apply_formatters_to_dict(
|
|
104
|
-
formatters:
|
|
105
|
-
value:
|
|
122
|
+
formatters: dict[Any, Any],
|
|
123
|
+
value: dict[Any, Any] | CamelModel,
|
|
106
124
|
unaliased: bool = False,
|
|
107
|
-
) ->
|
|
125
|
+
) -> dict[Any, Any]:
|
|
108
126
|
"""
|
|
109
127
|
Apply formatters to a dictionary of values. If the value is a pydantic model,
|
|
110
128
|
it will be serialized to a dictionary first, taking into account the
|
|
@@ -119,22 +137,21 @@ def apply_formatters_to_dict(
|
|
|
119
137
|
if isinstance(value, CamelModel):
|
|
120
138
|
value = value.model_dump(by_alias=not unaliased)
|
|
121
139
|
|
|
122
|
-
|
|
123
|
-
if key in formatters:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
yield key, item
|
|
140
|
+
def get_value(key: Any, val: Any) -> Any:
|
|
141
|
+
if key not in formatters:
|
|
142
|
+
return val
|
|
143
|
+
try:
|
|
144
|
+
return formatters[key](val)
|
|
145
|
+
except ValueError as exc:
|
|
146
|
+
raise ValueError(
|
|
147
|
+
f"Could not format invalid value {val!r} as field {key!r}"
|
|
148
|
+
) from exc
|
|
149
|
+
except TypeError as exc:
|
|
150
|
+
raise TypeError(
|
|
151
|
+
f"Could not format invalid type {val!r} as field {key!r}"
|
|
152
|
+
) from exc
|
|
153
|
+
|
|
154
|
+
return {key: get_value(key, val) for key, val in value.items()}
|
|
138
155
|
|
|
139
156
|
|
|
140
157
|
@return_arg_type(1)
|
|
@@ -146,9 +163,11 @@ def apply_formatter_to_array(
|
|
|
146
163
|
|
|
147
164
|
|
|
148
165
|
def apply_one_of_formatters(
|
|
149
|
-
formatter_condition_pairs:
|
|
150
|
-
|
|
151
|
-
|
|
166
|
+
formatter_condition_pairs: tuple[
|
|
167
|
+
tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]], ...
|
|
168
|
+
],
|
|
169
|
+
value: TArg,
|
|
170
|
+
) -> TReturn:
|
|
152
171
|
for condition, formatter in formatter_condition_pairs:
|
|
153
172
|
if condition(value):
|
|
154
173
|
return formatter(value)
|
|
@@ -158,10 +177,9 @@ def apply_one_of_formatters(
|
|
|
158
177
|
)
|
|
159
178
|
|
|
160
179
|
|
|
161
|
-
@to_dict
|
|
162
180
|
def apply_key_map(
|
|
163
|
-
key_mappings:
|
|
164
|
-
) ->
|
|
181
|
+
key_mappings: dict[Any, Any], value: Mapping[Any, Any]
|
|
182
|
+
) -> dict[Any, Any]:
|
|
165
183
|
key_conflicts = (
|
|
166
184
|
set(value.keys())
|
|
167
185
|
.difference(key_mappings.keys())
|
|
@@ -172,8 +190,7 @@ def apply_key_map(
|
|
|
172
190
|
f"Could not apply key map due to conflicting key(s): {key_conflicts}"
|
|
173
191
|
)
|
|
174
192
|
|
|
175
|
-
|
|
176
|
-
if key in key_mappings
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
yield key, item
|
|
193
|
+
def get_key(key: Any) -> Any:
|
|
194
|
+
return key_mappings[key] if key in key_mappings else key
|
|
195
|
+
|
|
196
|
+
return {get_key(key): item for key, item in value.items()}
|
|
Binary file
|