faster-eth-abi 5.2.10__tar.gz → 5.2.11__tar.gz
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-abi might be problematic. Click here for more details.
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/PKG-INFO +1 -1
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/_codec.py +0 -4
- faster_eth_abi-5.2.10/faster_eth_abi/grammar.py → faster_eth_abi-5.2.11/faster_eth_abi/_grammar.py +45 -164
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/codec.py +8 -9
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/from_type_str.py +3 -1
- faster_eth_abi-5.2.11/faster_eth_abi/grammar.py +170 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/registry.py +37 -24
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/tools/_strategies.py +9 -5
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/PKG-INFO +1 -1
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/SOURCES.txt +1 -0
- faster_eth_abi-5.2.11/faster_eth_abi.egg-info/top_level.txt +2 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/pyproject.toml +2 -2
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/setup.py +2 -1
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_decode.py +11 -4
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_encode.py +14 -3
- faster_eth_abi-5.2.10/faster_eth_abi.egg-info/top_level.txt +0 -2
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/LICENSE +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/MANIFEST.in +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/README.md +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/_decoding.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/_encoding.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/abi.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/base.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/constants.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/decoding.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/encoding.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/exceptions.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/io.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/packed.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/py.typed +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/tools/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/utils/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/utils/numeric.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/utils/padding.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/utils/string.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi/utils/validation.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/dependency_links.txt +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/not-zip-safe +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/requires.txt +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/benchmark/compare_benchmark_results.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/benchmark/generate_benchmark_markdown.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/benchmark/parse_benchmark_output.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/release/test_package.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/setup.cfg +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_is_encodable.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_is_encodable_type.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_reversibility_properties.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_uint_properties.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/base.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/common/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/common/strategies.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/common/unit.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/decoding/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/decoding/test_context_frames_bytes_io.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/decoding/test_decoder_properties.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/encoding/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/encoding/test_encoder_properties.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/end_to_end/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/end_to_end/test_custom_registrations.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/grammar.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/packed/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/packed/test_encode_packed.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/packed/test_is_encodable_packed.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/registry/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/registry/test_abi_registry.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/registry/test_predicate_mapping.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/registry/test_predicates.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/test_import_and_version.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/test_tools.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/__init__.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/test_abbr.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/test_ceil32.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/test_scale_places.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/test_validation_utils.py +0 -0
- {faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/utils/test_zpad.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: faster_eth_abi
|
|
3
|
-
Version: 5.2.
|
|
3
|
+
Version: 5.2.11
|
|
4
4
|
Summary: A faster fork of eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding. Implemented in C.
|
|
5
5
|
Home-page: https://github.com/BobTheBuidler/faster-eth-abi
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -39,8 +39,6 @@ def encode_c(
|
|
|
39
39
|
:returns: The head-tail encoded binary representation of the python
|
|
40
40
|
values in ``args`` as values of the ABI types in ``types``.
|
|
41
41
|
"""
|
|
42
|
-
# validate encode types and args
|
|
43
|
-
validate_list_like_param(types, "types")
|
|
44
42
|
validate_list_like_param(args, "args")
|
|
45
43
|
|
|
46
44
|
encoder = self._registry.get_tuple_encoder(*types)
|
|
@@ -71,8 +69,6 @@ def decode_c(
|
|
|
71
69
|
:returns: A tuple of equivalent python values for the ABI values
|
|
72
70
|
represented in ``data``.
|
|
73
71
|
"""
|
|
74
|
-
# validate decode types and data
|
|
75
|
-
validate_list_like_param(types, "types")
|
|
76
72
|
validate_bytes_param(data, "data")
|
|
77
73
|
|
|
78
74
|
decoder = self._registry.get_tuple_decoder(*types, strict=strict)
|
faster_eth_abi-5.2.10/faster_eth_abi/grammar.py → faster_eth_abi-5.2.11/faster_eth_abi/_grammar.py
RENAMED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import functools
|
|
2
1
|
import re
|
|
3
2
|
from typing import (
|
|
4
3
|
Any,
|
|
5
4
|
Final,
|
|
5
|
+
NewType,
|
|
6
6
|
NoReturn,
|
|
7
7
|
Optional,
|
|
8
8
|
Sequence,
|
|
9
9
|
Tuple,
|
|
10
10
|
TypeVar,
|
|
11
|
+
Union,
|
|
11
12
|
final,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
|
-
from eth_typing import (
|
|
15
|
+
from eth_typing.abi import (
|
|
15
16
|
TypeStr,
|
|
16
17
|
)
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
expressions,
|
|
18
|
+
from mypy_extensions import (
|
|
19
|
+
mypyc_attr,
|
|
20
20
|
)
|
|
21
21
|
from parsimonious.nodes import (
|
|
22
22
|
Node,
|
|
@@ -27,136 +27,29 @@ from typing_extensions import (
|
|
|
27
27
|
|
|
28
28
|
from faster_eth_abi.exceptions import (
|
|
29
29
|
ABITypeError,
|
|
30
|
-
ParseError,
|
|
31
30
|
)
|
|
32
31
|
|
|
33
|
-
grammar: Final = parsimonious.Grammar(
|
|
34
|
-
r"""
|
|
35
|
-
type = tuple_type / basic_type
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
base = alphas
|
|
46
|
-
|
|
47
|
-
sub = two_size / digits
|
|
48
|
-
two_size = (digits "x" digits)
|
|
49
|
-
|
|
50
|
-
arrlist = (const_arr / dynam_arr)+
|
|
51
|
-
const_arr = "[" digits "]"
|
|
52
|
-
dynam_arr = "[]"
|
|
33
|
+
TYPE_ALIASES: Final = {
|
|
34
|
+
"int": "int256",
|
|
35
|
+
"uint": "uint256",
|
|
36
|
+
"fixed": "fixed128x18",
|
|
37
|
+
"ufixed": "ufixed128x18",
|
|
38
|
+
"function": "bytes24",
|
|
39
|
+
"byte": "bytes1",
|
|
40
|
+
}
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"""
|
|
42
|
+
TYPE_ALIAS_RE: Final = re.compile(
|
|
43
|
+
rf"\b({'|'.join(map(re.escape, TYPE_ALIASES.keys()))})\b"
|
|
57
44
|
)
|
|
58
45
|
|
|
59
46
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Parsimonious node visitor which performs both parsing of type strings and
|
|
64
|
-
post-processing of parse trees. Parsing operations are cached.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
def __init__(self):
|
|
68
|
-
self.parse = functools.lru_cache(maxsize=None)(self._parse_uncached)
|
|
69
|
-
|
|
70
|
-
grammar = grammar
|
|
71
|
-
|
|
72
|
-
def visit_non_zero_tuple(self, node, visited_children):
|
|
73
|
-
# Ignore left and right parens
|
|
74
|
-
_, first, rest, _ = visited_children
|
|
75
|
-
|
|
76
|
-
return (first,) + rest
|
|
77
|
-
|
|
78
|
-
def visit_tuple_type(self, node, visited_children):
|
|
79
|
-
components, arrlist = visited_children
|
|
80
|
-
|
|
81
|
-
return TupleType(components, arrlist, node=node)
|
|
82
|
-
|
|
83
|
-
def visit_next_type(self, node, visited_children):
|
|
84
|
-
# Ignore comma
|
|
85
|
-
_, abi_type = visited_children
|
|
86
|
-
|
|
87
|
-
return abi_type
|
|
88
|
-
|
|
89
|
-
def visit_basic_type(self, node, visited_children):
|
|
90
|
-
base, sub, arrlist = visited_children
|
|
91
|
-
|
|
92
|
-
return BasicType(base, sub, arrlist, node=node)
|
|
93
|
-
|
|
94
|
-
def visit_two_size(self, node, visited_children):
|
|
95
|
-
# Ignore "x"
|
|
96
|
-
first, _, second = visited_children
|
|
97
|
-
|
|
98
|
-
return first, second
|
|
99
|
-
|
|
100
|
-
def visit_const_arr(self, node, visited_children):
|
|
101
|
-
# Ignore left and right brackets
|
|
102
|
-
_, int_value, _ = visited_children
|
|
103
|
-
|
|
104
|
-
return (int_value,)
|
|
105
|
-
|
|
106
|
-
def visit_dynam_arr(self, node, visited_children):
|
|
107
|
-
return ()
|
|
108
|
-
|
|
109
|
-
def visit_alphas(self, node, visited_children):
|
|
110
|
-
return node.text
|
|
111
|
-
|
|
112
|
-
def visit_digits(self, node, visited_children):
|
|
113
|
-
return int(node.text)
|
|
114
|
-
|
|
115
|
-
def generic_visit(self, node, visited_children):
|
|
116
|
-
expr = node.expr
|
|
117
|
-
if isinstance(expr, expressions.OneOf):
|
|
118
|
-
# Unwrap value chosen from alternatives
|
|
119
|
-
return visited_children[0]
|
|
120
|
-
|
|
121
|
-
if isinstance(expr, expressions.Quantifier) and expr.min == 0 and expr.max == 1:
|
|
122
|
-
# Unwrap optional value or return `None`
|
|
123
|
-
if len(visited_children) != 0:
|
|
124
|
-
return visited_children[0]
|
|
125
|
-
|
|
126
|
-
return None
|
|
127
|
-
|
|
128
|
-
return tuple(visited_children)
|
|
129
|
-
|
|
130
|
-
def _parse_uncached(self, type_str, **kwargs):
|
|
131
|
-
"""
|
|
132
|
-
Parses a type string into an appropriate instance of
|
|
133
|
-
:class:`~faster_eth_abi.grammar.ABIType`. If a type string cannot be parsed,
|
|
134
|
-
throws :class:`~faster_eth_abi.exceptions.ParseError`.
|
|
135
|
-
|
|
136
|
-
:param type_str: The type string to be parsed.
|
|
137
|
-
:returns: An instance of :class:`~faster_eth_abi.grammar.ABIType` containing
|
|
138
|
-
information about the parsed type string.
|
|
139
|
-
"""
|
|
140
|
-
if not isinstance(type_str, str):
|
|
141
|
-
raise TypeError(f"Can only parse string values: got {type(type_str)}")
|
|
142
|
-
|
|
143
|
-
try:
|
|
144
|
-
return super().parse(type_str, **kwargs)
|
|
145
|
-
except parsimonious.ParseError as e:
|
|
146
|
-
# This is a good place to add some better messaging around the type string.
|
|
147
|
-
# If this logic grows any bigger, we should abstract it to its own function.
|
|
148
|
-
if "()" in type_str:
|
|
149
|
-
# validate against zero-sized tuple types
|
|
150
|
-
raise ValueError(
|
|
151
|
-
'Zero-sized tuple types "()" are not supported.'
|
|
152
|
-
) from None
|
|
153
|
-
|
|
154
|
-
raise ParseError(e.text, e.pos, e.expr) from e
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
visitor: Final = NodeVisitor()
|
|
47
|
+
IntSubtype = NewType("IntSubtype", int)
|
|
48
|
+
FixedSubtype = NewType("FixedSubtype", Tuple[int, int])
|
|
49
|
+
Subtype = Union[IntSubtype, FixedSubtype]
|
|
158
50
|
|
|
159
51
|
|
|
52
|
+
@mypyc_attr(allow_interpreted_subclasses=True)
|
|
160
53
|
class ABIType:
|
|
161
54
|
"""
|
|
162
55
|
Base class for results of type string parsing operations.
|
|
@@ -165,7 +58,7 @@ class ABIType:
|
|
|
165
58
|
__slots__ = ("arrlist", "node")
|
|
166
59
|
|
|
167
60
|
def __init__(
|
|
168
|
-
self, arrlist: Optional[Sequence] = None, node: Optional[Node] = None
|
|
61
|
+
self, arrlist: Optional[Sequence[str]] = None, node: Optional[Node] = None
|
|
169
62
|
) -> None:
|
|
170
63
|
self.arrlist: Final = arrlist
|
|
171
64
|
"""
|
|
@@ -211,6 +104,7 @@ class ABIType:
|
|
|
211
104
|
"""
|
|
212
105
|
raise NotImplementedError("Must implement `validate`")
|
|
213
106
|
|
|
107
|
+
@final
|
|
214
108
|
def invalidate(self, error_msg: str) -> NoReturn:
|
|
215
109
|
# Invalidates an ABI type with the given error message. Expects that a
|
|
216
110
|
# parsimonious node was provided from the original parsing operation
|
|
@@ -222,6 +116,7 @@ class ABIType:
|
|
|
222
116
|
f"in '{node.full_text}': {error_msg}"
|
|
223
117
|
)
|
|
224
118
|
|
|
119
|
+
@final
|
|
225
120
|
@property
|
|
226
121
|
def is_array(self) -> bool:
|
|
227
122
|
"""
|
|
@@ -238,6 +133,7 @@ class ABIType:
|
|
|
238
133
|
"""
|
|
239
134
|
raise NotImplementedError("Must implement `is_dynamic`")
|
|
240
135
|
|
|
136
|
+
@final
|
|
241
137
|
@property
|
|
242
138
|
def _has_dynamic_arrlist(self) -> bool:
|
|
243
139
|
return self.is_array and any(len(dim) == 0 for dim in self.arrlist)
|
|
@@ -246,7 +142,7 @@ class ABIType:
|
|
|
246
142
|
TComp = TypeVar("TComp", bound=ABIType)
|
|
247
143
|
|
|
248
144
|
|
|
249
|
-
@
|
|
145
|
+
@mypyc_attr(allow_interpreted_subclasses=True)
|
|
250
146
|
class TupleType(ABIType):
|
|
251
147
|
"""
|
|
252
148
|
Represents the result of parsing a tuple type string e.g. "(int,bool)".
|
|
@@ -257,7 +153,7 @@ class TupleType(ABIType):
|
|
|
257
153
|
def __init__(
|
|
258
154
|
self,
|
|
259
155
|
components: Tuple[TComp, ...],
|
|
260
|
-
arrlist: Optional[Sequence] = None,
|
|
156
|
+
arrlist: Optional[Sequence[str]] = None,
|
|
261
157
|
*,
|
|
262
158
|
node: Optional[Node] = None,
|
|
263
159
|
) -> None:
|
|
@@ -273,7 +169,7 @@ class TupleType(ABIType):
|
|
|
273
169
|
arrlist = self.arrlist
|
|
274
170
|
|
|
275
171
|
if isinstance(arrlist, tuple):
|
|
276
|
-
arrlist = "".join(repr(list
|
|
172
|
+
arrlist = "".join(map(repr, map(list, arrlist)))
|
|
277
173
|
else:
|
|
278
174
|
arrlist = ""
|
|
279
175
|
|
|
@@ -286,11 +182,12 @@ class TupleType(ABIType):
|
|
|
286
182
|
f"Cannot determine item type for non-array type '{self.to_type_str()}'"
|
|
287
183
|
)
|
|
288
184
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
node=self.node
|
|
293
|
-
|
|
185
|
+
arrlist = self.arrlist[:-1] or None # type: ignore [index]
|
|
186
|
+
cls = type(self)
|
|
187
|
+
if cls is TupleType:
|
|
188
|
+
return TupleType(self.components, arrlist, node=self.node) # type: ignore [return-value]
|
|
189
|
+
else:
|
|
190
|
+
return cls(self.components, arrlist, node=self.node)
|
|
294
191
|
|
|
295
192
|
def validate(self) -> None:
|
|
296
193
|
for c in self.components:
|
|
@@ -304,7 +201,7 @@ class TupleType(ABIType):
|
|
|
304
201
|
return any(c.is_dynamic for c in self.components)
|
|
305
202
|
|
|
306
203
|
|
|
307
|
-
@
|
|
204
|
+
@mypyc_attr(allow_interpreted_subclasses=True)
|
|
308
205
|
class BasicType(ABIType):
|
|
309
206
|
"""
|
|
310
207
|
Represents the result of parsing a basic type string e.g. "uint", "address",
|
|
@@ -316,7 +213,7 @@ class BasicType(ABIType):
|
|
|
316
213
|
def __init__(
|
|
317
214
|
self,
|
|
318
215
|
base: str,
|
|
319
|
-
sub:
|
|
216
|
+
sub: Optional[Subtype] = None,
|
|
320
217
|
arrlist: Optional[Sequence] = None,
|
|
321
218
|
*,
|
|
322
219
|
node: Optional[Node] = None,
|
|
@@ -339,12 +236,12 @@ class BasicType(ABIType):
|
|
|
339
236
|
if isinstance(sub, int):
|
|
340
237
|
substr = str(sub)
|
|
341
238
|
elif isinstance(sub, tuple):
|
|
342
|
-
substr = "x".join(str
|
|
239
|
+
substr = "x".join(map(str, sub))
|
|
343
240
|
else:
|
|
344
241
|
substr = ""
|
|
345
242
|
|
|
346
243
|
if isinstance(arrlist, tuple):
|
|
347
|
-
return self.base + substr + "".join(repr(list
|
|
244
|
+
return self.base + substr + "".join(map(repr, map(list, arrlist)))
|
|
348
245
|
else:
|
|
349
246
|
return self.base + substr
|
|
350
247
|
|
|
@@ -355,22 +252,23 @@ class BasicType(ABIType):
|
|
|
355
252
|
f"Cannot determine item type for non-array type '{self.to_type_str()}'"
|
|
356
253
|
)
|
|
357
254
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
self.
|
|
362
|
-
|
|
363
|
-
|
|
255
|
+
cls = type(self)
|
|
256
|
+
arrlist = self.arrlist[:-1] or None # type: ignore [index]
|
|
257
|
+
if cls is BasicType:
|
|
258
|
+
return BasicType(self.base, self.sub, arrlist, node=self.node) # type: ignore [return-value]
|
|
259
|
+
else:
|
|
260
|
+
return cls(self.base, self.sub, arrlist, node=self.node)
|
|
364
261
|
|
|
365
262
|
@property
|
|
366
263
|
def is_dynamic(self) -> bool:
|
|
367
264
|
if self._has_dynamic_arrlist:
|
|
368
265
|
return True
|
|
369
266
|
|
|
370
|
-
|
|
267
|
+
base = self.base
|
|
268
|
+
if base == "string":
|
|
371
269
|
return True
|
|
372
270
|
|
|
373
|
-
if
|
|
271
|
+
if base == "bytes" and self.sub is None:
|
|
374
272
|
return True
|
|
375
273
|
|
|
376
274
|
return False
|
|
@@ -436,20 +334,6 @@ class BasicType(ABIType):
|
|
|
436
334
|
self.invalidate("address cannot have suffix")
|
|
437
335
|
|
|
438
336
|
|
|
439
|
-
TYPE_ALIASES: Final = {
|
|
440
|
-
"int": "int256",
|
|
441
|
-
"uint": "uint256",
|
|
442
|
-
"fixed": "fixed128x18",
|
|
443
|
-
"ufixed": "ufixed128x18",
|
|
444
|
-
"function": "bytes24",
|
|
445
|
-
"byte": "bytes1",
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
TYPE_ALIAS_RE: Final = re.compile(
|
|
449
|
-
rf"\b({'|'.join(re.escape(a) for a in TYPE_ALIASES.keys())})\b"
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
|
|
453
337
|
def normalize(type_str: TypeStr) -> TypeStr:
|
|
454
338
|
"""
|
|
455
339
|
Normalizes a type string into its canonical version e.g. the type string
|
|
@@ -463,6 +347,3 @@ def normalize(type_str: TypeStr) -> TypeStr:
|
|
|
463
347
|
|
|
464
348
|
def __normalize(match: "re.Match[str]") -> str:
|
|
465
349
|
return TYPE_ALIASES[match.group(0)]
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
parse: Final = visitor.parse
|
|
@@ -18,6 +18,7 @@ from faster_eth_abi.decoding import (
|
|
|
18
18
|
)
|
|
19
19
|
from faster_eth_abi.exceptions import (
|
|
20
20
|
EncodingError,
|
|
21
|
+
MultipleEntriesFound,
|
|
21
22
|
)
|
|
22
23
|
from faster_eth_abi.registry import (
|
|
23
24
|
ABIRegistry,
|
|
@@ -74,20 +75,18 @@ class ABIEncoder(BaseABICoder):
|
|
|
74
75
|
:returns: ``True`` if ``arg`` is encodable as a value of the ABI type
|
|
75
76
|
``typ``. Otherwise, ``False``.
|
|
76
77
|
"""
|
|
77
|
-
|
|
78
|
+
try:
|
|
79
|
+
encoder = self._registry.get_encoder(typ)
|
|
80
|
+
except MultipleEntriesFound:
|
|
81
|
+
raise
|
|
82
|
+
except:
|
|
78
83
|
return False
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
validate = getattr(encoder, "validate_value", encoder)
|
|
82
86
|
try:
|
|
83
|
-
|
|
87
|
+
validate(arg)
|
|
84
88
|
except EncodingError:
|
|
85
89
|
return False
|
|
86
|
-
except AttributeError:
|
|
87
|
-
try:
|
|
88
|
-
encoder(arg)
|
|
89
|
-
except EncodingError:
|
|
90
|
-
return False
|
|
91
90
|
|
|
92
91
|
return True
|
|
93
92
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import re
|
|
3
|
+
from typing import (
|
|
4
|
+
Any,
|
|
5
|
+
Final,
|
|
6
|
+
NoReturn,
|
|
7
|
+
Optional,
|
|
8
|
+
Sequence,
|
|
9
|
+
Tuple,
|
|
10
|
+
TypeVar,
|
|
11
|
+
final,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from eth_typing import (
|
|
15
|
+
TypeStr,
|
|
16
|
+
)
|
|
17
|
+
import parsimonious
|
|
18
|
+
from parsimonious import (
|
|
19
|
+
expressions,
|
|
20
|
+
)
|
|
21
|
+
from parsimonious.nodes import (
|
|
22
|
+
Node,
|
|
23
|
+
)
|
|
24
|
+
from typing_extensions import (
|
|
25
|
+
Self,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from faster_eth_abi._grammar import (
|
|
29
|
+
TYPE_ALIASES,
|
|
30
|
+
TYPE_ALIAS_RE,
|
|
31
|
+
ABIType,
|
|
32
|
+
BasicType,
|
|
33
|
+
TupleType,
|
|
34
|
+
normalize,
|
|
35
|
+
)
|
|
36
|
+
from faster_eth_abi.exceptions import (
|
|
37
|
+
ABITypeError,
|
|
38
|
+
ParseError,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
grammar: Final = parsimonious.Grammar(
|
|
42
|
+
r"""
|
|
43
|
+
type = tuple_type / basic_type
|
|
44
|
+
|
|
45
|
+
tuple_type = components arrlist?
|
|
46
|
+
components = non_zero_tuple
|
|
47
|
+
|
|
48
|
+
non_zero_tuple = "(" type next_type* ")"
|
|
49
|
+
next_type = "," type
|
|
50
|
+
|
|
51
|
+
basic_type = base sub? arrlist?
|
|
52
|
+
|
|
53
|
+
base = alphas
|
|
54
|
+
|
|
55
|
+
sub = two_size / digits
|
|
56
|
+
two_size = (digits "x" digits)
|
|
57
|
+
|
|
58
|
+
arrlist = (const_arr / dynam_arr)+
|
|
59
|
+
const_arr = "[" digits "]"
|
|
60
|
+
dynam_arr = "[]"
|
|
61
|
+
|
|
62
|
+
alphas = ~"[A-Za-z]+"
|
|
63
|
+
digits = ~"[1-9][0-9]*"
|
|
64
|
+
"""
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@final
|
|
69
|
+
class NodeVisitor(parsimonious.NodeVisitor): # type: ignore [misc]
|
|
70
|
+
"""
|
|
71
|
+
Parsimonious node visitor which performs both parsing of type strings and
|
|
72
|
+
post-processing of parse trees. Parsing operations are cached.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self):
|
|
76
|
+
self.parse = functools.lru_cache(maxsize=None)(self._parse_uncached)
|
|
77
|
+
|
|
78
|
+
grammar = grammar
|
|
79
|
+
|
|
80
|
+
def visit_non_zero_tuple(self, node, visited_children):
|
|
81
|
+
# Ignore left and right parens
|
|
82
|
+
_, first, rest, _ = visited_children
|
|
83
|
+
|
|
84
|
+
return (first,) + rest
|
|
85
|
+
|
|
86
|
+
def visit_tuple_type(self, node, visited_children):
|
|
87
|
+
components, arrlist = visited_children
|
|
88
|
+
|
|
89
|
+
return TupleType(components, arrlist, node=node)
|
|
90
|
+
|
|
91
|
+
def visit_next_type(self, node, visited_children):
|
|
92
|
+
# Ignore comma
|
|
93
|
+
_, abi_type = visited_children
|
|
94
|
+
|
|
95
|
+
return abi_type
|
|
96
|
+
|
|
97
|
+
def visit_basic_type(self, node, visited_children):
|
|
98
|
+
base, sub, arrlist = visited_children
|
|
99
|
+
|
|
100
|
+
return BasicType(base, sub, arrlist, node=node)
|
|
101
|
+
|
|
102
|
+
def visit_two_size(self, node, visited_children):
|
|
103
|
+
# Ignore "x"
|
|
104
|
+
first, _, second = visited_children
|
|
105
|
+
|
|
106
|
+
return first, second
|
|
107
|
+
|
|
108
|
+
def visit_const_arr(self, node, visited_children):
|
|
109
|
+
# Ignore left and right brackets
|
|
110
|
+
_, int_value, _ = visited_children
|
|
111
|
+
|
|
112
|
+
return (int_value,)
|
|
113
|
+
|
|
114
|
+
def visit_dynam_arr(self, node, visited_children):
|
|
115
|
+
return ()
|
|
116
|
+
|
|
117
|
+
def visit_alphas(self, node, visited_children):
|
|
118
|
+
return node.text
|
|
119
|
+
|
|
120
|
+
def visit_digits(self, node, visited_children):
|
|
121
|
+
return int(node.text)
|
|
122
|
+
|
|
123
|
+
def generic_visit(self, node, visited_children):
|
|
124
|
+
expr = node.expr
|
|
125
|
+
if isinstance(expr, expressions.OneOf):
|
|
126
|
+
# Unwrap value chosen from alternatives
|
|
127
|
+
return visited_children[0]
|
|
128
|
+
|
|
129
|
+
if isinstance(expr, expressions.Quantifier) and expr.min == 0 and expr.max == 1:
|
|
130
|
+
# Unwrap optional value or return `None`
|
|
131
|
+
if len(visited_children) != 0:
|
|
132
|
+
return visited_children[0]
|
|
133
|
+
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
return tuple(visited_children)
|
|
137
|
+
|
|
138
|
+
def _parse_uncached(self, type_str, **kwargs):
|
|
139
|
+
"""
|
|
140
|
+
Parses a type string into an appropriate instance of
|
|
141
|
+
:class:`~faster_eth_abi.grammar.ABIType`. If a type string cannot be parsed,
|
|
142
|
+
throws :class:`~faster_eth_abi.exceptions.ParseError`.
|
|
143
|
+
|
|
144
|
+
:param type_str: The type string to be parsed.
|
|
145
|
+
:returns: An instance of :class:`~faster_eth_abi.grammar.ABIType` containing
|
|
146
|
+
information about the parsed type string.
|
|
147
|
+
"""
|
|
148
|
+
if not isinstance(type_str, str):
|
|
149
|
+
raise TypeError(f"Can only parse string values: got {type(type_str)}")
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
return super().parse(type_str, **kwargs)
|
|
153
|
+
except parsimonious.ParseError as e:
|
|
154
|
+
# This is a good place to add some better messaging around the type string.
|
|
155
|
+
# If this logic grows any bigger, we should abstract it to its own function.
|
|
156
|
+
if "()" in type_str:
|
|
157
|
+
# validate against zero-sized tuple types
|
|
158
|
+
raise ValueError(
|
|
159
|
+
'Zero-sized tuple types "()" are not supported.'
|
|
160
|
+
) from None
|
|
161
|
+
|
|
162
|
+
raise ParseError(e.text, e.pos, e.expr) from e
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
visitor: Final = NodeVisitor()
|
|
166
|
+
|
|
167
|
+
parse: Final = visitor.parse
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
__all__ = ["NodeVisitor", "ABIType", "TupleType", "BasicType", "grammar", "parse", "normalize", "visitor", "TYPE_ALIASES", "TYPE_ALIAS_RE"]
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
import copy
|
|
3
2
|
import functools
|
|
3
|
+
from copy import copy
|
|
4
4
|
from typing import (
|
|
5
5
|
Any,
|
|
6
6
|
Callable,
|
|
7
|
+
Dict,
|
|
8
|
+
Final,
|
|
9
|
+
Generic,
|
|
7
10
|
Optional,
|
|
8
11
|
Type,
|
|
12
|
+
TypeVar,
|
|
9
13
|
Union,
|
|
10
14
|
)
|
|
11
15
|
|
|
12
16
|
from eth_typing import (
|
|
13
17
|
TypeStr,
|
|
14
18
|
)
|
|
19
|
+
from typing_extensions import (
|
|
20
|
+
Self,
|
|
21
|
+
)
|
|
15
22
|
|
|
16
23
|
from . import (
|
|
17
24
|
decoding,
|
|
@@ -30,6 +37,8 @@ from .io import (
|
|
|
30
37
|
ContextFramesBytesIO,
|
|
31
38
|
)
|
|
32
39
|
|
|
40
|
+
T = TypeVar("T")
|
|
41
|
+
|
|
33
42
|
Lookup = Union[TypeStr, Callable[[TypeStr], bool]]
|
|
34
43
|
|
|
35
44
|
EncoderCallable = Callable[[Any], bytes]
|
|
@@ -51,34 +60,35 @@ class Copyable(abc.ABC):
|
|
|
51
60
|
return self.copy()
|
|
52
61
|
|
|
53
62
|
|
|
54
|
-
class PredicateMapping(Copyable):
|
|
63
|
+
class PredicateMapping(Copyable, Generic[T]):
|
|
55
64
|
"""
|
|
56
65
|
Acts as a mapping from predicate functions to values. Values are retrieved
|
|
57
66
|
when their corresponding predicate matches a given input. Predicates can
|
|
58
67
|
also be labeled to facilitate removal from the mapping.
|
|
59
68
|
"""
|
|
60
69
|
|
|
61
|
-
def __init__(self, name):
|
|
62
|
-
self._name = name
|
|
63
|
-
self._values = {}
|
|
64
|
-
self._labeled_predicates = {}
|
|
70
|
+
def __init__(self, name: str):
|
|
71
|
+
self._name: Final = name
|
|
72
|
+
self._values: Dict[Lookup, T] = {}
|
|
73
|
+
self._labeled_predicates: Dict[str, Lookup] = {}
|
|
65
74
|
|
|
66
|
-
def add(self, predicate, value, label=None):
|
|
75
|
+
def add(self, predicate: Lookup, value: T, label: Optional[str] = None) -> None:
|
|
67
76
|
if predicate in self._values:
|
|
68
77
|
raise ValueError(f"Matcher {predicate!r} already exists in {self._name}")
|
|
69
78
|
|
|
70
79
|
if label is not None:
|
|
71
|
-
|
|
80
|
+
labeled_predicates = self._labeled_predicates
|
|
81
|
+
if label in labeled_predicates:
|
|
72
82
|
raise ValueError(
|
|
73
83
|
f"Matcher {predicate!r} with label '{label}' "
|
|
74
84
|
f"already exists in {self._name}"
|
|
75
85
|
)
|
|
76
86
|
|
|
77
|
-
|
|
87
|
+
labeled_predicates[label] = predicate
|
|
78
88
|
|
|
79
89
|
self._values[predicate] = value
|
|
80
90
|
|
|
81
|
-
def find(self, type_str):
|
|
91
|
+
def find(self, type_str: TypeStr) -> T:
|
|
82
92
|
results = tuple(
|
|
83
93
|
(predicate, value)
|
|
84
94
|
for predicate, value in self._values.items()
|
|
@@ -103,9 +113,9 @@ class PredicateMapping(Copyable):
|
|
|
103
113
|
"documentation for more information."
|
|
104
114
|
)
|
|
105
115
|
|
|
106
|
-
return values[0]
|
|
116
|
+
return values[0] # type: ignore [no-any-return]
|
|
107
117
|
|
|
108
|
-
def remove_by_equality(self, predicate):
|
|
118
|
+
def remove_by_equality(self, predicate: Lookup) -> None:
|
|
109
119
|
# Delete the predicate mapping to the previously stored value
|
|
110
120
|
try:
|
|
111
121
|
del self._values[predicate]
|
|
@@ -120,7 +130,7 @@ class PredicateMapping(Copyable):
|
|
|
120
130
|
else:
|
|
121
131
|
del self._labeled_predicates[label]
|
|
122
132
|
|
|
123
|
-
def _label_for_predicate(self, predicate):
|
|
133
|
+
def _label_for_predicate(self, predicate: Lookup) -> str:
|
|
124
134
|
# Both keys and values in `_labeled_predicates` are unique since the
|
|
125
135
|
# `add` method enforces this
|
|
126
136
|
for key, value in self._labeled_predicates.items():
|
|
@@ -131,16 +141,17 @@ class PredicateMapping(Copyable):
|
|
|
131
141
|
f"Matcher {predicate!r} not referred to by any label in {self._name}"
|
|
132
142
|
)
|
|
133
143
|
|
|
134
|
-
def remove_by_label(self, label):
|
|
144
|
+
def remove_by_label(self, label: str) -> None:
|
|
145
|
+
labeled_predicates = self._labeled_predicates
|
|
135
146
|
try:
|
|
136
|
-
predicate =
|
|
147
|
+
predicate = labeled_predicates[label]
|
|
137
148
|
except KeyError:
|
|
138
149
|
raise KeyError(f"Label '{label}' not found in {self._name}")
|
|
139
150
|
|
|
140
|
-
del
|
|
151
|
+
del labeled_predicates[label]
|
|
141
152
|
del self._values[predicate]
|
|
142
153
|
|
|
143
|
-
def remove(self, predicate_or_label):
|
|
154
|
+
def remove(self, predicate_or_label: Union[Lookup, str]) -> None:
|
|
144
155
|
if callable(predicate_or_label):
|
|
145
156
|
self.remove_by_equality(predicate_or_label)
|
|
146
157
|
elif isinstance(predicate_or_label, str):
|
|
@@ -151,11 +162,11 @@ class PredicateMapping(Copyable):
|
|
|
151
162
|
f"{type(predicate_or_label)}"
|
|
152
163
|
)
|
|
153
164
|
|
|
154
|
-
def copy(self):
|
|
165
|
+
def copy(self) -> Self:
|
|
155
166
|
cpy = type(self)(self._name)
|
|
156
167
|
|
|
157
|
-
cpy._values = copy
|
|
158
|
-
cpy._labeled_predicates = copy
|
|
168
|
+
cpy._values = copy(self._values)
|
|
169
|
+
cpy._labeled_predicates = copy(self._labeled_predicates)
|
|
159
170
|
|
|
160
171
|
return cpy
|
|
161
172
|
|
|
@@ -282,6 +293,7 @@ def _clear_encoder_cache(old_method: Callable[..., None]) -> Callable[..., None]
|
|
|
282
293
|
@functools.wraps(old_method)
|
|
283
294
|
def new_method(self: "ABIRegistry", *args: Any, **kwargs: Any) -> None:
|
|
284
295
|
self.get_encoder.cache_clear()
|
|
296
|
+
self.get_tuple_encoder.cache_clear()
|
|
285
297
|
return old_method(self, *args, **kwargs)
|
|
286
298
|
|
|
287
299
|
return new_method
|
|
@@ -291,6 +303,7 @@ def _clear_decoder_cache(old_method: Callable[..., None]) -> Callable[..., None]
|
|
|
291
303
|
@functools.wraps(old_method)
|
|
292
304
|
def new_method(self: "ABIRegistry", *args: Any, **kwargs: Any) -> None:
|
|
293
305
|
self.get_decoder.cache_clear()
|
|
306
|
+
self.get_tuple_decoder.cache_clear()
|
|
294
307
|
return old_method(self, *args, **kwargs)
|
|
295
308
|
|
|
296
309
|
return new_method
|
|
@@ -343,8 +356,8 @@ class BaseRegistry:
|
|
|
343
356
|
|
|
344
357
|
class ABIRegistry(Copyable, BaseRegistry):
|
|
345
358
|
def __init__(self):
|
|
346
|
-
self._encoders = PredicateMapping("encoder registry")
|
|
347
|
-
self._decoders = PredicateMapping("decoder registry")
|
|
359
|
+
self._encoders: PredicateMapping[Encoder] = PredicateMapping("encoder registry")
|
|
360
|
+
self._decoders: PredicateMapping[Decoder] = PredicateMapping("decoder registry")
|
|
348
361
|
self.get_encoder = functools.lru_cache(maxsize=None)(self._get_encoder_uncached)
|
|
349
362
|
self.get_decoder = functools.lru_cache(maxsize=None)(self._get_decoder_uncached)
|
|
350
363
|
self.get_tuple_encoder = functools.lru_cache(maxsize=None)(
|
|
@@ -518,8 +531,8 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
518
531
|
"""
|
|
519
532
|
cpy = type(self)()
|
|
520
533
|
|
|
521
|
-
cpy._encoders = copy
|
|
522
|
-
cpy._decoders = copy
|
|
534
|
+
cpy._encoders = copy(self._encoders)
|
|
535
|
+
cpy._decoders = copy(self._decoders)
|
|
523
536
|
|
|
524
537
|
return cpy
|
|
525
538
|
|
|
@@ -2,7 +2,9 @@ from typing import (
|
|
|
2
2
|
Callable,
|
|
3
3
|
Final,
|
|
4
4
|
Optional,
|
|
5
|
+
Tuple,
|
|
5
6
|
Union,
|
|
7
|
+
cast,
|
|
6
8
|
)
|
|
7
9
|
|
|
8
10
|
from cchecksum import (
|
|
@@ -15,11 +17,13 @@ from hypothesis import (
|
|
|
15
17
|
strategies as st,
|
|
16
18
|
)
|
|
17
19
|
|
|
18
|
-
from faster_eth_abi.
|
|
20
|
+
from faster_eth_abi._grammar import (
|
|
19
21
|
ABIType,
|
|
20
22
|
BasicType,
|
|
21
23
|
TupleType,
|
|
22
24
|
normalize,
|
|
25
|
+
)
|
|
26
|
+
from faster_eth_abi.grammar import (
|
|
23
27
|
parse,
|
|
24
28
|
)
|
|
25
29
|
from faster_eth_abi.registry import (
|
|
@@ -81,7 +85,7 @@ class StrategyRegistry(BaseRegistry):
|
|
|
81
85
|
def get_uint_strategy(
|
|
82
86
|
abi_type: BasicType, registry: StrategyRegistry
|
|
83
87
|
) -> st.SearchStrategy:
|
|
84
|
-
bits = abi_type.sub
|
|
88
|
+
bits = cast(int, abi_type.sub)
|
|
85
89
|
|
|
86
90
|
return st.integers(
|
|
87
91
|
min_value=0,
|
|
@@ -92,7 +96,7 @@ def get_uint_strategy(
|
|
|
92
96
|
def get_int_strategy(
|
|
93
97
|
abi_type: BasicType, registry: StrategyRegistry
|
|
94
98
|
) -> st.SearchStrategy:
|
|
95
|
-
bits = abi_type.sub
|
|
99
|
+
bits = cast(int, abi_type.sub)
|
|
96
100
|
|
|
97
101
|
return st.integers(
|
|
98
102
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -107,7 +111,7 @@ bool_strategy: Final = st.booleans()
|
|
|
107
111
|
def get_ufixed_strategy(
|
|
108
112
|
abi_type: BasicType, registry: StrategyRegistry
|
|
109
113
|
) -> st.SearchStrategy:
|
|
110
|
-
bits, places = abi_type.sub
|
|
114
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
111
115
|
|
|
112
116
|
return st.decimals(
|
|
113
117
|
min_value=0,
|
|
@@ -119,7 +123,7 @@ def get_ufixed_strategy(
|
|
|
119
123
|
def get_fixed_strategy(
|
|
120
124
|
abi_type: BasicType, registry: StrategyRegistry
|
|
121
125
|
) -> st.SearchStrategy:
|
|
122
|
-
bits, places = abi_type.sub
|
|
126
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
123
127
|
|
|
124
128
|
return st.decimals(
|
|
125
129
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: faster-eth-abi
|
|
3
|
-
Version: 5.2.
|
|
3
|
+
Version: 5.2.11
|
|
4
4
|
Summary: A faster fork of eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding. Implemented in C.
|
|
5
5
|
Home-page: https://github.com/BobTheBuidler/faster-eth-abi
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -5,8 +5,8 @@ requires = [
|
|
|
5
5
|
"mypy[mypyc]>=1.14.1,<1.18.3",
|
|
6
6
|
"mypy_extensions",
|
|
7
7
|
"cchecksum>=0.2.6,<0.4",
|
|
8
|
-
|
|
9
|
-
"faster-eth-utils>=2.0.0; python_version
|
|
8
|
+
# pydantic-core (installed with faster-eth-utils) is unable to build on Python3.14 on 32-bit Linux distros
|
|
9
|
+
"faster-eth-utils>=2.0.0; platform_system != 'Linux' or python_version != '3.14' or platform_machine != 'i686'",
|
|
10
10
|
"eth-typing>=3.0.0",
|
|
11
11
|
"parsimonious>=0.10.0,<0.11.0",
|
|
12
12
|
]
|
|
@@ -55,6 +55,7 @@ ext_modules = mypycify(
|
|
|
55
55
|
"faster_eth_abi/_codec.py",
|
|
56
56
|
"faster_eth_abi/_decoding.py",
|
|
57
57
|
"faster_eth_abi/_encoding.py",
|
|
58
|
+
"faster_eth_abi/_grammar.py",
|
|
58
59
|
"faster_eth_abi/abi.py",
|
|
59
60
|
"faster_eth_abi/constants.py",
|
|
60
61
|
"faster_eth_abi/from_type_str.py",
|
|
@@ -73,7 +74,7 @@ ext_modules = mypycify(
|
|
|
73
74
|
setup(
|
|
74
75
|
name="faster_eth_abi",
|
|
75
76
|
# *IMPORTANT*: Don't manually change the version here. See Contributing docs for the release process.
|
|
76
|
-
version="5.2.
|
|
77
|
+
version="5.2.11",
|
|
77
78
|
description="""A faster fork of eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding. Implemented in C.""",
|
|
78
79
|
long_description=long_description,
|
|
79
80
|
long_description_content_type="text/markdown",
|
|
@@ -7,6 +7,7 @@ from faster_eth_abi.abi import (
|
|
|
7
7
|
from faster_eth_abi.exceptions import (
|
|
8
8
|
InsufficientDataBytes,
|
|
9
9
|
InvalidPointer,
|
|
10
|
+
NoEntriesFound,
|
|
10
11
|
)
|
|
11
12
|
from faster_eth_abi.grammar import (
|
|
12
13
|
parse,
|
|
@@ -90,9 +91,9 @@ def test_abi_decode_wrong_data_param_type_raises(data, strict):
|
|
|
90
91
|
@pytest.mark.parametrize(
|
|
91
92
|
"types",
|
|
92
93
|
(
|
|
93
|
-
"",
|
|
94
|
+
# "", This parametrization is disabled because we don't type check `types` and when iterated upon, `""` yields no items and ends iteration.
|
|
94
95
|
123,
|
|
95
|
-
b"",
|
|
96
|
+
# b"", This parametrization is disabled because we don't type check `types` and when iterated upon, `""` yields no items and ends iteration.
|
|
96
97
|
b"\xff",
|
|
97
98
|
b"david attenborough",
|
|
98
99
|
bytearray(b"\x01\xff"),
|
|
@@ -101,9 +102,15 @@ def test_abi_decode_wrong_data_param_type_raises(data, strict):
|
|
|
101
102
|
),
|
|
102
103
|
)
|
|
103
104
|
def test_abi_decode_wrong_types_param_type_raises(types, strict):
|
|
105
|
+
if types == {"key": "val"}:
|
|
106
|
+
expected_exc = NoEntriesFound
|
|
107
|
+
else:
|
|
108
|
+
expected_exc = TypeError
|
|
104
109
|
with pytest.raises(
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
expected_exc,
|
|
111
|
+
# NOTE The `match` arg was commented out because faster-eth-abi might not raise
|
|
112
|
+
# the same exception, but we should still test that it raises an Exception like eth-abi
|
|
113
|
+
# match=f"The `types` value type must be one of list or tuple. Got {type(types)}",
|
|
107
114
|
):
|
|
108
115
|
decode(types, b"\x00" * 32, strict=strict)
|
|
109
116
|
|
|
@@ -4,6 +4,10 @@ import re
|
|
|
4
4
|
from faster_eth_abi import (
|
|
5
5
|
encode,
|
|
6
6
|
)
|
|
7
|
+
from faster_eth_abi.exceptions import (
|
|
8
|
+
NoEntriesFound,
|
|
9
|
+
ValueOutOfBounds,
|
|
10
|
+
)
|
|
7
11
|
from faster_eth_abi.grammar import (
|
|
8
12
|
parse,
|
|
9
13
|
)
|
|
@@ -101,10 +105,17 @@ def test_abi_encode_for_single_dynamic_types(
|
|
|
101
105
|
)
|
|
102
106
|
def test_abi_encode_raises_for_non_list_like_params(non_list_like_value):
|
|
103
107
|
# test raises when `types` param is not list-like
|
|
108
|
+
if non_list_like_value in ("", b""):
|
|
109
|
+
expected_exc = ValueOutOfBounds
|
|
110
|
+
elif non_list_like_value == {"key": "val"}:
|
|
111
|
+
expected_exc = NoEntriesFound
|
|
112
|
+
else:
|
|
113
|
+
expected_exc = TypeError
|
|
104
114
|
with pytest.raises(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
115
|
+
expected_exc,
|
|
116
|
+
# NOTE The `match` arg was commented out because faster-eth-abi might not raise
|
|
117
|
+
# the same exception, but we should still test that it raises an Exception like eth-abi
|
|
118
|
+
# match=f"The `types` value type must be one of list or tuple. Got {type(non_list_like_value)}",
|
|
108
119
|
):
|
|
109
120
|
encode(non_list_like_value, ["bytes"])
|
|
110
121
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/faster_eth_abi.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/benchmark/compare_benchmark_results.py
RENAMED
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/scripts/benchmark/generate_benchmark_markdown.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_is_encodable_type.py
RENAMED
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/abi_tests/test_uint_properties.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/decoding/test_context_frames_bytes_io.py
RENAMED
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/decoding/test_decoder_properties.py
RENAMED
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/encoding/test_encoder_properties.py
RENAMED
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/end_to_end/test_custom_registrations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/packed/test_is_encodable_packed.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{faster_eth_abi-5.2.10 → faster_eth_abi-5.2.11}/tests/core/registry/test_predicate_mapping.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|