faster-eth-utils 5.3.22__cp312-cp312-musllinux_1_2_x86_64.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.

Files changed (53) hide show
  1. faster_eth_utils/__init__.py +144 -0
  2. faster_eth_utils/__json/eth_networks.json +1 -0
  3. faster_eth_utils/__main__.py +5 -0
  4. faster_eth_utils/abi.cpython-312-x86_64-linux-musl.so +0 -0
  5. faster_eth_utils/abi.py +868 -0
  6. faster_eth_utils/address.cpython-312-x86_64-linux-musl.so +0 -0
  7. faster_eth_utils/address.py +138 -0
  8. faster_eth_utils/applicators.cpython-312-x86_64-linux-musl.so +0 -0
  9. faster_eth_utils/applicators.py +196 -0
  10. faster_eth_utils/conversions.cpython-312-x86_64-linux-musl.so +0 -0
  11. faster_eth_utils/conversions.py +189 -0
  12. faster_eth_utils/crypto.cpython-312-x86_64-linux-musl.so +0 -0
  13. faster_eth_utils/crypto.py +16 -0
  14. faster_eth_utils/currency.cpython-312-x86_64-linux-musl.so +0 -0
  15. faster_eth_utils/currency.py +144 -0
  16. faster_eth_utils/curried/__init__.py +297 -0
  17. faster_eth_utils/debug.cpython-312-x86_64-linux-musl.so +0 -0
  18. faster_eth_utils/debug.py +20 -0
  19. faster_eth_utils/decorators.cpython-312-x86_64-linux-musl.so +0 -0
  20. faster_eth_utils/decorators.py +115 -0
  21. faster_eth_utils/encoding.cpython-312-x86_64-linux-musl.so +0 -0
  22. faster_eth_utils/encoding.py +6 -0
  23. faster_eth_utils/exceptions.cpython-312-x86_64-linux-musl.so +0 -0
  24. faster_eth_utils/exceptions.py +11 -0
  25. faster_eth_utils/functional.cpython-312-x86_64-linux-musl.so +0 -0
  26. faster_eth_utils/functional.py +87 -0
  27. faster_eth_utils/hexadecimal.cpython-312-x86_64-linux-musl.so +0 -0
  28. faster_eth_utils/hexadecimal.py +76 -0
  29. faster_eth_utils/humanize.cpython-312-x86_64-linux-musl.so +0 -0
  30. faster_eth_utils/humanize.py +201 -0
  31. faster_eth_utils/logging.py +152 -0
  32. faster_eth_utils/module_loading.cpython-312-x86_64-linux-musl.so +0 -0
  33. faster_eth_utils/module_loading.py +31 -0
  34. faster_eth_utils/network.cpython-312-x86_64-linux-musl.so +0 -0
  35. faster_eth_utils/network.py +91 -0
  36. faster_eth_utils/numeric.cpython-312-x86_64-linux-musl.so +0 -0
  37. faster_eth_utils/numeric.py +43 -0
  38. faster_eth_utils/py.typed +0 -0
  39. faster_eth_utils/pydantic.py +103 -0
  40. faster_eth_utils/toolz.cpython-312-x86_64-linux-musl.so +0 -0
  41. faster_eth_utils/toolz.py +84 -0
  42. faster_eth_utils/types.cpython-312-x86_64-linux-musl.so +0 -0
  43. faster_eth_utils/types.py +65 -0
  44. faster_eth_utils/typing/__init__.py +18 -0
  45. faster_eth_utils/typing/misc.py +14 -0
  46. faster_eth_utils/units.cpython-312-x86_64-linux-musl.so +0 -0
  47. faster_eth_utils/units.py +31 -0
  48. faster_eth_utils-5.3.22.dist-info/METADATA +192 -0
  49. faster_eth_utils-5.3.22.dist-info/RECORD +53 -0
  50. faster_eth_utils-5.3.22.dist-info/WHEEL +5 -0
  51. faster_eth_utils-5.3.22.dist-info/licenses/LICENSE +21 -0
  52. faster_eth_utils-5.3.22.dist-info/top_level.txt +3 -0
  53. faster_eth_utils__mypyc.cpython-312-x86_64-linux-musl.so +0 -0
@@ -0,0 +1,297 @@
1
+ import sys
2
+ from collections.abc import Callable, Generator, Sequence
3
+ from typing import (
4
+ TYPE_CHECKING,
5
+ Any,
6
+ Optional,
7
+ TypeGuard,
8
+ TypeVar,
9
+ Union,
10
+ overload,
11
+ )
12
+
13
+ from faster_eth_utils import (
14
+ CamelModel,
15
+ ExtendedDebugLogger,
16
+ HasExtendedDebugLogger,
17
+ HasExtendedDebugLoggerMeta,
18
+ HasLogger,
19
+ HasLoggerMeta,
20
+ Network,
21
+ ValidationError,
22
+ abi_to_signature,
23
+ add_0x_prefix,
24
+ apply_formatter_at_index,
25
+ apply_formatter_if as non_curried_apply_formatter_if,
26
+ apply_formatter_to_array,
27
+ apply_formatters_to_dict as non_curried_apply_formatters_to_dict,
28
+ apply_formatters_to_sequence,
29
+ apply_key_map,
30
+ apply_one_of_formatters as non_curried_apply_one_of_formatters,
31
+ apply_to_return_value,
32
+ big_endian_to_int,
33
+ clamp,
34
+ collapse_if_tuple,
35
+ combine_argument_formatters,
36
+ combomethod,
37
+ decode_hex,
38
+ denoms,
39
+ encode_hex,
40
+ event_abi_to_log_topic,
41
+ event_signature_to_log_topic,
42
+ filter_abi_by_name,
43
+ filter_abi_by_type,
44
+ flatten_return,
45
+ from_wei,
46
+ from_wei_decimals,
47
+ function_abi_to_4byte_selector,
48
+ function_signature_to_4byte_selector,
49
+ get_abi_input_names,
50
+ get_abi_input_types,
51
+ get_abi_output_names,
52
+ get_abi_output_types,
53
+ get_aligned_abi_inputs,
54
+ get_all_event_abis,
55
+ get_all_function_abis,
56
+ get_extended_debug_logger,
57
+ get_logger,
58
+ get_normalized_abi_inputs,
59
+ hexstr_if_str as non_curried_hexstr_if_str,
60
+ humanize_bytes,
61
+ humanize_hash,
62
+ humanize_hexstr,
63
+ humanize_integer_sequence,
64
+ humanize_ipfs_uri,
65
+ humanize_seconds,
66
+ humanize_wei,
67
+ import_string,
68
+ int_to_big_endian,
69
+ is_0x_prefixed,
70
+ is_address,
71
+ is_binary_address,
72
+ is_boolean,
73
+ is_bytes,
74
+ is_canonical_address,
75
+ is_checksum_address,
76
+ is_checksum_formatted_address,
77
+ is_dict,
78
+ is_hex,
79
+ is_hex_address,
80
+ is_hexstr,
81
+ is_integer,
82
+ is_list,
83
+ is_list_like,
84
+ is_normalized_address,
85
+ is_null,
86
+ is_number,
87
+ is_same_address,
88
+ is_string,
89
+ is_text,
90
+ is_tuple,
91
+ keccak,
92
+ name_from_chain_id,
93
+ network_from_chain_id,
94
+ remove_0x_prefix,
95
+ replace_exceptions,
96
+ reversed_return,
97
+ setup_DEBUG2_logging,
98
+ short_name_from_chain_id,
99
+ sort_return,
100
+ text_if_str as non_curried_text_if_str,
101
+ to_bytes,
102
+ to_canonical_address,
103
+ to_checksum_address,
104
+ to_dict,
105
+ to_hex,
106
+ to_int,
107
+ to_list,
108
+ to_normalized_address,
109
+ to_ordered_dict,
110
+ to_set,
111
+ to_text,
112
+ to_tuple,
113
+ to_wei,
114
+ to_wei_decimals,
115
+ )
116
+ from faster_eth_utils.toolz import (
117
+ curry,
118
+ )
119
+
120
+ if TYPE_CHECKING:
121
+ from _typeshed import SupportsBool
122
+ # We have to sacrifice a little bit of specificity on dinosaur Python3.8
123
+
124
+
125
+ TArg = TypeVar("TArg")
126
+ TOther = TypeVar("TOther")
127
+ TReturn = TypeVar("TReturn")
128
+ TValue = TypeVar("TValue")
129
+
130
+
131
+ @overload
132
+ def apply_formatter_if(
133
+ condition: Callable[[TArg], TypeGuard[TOther]],
134
+ ) -> Callable[[Callable[[TOther], TReturn]], Callable[[TArg], TReturn | TArg]]:
135
+ ...
136
+
137
+ @overload
138
+ def apply_formatter_if(
139
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn]
140
+ ) -> Callable[[TArg], TReturn | TArg]:
141
+ ...
142
+
143
+ @overload
144
+ def apply_formatter_if(
145
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn], value: TArg
146
+ ) -> TReturn | TArg:
147
+ ...
148
+
149
+ @overload
150
+ def apply_formatter_if(
151
+ condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
152
+ ) -> TReturn | TArg:
153
+ ...
154
+
155
+ def apply_formatter_if( # type: ignore
156
+ condition: Callable[[TArg], TypeGuard[TOther]] | Callable[[TArg], bool],
157
+ formatter: Callable[[TOther], TReturn] | Callable[[TArg], TReturn] | None = None,
158
+ value: TArg | None = None,
159
+ ) -> (
160
+ Callable[[Callable[[TOther], TReturn]], Callable[[TArg], TReturn | TArg]] |
161
+ Callable[[TArg], TReturn | TArg] |
162
+ TReturn |
163
+ TArg
164
+ ):
165
+ pass
166
+
167
+
168
+ @overload
169
+ def apply_one_of_formatters(
170
+ formatter_condition_pairs: Sequence[
171
+ tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
172
+ ],
173
+ ) -> Callable[[TArg], TReturn]: ...
174
+
175
+
176
+ @overload
177
+ def apply_one_of_formatters(
178
+ formatter_condition_pairs: Sequence[
179
+ tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
180
+ ],
181
+ value: TArg,
182
+ ) -> TReturn: ...
183
+
184
+
185
+ # This is just a stub to appease mypy, it gets overwritten later
186
+ def apply_one_of_formatters( # type: ignore[empty-body]
187
+ formatter_condition_pairs: Sequence[
188
+ tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
189
+ ],
190
+ value: TArg | None = None,
191
+ ) -> Callable[[TArg], TReturn] | TReturn: ...
192
+
193
+
194
+ @overload
195
+ def hexstr_if_str(
196
+ to_type: Callable[..., TReturn],
197
+ ) -> Callable[[bytes | int | str], TReturn]: ...
198
+
199
+
200
+ @overload
201
+ def hexstr_if_str(
202
+ to_type: Callable[..., TReturn], to_format: bytes | int | str
203
+ ) -> TReturn: ...
204
+
205
+
206
+ # This is just a stub to appease mypy, it gets overwritten later
207
+ def hexstr_if_str( # type: ignore
208
+ to_type: Callable[..., TReturn], to_format: bytes | int | str | None = None
209
+ ) -> TReturn: ...
210
+
211
+
212
+ @overload
213
+ def text_if_str(
214
+ to_type: Callable[..., TReturn],
215
+ ) -> Callable[[bytes | int | str], TReturn]: ...
216
+
217
+
218
+ @overload
219
+ def text_if_str(
220
+ to_type: Callable[..., TReturn], text_or_primitive: bytes | int | str
221
+ ) -> TReturn: ...
222
+
223
+
224
+ # This is just a stub to appease mypy, it gets overwritten later
225
+ def text_if_str( # type: ignore
226
+ to_type: Callable[..., TReturn],
227
+ text_or_primitive: bytes | int | str | None = None,
228
+ ) -> TReturn: ...
229
+
230
+
231
+ @overload
232
+ def apply_formatters_to_dict(
233
+ formatters: dict[Any, Any], unaliased: bool = False
234
+ ) -> Callable[[dict[Any, Any] | CamelModel], dict[Any, Any]]:
235
+ ...
236
+
237
+
238
+ @overload
239
+ def apply_formatters_to_dict(
240
+ formatters: dict[Any, Any], value: dict[Any, Any] | CamelModel, unaliased: bool = False
241
+ ) -> dict[Any, Any]:
242
+ ...
243
+
244
+
245
+ # This is just a stub to appease mypy, it gets overwritten later
246
+ def apply_formatters_to_dict(
247
+ formatters: dict[Any, Any],
248
+ value: dict[Any, Any] | CamelModel | None = None,
249
+ unaliased: bool = False,
250
+ ) -> dict[Any, Any]: ...
251
+
252
+
253
+ apply_formatter_at_index = curry(apply_formatter_at_index)
254
+ apply_formatter_if = curry(non_curried_apply_formatter_if) # noqa: F811
255
+ apply_formatter_to_array = curry(apply_formatter_to_array)
256
+ apply_formatters_to_dict = curry(non_curried_apply_formatters_to_dict) # noqa: F811
257
+ apply_formatters_to_sequence = curry(apply_formatters_to_sequence)
258
+ apply_key_map = curry(apply_key_map)
259
+ apply_one_of_formatters = curry(non_curried_apply_one_of_formatters) # noqa: F811
260
+ filter_abi_by_name = curry(filter_abi_by_name)
261
+ filter_abi_by_type = curry(filter_abi_by_type)
262
+ flatten_return = curry(flatten_return)
263
+ from_wei = curry(from_wei)
264
+ from_wei_decimals = curry(from_wei_decimals)
265
+ get_aligned_abi_inputs = curry(get_aligned_abi_inputs)
266
+ get_logger = curry(get_logger)
267
+ get_normalized_abi_inputs = curry(get_normalized_abi_inputs)
268
+ hexstr_if_str = curry(non_curried_hexstr_if_str) # noqa: F811
269
+ is_same_address = curry(is_same_address)
270
+ sort_return = curry(sort_return)
271
+ text_if_str = curry(non_curried_text_if_str) # noqa: F811
272
+ to_ordered_dict = curry(to_ordered_dict)
273
+ to_wei = curry(to_wei)
274
+ to_wei_decimals = curry(to_wei_decimals)
275
+ clamp = curry(clamp)
276
+
277
+ # Delete any methods and classes that are not intended to be importable from
278
+ # `eth_utils.curried`. We do this approach instead of __all__ because this approach
279
+ # actually prevents importing the wrong thing, while __all__ only affects
280
+ # `from eth_utils.curried import *`
281
+ del Any
282
+ del Callable
283
+ del Generator
284
+ del Optional
285
+ del Sequence
286
+ del TReturn
287
+ del TValue
288
+ del TypeGuard
289
+ del TypeVar
290
+ del Union
291
+ del curry
292
+ del non_curried_apply_formatter_if
293
+ del non_curried_apply_one_of_formatters
294
+ del non_curried_apply_formatters_to_dict
295
+ del non_curried_hexstr_if_str
296
+ del non_curried_text_if_str
297
+ del overload
@@ -0,0 +1,20 @@
1
+ import platform
2
+ import subprocess
3
+ import sys
4
+
5
+
6
+ def pip_freeze() -> str:
7
+ result = subprocess.run("python -m pip freeze".split(), stdout=subprocess.PIPE)
8
+ return f"python -m pip freeze result:\n{result.stdout.decode()}"
9
+
10
+
11
+ def python_version() -> str:
12
+ return f"Python version:\n{sys.version}"
13
+
14
+
15
+ def platform_info() -> str:
16
+ return f"Operating System: {platform.platform()}"
17
+
18
+
19
+ def get_environment_summary() -> str:
20
+ return "\n\n".join([python_version(), platform_info(), pip_freeze()])
@@ -0,0 +1,115 @@
1
+ import functools
2
+ from collections.abc import Callable
3
+ from typing import (
4
+ Any,
5
+ Concatenate,
6
+ Final,
7
+ Generic,
8
+ TypeVar,
9
+ final,
10
+ )
11
+
12
+ from typing_extensions import ParamSpec
13
+
14
+ P = ParamSpec("P")
15
+
16
+ T = TypeVar("T")
17
+
18
+ TInstance = TypeVar("TInstance", bound=object)
19
+ """A TypeVar representing an instance that a method can bind to."""
20
+
21
+
22
+ @final
23
+ class combomethod(Generic[TInstance, P, T]):
24
+ def __init__(
25
+ self, method: Callable[Concatenate[TInstance | type[TInstance], P], T]
26
+ ) -> None:
27
+ self.method: Final = method
28
+
29
+ def __repr__(self) -> str:
30
+ return f"combomethod({self.method})"
31
+
32
+ def __get__(
33
+ self,
34
+ obj: TInstance | None,
35
+ objtype: type[TInstance],
36
+ ) -> Callable[P, T]:
37
+
38
+ method = self.method
39
+ bound_arg = objtype if obj is None else obj
40
+
41
+ @functools.wraps(method)
42
+ def _wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
43
+ return method(bound_arg, *args, **kwargs)
44
+
45
+ return _wrapper
46
+
47
+
48
+ _return_arg_type_deco_cache: Final[
49
+ dict[int, Callable[[Callable[P, T]], Callable[P, Any]]]
50
+ ] = {}
51
+ # No need to hold so many unique instances in memory
52
+
53
+
54
+ def return_arg_type(at_position: int) -> Callable[[Callable[P, T]], Callable[P, Any]]:
55
+ """
56
+ Wrap the return value with the result of `type(args[at_position])`.
57
+ """
58
+ if deco := _return_arg_type_deco_cache.get(at_position):
59
+ return deco
60
+
61
+ def decorator(to_wrap: Callable[P, Any]) -> Callable[P, Any]:
62
+ @functools.wraps(to_wrap)
63
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
64
+ result = to_wrap(*args, **kwargs)
65
+ ReturnType = type(args[at_position])
66
+ return ReturnType(result) # type: ignore [call-arg]
67
+
68
+ return wrapper
69
+
70
+ _return_arg_type_deco_cache[at_position] = decorator
71
+
72
+ return decorator
73
+
74
+
75
+ ExcType = type[BaseException]
76
+
77
+ ReplaceExceptionsCache = dict[
78
+ tuple[tuple[ExcType, ExcType], ...],
79
+ Callable[[Callable[P, T]], Callable[P, T]],
80
+ ]
81
+
82
+ _replace_exceptions_deco_cache: Final[ReplaceExceptionsCache[..., Any]] = {}
83
+ # No need to hold so many unique instances in memory
84
+
85
+
86
+ def replace_exceptions(
87
+ old_to_new_exceptions: dict[ExcType, ExcType],
88
+ ) -> Callable[[Callable[P, T]], Callable[P, T]]:
89
+ """
90
+ Replaces old exceptions with new exceptions to be raised in their place.
91
+ """
92
+ cache_key = tuple(old_to_new_exceptions.items())
93
+ if deco := _replace_exceptions_deco_cache.get(cache_key):
94
+ return deco
95
+
96
+ old_exceptions = tuple(old_to_new_exceptions)
97
+
98
+ def decorator(to_wrap: Callable[P, T]) -> Callable[P, T]:
99
+ @functools.wraps(to_wrap)
100
+ def wrapped(*args: P.args, **kwargs: P.kwargs) -> T:
101
+ try:
102
+ return to_wrap(*args, **kwargs)
103
+ except old_exceptions as err:
104
+ try:
105
+ raise old_to_new_exceptions[type(err)](err) from err
106
+ except KeyError:
107
+ raise TypeError(
108
+ f"could not look up new exception to use for {repr(err)}"
109
+ ) from err
110
+
111
+ return wrapped
112
+
113
+ _replace_exceptions_deco_cache[cache_key] = decorator
114
+
115
+ return decorator
@@ -0,0 +1,6 @@
1
+ def int_to_big_endian(value: int) -> bytes:
2
+ return value.to_bytes((value.bit_length() + 7) // 8 or 1, "big")
3
+
4
+
5
+ def big_endian_to_int(value: bytes | bytearray) -> int:
6
+ return int.from_bytes(value, "big")
@@ -0,0 +1,11 @@
1
+ """
2
+ faster-eth-utils exceptions always inherit from eth-utils exceptions, so porting to faster-eth-utils
3
+ does not require any change to your existing exception handlers. They will continue to work.
4
+ """
5
+
6
+ import eth_utils.exceptions
7
+
8
+ class ValidationError(eth_utils.exceptions.ValidationError): # type: ignore[misc]
9
+ """
10
+ Raised when something does not pass a validation check.
11
+ """
@@ -0,0 +1,87 @@
1
+ import collections
2
+ import functools
3
+ import itertools
4
+ from collections.abc import Callable, Iterable, Mapping
5
+ from typing import ( # noqa: F401
6
+ Dict,
7
+ List,
8
+ Set,
9
+ Tuple,
10
+ TypeVar,
11
+ Union,
12
+ )
13
+
14
+ from typing_extensions import ParamSpec
15
+
16
+ from .toolz import (
17
+ compose as _compose,
18
+ )
19
+
20
+ P = ParamSpec("P")
21
+ T = TypeVar("T")
22
+
23
+
24
+ def identity(value: T) -> T:
25
+ return value
26
+
27
+
28
+ TGIn = TypeVar("TGIn")
29
+ TGOut = TypeVar("TGOut")
30
+ TFOut = TypeVar("TFOut")
31
+
32
+
33
+ def combine(
34
+ f: Callable[[TGOut], TFOut], g: Callable[[TGIn], TGOut]
35
+ ) -> Callable[[TGIn], TFOut]:
36
+ def combined(x: TGIn) -> TFOut:
37
+ return f(g(x))
38
+ return combined
39
+
40
+
41
+ TCb = TypeVar("TCb")
42
+
43
+
44
+ def apply_to_return_value(
45
+ callback: Callable[[T], TCb]
46
+ ) -> Callable[[Callable[P, T]], Callable[P, TCb]]:
47
+ def outer(fn: Callable[P, T]) -> Callable[P, TCb]:
48
+ @functools.wraps(fn)
49
+ def inner(*args: P.args, **kwargs: P.kwargs) -> TCb:
50
+ return callback(fn(*args, **kwargs))
51
+ return inner
52
+ return outer
53
+
54
+
55
+ TVal = TypeVar("TVal")
56
+ TKey = TypeVar("TKey")
57
+
58
+ def to_tuple(fn: Callable[P, Iterable[TVal]]) -> Callable[P, tuple[TVal, ...]]:
59
+ def to_tuple_wrap(*args: P.args, **kwargs: P.kwargs) -> tuple[TVal, ...]:
60
+ return tuple(fn(*args, **kwargs))
61
+ return to_tuple_wrap
62
+
63
+ def to_list(fn: Callable[P, Iterable[TVal]]) -> Callable[P, list[TVal]]:
64
+ def to_list_wrap(*args: P.args, **kwargs: P.kwargs) -> list[TVal]:
65
+ return list(fn(*args, **kwargs))
66
+ return to_list_wrap
67
+
68
+ def to_set(fn: Callable[P, Iterable[TVal]]) -> Callable[P, set[TVal]]:
69
+ def to_set_wrap(*args: P.args, **kwargs: P.kwargs) -> set[TVal]:
70
+ return set(fn(*args, **kwargs))
71
+ return to_set_wrap
72
+
73
+ def to_dict(
74
+ fn: Callable[P, Mapping[TKey, TVal] | Iterable[tuple[TKey, TVal]]]
75
+ ) -> Callable[P, dict[TKey, TVal]]:
76
+ def to_dict_wrap(*args: P.args, **kwargs: P.kwargs) -> dict[TKey, TVal]:
77
+ return dict(fn(*args, **kwargs))
78
+ return to_dict_wrap
79
+
80
+ to_ordered_dict = apply_to_return_value( # type: ignore [assignment]
81
+ collections.OrderedDict
82
+ ) # type: Callable[[Callable[P, Union[Mapping[TKey, TVal], Iterable[Tuple[TKey, TVal]]]]], Callable[P, collections.OrderedDict[TKey, TVal]]] # noqa: E501
83
+ sort_return = _compose(to_tuple, apply_to_return_value(sorted))
84
+ flatten_return = _compose(
85
+ to_tuple, apply_to_return_value(itertools.chain.from_iterable)
86
+ )
87
+ reversed_return = _compose(to_tuple, apply_to_return_value(reversed), to_tuple)
@@ -0,0 +1,76 @@
1
+ # String encodings and numeric representations
2
+
3
+ import binascii
4
+ import re
5
+ from typing import (
6
+ Any,
7
+ Final,
8
+ TypeGuard,
9
+ )
10
+
11
+ from eth_typing import (
12
+ HexStr,
13
+ )
14
+
15
+ _HEX_REGEXP_MATCH: Final = re.compile("(0[xX])?[0-9a-fA-F]*").fullmatch
16
+
17
+ _hexlify: Final = binascii.hexlify
18
+ _unhexlify: Final = binascii.unhexlify
19
+
20
+
21
+
22
+ def decode_hex(value: str) -> bytes:
23
+ if not isinstance(value, str):
24
+ raise TypeError("Value must be an instance of str")
25
+ non_prefixed = remove_0x_prefix(HexStr(value))
26
+ # unhexlify will only accept bytes type someday
27
+ ascii_hex = non_prefixed.encode("ascii")
28
+ return _unhexlify(ascii_hex)
29
+
30
+
31
+ def encode_hex(value: str | bytes | bytearray) -> HexStr:
32
+ ascii_bytes: bytes | bytearray
33
+ if isinstance(value, (bytes, bytearray)):
34
+ ascii_bytes = value
35
+ elif isinstance(value, str):
36
+ ascii_bytes = value.encode("ascii")
37
+ else:
38
+ raise TypeError("Value must be an instance of str or unicode")
39
+
40
+ binary_hex = _hexlify(ascii_bytes)
41
+ return add_0x_prefix(HexStr(binary_hex.decode("ascii")))
42
+
43
+
44
+ def is_0x_prefixed(value: str) -> bool:
45
+ # this check is not needed in the compiled version
46
+ # if not isinstance(value, str):
47
+ # raise TypeError(
48
+ # f"is_0x_prefixed requires text typed arguments. Got: {repr(value)}"
49
+ # )
50
+ return value.startswith("0x") or value.startswith("0X")
51
+
52
+
53
+ def remove_0x_prefix(value: HexStr) -> HexStr:
54
+ if is_0x_prefixed(value):
55
+ return HexStr(value[2:])
56
+ return value
57
+
58
+
59
+ def add_0x_prefix(value: HexStr) -> HexStr:
60
+ if is_0x_prefixed(value):
61
+ return value
62
+ return HexStr("0x" + value)
63
+
64
+
65
+ def is_hexstr(value: Any) -> TypeGuard[HexStr]:
66
+ if not isinstance(value, str) or not value:
67
+ return False
68
+ return _HEX_REGEXP_MATCH(value) is not None
69
+
70
+
71
+ def is_hex(value: Any) -> TypeGuard[HexStr]:
72
+ if not isinstance(value, str):
73
+ raise TypeError(f"is_hex requires text typed arguments. Got: {repr(value)}")
74
+ if not value:
75
+ return False
76
+ return _HEX_REGEXP_MATCH(value) is not None