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.

Files changed (53) 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 +819 -37
  6. faster_eth_utils/address.cp311-win32.pyd +0 -0
  7. faster_eth_utils/address.py +57 -62
  8. faster_eth_utils/applicators.cp311-win32.pyd +0 -0
  9. faster_eth_utils/applicators.py +138 -70
  10. faster_eth_utils/conversions.cp311-win32.pyd +0 -0
  11. faster_eth_utils/conversions.py +54 -25
  12. faster_eth_utils/crypto.cp311-win32.pyd +0 -0
  13. faster_eth_utils/crypto.py +15 -5
  14. faster_eth_utils/currency.cp311-win32.pyd +0 -0
  15. faster_eth_utils/currency.py +70 -32
  16. faster_eth_utils/curried/__init__.py +107 -77
  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 -20
  21. faster_eth_utils/encoding.cp311-win32.pyd +0 -0
  22. faster_eth_utils/exceptions.cp311-win32.pyd +0 -0
  23. faster_eth_utils/exceptions.py +8 -3
  24. faster_eth_utils/functional.cp311-win32.pyd +0 -0
  25. faster_eth_utils/functional.py +41 -25
  26. faster_eth_utils/hexadecimal.cp311-win32.pyd +0 -0
  27. faster_eth_utils/hexadecimal.py +36 -24
  28. faster_eth_utils/humanize.cp311-win32.pyd +0 -0
  29. faster_eth_utils/humanize.py +46 -18
  30. faster_eth_utils/logging.py +43 -48
  31. faster_eth_utils/module_loading.cp311-win32.pyd +0 -0
  32. faster_eth_utils/module_loading.py +8 -7
  33. faster_eth_utils/network.cp311-win32.pyd +0 -0
  34. faster_eth_utils/network.py +25 -13
  35. faster_eth_utils/numeric.cp311-win32.pyd +0 -0
  36. faster_eth_utils/numeric.py +11 -4
  37. faster_eth_utils/pydantic.py +101 -0
  38. faster_eth_utils/toolz.cp311-win32.pyd +0 -0
  39. faster_eth_utils/toolz.py +82 -152
  40. faster_eth_utils/types.cp311-win32.pyd +0 -0
  41. faster_eth_utils/types.py +37 -21
  42. faster_eth_utils/typing/misc.py +3 -1
  43. faster_eth_utils/units.cp311-win32.pyd +0 -0
  44. faster_eth_utils-5.3.19.dist-info/METADATA +193 -0
  45. faster_eth_utils-5.3.19.dist-info/RECORD +53 -0
  46. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/licenses/LICENSE +1 -1
  47. faster_eth_utils-5.3.19.dist-info/top_level.txt +3 -0
  48. faster_eth_utils__mypyc.cp311-win32.pyd +0 -0
  49. bce0bfc64ce5e845ec4a__mypyc.cp311-win32.pyd +0 -0
  50. faster_eth_utils-2.3.1.dist-info/METADATA +0 -160
  51. faster_eth_utils-2.3.1.dist-info/RECORD +0 -45
  52. faster_eth_utils-2.3.1.dist-info/top_level.txt +0 -3
  53. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/WHEEL +0 -0
Binary file
@@ -1,17 +1,51 @@
1
1
  import re
2
- from typing import Any, Final, Union, cast
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
- from eth_typing import Address, AnyAddress, ChecksumAddress, HexAddress, HexStr
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
- _HEX_ADDRESS_REGEXP: Final = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
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) -> bool:
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) -> bool:
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 {!r}, attempted to normalize to {!r}".format(
65
- value, hex_address
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) -> bool:
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
- if not is_address(value):
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) -> bool:
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
- 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)
114
+ return is_binary_address(address) and address == to_canonical_address(address)
115
+ 8
96
116
 
97
-
98
- def is_same_address(left: AnyAddress, right: AnyAddress) -> bool:
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 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
-
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
- is_equal = value == to_checksum_address(value)
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:
@@ -1,30 +1,70 @@
1
- from typing import Any, Callable, Dict, Generator, List, Tuple
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 .decorators import return_arg_type
5
- from .functional import to_dict
6
- from .toolz import compose, curry
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[..., Any], at_index: int, value: List[Any]
14
- ) -> Generator[List[Any], None, None]:
15
- if at_index + 1 > len(value):
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. 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
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: List[Callable[..., Any]]) -> 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: List[Any]
50
- ) -> Generator[List[Any], None, None]:
51
- if len(formatters) > len(sequence):
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 {!r}".format(
54
- len(formatters), sequence
55
- )
99
+ f"Too many formatters for sequence: {num_formatters} formatters for "
100
+ f"{sequence!r}"
56
101
  )
57
- elif len(formatters) < len(sequence):
102
+ else:
58
103
  raise IndexError(
59
- "Too few formatters for sequence: {} formatters for {!r}".format(
60
- len(formatters), sequence
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[..., bool], formatter: Callable[..., Any], value: Any
70
- ) -> Any:
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], 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
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[..., Any], value: List[Any]
103
- ) -> Generator[List[Any], None, None]:
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[Tuple[Callable[..., Any], Callable[..., Any]]],
110
- value: Any,
111
- ) -> Any:
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: Dict[Any, Any]
124
- ) -> Generator[Tuple[Any, Any], None, None]:
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): {}".format(
133
- key_conflicts
134
- )
203
+ f"Could not apply key map due to conflicting key(s): {key_conflicts}"
135
204
  )
136
205
 
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
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()}
@@ -1,8 +1,19 @@
1
- from typing import Callable, TypeVar, Union
1
+ from typing import (
2
+ Callable,
3
+ Optional,
4
+ TypeVar,
5
+ Union,
6
+ )
2
7
 
3
- from eth_typing import HexStr, Primitives
8
+ from eth_typing import (
9
+ HexStr,
10
+ Primitives,
11
+ )
4
12
 
5
- from .encoding import big_endian_to_int, int_to_big_endian
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 is_boolean, is_integer, is_string
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: Primitives = None, hexstr: HexStr = None, text: str = None
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 is_boolean(primitive):
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 is_integer(primitive):
64
+ if isinstance(primitive, int):
44
65
  return HexStr(hex(primitive))
45
66
 
46
67
  raise TypeError(
47
- "Unsupported type: '{0}'. Must be one of: bool, str, bytes, bytearray"
48
- "or int.".format(repr(type(primitive)))
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: Primitives = None, hexstr: HexStr = None, text: str = None
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, bytearrays: big-endian integer
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. Expected one of int/bool/str/bytes/bytearray. Got "
79
- "{0}".format(type(primitive))
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: Primitives = None, hexstr: HexStr = None, text: str = None
110
+ primitive: Optional[BytesLike] = None,
111
+ hexstr: Optional[HexStr] = None,
112
+ text: Optional[str] = None,
85
113
  ) -> bytes:
86
- if is_boolean(primitive):
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 is_integer(primitive):
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
- # type check ignored here because casting an
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: Primitives = None, hexstr: HexStr = None, text: str = None
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 is_integer(primitive):
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. Got: {0!r}".format(
157
- hexstr_or_primitive
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
@@ -1,11 +1,21 @@
1
- from typing import Union
1
+ from typing import (
2
+ Optional,
3
+ Union,
4
+ )
2
5
 
3
- from eth_hash.auto import keccak as keccak_256
6
+ from eth_hash.auto import (
7
+ keccak as keccak_256,
8
+ )
9
+ from eth_typing import HexStr
4
10
 
5
- from .conversions import to_bytes
11
+ from .conversions import (
12
+ to_bytes,
13
+ )
6
14
 
7
15
 
8
16
  def keccak(
9
- primitive: Union[bytes, int, bool] = None, hexstr: str = None, text: str = 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