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