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.

Files changed (54) hide show
  1. faster_eth_utils/__init__.py +54 -17
  2. faster_eth_utils/__json/eth_networks.json +1 -0
  3. faster_eth_utils/__main__.py +3 -1
  4. faster_eth_utils/abi.cp311-win32.pyd +0 -0
  5. faster_eth_utils/abi.py +840 -37
  6. faster_eth_utils/address.cp311-win32.pyd +0 -0
  7. faster_eth_utils/address.py +54 -66
  8. faster_eth_utils/applicators.cp311-win32.pyd +0 -0
  9. faster_eth_utils/applicators.py +126 -71
  10. faster_eth_utils/conversions.cp311-win32.pyd +0 -0
  11. faster_eth_utils/conversions.py +57 -30
  12. faster_eth_utils/crypto.cp311-win32.pyd +0 -0
  13. faster_eth_utils/crypto.py +11 -6
  14. faster_eth_utils/currency.cp311-win32.pyd +0 -0
  15. faster_eth_utils/currency.py +74 -33
  16. faster_eth_utils/curried/__init__.py +110 -89
  17. faster_eth_utils/debug.cp311-win32.pyd +0 -0
  18. faster_eth_utils/debug.py +3 -3
  19. faster_eth_utils/decorators.cp311-win32.pyd +0 -0
  20. faster_eth_utils/decorators.py +73 -24
  21. faster_eth_utils/encoding.cp311-win32.pyd +0 -0
  22. faster_eth_utils/encoding.py +1 -1
  23. faster_eth_utils/exceptions.cp311-win32.pyd +0 -0
  24. faster_eth_utils/exceptions.py +8 -3
  25. faster_eth_utils/functional.cp311-win32.pyd +0 -0
  26. faster_eth_utils/functional.py +42 -28
  27. faster_eth_utils/hexadecimal.cp311-win32.pyd +0 -0
  28. faster_eth_utils/hexadecimal.py +34 -26
  29. faster_eth_utils/humanize.cp311-win32.pyd +0 -0
  30. faster_eth_utils/humanize.py +55 -27
  31. faster_eth_utils/logging.py +65 -64
  32. faster_eth_utils/module_loading.cp311-win32.pyd +0 -0
  33. faster_eth_utils/module_loading.py +8 -7
  34. faster_eth_utils/network.cp311-win32.pyd +0 -0
  35. faster_eth_utils/network.py +25 -14
  36. faster_eth_utils/numeric.cp311-win32.pyd +0 -0
  37. faster_eth_utils/numeric.py +11 -4
  38. faster_eth_utils/pydantic.py +99 -0
  39. faster_eth_utils/toolz.cp311-win32.pyd +0 -0
  40. faster_eth_utils/toolz.py +82 -152
  41. faster_eth_utils/types.cp311-win32.pyd +0 -0
  42. faster_eth_utils/types.py +34 -21
  43. faster_eth_utils/typing/misc.py +3 -1
  44. faster_eth_utils/units.cp311-win32.pyd +0 -0
  45. faster_eth_utils-5.3.23.dist-info/METADATA +192 -0
  46. faster_eth_utils-5.3.23.dist-info/RECORD +53 -0
  47. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.23.dist-info}/licenses/LICENSE +1 -1
  48. faster_eth_utils-5.3.23.dist-info/top_level.txt +3 -0
  49. faster_eth_utils__mypyc.cp311-win32.pyd +0 -0
  50. bce0bfc64ce5e845ec4a__mypyc.cp311-win32.pyd +0 -0
  51. faster_eth_utils-2.3.1.dist-info/METADATA +0 -160
  52. faster_eth_utils-2.3.1.dist-info/RECORD +0 -45
  53. faster_eth_utils-2.3.1.dist-info/top_level.txt +0 -3
  54. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.23.dist-info}/WHEEL +0 -0
Binary file
@@ -1,17 +1,43 @@
1
1
  import re
2
- from typing import Any, Final, Union, cast
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
- from eth_typing import Address, AnyAddress, ChecksumAddress, HexAddress, HexStr
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
- _HEX_ADDRESS_REGEXP: Final = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
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) -> bool:
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) -> bool:
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: Union[AnyAddress, str, bytes]) -> HexAddress:
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 {!r}, attempted to normalize to {!r}".format(
65
- value, hex_address
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) -> bool:
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
- if not is_address(value):
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: Union[AnyAddress, str, bytes]) -> 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) -> bool:
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
- if not is_bytes(address) or len(address) != 20:
93
- return False
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(left: AnyAddress, right: AnyAddress) -> bool:
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
- else:
105
- return to_normalized_address(left) == to_normalized_address(right)
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
- is_equal = value == to_checksum_address(value)
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:
@@ -1,30 +1,57 @@
1
- from typing import Any, Callable, Dict, Generator, List, Tuple
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 return_arg_type
5
- from .functional import to_dict
6
- from .toolz import compose, curry
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[[List[Any]], List[Any]]
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[..., Any], at_index: int, value: List[Any]
14
- ) -> Generator[List[Any], None, None]:
15
- if at_index + 1 > len(value):
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. Got: {0}. "
18
- "Need: {1}".format(len(value), at_index + 1)
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
- def combine_argument_formatters(*formatters: List[Callable[..., Any]]) -> Formatters:
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: List[Any], sequence: List[Any]
50
- ) -> Generator[List[Any], None, None]:
51
- if len(formatters) > len(sequence):
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 {!r}".format(
54
- len(formatters), sequence
55
- )
86
+ f"Too many formatters for sequence: {num_formatters} formatters for "
87
+ f"{sequence!r}"
56
88
  )
57
- elif len(formatters) < len(sequence):
89
+ else:
58
90
  raise IndexError(
59
- "Too few formatters for sequence: {} formatters for {!r}".format(
60
- len(formatters), sequence
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[..., bool], formatter: Callable[..., Any], value: Any
70
- ) -> Any:
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: Dict[Any, Any], value: Dict[Any, Any]
80
- ) -> Generator[Tuple[Any, Any], None, None]:
81
- for key, item in value.items():
82
- if key in formatters:
83
- try:
84
- yield key, formatters[key](item)
85
- except ValueError as exc:
86
- new_error_message = "Could not format invalid value %r as field %r" % (
87
- item,
88
- key,
89
- )
90
- raise ValueError(new_error_message) from exc
91
- except TypeError as exc:
92
- new_error_message = (
93
- "Could not format invalid type of %r for field %r" % (item, key)
94
- )
95
- raise TypeError(new_error_message) from exc
96
- else:
97
- yield key, item
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[..., Any], value: List[Any]
103
- ) -> Generator[List[Any], None, None]:
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: Tuple[Tuple[Callable[..., Any], Callable[..., Any]]],
110
- value: Any,
111
- ) -> Any:
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: Dict[Any, Any], value: Dict[Any, Any]
124
- ) -> Generator[Tuple[Any, Any], None, None]:
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): {}".format(
133
- key_conflicts
134
- )
190
+ f"Could not apply key map due to conflicting key(s): {key_conflicts}"
135
191
  )
136
192
 
137
- for key, item in value.items():
138
- if key in key_mappings:
139
- yield key_mappings[key], item
140
- else:
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()}
@@ -1,8 +1,18 @@
1
- from typing import Callable, TypeVar, Union
1
+ from typing import (
2
+ TypeVar,
3
+ Union,
4
+ )
5
+ from collections.abc import Callable
2
6
 
3
- from eth_typing import HexStr, Primitives
7
+ from eth_typing import (
8
+ HexStr,
9
+ Primitives,
10
+ )
4
11
 
5
- from .encoding import big_endian_to_int, int_to_big_endian
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 is_boolean, is_integer, is_string
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: Primitives = None, hexstr: HexStr = None, text: str = None
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 is_boolean(primitive):
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 is_integer(primitive):
63
+ if isinstance(primitive, int):
44
64
  return HexStr(hex(primitive))
45
65
 
46
66
  raise TypeError(
47
- "Unsupported type: '{0}'. Must be one of: bool, str, bytes, bytearray"
48
- "or int.".format(repr(type(primitive)))
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: Primitives = None, hexstr: HexStr = None, text: str = None
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, bytearrays: big-endian integer
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. Expected one of int/bool/str/bytes/bytearray. Got "
79
- "{0}".format(type(primitive))
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: Primitives = None, hexstr: HexStr = None, text: str = None
109
+ primitive: BytesLike | None = None,
110
+ hexstr: HexStr | None = None,
111
+ text: str | None = None,
85
112
  ) -> bytes:
86
- if is_boolean(primitive):
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 is_integer(primitive):
93
- return to_bytes(hexstr=to_hex(primitive))
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
- # type check ignored here because casting an
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: Primitives = None, hexstr: HexStr = None, text: str = None
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 is_integer(primitive):
120
- byte_encoding = int_to_big_endian(primitive)
121
- return to_text(byte_encoding)
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: Union[bytes, int, str]
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: Union[bytes, int, str]
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. Got: {0!r}".format(
157
- hexstr_or_primitive
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
@@ -1,11 +1,16 @@
1
- from typing import Union
1
+ from eth_hash.auto import (
2
+ keccak as keccak_256,
3
+ )
4
+ from eth_typing import HexStr
2
5
 
3
- from eth_hash.auto import keccak as keccak_256
4
-
5
- from .conversions import to_bytes
6
+ from .conversions import (
7
+ to_bytes,
8
+ )
6
9
 
7
10
 
8
11
  def keccak(
9
- primitive: Union[bytes, int, bool] = None, hexstr: str = None, text: str = None
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