faster-eth-utils 4.1.7__cp314-cp314t-win_amd64.whl → 5.3.22__cp314-cp314t-win_amd64.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 (46) hide show
  1. faster_eth_utils/__init__.py +19 -1
  2. faster_eth_utils/abi.cp314t-win_amd64.pyd +0 -0
  3. faster_eth_utils/abi.py +834 -34
  4. faster_eth_utils/address.cp314t-win_amd64.pyd +0 -0
  5. faster_eth_utils/address.py +19 -43
  6. faster_eth_utils/applicators.cp314t-win_amd64.pyd +0 -0
  7. faster_eth_utils/applicators.py +109 -64
  8. faster_eth_utils/conversions.cp314t-win_amd64.pyd +0 -0
  9. faster_eth_utils/conversions.py +36 -29
  10. faster_eth_utils/crypto.cp314t-win_amd64.pyd +0 -0
  11. faster_eth_utils/crypto.py +3 -8
  12. faster_eth_utils/currency.cp314t-win_amd64.pyd +0 -0
  13. faster_eth_utils/currency.py +55 -21
  14. faster_eth_utils/curried/__init__.py +91 -67
  15. faster_eth_utils/debug.cp314t-win_amd64.pyd +0 -0
  16. faster_eth_utils/decorators.cp314t-win_amd64.pyd +0 -0
  17. faster_eth_utils/decorators.py +65 -29
  18. faster_eth_utils/encoding.cp314t-win_amd64.pyd +0 -0
  19. faster_eth_utils/encoding.py +1 -1
  20. faster_eth_utils/exceptions.cp314t-win_amd64.pyd +0 -0
  21. faster_eth_utils/exceptions.py +8 -1
  22. faster_eth_utils/functional.cp314t-win_amd64.pyd +0 -0
  23. faster_eth_utils/functional.py +10 -12
  24. faster_eth_utils/hexadecimal.cp314t-win_amd64.pyd +0 -0
  25. faster_eth_utils/hexadecimal.py +19 -16
  26. faster_eth_utils/humanize.cp314t-win_amd64.pyd +0 -0
  27. faster_eth_utils/humanize.py +35 -23
  28. faster_eth_utils/logging.py +54 -61
  29. faster_eth_utils/module_loading.cp314t-win_amd64.pyd +0 -0
  30. faster_eth_utils/network.cp314t-win_amd64.pyd +0 -0
  31. faster_eth_utils/network.py +2 -3
  32. faster_eth_utils/numeric.cp314t-win_amd64.pyd +0 -0
  33. faster_eth_utils/pydantic.py +103 -0
  34. faster_eth_utils/toolz.cp314t-win_amd64.pyd +0 -0
  35. faster_eth_utils/types.cp314t-win_amd64.pyd +0 -0
  36. faster_eth_utils/types.py +20 -17
  37. faster_eth_utils/units.cp314t-win_amd64.pyd +0 -0
  38. {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/METADATA +59 -17
  39. faster_eth_utils-5.3.22.dist-info/RECORD +53 -0
  40. {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/licenses/LICENSE +1 -1
  41. faster_eth_utils-5.3.22.dist-info/top_level.txt +3 -0
  42. faster_eth_utils__mypyc.cp314t-win_amd64.pyd +0 -0
  43. 99c07adba6ff961eaf3e__mypyc.cp314t-win_amd64.pyd +0 -0
  44. faster_eth_utils-4.1.7.dist-info/RECORD +0 -52
  45. faster_eth_utils-4.1.7.dist-info/top_level.txt +0 -3
  46. {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/WHEEL +0 -0
@@ -1,10 +1,10 @@
1
+ from collections.abc import (
2
+ Iterable,
3
+ Iterator,
4
+ )
1
5
  from typing import (
2
6
  Any,
3
7
  Final,
4
- Iterable,
5
- Iterator,
6
- Tuple,
7
- Union,
8
8
  )
9
9
  from urllib import (
10
10
  parse,
@@ -20,19 +20,17 @@ from faster_eth_utils.currency import (
20
20
  from_wei,
21
21
  )
22
22
 
23
- from .toolz import (
24
- sliding_window,
25
- take,
26
- )
23
+ from . import toolz
27
24
 
28
25
 
29
- def humanize_seconds(seconds: Union[float, int]) -> str:
30
- if int(seconds) == 0:
26
+ def humanize_seconds(seconds: float | int) -> str:
27
+ seconds_int = int(seconds)
28
+ if seconds_int == 0:
31
29
  return "0s"
32
30
 
33
- unit_values = _consume_leading_zero_units(_humanize_seconds(int(seconds)))
31
+ unit_values = _consume_leading_zero_units(_humanize_seconds(seconds_int))
34
32
 
35
- return "".join((f"{amount}{unit}" for amount, unit in take(3, unit_values)))
33
+ return "".join(f"{amount}{unit}" for amount, unit in toolz.take(3, unit_values))
36
34
 
37
35
 
38
36
  SECOND: Final = 1
@@ -56,8 +54,8 @@ UNITS: Final = (
56
54
 
57
55
 
58
56
  def _consume_leading_zero_units(
59
- units_iter: Iterator[Tuple[int, str]]
60
- ) -> Iterator[Tuple[int, str]]:
57
+ units_iter: Iterator[tuple[int, str]]
58
+ ) -> Iterator[tuple[int, str]]:
61
59
  for amount, unit in units_iter:
62
60
  if amount == 0:
63
61
  continue
@@ -68,7 +66,7 @@ def _consume_leading_zero_units(
68
66
  yield from units_iter
69
67
 
70
68
 
71
- def _humanize_seconds(seconds: int) -> Iterator[Tuple[int, str]]:
69
+ def _humanize_seconds(seconds: int) -> Iterator[tuple[int, str]]:
72
70
  remainder = seconds
73
71
 
74
72
  for duration, unit in UNITS:
@@ -93,6 +91,21 @@ def humanize_bytes(value: bytes) -> str:
93
91
  return f"{head}..{tail}"
94
92
 
95
93
 
94
+ def humanize_hexstr(value: str) -> str:
95
+ tail = value[-1 * DISPLAY_HASH_CHARS :]
96
+
97
+ if value[:2] == "0x":
98
+ if len(value[2:]) <= DISPLAY_HASH_CHARS * 2:
99
+ return value
100
+ head = value[2 : DISPLAY_HASH_CHARS + 2]
101
+ return f"0x{head}..{tail}"
102
+ else:
103
+ if len(value) <= DISPLAY_HASH_CHARS * 2:
104
+ return value
105
+ head = value[:DISPLAY_HASH_CHARS]
106
+ return f"{head}..{tail}"
107
+
108
+
96
109
  def humanize_hash(value: Hash32) -> str:
97
110
  return humanize_bytes(value)
98
111
 
@@ -128,9 +141,9 @@ def _is_CIDv0_ipfs_hash(ipfs_hash: str) -> bool:
128
141
  return False
129
142
 
130
143
 
131
- def _find_breakpoints(*values: int) -> Iterator[int]:
144
+ def _find_breakpoints(values: tuple[int, ...]) -> Iterator[int]:
132
145
  yield 0
133
- for index, (left, right) in enumerate(sliding_window(2, values), 1):
146
+ for index, (left, right) in enumerate(toolz.sliding_window(2, values), 1):
134
147
  if left + 1 == right:
135
148
  continue
136
149
  else:
@@ -138,7 +151,7 @@ def _find_breakpoints(*values: int) -> Iterator[int]:
138
151
  yield len(values)
139
152
 
140
153
 
141
- def _extract_integer_ranges(*values: int) -> Iterator[Tuple[int, int]]:
154
+ def _extract_integer_ranges(values: tuple[int, ...]) -> Iterator[tuple[int, int]]:
142
155
  """
143
156
  Return a tuple of consecutive ranges of integers.
144
157
 
@@ -148,12 +161,12 @@ def _extract_integer_ranges(*values: int) -> Iterator[Tuple[int, int]]:
148
161
  - fn(1, 2, 3, 7, 8, 9) -> ((1, 3), (7, 9))
149
162
  - fn(1, 7, 8, 9) -> ((1, 1), (7, 9))
150
163
  """
151
- for left, right in sliding_window(2, _find_breakpoints(*values)):
164
+ for left, right in toolz.sliding_window(2, _find_breakpoints(values)):
152
165
  chunk = values[left:right]
153
166
  yield chunk[0], chunk[-1]
154
167
 
155
168
 
156
- def _humanize_range(bounds: Tuple[int, int]) -> str:
169
+ def _humanize_range(bounds: tuple[int, int]) -> str:
157
170
  left, right = bounds
158
171
  if left == right:
159
172
  return str(left)
@@ -174,7 +187,7 @@ def humanize_integer_sequence(values_iter: Iterable[int]) -> str:
174
187
  if not values:
175
188
  return "(empty)"
176
189
  else:
177
- return "|".join(map(_humanize_range, _extract_integer_ranges(*values)))
190
+ return "|".join(_humanize_range(range) for range in _extract_integer_ranges(values))
178
191
 
179
192
 
180
193
  def humanize_wei(number: int) -> str:
@@ -185,5 +198,4 @@ def humanize_wei(number: int) -> str:
185
198
  else:
186
199
  unit = "wei"
187
200
  amount = from_wei(number, unit)
188
- x = f"{str(amount)} {unit}"
189
- return x
201
+ return f"{str(amount)} {unit}"
@@ -1,17 +1,19 @@
1
- import contextlib
1
+ import logging
2
+ from collections.abc import (
3
+ Iterator,
4
+ )
5
+ from contextlib import (
6
+ contextmanager,
7
+ )
2
8
  from functools import (
3
9
  cached_property,
4
10
  )
5
- import logging
6
11
  from typing import (
7
12
  Any,
8
- Dict,
9
- Iterator,
10
- Tuple,
11
- Type,
13
+ Final,
12
14
  TypeVar,
13
- Union,
14
15
  cast,
16
+ overload,
15
17
  )
16
18
 
17
19
  from .toolz import (
@@ -22,6 +24,11 @@ DEBUG2_LEVEL_NUM = 8
22
24
 
23
25
  TLogger = TypeVar("TLogger", bound=logging.Logger)
24
26
 
27
+ Logger: Final = logging.Logger
28
+ getLogger: Final = logging.getLogger
29
+ getLoggerClass: Final = logging.getLoggerClass
30
+ setLoggerClass: Final = logging.setLoggerClass
31
+
25
32
 
26
33
  class ExtendedDebugLogger(logging.Logger):
27
34
  """
@@ -41,7 +48,7 @@ class ExtendedDebugLogger(logging.Logger):
41
48
  # lambda to further speed up
42
49
  self.__dict__["debug2"] = lambda message, *args, **kwargs: None
43
50
 
44
- def __reduce__(self) -> Tuple[Any, ...]:
51
+ def __reduce__(self) -> tuple[Any, ...]:
45
52
  # This is needed because our parent's implementation could
46
53
  # cause us to become a regular Logger on unpickling.
47
54
  return get_extended_debug_logger, (self.name,)
@@ -53,37 +60,38 @@ def setup_DEBUG2_logging() -> None:
53
60
  """
54
61
  if not hasattr(logging, "DEBUG2"):
55
62
  logging.addLevelName(DEBUG2_LEVEL_NUM, "DEBUG2")
56
- logging.DEBUG2 = DEBUG2_LEVEL_NUM # type: ignore
63
+ logging.DEBUG2 = DEBUG2_LEVEL_NUM # type: ignore [attr-defined]
57
64
 
58
-
59
- @contextlib.contextmanager
60
- def _use_logger_class(logger_class: Type[logging.Logger]) -> Iterator[None]:
61
- original_logger_class = logging.getLoggerClass()
62
- logging.setLoggerClass(logger_class)
65
+ @contextmanager
66
+ def _use_logger_class(logger_class: type[logging.Logger]) -> Iterator[None]:
67
+ original_logger_class = getLoggerClass()
68
+ setLoggerClass(logger_class)
63
69
  try:
64
70
  yield
65
71
  finally:
66
- logging.setLoggerClass(original_logger_class)
72
+ setLoggerClass(original_logger_class)
67
73
 
68
74
 
69
- def get_logger(name: str, logger_class: Union[Type[TLogger], None] = None) -> TLogger:
75
+ @overload
76
+ def get_logger(name: str, logger_class: type[TLogger]) -> TLogger: ...
77
+ @overload
78
+ def get_logger(name: str, logger_class: None = None) -> logging.Logger: ...
79
+ def get_logger(name: str, logger_class: type[TLogger] | None = None) -> TLogger | logging.Logger:
70
80
  if logger_class is None:
71
- return cast(TLogger, logging.getLogger(name))
72
- else:
73
- with _use_logger_class(logger_class):
74
- # The logging module caches logger instances. The following code
75
- # ensures that if there is a cached instance that we don't
76
- # accidentally return the incorrect logger type because the logging
77
- # module does not *update* the cached instance in the event that
78
- # the global logging class changes.
79
- #
80
- # types ignored b/c mypy doesn't identify presence of
81
- # manager on logging.Logger
82
- manager = logging.Logger.manager
83
- if name in manager.loggerDict:
84
- if type(manager.loggerDict[name]) is not logger_class:
85
- del manager.loggerDict[name]
86
- return cast(TLogger, logging.getLogger(name))
81
+ return getLogger(name)
82
+
83
+ with _use_logger_class(logger_class):
84
+ # The logging module caches logger instances. The following code
85
+ # ensures that if there is a cached instance that we don't
86
+ # accidentally return the incorrect logger type because the logging
87
+ # module does not *update* the cached instance in the event that
88
+ # the global logging class changes.
89
+ manager = Logger.manager
90
+ logger_dict = manager.loggerDict
91
+ cached_logger = logger_dict.get(name)
92
+ if cached_logger is not None and type(cached_logger) is not logger_class:
93
+ del logger_dict[name]
94
+ return cast(TLogger, getLogger(name))
87
95
 
88
96
 
89
97
  def get_extended_debug_logger(name: str) -> ExtendedDebugLogger:
@@ -101,13 +109,13 @@ class HasLoggerMeta(type):
101
109
  to use when creating the associated logger for a given class.
102
110
  """
103
111
 
104
- logger_class = logging.Logger
112
+ logger_class = Logger
105
113
 
106
114
  def __new__(
107
- mcls: Type[THasLoggerMeta],
115
+ mcls: type[THasLoggerMeta],
108
116
  name: str,
109
- bases: Tuple[Type[Any]],
110
- namespace: Dict[str, Any],
117
+ bases: tuple[type[Any]],
118
+ namespace: dict[str, Any],
111
119
  ) -> THasLoggerMeta:
112
120
  if "logger" in namespace:
113
121
  # If a logger was explicitly declared we shouldn't do anything to
@@ -115,45 +123,30 @@ class HasLoggerMeta(type):
115
123
  return super().__new__(mcls, name, bases, namespace)
116
124
  if "__qualname__" not in namespace:
117
125
  raise AttributeError("Missing __qualname__")
118
-
119
- with _use_logger_class(mcls.logger_class):
120
- logger = logging.getLogger(namespace["__qualname__"])
126
+
127
+ logger = get_logger(namespace["__qualname__"], mcls.logger_class)
121
128
 
122
129
  return super().__new__(mcls, name, bases, assoc(namespace, "logger", logger))
123
130
 
124
131
  @classmethod
125
132
  def replace_logger_class(
126
- mcls: Type[THasLoggerMeta], value: Type[logging.Logger]
127
- ) -> Type[THasLoggerMeta]:
133
+ mcls: type[THasLoggerMeta], value: type[logging.Logger]
134
+ ) -> type[THasLoggerMeta]:
128
135
  return type(mcls.__name__, (mcls,), {"logger_class": value})
129
136
 
130
137
  @classmethod
131
138
  def meta_compat(
132
- mcls: Type[THasLoggerMeta], other: Type[type]
133
- ) -> Type[THasLoggerMeta]:
139
+ mcls: type[THasLoggerMeta], other: type[type]
140
+ ) -> type[THasLoggerMeta]:
134
141
  return type(mcls.__name__, (mcls, other), {})
135
142
 
136
143
 
137
- class _BaseHasLogger(metaclass=HasLoggerMeta):
138
- # This class exists to a allow us to define the type of the logger. Once
139
- # python3.5 is deprecated this can be removed in favor of a simple type
140
- # annotation on the main class.
141
- logger = logging.Logger("") # type: logging.Logger
142
-
143
-
144
- class HasLogger(_BaseHasLogger):
145
- pass
144
+ class HasLogger(metaclass=HasLoggerMeta):
145
+ logger: logging.Logger
146
146
 
147
147
 
148
148
  HasExtendedDebugLoggerMeta = HasLoggerMeta.replace_logger_class(ExtendedDebugLogger)
149
149
 
150
150
 
151
- class _BaseHasExtendedDebugLogger(metaclass=HasExtendedDebugLoggerMeta): # type: ignore
152
- # This class exists to a allow us to define the type of the logger. Once
153
- # python3.5 is deprecated this can be removed in favor of a simple type
154
- # annotation on the main class.
155
- logger = ExtendedDebugLogger("") # type: ExtendedDebugLogger
156
-
157
-
158
- class HasExtendedDebugLogger(_BaseHasExtendedDebugLogger):
159
- pass
151
+ class HasExtendedDebugLogger(metaclass=HasExtendedDebugLoggerMeta): # type: ignore[metaclass]
152
+ logger: ExtendedDebugLogger
@@ -9,14 +9,13 @@ from pathlib import (
9
9
  )
10
10
  from typing import (
11
11
  Final,
12
- List,
13
12
  )
14
13
 
15
14
  from eth_typing import (
16
15
  ChainId,
17
16
  )
18
17
 
19
- from faster_eth_utils import (
18
+ from faster_eth_utils.exceptions import (
20
19
  ValidationError,
21
20
  )
22
21
 
@@ -32,7 +31,7 @@ class Network:
32
31
  symbol: ChainId
33
32
 
34
33
 
35
- def initialize_network_objects() -> List[Network]:
34
+ def initialize_network_objects() -> list[Network]:
36
35
  networks_obj = []
37
36
 
38
37
  networks_json_path = os.path.abspath(
@@ -0,0 +1,103 @@
1
+ from typing import (
2
+ Any,
3
+ cast,
4
+ )
5
+
6
+ from pydantic import (
7
+ BaseModel,
8
+ ConfigDict,
9
+ )
10
+ from pydantic._internal._core_utils import (
11
+ CoreSchemaField,
12
+ )
13
+ from pydantic.alias_generators import (
14
+ to_camel,
15
+ )
16
+ from pydantic.json_schema import (
17
+ DEFAULT_REF_TEMPLATE,
18
+ GenerateJsonSchema,
19
+ JsonSchemaMode,
20
+ )
21
+
22
+
23
+ class OmitJsonSchema(GenerateJsonSchema): # type: ignore[misc]
24
+ """
25
+ Custom JSON schema generator that omits the schema generation for fields that are
26
+ invalid. Excluded fields (``Field(exclude=True)``) are generally useful as
27
+ properties of the model but are not meant to be serialized to JSON.
28
+ """
29
+
30
+ def field_is_present(self, field: CoreSchemaField) -> bool:
31
+ # override ``field_is_present`` and omit excluded fields from the schema
32
+ if field.get("serialization_exclude", False):
33
+ return False
34
+ return cast(bool, super().field_is_present(field))
35
+
36
+
37
+ class CamelModel(BaseModel): # type: ignore[misc]
38
+ """
39
+ Camel-case pydantic model. This model is used to ensure serialization in a
40
+ consistent manner, aliasing as camelCase serialization. This is useful for models
41
+ that are used in JSON-RPC requests and responses, marking useful fields for the
42
+ model, but that are not part of the JSON-RPC object, with ``Field(exclude=True)``.
43
+ To serialize a model to the expected JSON-RPC format, or camelCase, use
44
+ ``model_dump(by_alias=True)``.
45
+
46
+ .. code-block:: python
47
+
48
+ >>> from eth_utils.pydantic import CamelModel
49
+ >>> from pydantic import Field
50
+
51
+ >>> class SignedSetCodeAuthorization(CamelModel):
52
+ ... chain_id: int
53
+ ... address: bytes
54
+ ... nonce: int
55
+ ...
56
+ ... # useful fields for the object but excluded from serialization
57
+ ... # (not part of the JSON-RPC object)
58
+ ... authorization_hash: bytes = Field(exclude=True)
59
+ ... signature: bytes = Field(exclude=True)
60
+
61
+ >>> auth = SignedSetCodeAuthorization(
62
+ ... chain_id=1,
63
+ ... address=b"0x0000000000000000000000000000000000000000",
64
+ ... nonce=0,
65
+ ... authorization_hash=generated_hash,
66
+ ... signature=generated_signature,
67
+ ... )
68
+ >>> auth.model_dump(by_alias=True)
69
+ {'chainId': 1, 'address': '0x000000000000000000000000000000000000', 'nonce': 0}
70
+ """
71
+
72
+ model_config = ConfigDict(
73
+ arbitrary_types_allowed=True,
74
+ # populate by snake_case (python) args
75
+ populate_by_name=True,
76
+ # serialize by camelCase (json-rpc) keys
77
+ alias_generator=to_camel,
78
+ # validate default values
79
+ validate_default=True,
80
+ )
81
+
82
+ @classmethod
83
+ def model_json_schema( # type: ignore [override]
84
+ cls,
85
+ by_alias: bool = True,
86
+ ref_template: str = DEFAULT_REF_TEMPLATE,
87
+ # default to ``OmitJsonSchema`` to prevent errors from excluded fields
88
+ schema_generator: type[GenerateJsonSchema] = OmitJsonSchema,
89
+ mode: JsonSchemaMode = "validation",
90
+ ) -> dict[str, Any]:
91
+ """
92
+ Omits excluded fields from the JSON schema, preventing errors that would
93
+ otherwise be raised by the default schema generator.
94
+ """
95
+ return cast(
96
+ dict[str, Any],
97
+ super().model_json_schema(
98
+ by_alias=by_alias,
99
+ ref_template=ref_template,
100
+ schema_generator=schema_generator,
101
+ mode=mode,
102
+ ),
103
+ )
Binary file
Binary file
faster_eth_utils/types.py CHANGED
@@ -2,35 +2,38 @@ import collections.abc
2
2
  import numbers
3
3
  from typing import (
4
4
  Any,
5
- List,
5
+ Final,
6
6
  Literal,
7
- Tuple,
8
- Union,
9
7
  )
10
8
 
11
- from typing_extensions import (
9
+ from typing import (
12
10
  TypeGuard,
13
11
  )
14
12
 
15
- bytes_types = (bytes, bytearray)
16
- integer_types = (int,)
17
- text_types = (str,)
18
- string_types = (bytes, str, bytearray)
13
+ Mapping: Final = collections.abc.Mapping
14
+ Sequence: Final = collections.abc.Sequence
15
+
16
+ Number: Final = numbers.Number
17
+
18
+ bytes_types: Final = (bytes, bytearray)
19
+ integer_types: Final = (int,)
20
+ text_types: Final = (str,)
21
+ string_types: Final = (bytes, str, bytearray)
19
22
 
20
23
 
21
24
  def is_integer(value: Any) -> TypeGuard[int]:
22
- return isinstance(value, integer_types) and not isinstance(value, bool)
25
+ return isinstance(value, int) and not isinstance(value, bool)
23
26
 
24
27
 
25
- def is_bytes(value: Any) -> TypeGuard[Union[bytes, bytearray]]:
28
+ def is_bytes(value: Any) -> TypeGuard[bytes | bytearray]:
26
29
  return isinstance(value, bytes_types)
27
30
 
28
31
 
29
32
  def is_text(value: Any) -> TypeGuard[str]:
30
- return isinstance(value, text_types)
33
+ return isinstance(value, str)
31
34
 
32
35
 
33
- def is_string(value: Any) -> TypeGuard[Union[bytes, str, bytearray]]:
36
+ def is_string(value: Any) -> TypeGuard[bytes | str | bytearray]:
34
37
  return isinstance(value, string_types)
35
38
 
36
39
 
@@ -39,18 +42,18 @@ def is_boolean(value: Any) -> TypeGuard[bool]:
39
42
 
40
43
 
41
44
  def is_dict(obj: Any) -> TypeGuard[collections.abc.Mapping[Any, Any]]:
42
- return isinstance(obj, collections.abc.Mapping)
45
+ return isinstance(obj, dict) or isinstance(obj, Mapping)
43
46
 
44
47
 
45
48
  def is_list_like(obj: Any) -> TypeGuard[collections.abc.Sequence[Any]]:
46
- return not is_string(obj) and isinstance(obj, collections.abc.Sequence)
49
+ return isinstance(obj, (list, tuple)) or not is_string(obj) and isinstance(obj, Sequence)
47
50
 
48
51
 
49
- def is_list(obj: Any) -> TypeGuard[List[Any]]:
52
+ def is_list(obj: Any) -> TypeGuard[list[Any]]:
50
53
  return isinstance(obj, list)
51
54
 
52
55
 
53
- def is_tuple(obj: Any) -> TypeGuard[Tuple[Any, ...]]:
56
+ def is_tuple(obj: Any) -> TypeGuard[tuple[Any, ...]]:
54
57
  return isinstance(obj, tuple)
55
58
 
56
59
 
@@ -59,4 +62,4 @@ def is_null(obj: Any) -> TypeGuard[Literal[None]]:
59
62
 
60
63
 
61
64
  def is_number(obj: Any) -> TypeGuard[numbers.Number]:
62
- return isinstance(obj, numbers.Number)
65
+ return isinstance(obj, Number)
Binary file
@@ -1,34 +1,45 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: faster-eth-utils
3
- Version: 4.1.7
4
- Summary: A fork of eth-utils: Common utility functions for python code that interacts with Ethereum, implemented in C
5
- Home-page: https://github.com/BobTheBuidler/eth-utils
3
+ Version: 5.3.22
4
+ Summary: A faster fork of eth-utils: Common utility functions for python code that interacts with Ethereum. Implemented in C
5
+ Home-page: https://github.com/BobTheBuidler/faster-eth-utils
6
6
  Author: The Ethereum Foundation
7
7
  Author-email: snakecharmers@ethereum.org
8
8
  License: MIT
9
+ Project-URL: Documentation, https://eth-utils.readthedocs.io/en/stable/
10
+ Project-URL: Release Notes, https://github.com/BobTheBuidler/faster-eth-utils/releases
11
+ Project-URL: Issues, https://github.com/BobTheBuidler/faster-eth-utils/issues
12
+ Project-URL: Source - Precompiled (.py), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/faster_eth_utils
13
+ Project-URL: Source - Compiled (.c), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/build
14
+ Project-URL: Benchmarks, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks
15
+ Project-URL: Benchmarks - Results, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks/results
16
+ Project-URL: Original, https://github.com/ethereum/eth-utils
9
17
  Keywords: ethereum
10
18
  Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
19
  Classifier: Natural Language :: English
13
20
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
21
  Classifier: Programming Language :: Python :: 3.10
17
22
  Classifier: Programming Language :: Python :: 3.11
18
23
  Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
19
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
- Requires-Python: >=3.8, <4
27
+ Requires-Python: >=3.10, <4
21
28
  Description-Content-Type: text/markdown
22
29
  License-File: LICENSE
30
+ Requires-Dist: cchecksum==0.3.9
23
31
  Requires-Dist: eth-hash>=0.3.1
24
- Requires-Dist: eth-typing>=3.0.0
32
+ Requires-Dist: eth-typing==5.2.1
33
+ Requires-Dist: eth-utils==5.3.1
25
34
  Requires-Dist: toolz>0.8.2; implementation_name == "pypy"
26
35
  Requires-Dist: cytoolz>=0.10.1; implementation_name == "cpython"
36
+ Requires-Dist: pydantic<3,>=2.0.0
27
37
  Provides-Extra: dev
28
38
  Requires-Dist: build>=0.9.0; extra == "dev"
29
- Requires-Dist: bumpversion>=0.5.3; extra == "dev"
39
+ Requires-Dist: bump_my_version>=0.19.0; extra == "dev"
30
40
  Requires-Dist: eth-hash[pycryptodome]; extra == "dev"
31
41
  Requires-Dist: ipython; extra == "dev"
42
+ Requires-Dist: mypy[mypyc]<1.20,>=1.14.1; extra == "dev"
32
43
  Requires-Dist: pre-commit>=3.4.0; extra == "dev"
33
44
  Requires-Dist: tox>=4.0.0; extra == "dev"
34
45
  Requires-Dist: twine; extra == "dev"
@@ -36,21 +47,31 @@ Requires-Dist: wheel; extra == "dev"
36
47
  Requires-Dist: sphinx>=6.0.0; extra == "dev"
37
48
  Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "dev"
38
49
  Requires-Dist: sphinx_rtd_theme>=1.0.0; extra == "dev"
39
- Requires-Dist: towncrier<22,>=21; extra == "dev"
50
+ Requires-Dist: towncrier<26,>=24; extra == "dev"
40
51
  Requires-Dist: hypothesis>=4.43.0; extra == "dev"
41
- Requires-Dist: mypy==1.5.1; extra == "dev"
42
- Requires-Dist: pytest>=7.0.0; extra == "dev"
52
+ Requires-Dist: mypy[mypyc]<1.20,>=1.14.1; extra == "dev"
43
53
  Requires-Dist: pytest-xdist>=2.4.0; extra == "dev"
54
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
44
55
  Provides-Extra: docs
45
56
  Requires-Dist: sphinx>=6.0.0; extra == "docs"
46
57
  Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "docs"
47
58
  Requires-Dist: sphinx_rtd_theme>=1.0.0; extra == "docs"
48
- Requires-Dist: towncrier<22,>=21; extra == "docs"
59
+ Requires-Dist: towncrier<26,>=24; extra == "docs"
49
60
  Provides-Extra: test
50
61
  Requires-Dist: hypothesis>=4.43.0; extra == "test"
51
- Requires-Dist: mypy==1.5.1; extra == "test"
52
- Requires-Dist: pytest>=7.0.0; extra == "test"
62
+ Requires-Dist: mypy[mypyc]<1.20,>=1.14.1; extra == "test"
53
63
  Requires-Dist: pytest-xdist>=2.4.0; extra == "test"
64
+ Requires-Dist: pytest>=7.0.0; extra == "test"
65
+ Provides-Extra: codspeed
66
+ Requires-Dist: pytest-codspeed<4.3,>=4.2; extra == "codspeed"
67
+ Requires-Dist: pytest-test-groups; extra == "codspeed"
68
+ Requires-Dist: pytest>=7.0.0; extra == "codspeed"
69
+ Provides-Extra: benchmark
70
+ Requires-Dist: eth-utils==5.3.1; extra == "benchmark"
71
+ Requires-Dist: pytest-benchmark<5.3,>=5.2; extra == "benchmark"
72
+ Requires-Dist: pytest-codspeed<4.3,>=4.2; extra == "benchmark"
73
+ Requires-Dist: pytest-test-groups; extra == "benchmark"
74
+ Requires-Dist: pytest>=7.0.0; extra == "benchmark"
54
75
  Dynamic: author
55
76
  Dynamic: author-email
56
77
  Dynamic: classifier
@@ -60,11 +81,30 @@ Dynamic: home-page
60
81
  Dynamic: keywords
61
82
  Dynamic: license
62
83
  Dynamic: license-file
84
+ Dynamic: project-url
63
85
  Dynamic: provides-extra
64
86
  Dynamic: requires-dist
65
87
  Dynamic: requires-python
66
88
  Dynamic: summary
67
89
 
90
+ ### I forked eth-utils and compiled it to C. It does the same stuff, now faster
91
+
92
+ [![PyPI](https://img.shields.io/pypi/v/faster-eth-utils.svg?logo=Python&logoColor=white)](https://pypi.org/project/faster-eth-utils)
93
+ [![Monthly Downloads](https://img.shields.io/pypi/dm/faster-eth-utils)](https://pypistats.org/packages/faster-eth-utils)
94
+ [![Codspeed.io Status](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/BobTheBuidler/faster-eth-utils)
95
+
96
+ ##### This fork will be kept up-to-date with [eth-utils](https://github.com/ethereum/eth-utils). I will pull updates as they are released and push new [faster-eth-utils](https://github.com/BobTheBuidler/faster-eth-utils) releases to [PyPI](https://pypi.org/project/faster-eth-utils/).
97
+
98
+ ##### Starting in [v5.3.11](https://github.com/BobTheBuidler/faster-eth-utils/releases/tag/v5.3.11), all `faster-eth-utils` Exception classes inherit from the matching Exception class in `eth-utils`, so porting to `faster-eth-utils` does not require any change to your existing exception handlers. All existing exception handling in your codebase will continue to work as it did when originaly implemented.
99
+
100
+ ##### We benchmark `faster-eth-utils` against the original `eth-utils` for your convenience. [See results](https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks/results).
101
+
102
+ ##### You can find the compiled C code and header files in the [build](https://github.com/BobTheBuidler/eth-utils/tree/master/build) directory.
103
+
104
+ ###### You may also be interested in: [faster-web3.py](https://github.com/BobTheBuidler/faster-web3.py/), [faster-eth-abi](https://github.com/BobTheBuidler/faster-eth-abi/), and [faster-hexbytes](https://github.com/BobTheBuidler/faster-hexbytes/)
105
+
106
+ ##### The original eth-utils readme is below:
107
+
68
108
  # Ethereum Utilities
69
109
 
70
110
  [![Join the conversation on Discord](https://img.shields.io/discord/809793915578089484?color=blue&label=chat&logo=discord&logoColor=white)](https://discord.gg/GHryRvPB84)
@@ -75,9 +115,11 @@ Dynamic: summary
75
115
 
76
116
  Common utility functions for python code that interacts with Ethereum
77
117
 
78
- Read more in the [documentation on ReadTheDocs](https://eth-utils.readthedocs.io/). [View the change log](https://eth-utils.readthedocs.io/en/latest/release_notes.html).
118
+ Read the [documentation](https://eth-utils.readthedocs.io/).
119
+
120
+ View the [change log](https://eth-utils.readthedocs.io/en/latest/release_notes.html).
79
121
 
80
- ## Quickstart
122
+ ## Installation
81
123
 
82
124
  ```sh
83
125
  python -m pip install eth-utils