faster-eth-utils 2.3.1__cp311-cp311-win32.whl → 5.3.19__cp311-cp311-win32.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.
Potentially problematic release.
This version of faster-eth-utils might be problematic. Click here for more details.
- faster_eth_utils/__init__.py +54 -17
- faster_eth_utils/__json/eth_networks.json +1 -0
- faster_eth_utils/__main__.py +3 -1
- faster_eth_utils/abi.cp311-win32.pyd +0 -0
- faster_eth_utils/abi.py +819 -37
- faster_eth_utils/address.cp311-win32.pyd +0 -0
- faster_eth_utils/address.py +57 -62
- faster_eth_utils/applicators.cp311-win32.pyd +0 -0
- faster_eth_utils/applicators.py +138 -70
- faster_eth_utils/conversions.cp311-win32.pyd +0 -0
- faster_eth_utils/conversions.py +54 -25
- faster_eth_utils/crypto.cp311-win32.pyd +0 -0
- faster_eth_utils/crypto.py +15 -5
- faster_eth_utils/currency.cp311-win32.pyd +0 -0
- faster_eth_utils/currency.py +70 -32
- faster_eth_utils/curried/__init__.py +107 -77
- faster_eth_utils/debug.cp311-win32.pyd +0 -0
- faster_eth_utils/debug.py +3 -3
- faster_eth_utils/decorators.cp311-win32.pyd +0 -0
- faster_eth_utils/decorators.py +73 -20
- faster_eth_utils/encoding.cp311-win32.pyd +0 -0
- faster_eth_utils/exceptions.cp311-win32.pyd +0 -0
- faster_eth_utils/exceptions.py +8 -3
- faster_eth_utils/functional.cp311-win32.pyd +0 -0
- faster_eth_utils/functional.py +41 -25
- faster_eth_utils/hexadecimal.cp311-win32.pyd +0 -0
- faster_eth_utils/hexadecimal.py +36 -24
- faster_eth_utils/humanize.cp311-win32.pyd +0 -0
- faster_eth_utils/humanize.py +46 -18
- faster_eth_utils/logging.py +43 -48
- faster_eth_utils/module_loading.cp311-win32.pyd +0 -0
- faster_eth_utils/module_loading.py +8 -7
- faster_eth_utils/network.cp311-win32.pyd +0 -0
- faster_eth_utils/network.py +25 -13
- faster_eth_utils/numeric.cp311-win32.pyd +0 -0
- faster_eth_utils/numeric.py +11 -4
- faster_eth_utils/pydantic.py +101 -0
- faster_eth_utils/toolz.cp311-win32.pyd +0 -0
- faster_eth_utils/toolz.py +82 -152
- faster_eth_utils/types.cp311-win32.pyd +0 -0
- faster_eth_utils/types.py +37 -21
- faster_eth_utils/typing/misc.py +3 -1
- faster_eth_utils/units.cp311-win32.pyd +0 -0
- faster_eth_utils-5.3.19.dist-info/METADATA +193 -0
- faster_eth_utils-5.3.19.dist-info/RECORD +53 -0
- {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/licenses/LICENSE +1 -1
- faster_eth_utils-5.3.19.dist-info/top_level.txt +3 -0
- faster_eth_utils__mypyc.cp311-win32.pyd +0 -0
- bce0bfc64ce5e845ec4a__mypyc.cp311-win32.pyd +0 -0
- faster_eth_utils-2.3.1.dist-info/METADATA +0 -160
- faster_eth_utils-2.3.1.dist-info/RECORD +0 -45
- faster_eth_utils-2.3.1.dist-info/top_level.txt +0 -3
- {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/WHEEL +0 -0
|
Binary file
|
faster_eth_utils/address.py
CHANGED
|
@@ -1,17 +1,51 @@
|
|
|
1
1
|
import re
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Final,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
import cchecksum
|
|
9
|
+
from eth_typing import (
|
|
10
|
+
Address,
|
|
11
|
+
AnyAddress,
|
|
12
|
+
ChecksumAddress,
|
|
13
|
+
HexAddress,
|
|
14
|
+
HexStr,
|
|
15
|
+
)
|
|
16
|
+
from typing_extensions import (
|
|
17
|
+
TypeGuard,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .conversions import (
|
|
21
|
+
hexstr_if_str,
|
|
22
|
+
to_hex,
|
|
23
|
+
)
|
|
24
|
+
from .crypto import (
|
|
25
|
+
keccak,
|
|
26
|
+
)
|
|
27
|
+
from .hexadecimal import (
|
|
28
|
+
add_0x_prefix,
|
|
29
|
+
decode_hex,
|
|
30
|
+
encode_hex,
|
|
31
|
+
remove_0x_prefix,
|
|
32
|
+
)
|
|
33
|
+
from .types import (
|
|
34
|
+
is_bytes,
|
|
35
|
+
is_text,
|
|
36
|
+
)
|
|
3
37
|
|
|
4
|
-
|
|
38
|
+
_HEX_ADDRESS_REGEXP: Final = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
|
|
5
39
|
|
|
6
|
-
from .conversions import hexstr_if_str, to_hex
|
|
7
|
-
from .crypto import keccak
|
|
8
|
-
from .hexadecimal import add_0x_prefix, decode_hex, encode_hex, remove_0x_prefix
|
|
9
|
-
from .types import is_bytes, is_text
|
|
10
40
|
|
|
11
|
-
|
|
41
|
+
to_checksum_address: Final = cchecksum.to_checksum_address
|
|
42
|
+
"""
|
|
43
|
+
Makes a checksum address given a supported format.
|
|
44
|
+
We use the `cchecksum` implementation for max speed.
|
|
45
|
+
"""
|
|
12
46
|
|
|
13
47
|
|
|
14
|
-
def is_hex_address(value: Any) ->
|
|
48
|
+
def is_hex_address(value: Any) -> TypeGuard[HexAddress]:
|
|
15
49
|
"""
|
|
16
50
|
Checks if the given string of text type is an address in hexadecimal encoded form.
|
|
17
51
|
"""
|
|
@@ -20,7 +54,7 @@ def is_hex_address(value: Any) -> bool:
|
|
|
20
54
|
return _HEX_ADDRESS_REGEXP.fullmatch(value) is not None
|
|
21
55
|
|
|
22
56
|
|
|
23
|
-
def is_binary_address(value: Any) ->
|
|
57
|
+
def is_binary_address(value: Any) -> TypeGuard[bytes]:
|
|
24
58
|
"""
|
|
25
59
|
Checks if the given string is an address in raw bytes form.
|
|
26
60
|
"""
|
|
@@ -36,12 +70,7 @@ def is_address(value: Any) -> bool:
|
|
|
36
70
|
"""
|
|
37
71
|
Is the given string an address in any of the known formats?
|
|
38
72
|
"""
|
|
39
|
-
if is_hex_address(value):
|
|
40
|
-
if _is_checksum_formatted(value):
|
|
41
|
-
return is_checksum_address(value)
|
|
42
|
-
return True
|
|
43
|
-
|
|
44
|
-
if is_binary_address(value):
|
|
73
|
+
if is_hex_address(value) or is_binary_address(value):
|
|
45
74
|
return True
|
|
46
75
|
|
|
47
76
|
return False
|
|
@@ -54,28 +83,21 @@ def to_normalized_address(value: Union[AnyAddress, str, bytes]) -> HexAddress:
|
|
|
54
83
|
try:
|
|
55
84
|
hex_address = hexstr_if_str(to_hex, value).lower()
|
|
56
85
|
except AttributeError:
|
|
57
|
-
raise TypeError(
|
|
58
|
-
"Value must be any string, instead got type {}".format(type(value))
|
|
59
|
-
)
|
|
86
|
+
raise TypeError(f"Value must be any string, instead got type {type(value)}")
|
|
60
87
|
if is_address(hex_address):
|
|
61
88
|
return HexAddress(HexStr(hex_address))
|
|
62
89
|
else:
|
|
63
90
|
raise ValueError(
|
|
64
|
-
"Unknown format {
|
|
65
|
-
|
|
66
|
-
)
|
|
91
|
+
f"Unknown format {repr(value)}, attempted to normalize to "
|
|
92
|
+
f"{repr(hex_address)}"
|
|
67
93
|
)
|
|
68
94
|
|
|
69
95
|
|
|
70
|
-
def is_normalized_address(value: Any) ->
|
|
96
|
+
def is_normalized_address(value: Any) -> TypeGuard[HexAddress]:
|
|
71
97
|
"""
|
|
72
98
|
Returns whether the provided value is an address in its normalized form.
|
|
73
99
|
"""
|
|
74
|
-
|
|
75
|
-
return False
|
|
76
|
-
else:
|
|
77
|
-
is_equal = value == to_normalized_address(value)
|
|
78
|
-
return cast(bool, is_equal)
|
|
100
|
+
return is_address(value) and value == to_normalized_address(value)
|
|
79
101
|
|
|
80
102
|
|
|
81
103
|
def to_canonical_address(address: Union[AnyAddress, str, bytes]) -> Address:
|
|
@@ -85,17 +107,16 @@ def to_canonical_address(address: Union[AnyAddress, str, bytes]) -> Address:
|
|
|
85
107
|
return Address(decode_hex(to_normalized_address(address)))
|
|
86
108
|
|
|
87
109
|
|
|
88
|
-
def is_canonical_address(address: Any) ->
|
|
110
|
+
def is_canonical_address(address: Any) -> TypeGuard[Address]:
|
|
89
111
|
"""
|
|
90
112
|
Returns `True` if the `value` is an address in its canonical form.
|
|
91
113
|
"""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
is_equal = address == to_canonical_address(address)
|
|
95
|
-
return cast(bool, is_equal)
|
|
114
|
+
return is_binary_address(address) and address == to_canonical_address(address)
|
|
115
|
+
8
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
def is_same_address(
|
|
118
|
+
left: Union[AnyAddress, str, bytes], right: Union[AnyAddress, str, bytes]
|
|
119
|
+
) -> bool:
|
|
99
120
|
"""
|
|
100
121
|
Checks if both addresses are same or not.
|
|
101
122
|
"""
|
|
@@ -105,36 +126,10 @@ def is_same_address(left: AnyAddress, right: AnyAddress) -> bool:
|
|
|
105
126
|
return to_normalized_address(left) == to_normalized_address(right)
|
|
106
127
|
|
|
107
128
|
|
|
108
|
-
def
|
|
109
|
-
"""
|
|
110
|
-
Makes a checksum address given a supported format.
|
|
111
|
-
"""
|
|
112
|
-
norm_address = to_normalized_address(value)
|
|
113
|
-
address_hash = encode_hex(keccak(text=remove_0x_prefix(HexStr(norm_address))))
|
|
114
|
-
|
|
115
|
-
checksum_address = add_0x_prefix(
|
|
116
|
-
HexStr(
|
|
117
|
-
"".join(
|
|
118
|
-
(
|
|
119
|
-
norm_address[i].upper()
|
|
120
|
-
if int(address_hash[i], 16) > 7
|
|
121
|
-
else norm_address[i]
|
|
122
|
-
)
|
|
123
|
-
for i in range(2, 42)
|
|
124
|
-
)
|
|
125
|
-
)
|
|
126
|
-
)
|
|
127
|
-
return ChecksumAddress(HexAddress(checksum_address))
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def is_checksum_address(value: Any) -> bool:
|
|
131
|
-
if not is_text(value):
|
|
132
|
-
return False
|
|
133
|
-
|
|
129
|
+
def is_checksum_address(value: Any) -> TypeGuard[ChecksumAddress]:
|
|
134
130
|
if not is_hex_address(value):
|
|
135
131
|
return False
|
|
136
|
-
|
|
137
|
-
return cast(bool, is_equal)
|
|
132
|
+
return value == to_checksum_address(value)
|
|
138
133
|
|
|
139
134
|
|
|
140
135
|
def _is_checksum_formatted(value: Any) -> bool:
|
|
Binary file
|
faster_eth_utils/applicators.py
CHANGED
|
@@ -1,30 +1,70 @@
|
|
|
1
|
-
|
|
1
|
+
import sys
|
|
2
|
+
from typing import (
|
|
3
|
+
TYPE_CHECKING,
|
|
4
|
+
Any,
|
|
5
|
+
Callable,
|
|
6
|
+
Dict,
|
|
7
|
+
Generator,
|
|
8
|
+
List,
|
|
9
|
+
Mapping,
|
|
10
|
+
Sequence,
|
|
11
|
+
Tuple,
|
|
12
|
+
TypeVar,
|
|
13
|
+
Union,
|
|
14
|
+
cast,
|
|
15
|
+
overload,
|
|
16
|
+
)
|
|
2
17
|
import warnings
|
|
3
18
|
|
|
4
|
-
from
|
|
5
|
-
|
|
6
|
-
|
|
19
|
+
from typing_extensions import (
|
|
20
|
+
TypeGuard,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .decorators import (
|
|
24
|
+
return_arg_type,
|
|
25
|
+
)
|
|
26
|
+
from .pydantic import (
|
|
27
|
+
CamelModel,
|
|
28
|
+
)
|
|
29
|
+
from .toolz import (
|
|
30
|
+
compose,
|
|
31
|
+
curry,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
if sys.version_info >= (3, 9):
|
|
36
|
+
from _typeshed import SupportsBool
|
|
37
|
+
# We have to sacrifice a little bit of specificity on dinosaur Python3.8
|
|
38
|
+
else:
|
|
39
|
+
SupportsBool = Any
|
|
40
|
+
|
|
41
|
+
TArg = TypeVar("TArg")
|
|
42
|
+
TReturn = TypeVar("TReturn")
|
|
43
|
+
TOther = TypeVar("TOther")
|
|
7
44
|
|
|
8
45
|
Formatters = Callable[[List[Any]], List[Any]]
|
|
9
46
|
|
|
10
47
|
|
|
11
48
|
@return_arg_type(2)
|
|
12
49
|
def apply_formatter_at_index(
|
|
13
|
-
formatter: Callable[
|
|
14
|
-
|
|
15
|
-
|
|
50
|
+
formatter: Callable[[TArg], TReturn],
|
|
51
|
+
at_index: int,
|
|
52
|
+
value: Sequence[Union[TArg, TOther]],
|
|
53
|
+
) -> Generator[Union[TOther, TReturn], None, None]:
|
|
54
|
+
try:
|
|
55
|
+
item = value[at_index]
|
|
56
|
+
except IndexError:
|
|
16
57
|
raise IndexError(
|
|
17
|
-
"Not enough values in iterable to apply formatter.
|
|
18
|
-
"Need: {
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
yield item
|
|
58
|
+
f"Not enough values in iterable to apply formatter. Got: {len(value)}. "
|
|
59
|
+
f"Need: {at_index + 1}"
|
|
60
|
+
) from None
|
|
61
|
+
|
|
62
|
+
yield from cast(Sequence[TOther], value[:at_index])
|
|
63
|
+
yield formatter(cast(TArg, item))
|
|
64
|
+
yield from cast(Sequence[TOther], value[at_index + 1 :])
|
|
25
65
|
|
|
26
66
|
|
|
27
|
-
def combine_argument_formatters(*formatters:
|
|
67
|
+
def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
28
68
|
warnings.warn(
|
|
29
69
|
DeprecationWarning(
|
|
30
70
|
"combine_argument_formatters(formatter1, formatter2)([item1, item2])"
|
|
@@ -32,11 +72,12 @@ def combine_argument_formatters(*formatters: List[Callable[..., Any]]) -> Format
|
|
|
32
72
|
"release of the eth-utils library. Update your calls to use "
|
|
33
73
|
"apply_formatters_to_sequence([formatter1, formatter2], [item1, item2]) "
|
|
34
74
|
"instead."
|
|
35
|
-
)
|
|
75
|
+
),
|
|
76
|
+
stacklevel=2,
|
|
36
77
|
)
|
|
37
78
|
|
|
38
79
|
_formatter_at_index = curry(apply_formatter_at_index)
|
|
39
|
-
return compose( # type: ignore
|
|
80
|
+
return compose( # type: ignore [no-any-return]
|
|
40
81
|
*(
|
|
41
82
|
_formatter_at_index(formatter, index)
|
|
42
83
|
for index, formatter in enumerate(formatters)
|
|
@@ -46,69 +87,100 @@ def combine_argument_formatters(*formatters: List[Callable[..., Any]]) -> Format
|
|
|
46
87
|
|
|
47
88
|
@return_arg_type(1)
|
|
48
89
|
def apply_formatters_to_sequence(
|
|
49
|
-
formatters: List[Any], sequence:
|
|
50
|
-
) -> Generator[
|
|
51
|
-
|
|
90
|
+
formatters: List[Callable[[Any], TReturn]], sequence: Sequence[Any]
|
|
91
|
+
) -> Generator[TReturn, None, None]:
|
|
92
|
+
num_formatters = len(formatters)
|
|
93
|
+
num_items = len(sequence)
|
|
94
|
+
if num_formatters == num_items:
|
|
95
|
+
for formatter, item in zip(formatters, sequence):
|
|
96
|
+
yield formatter(item)
|
|
97
|
+
elif num_formatters > num_items:
|
|
52
98
|
raise IndexError(
|
|
53
|
-
"Too many formatters for sequence: {} formatters for
|
|
54
|
-
|
|
55
|
-
)
|
|
99
|
+
f"Too many formatters for sequence: {num_formatters} formatters for "
|
|
100
|
+
f"{sequence!r}"
|
|
56
101
|
)
|
|
57
|
-
|
|
102
|
+
else:
|
|
58
103
|
raise IndexError(
|
|
59
|
-
"Too few formatters for sequence: {} formatters for
|
|
60
|
-
|
|
61
|
-
)
|
|
104
|
+
f"Too few formatters for sequence: {num_formatters} formatters for "
|
|
105
|
+
f"{sequence!r}"
|
|
62
106
|
)
|
|
63
|
-
else:
|
|
64
|
-
for formatter, item in zip(formatters, sequence):
|
|
65
|
-
yield formatter(item)
|
|
66
107
|
|
|
67
108
|
|
|
109
|
+
@overload
|
|
68
110
|
def apply_formatter_if(
|
|
69
|
-
condition: Callable[
|
|
70
|
-
|
|
111
|
+
condition: Callable[[TArg], TypeGuard[TOther]],
|
|
112
|
+
formatter: Callable[[TOther], TReturn],
|
|
113
|
+
value: TArg,
|
|
114
|
+
) -> Union[TArg, TReturn]: ...
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@overload
|
|
118
|
+
def apply_formatter_if(
|
|
119
|
+
condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
|
|
120
|
+
) -> Union[TArg, TReturn]: ...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def apply_formatter_if( # type: ignore [misc]
|
|
124
|
+
condition: Union[Callable[[TArg], TypeGuard[TOther]], Callable[[TArg], bool]],
|
|
125
|
+
formatter: Union[Callable[[TOther], TReturn], Callable[[TArg], TReturn]],
|
|
126
|
+
value: TArg,
|
|
127
|
+
) -> Union[TArg, TReturn]:
|
|
71
128
|
if condition(value):
|
|
72
|
-
return formatter(value)
|
|
129
|
+
return formatter(value) # type: ignore [arg-type]
|
|
73
130
|
else:
|
|
74
131
|
return value
|
|
75
132
|
|
|
76
133
|
|
|
77
|
-
@to_dict
|
|
78
134
|
def apply_formatters_to_dict(
|
|
79
|
-
formatters: Dict[Any, Any],
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
135
|
+
formatters: Dict[Any, Any],
|
|
136
|
+
value: Union[Dict[Any, Any], CamelModel],
|
|
137
|
+
unaliased: bool = False,
|
|
138
|
+
) -> Dict[Any, Any]:
|
|
139
|
+
"""
|
|
140
|
+
Apply formatters to a dictionary of values. If the value is a pydantic model,
|
|
141
|
+
it will be serialized to a dictionary first, taking into account the
|
|
142
|
+
``unaliased`` parameter.
|
|
143
|
+
|
|
144
|
+
:param formatters: The formatters to apply to the dictionary.
|
|
145
|
+
:param value: The dictionary-like object to apply the formatters to.
|
|
146
|
+
:param unaliased: If the model is a ``CamelModel``, whether to turn off
|
|
147
|
+
serialization by alias (camelCase).
|
|
148
|
+
:return: A generator that yields the formatted key-value pairs.
|
|
149
|
+
"""
|
|
150
|
+
if isinstance(value, CamelModel):
|
|
151
|
+
value = value.model_dump(by_alias=not unaliased)
|
|
152
|
+
|
|
153
|
+
def get_value(key: Any, val: Any) -> Any:
|
|
154
|
+
if key not in formatters:
|
|
155
|
+
return val
|
|
156
|
+
try:
|
|
157
|
+
return formatters[key](val)
|
|
158
|
+
except ValueError as exc:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
f"Could not format invalid value {val!r} as field {key!r}"
|
|
161
|
+
) from exc
|
|
162
|
+
except TypeError as exc:
|
|
163
|
+
raise TypeError(
|
|
164
|
+
f"Could not format invalid type {val!r} as field {key!r}"
|
|
165
|
+
) from exc
|
|
166
|
+
|
|
167
|
+
return {key: get_value(key, val) for key, val in value.items()}
|
|
98
168
|
|
|
99
169
|
|
|
100
170
|
@return_arg_type(1)
|
|
101
171
|
def apply_formatter_to_array(
|
|
102
|
-
formatter: Callable[
|
|
103
|
-
) -> Generator[
|
|
172
|
+
formatter: Callable[[TArg], TReturn], value: Sequence[TArg]
|
|
173
|
+
) -> Generator[TReturn, None, None]:
|
|
104
174
|
for item in value:
|
|
105
175
|
yield formatter(item)
|
|
106
176
|
|
|
107
177
|
|
|
108
178
|
def apply_one_of_formatters(
|
|
109
|
-
formatter_condition_pairs: Tuple[
|
|
110
|
-
|
|
111
|
-
|
|
179
|
+
formatter_condition_pairs: Tuple[
|
|
180
|
+
Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]], ...
|
|
181
|
+
],
|
|
182
|
+
value: TArg,
|
|
183
|
+
) -> TReturn:
|
|
112
184
|
for condition, formatter in formatter_condition_pairs:
|
|
113
185
|
if condition(value):
|
|
114
186
|
return formatter(value)
|
|
@@ -118,10 +190,9 @@ def apply_one_of_formatters(
|
|
|
118
190
|
)
|
|
119
191
|
|
|
120
192
|
|
|
121
|
-
@to_dict
|
|
122
193
|
def apply_key_map(
|
|
123
|
-
key_mappings: Dict[Any, Any], value:
|
|
124
|
-
) ->
|
|
194
|
+
key_mappings: Dict[Any, Any], value: Mapping[Any, Any]
|
|
195
|
+
) -> Dict[Any, Any]:
|
|
125
196
|
key_conflicts = (
|
|
126
197
|
set(value.keys())
|
|
127
198
|
.difference(key_mappings.keys())
|
|
@@ -129,13 +200,10 @@ def apply_key_map(
|
|
|
129
200
|
)
|
|
130
201
|
if key_conflicts:
|
|
131
202
|
raise KeyError(
|
|
132
|
-
"Could not apply key map due to conflicting key(s): {}"
|
|
133
|
-
key_conflicts
|
|
134
|
-
)
|
|
203
|
+
f"Could not apply key map due to conflicting key(s): {key_conflicts}"
|
|
135
204
|
)
|
|
136
205
|
|
|
137
|
-
|
|
138
|
-
if key in key_mappings
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
yield key, item
|
|
206
|
+
def get_key(key: Any) -> Any:
|
|
207
|
+
return key_mappings[key] if key in key_mappings else key
|
|
208
|
+
|
|
209
|
+
return {get_key(key): item for key, item in value.items()}
|
|
Binary file
|
faster_eth_utils/conversions.py
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import (
|
|
2
|
+
Callable,
|
|
3
|
+
Optional,
|
|
4
|
+
TypeVar,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
2
7
|
|
|
3
|
-
from eth_typing import
|
|
8
|
+
from eth_typing import (
|
|
9
|
+
HexStr,
|
|
10
|
+
Primitives,
|
|
11
|
+
)
|
|
4
12
|
|
|
5
|
-
from .encoding import
|
|
13
|
+
from .encoding import (
|
|
14
|
+
big_endian_to_int,
|
|
15
|
+
int_to_big_endian,
|
|
16
|
+
)
|
|
6
17
|
from .hexadecimal import (
|
|
7
18
|
add_0x_prefix,
|
|
8
19
|
decode_hex,
|
|
@@ -10,13 +21,19 @@ from .hexadecimal import (
|
|
|
10
21
|
is_hexstr,
|
|
11
22
|
remove_0x_prefix,
|
|
12
23
|
)
|
|
13
|
-
from .types import
|
|
24
|
+
from .types import (
|
|
25
|
+
is_string,
|
|
26
|
+
)
|
|
14
27
|
|
|
15
28
|
T = TypeVar("T")
|
|
16
29
|
|
|
30
|
+
BytesLike = Union[Primitives, bytearray, memoryview]
|
|
31
|
+
|
|
17
32
|
|
|
18
33
|
def to_hex(
|
|
19
|
-
primitive:
|
|
34
|
+
primitive: Optional[BytesLike] = None,
|
|
35
|
+
hexstr: Optional[HexStr] = None,
|
|
36
|
+
text: Optional[str] = None,
|
|
20
37
|
) -> HexStr:
|
|
21
38
|
"""
|
|
22
39
|
Auto converts any supported value into its hex representation.
|
|
@@ -29,28 +46,34 @@ def to_hex(
|
|
|
29
46
|
if text is not None:
|
|
30
47
|
return encode_hex(text.encode("utf-8"))
|
|
31
48
|
|
|
32
|
-
if
|
|
49
|
+
if isinstance(primitive, bool):
|
|
33
50
|
return HexStr("0x1") if primitive else HexStr("0x0")
|
|
34
51
|
|
|
35
52
|
if isinstance(primitive, (bytes, bytearray)):
|
|
36
53
|
return encode_hex(primitive)
|
|
54
|
+
|
|
55
|
+
if isinstance(primitive, memoryview):
|
|
56
|
+
return encode_hex(bytes(primitive))
|
|
57
|
+
|
|
37
58
|
elif is_string(primitive):
|
|
38
59
|
raise TypeError(
|
|
39
60
|
"Unsupported type: The primitive argument must be one of: bytes,"
|
|
40
61
|
"bytearray, int or bool and not str"
|
|
41
62
|
)
|
|
42
63
|
|
|
43
|
-
if
|
|
64
|
+
if isinstance(primitive, int):
|
|
44
65
|
return HexStr(hex(primitive))
|
|
45
66
|
|
|
46
67
|
raise TypeError(
|
|
47
|
-
"Unsupported type: '{
|
|
48
|
-
"or int."
|
|
68
|
+
f"Unsupported type: '{repr(type(primitive))}'. Must be one of: bool, str, "
|
|
69
|
+
"bytes, bytearray or int."
|
|
49
70
|
)
|
|
50
71
|
|
|
51
72
|
|
|
52
73
|
def to_int(
|
|
53
|
-
primitive:
|
|
74
|
+
primitive: Optional[BytesLike] = None,
|
|
75
|
+
hexstr: Optional[HexStr] = None,
|
|
76
|
+
text: Optional[str] = None,
|
|
54
77
|
) -> int:
|
|
55
78
|
"""
|
|
56
79
|
Converts value to its integer representation.
|
|
@@ -58,8 +81,9 @@ def to_int(
|
|
|
58
81
|
|
|
59
82
|
* primitive:
|
|
60
83
|
|
|
61
|
-
* bytes,
|
|
84
|
+
* bytes, bytearray, memoryview: big-endian integer
|
|
62
85
|
* bool: True => 1, False => 0
|
|
86
|
+
* int: unchanged
|
|
63
87
|
* hexstr: interpret hex as integer
|
|
64
88
|
* text: interpret as string of digits, like '12' => 12
|
|
65
89
|
"""
|
|
@@ -69,33 +93,35 @@ def to_int(
|
|
|
69
93
|
return int(text)
|
|
70
94
|
elif isinstance(primitive, (bytes, bytearray)):
|
|
71
95
|
return big_endian_to_int(primitive)
|
|
96
|
+
elif isinstance(primitive, memoryview):
|
|
97
|
+
return big_endian_to_int(bytes(primitive))
|
|
72
98
|
elif isinstance(primitive, str):
|
|
73
99
|
raise TypeError("Pass in strings with keyword hexstr or text")
|
|
74
100
|
elif isinstance(primitive, (int, bool)):
|
|
75
101
|
return int(primitive)
|
|
76
102
|
else:
|
|
77
103
|
raise TypeError(
|
|
78
|
-
"Invalid type.
|
|
79
|
-
"{
|
|
104
|
+
"Invalid type. Expected one of int/bool/str/bytes/bytearray. Got "
|
|
105
|
+
f"{type(primitive)}"
|
|
80
106
|
)
|
|
81
107
|
|
|
82
108
|
|
|
83
109
|
def to_bytes(
|
|
84
|
-
primitive:
|
|
110
|
+
primitive: Optional[BytesLike] = None,
|
|
111
|
+
hexstr: Optional[HexStr] = None,
|
|
112
|
+
text: Optional[str] = None,
|
|
85
113
|
) -> bytes:
|
|
86
|
-
if
|
|
114
|
+
if isinstance(primitive, bool):
|
|
87
115
|
return b"\x01" if primitive else b"\x00"
|
|
88
|
-
elif isinstance(primitive, bytearray):
|
|
116
|
+
elif isinstance(primitive, (bytearray, memoryview)):
|
|
89
117
|
return bytes(primitive)
|
|
90
118
|
elif isinstance(primitive, bytes):
|
|
91
119
|
return primitive
|
|
92
|
-
elif
|
|
120
|
+
elif isinstance(primitive, int):
|
|
93
121
|
return to_bytes(hexstr=to_hex(primitive))
|
|
94
122
|
elif hexstr is not None:
|
|
95
123
|
if len(hexstr) % 2:
|
|
96
|
-
|
|
97
|
-
# Optional arg to str is not possible
|
|
98
|
-
hexstr = "0x0" + remove_0x_prefix(hexstr) # type: ignore
|
|
124
|
+
hexstr = "0x0" + remove_0x_prefix(hexstr) # type: ignore [assignment]
|
|
99
125
|
return decode_hex(hexstr)
|
|
100
126
|
elif text is not None:
|
|
101
127
|
return text.encode("utf-8")
|
|
@@ -106,7 +132,9 @@ def to_bytes(
|
|
|
106
132
|
|
|
107
133
|
|
|
108
134
|
def to_text(
|
|
109
|
-
primitive:
|
|
135
|
+
primitive: Optional[BytesLike] = None,
|
|
136
|
+
hexstr: Optional[HexStr] = None,
|
|
137
|
+
text: Optional[str] = None,
|
|
110
138
|
) -> str:
|
|
111
139
|
if hexstr is not None:
|
|
112
140
|
return to_bytes(hexstr=hexstr).decode("utf-8")
|
|
@@ -116,7 +144,9 @@ def to_text(
|
|
|
116
144
|
return to_text(hexstr=primitive)
|
|
117
145
|
elif isinstance(primitive, (bytes, bytearray)):
|
|
118
146
|
return primitive.decode("utf-8")
|
|
119
|
-
elif
|
|
147
|
+
elif isinstance(primitive, memoryview):
|
|
148
|
+
return bytes(primitive).decode("utf-8")
|
|
149
|
+
elif isinstance(primitive, int):
|
|
120
150
|
byte_encoding = int_to_big_endian(primitive)
|
|
121
151
|
return to_text(byte_encoding)
|
|
122
152
|
raise TypeError("Expected an int, bytes, bytearray or hexstr.")
|
|
@@ -153,9 +183,8 @@ def hexstr_if_str(
|
|
|
153
183
|
hexstr_or_primitive
|
|
154
184
|
):
|
|
155
185
|
raise ValueError(
|
|
156
|
-
"when sending a str, it must be a hex string.
|
|
157
|
-
|
|
158
|
-
)
|
|
186
|
+
"when sending a str, it must be a hex string. "
|
|
187
|
+
f"Got: {repr(hexstr_or_primitive)}"
|
|
159
188
|
)
|
|
160
189
|
return to_type(hexstr=hexstr_or_primitive)
|
|
161
190
|
else:
|
|
Binary file
|
faster_eth_utils/crypto.py
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import (
|
|
2
|
+
Optional,
|
|
3
|
+
Union,
|
|
4
|
+
)
|
|
2
5
|
|
|
3
|
-
from eth_hash.auto import
|
|
6
|
+
from eth_hash.auto import (
|
|
7
|
+
keccak as keccak_256,
|
|
8
|
+
)
|
|
9
|
+
from eth_typing import HexStr
|
|
4
10
|
|
|
5
|
-
from .conversions import
|
|
11
|
+
from .conversions import (
|
|
12
|
+
to_bytes,
|
|
13
|
+
)
|
|
6
14
|
|
|
7
15
|
|
|
8
16
|
def keccak(
|
|
9
|
-
primitive: Union[bytes, int, bool] = None,
|
|
17
|
+
primitive: Optional[Union[bytes, int, bool]] = None,
|
|
18
|
+
hexstr: Optional[HexStr] = None,
|
|
19
|
+
text: Optional[str] = None,
|
|
10
20
|
) -> bytes:
|
|
11
|
-
return keccak_256(to_bytes(primitive, hexstr, text))
|
|
21
|
+
return bytes(keccak_256(to_bytes(primitive, hexstr, text)))
|
|
Binary file
|