faster-eth-abi 5.2.3__cp310-cp310-win_amd64.whl → 5.2.19__cp310-cp310-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-abi might be problematic. Click here for more details.
- faster_eth_abi/_codec.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/_codec.py +83 -0
- faster_eth_abi/_decoding.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/_decoding.py +299 -0
- faster_eth_abi/_encoding.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/_encoding.py +251 -0
- faster_eth_abi/_grammar.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/_grammar.py +375 -0
- faster_eth_abi/abi.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/base.py +5 -1
- faster_eth_abi/codec.py +2694 -52
- faster_eth_abi/constants.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/decoding.py +263 -242
- faster_eth_abi/encoding.py +201 -154
- faster_eth_abi/exceptions.py +26 -14
- faster_eth_abi/from_type_str.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/from_type_str.py +7 -1
- faster_eth_abi/grammar.py +30 -325
- faster_eth_abi/io.py +5 -1
- faster_eth_abi/packed.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/packed.py +4 -0
- faster_eth_abi/registry.py +201 -83
- faster_eth_abi/tools/__init__.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/tools/_strategies.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/tools/_strategies.py +12 -6
- faster_eth_abi/typing.py +4627 -0
- faster_eth_abi/utils/__init__.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/utils/numeric.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/utils/numeric.py +51 -20
- faster_eth_abi/utils/padding.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/utils/string.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/utils/validation.cp310-win_amd64.pyd +0 -0
- faster_eth_abi/utils/validation.py +1 -5
- faster_eth_abi-5.2.19.dist-info/METADATA +136 -0
- faster_eth_abi-5.2.19.dist-info/RECORD +46 -0
- faster_eth_abi-5.2.19.dist-info/top_level.txt +2 -0
- faster_eth_abi__mypyc.cp310-win_amd64.pyd +0 -0
- a1f8aa123fabc88e2b56__mypyc.cp310-win_amd64.pyd +0 -0
- faster_eth_abi-5.2.3.dist-info/METADATA +0 -95
- faster_eth_abi-5.2.3.dist-info/RECORD +0 -38
- faster_eth_abi-5.2.3.dist-info/licenses/LICENSE +0 -21
- faster_eth_abi-5.2.3.dist-info/top_level.txt +0 -3
- {faster_eth_abi-5.2.3.dist-info → faster_eth_abi-5.2.19.dist-info}/WHEEL +0 -0
faster_eth_abi/registry.py
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
+
"""Registry and predicate logic for ABI encoders and decoders.
|
|
2
|
+
|
|
3
|
+
Implements registration, lookup, and matching of encoders and decoders for ABI type strings.
|
|
4
|
+
"""
|
|
1
5
|
import abc
|
|
2
|
-
import
|
|
6
|
+
from copy import (
|
|
7
|
+
copy,
|
|
8
|
+
)
|
|
3
9
|
import functools
|
|
4
10
|
from typing import (
|
|
5
11
|
Any,
|
|
6
12
|
Callable,
|
|
13
|
+
Dict,
|
|
14
|
+
Final,
|
|
15
|
+
Generic,
|
|
16
|
+
Iterator,
|
|
7
17
|
Optional,
|
|
8
18
|
Type,
|
|
19
|
+
TypeVar,
|
|
9
20
|
Union,
|
|
21
|
+
cast,
|
|
22
|
+
final,
|
|
10
23
|
)
|
|
11
24
|
|
|
12
25
|
from eth_typing import (
|
|
13
26
|
TypeStr,
|
|
14
27
|
)
|
|
28
|
+
from typing_extensions import (
|
|
29
|
+
Concatenate,
|
|
30
|
+
ParamSpec,
|
|
31
|
+
Self,
|
|
32
|
+
)
|
|
15
33
|
|
|
16
34
|
from . import (
|
|
17
35
|
decoding,
|
|
@@ -30,6 +48,9 @@ from .io import (
|
|
|
30
48
|
ContextFramesBytesIO,
|
|
31
49
|
)
|
|
32
50
|
|
|
51
|
+
T = TypeVar("T")
|
|
52
|
+
P = ParamSpec("P")
|
|
53
|
+
|
|
33
54
|
Lookup = Union[TypeStr, Callable[[TypeStr], bool]]
|
|
34
55
|
|
|
35
56
|
EncoderCallable = Callable[[Any], bytes]
|
|
@@ -41,44 +62,45 @@ Decoder = Union[DecoderCallable, Type[decoding.BaseDecoder]]
|
|
|
41
62
|
|
|
42
63
|
class Copyable(abc.ABC):
|
|
43
64
|
@abc.abstractmethod
|
|
44
|
-
def copy(self):
|
|
65
|
+
def copy(self) -> Self:
|
|
45
66
|
pass
|
|
46
67
|
|
|
47
|
-
def __copy__(self):
|
|
68
|
+
def __copy__(self) -> Self:
|
|
48
69
|
return self.copy()
|
|
49
70
|
|
|
50
|
-
def __deepcopy__(self, *args):
|
|
71
|
+
def __deepcopy__(self, *args: Any) -> Self:
|
|
51
72
|
return self.copy()
|
|
52
73
|
|
|
53
74
|
|
|
54
|
-
class PredicateMapping(Copyable):
|
|
75
|
+
class PredicateMapping(Copyable, Generic[T]):
|
|
55
76
|
"""
|
|
56
77
|
Acts as a mapping from predicate functions to values. Values are retrieved
|
|
57
78
|
when their corresponding predicate matches a given input. Predicates can
|
|
58
79
|
also be labeled to facilitate removal from the mapping.
|
|
59
80
|
"""
|
|
60
81
|
|
|
61
|
-
def __init__(self, name):
|
|
62
|
-
self._name = name
|
|
63
|
-
self._values = {}
|
|
64
|
-
self._labeled_predicates = {}
|
|
82
|
+
def __init__(self, name: str):
|
|
83
|
+
self._name: Final = name
|
|
84
|
+
self._values: Dict[Lookup, T] = {}
|
|
85
|
+
self._labeled_predicates: Dict[str, Lookup] = {}
|
|
65
86
|
|
|
66
|
-
def add(self, predicate, value, label=None):
|
|
87
|
+
def add(self, predicate: Lookup, value: T, label: Optional[str] = None) -> None:
|
|
67
88
|
if predicate in self._values:
|
|
68
89
|
raise ValueError(f"Matcher {predicate!r} already exists in {self._name}")
|
|
69
90
|
|
|
70
91
|
if label is not None:
|
|
71
|
-
|
|
92
|
+
labeled_predicates = self._labeled_predicates
|
|
93
|
+
if label in labeled_predicates:
|
|
72
94
|
raise ValueError(
|
|
73
95
|
f"Matcher {predicate!r} with label '{label}' "
|
|
74
96
|
f"already exists in {self._name}"
|
|
75
97
|
)
|
|
76
98
|
|
|
77
|
-
|
|
99
|
+
labeled_predicates[label] = predicate
|
|
78
100
|
|
|
79
101
|
self._values[predicate] = value
|
|
80
102
|
|
|
81
|
-
def find(self, type_str):
|
|
103
|
+
def find(self, type_str: TypeStr) -> T:
|
|
82
104
|
results = tuple(
|
|
83
105
|
(predicate, value)
|
|
84
106
|
for predicate, value in self._values.items()
|
|
@@ -103,9 +125,9 @@ class PredicateMapping(Copyable):
|
|
|
103
125
|
"documentation for more information."
|
|
104
126
|
)
|
|
105
127
|
|
|
106
|
-
return values[0]
|
|
128
|
+
return values[0] # type: ignore [no-any-return]
|
|
107
129
|
|
|
108
|
-
def remove_by_equality(self, predicate):
|
|
130
|
+
def remove_by_equality(self, predicate: Lookup) -> None:
|
|
109
131
|
# Delete the predicate mapping to the previously stored value
|
|
110
132
|
try:
|
|
111
133
|
del self._values[predicate]
|
|
@@ -120,7 +142,7 @@ class PredicateMapping(Copyable):
|
|
|
120
142
|
else:
|
|
121
143
|
del self._labeled_predicates[label]
|
|
122
144
|
|
|
123
|
-
def _label_for_predicate(self, predicate):
|
|
145
|
+
def _label_for_predicate(self, predicate: Lookup) -> str:
|
|
124
146
|
# Both keys and values in `_labeled_predicates` are unique since the
|
|
125
147
|
# `add` method enforces this
|
|
126
148
|
for key, value in self._labeled_predicates.items():
|
|
@@ -131,16 +153,17 @@ class PredicateMapping(Copyable):
|
|
|
131
153
|
f"Matcher {predicate!r} not referred to by any label in {self._name}"
|
|
132
154
|
)
|
|
133
155
|
|
|
134
|
-
def remove_by_label(self, label):
|
|
156
|
+
def remove_by_label(self, label: str) -> None:
|
|
157
|
+
labeled_predicates = self._labeled_predicates
|
|
135
158
|
try:
|
|
136
|
-
predicate =
|
|
159
|
+
predicate = labeled_predicates[label]
|
|
137
160
|
except KeyError:
|
|
138
161
|
raise KeyError(f"Label '{label}' not found in {self._name}")
|
|
139
162
|
|
|
140
|
-
del
|
|
163
|
+
del labeled_predicates[label]
|
|
141
164
|
del self._values[predicate]
|
|
142
165
|
|
|
143
|
-
def remove(self, predicate_or_label):
|
|
166
|
+
def remove(self, predicate_or_label: Union[Lookup, str]) -> None:
|
|
144
167
|
if callable(predicate_or_label):
|
|
145
168
|
self.remove_by_equality(predicate_or_label)
|
|
146
169
|
elif isinstance(predicate_or_label, str):
|
|
@@ -151,61 +174,79 @@ class PredicateMapping(Copyable):
|
|
|
151
174
|
f"{type(predicate_or_label)}"
|
|
152
175
|
)
|
|
153
176
|
|
|
154
|
-
def copy(self):
|
|
177
|
+
def copy(self) -> Self:
|
|
155
178
|
cpy = type(self)(self._name)
|
|
156
179
|
|
|
157
|
-
cpy._values = copy
|
|
158
|
-
cpy._labeled_predicates = copy
|
|
180
|
+
cpy._values = copy(self._values)
|
|
181
|
+
cpy._labeled_predicates = copy(self._labeled_predicates)
|
|
159
182
|
|
|
160
183
|
return cpy
|
|
161
184
|
|
|
162
185
|
|
|
163
|
-
class Predicate:
|
|
186
|
+
class Predicate(Generic[T]):
|
|
164
187
|
"""
|
|
165
188
|
Represents a predicate function to be used for type matching in
|
|
166
189
|
``ABIRegistry``.
|
|
167
190
|
"""
|
|
168
191
|
|
|
169
|
-
__slots__ =
|
|
192
|
+
__slots__ = ("_string", "__hash")
|
|
193
|
+
|
|
194
|
+
_string: Optional[str]
|
|
195
|
+
|
|
196
|
+
def __init__(self) -> None:
|
|
197
|
+
self._string = None
|
|
198
|
+
self.__hash = None
|
|
170
199
|
|
|
171
|
-
def __call__(self,
|
|
200
|
+
def __call__(self, arg: TypeStr) -> None:
|
|
172
201
|
raise NotImplementedError("Must implement `__call__`")
|
|
173
202
|
|
|
174
|
-
def __str__(self)
|
|
203
|
+
def __str__(self) -> str:
|
|
175
204
|
raise NotImplementedError("Must implement `__str__`")
|
|
176
205
|
|
|
177
|
-
def __repr__(self):
|
|
206
|
+
def __repr__(self) -> str:
|
|
178
207
|
return f"<{type(self).__name__} {self}>"
|
|
179
208
|
|
|
180
|
-
def __iter__(self):
|
|
181
|
-
|
|
182
|
-
yield getattr(self, attr)
|
|
209
|
+
def __iter__(self) -> Iterator[T]:
|
|
210
|
+
raise NotImplementedError("must be implemented by subclass")
|
|
183
211
|
|
|
184
|
-
def __hash__(self):
|
|
185
|
-
|
|
212
|
+
def __hash__(self) -> int:
|
|
213
|
+
hashval = self.__hash
|
|
214
|
+
if hashval is None:
|
|
215
|
+
self.__hash = hashval = hash(tuple(self))
|
|
216
|
+
return hashval
|
|
186
217
|
|
|
187
|
-
def __eq__(self, other):
|
|
218
|
+
def __eq__(self, other: "Predicate") -> bool:
|
|
188
219
|
return type(self) is type(other) and tuple(self) == tuple(other)
|
|
189
220
|
|
|
190
221
|
|
|
191
|
-
|
|
222
|
+
@final
|
|
223
|
+
class Equals(Predicate[str]):
|
|
192
224
|
"""
|
|
193
225
|
A predicate that matches any input equal to `value`.
|
|
194
226
|
"""
|
|
195
227
|
|
|
196
228
|
__slots__ = ("value",)
|
|
197
229
|
|
|
198
|
-
def __init__(self, value):
|
|
199
|
-
|
|
230
|
+
def __init__(self, value: str) -> None:
|
|
231
|
+
super().__init__()
|
|
232
|
+
self.value: Final = value
|
|
200
233
|
|
|
201
|
-
def __call__(self, other):
|
|
234
|
+
def __call__(self, other: TypeStr) -> bool:
|
|
202
235
|
return self.value == other
|
|
203
236
|
|
|
204
|
-
def __str__(self):
|
|
205
|
-
|
|
237
|
+
def __str__(self) -> str:
|
|
238
|
+
# NOTE should this just be done at init time? is it always called?
|
|
239
|
+
string = self._string
|
|
240
|
+
if string is None:
|
|
241
|
+
self._string = string = f"(== {self.value!r})"
|
|
242
|
+
return string
|
|
206
243
|
|
|
244
|
+
def __iter__(self) -> Iterator[str]:
|
|
245
|
+
yield self.value
|
|
207
246
|
|
|
208
|
-
|
|
247
|
+
|
|
248
|
+
@final
|
|
249
|
+
class BaseEquals(Predicate[Union[str, bool, None]]):
|
|
209
250
|
"""
|
|
210
251
|
A predicate that matches a basic type string with a base component equal to
|
|
211
252
|
`value` and no array component. If `with_sub` is `True`, the type string
|
|
@@ -216,11 +257,12 @@ class BaseEquals(Predicate):
|
|
|
216
257
|
|
|
217
258
|
__slots__ = ("base", "with_sub")
|
|
218
259
|
|
|
219
|
-
def __init__(self, base, *, with_sub=None):
|
|
220
|
-
|
|
221
|
-
self.
|
|
260
|
+
def __init__(self, base: TypeStr, *, with_sub: Optional[bool] = None):
|
|
261
|
+
super().__init__()
|
|
262
|
+
self.base: Final = base
|
|
263
|
+
self.with_sub: Final = with_sub
|
|
222
264
|
|
|
223
|
-
def __call__(self, type_str):
|
|
265
|
+
def __call__(self, type_str: TypeStr) -> bool:
|
|
224
266
|
try:
|
|
225
267
|
abi_type = grammar.parse(type_str)
|
|
226
268
|
except (exceptions.ParseError, ValueError):
|
|
@@ -230,10 +272,12 @@ class BaseEquals(Predicate):
|
|
|
230
272
|
if abi_type.arrlist is not None:
|
|
231
273
|
return False
|
|
232
274
|
|
|
233
|
-
|
|
234
|
-
|
|
275
|
+
with_sub = self.with_sub
|
|
276
|
+
if with_sub is not None:
|
|
277
|
+
abi_subtype = abi_type.sub
|
|
278
|
+
if with_sub and abi_subtype is None:
|
|
235
279
|
return False
|
|
236
|
-
if not
|
|
280
|
+
if not with_sub and abi_subtype is not None:
|
|
237
281
|
return False
|
|
238
282
|
|
|
239
283
|
return abi_type.base == self.base
|
|
@@ -242,19 +286,25 @@ class BaseEquals(Predicate):
|
|
|
242
286
|
# e.g. if it contained a tuple type
|
|
243
287
|
return False
|
|
244
288
|
|
|
245
|
-
def __str__(self):
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
289
|
+
def __str__(self) -> str:
|
|
290
|
+
# NOTE should this just be done at init time? is it always called?
|
|
291
|
+
string = self._string
|
|
292
|
+
if string is None:
|
|
293
|
+
if self.with_sub is None:
|
|
294
|
+
string = f"(base == {self.base!r})"
|
|
295
|
+
elif self.with_sub:
|
|
296
|
+
string = f"(base == {self.base!r} and sub is not None)"
|
|
297
|
+
else:
|
|
298
|
+
string = f"(base == {self.base!r} and sub is None)"
|
|
299
|
+
self._string = string
|
|
300
|
+
return string
|
|
301
|
+
|
|
302
|
+
def __iter__(self) -> Iterator[Union[str, bool, None]]:
|
|
303
|
+
yield self.base
|
|
304
|
+
yield self.with_sub
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def has_arrlist(type_str: TypeStr) -> bool:
|
|
258
308
|
"""
|
|
259
309
|
A predicate that matches a type string with an array dimension list.
|
|
260
310
|
"""
|
|
@@ -266,7 +316,7 @@ def has_arrlist(type_str):
|
|
|
266
316
|
return abi_type.arrlist is not None
|
|
267
317
|
|
|
268
318
|
|
|
269
|
-
def is_base_tuple(type_str):
|
|
319
|
+
def is_base_tuple(type_str: TypeStr) -> bool:
|
|
270
320
|
"""
|
|
271
321
|
A predicate that matches a tuple type with no array dimension list.
|
|
272
322
|
"""
|
|
@@ -278,19 +328,25 @@ def is_base_tuple(type_str):
|
|
|
278
328
|
return isinstance(abi_type, grammar.TupleType) and abi_type.arrlist is None
|
|
279
329
|
|
|
280
330
|
|
|
281
|
-
def _clear_encoder_cache(
|
|
331
|
+
def _clear_encoder_cache(
|
|
332
|
+
old_method: Callable[Concatenate["ABIRegistry", P], T]
|
|
333
|
+
) -> Callable[Concatenate["ABIRegistry", P], T]:
|
|
282
334
|
@functools.wraps(old_method)
|
|
283
|
-
def new_method(self: "ABIRegistry", *args:
|
|
335
|
+
def new_method(self: "ABIRegistry", *args: P.args, **kwargs: P.kwargs) -> T:
|
|
284
336
|
self.get_encoder.cache_clear()
|
|
337
|
+
self.get_tuple_encoder.cache_clear()
|
|
285
338
|
return old_method(self, *args, **kwargs)
|
|
286
339
|
|
|
287
340
|
return new_method
|
|
288
341
|
|
|
289
342
|
|
|
290
|
-
def _clear_decoder_cache(
|
|
343
|
+
def _clear_decoder_cache(
|
|
344
|
+
old_method: Callable[Concatenate["ABIRegistry", P], T]
|
|
345
|
+
) -> Callable[Concatenate["ABIRegistry", P], T]:
|
|
291
346
|
@functools.wraps(old_method)
|
|
292
|
-
def new_method(self: "ABIRegistry", *args:
|
|
347
|
+
def new_method(self: "ABIRegistry", *args: P.args, **kwargs: P.kwargs) -> T:
|
|
293
348
|
self.get_decoder.cache_clear()
|
|
349
|
+
self.get_tuple_decoder.cache_clear()
|
|
294
350
|
return old_method(self, *args, **kwargs)
|
|
295
351
|
|
|
296
352
|
return new_method
|
|
@@ -298,7 +354,12 @@ def _clear_decoder_cache(old_method: Callable[..., None]) -> Callable[..., None]
|
|
|
298
354
|
|
|
299
355
|
class BaseRegistry:
|
|
300
356
|
@staticmethod
|
|
301
|
-
def _register(
|
|
357
|
+
def _register(
|
|
358
|
+
mapping: PredicateMapping[T],
|
|
359
|
+
lookup: Lookup,
|
|
360
|
+
value: T,
|
|
361
|
+
label: Optional[str] = None,
|
|
362
|
+
) -> None:
|
|
302
363
|
if callable(lookup):
|
|
303
364
|
mapping.add(lookup, value, label)
|
|
304
365
|
return
|
|
@@ -312,7 +373,7 @@ class BaseRegistry:
|
|
|
312
373
|
)
|
|
313
374
|
|
|
314
375
|
@staticmethod
|
|
315
|
-
def _unregister(mapping, lookup_or_label):
|
|
376
|
+
def _unregister(mapping: PredicateMapping[Any], lookup_or_label: Lookup) -> None:
|
|
316
377
|
if callable(lookup_or_label):
|
|
317
378
|
mapping.remove_by_equality(lookup_or_label)
|
|
318
379
|
return
|
|
@@ -327,7 +388,7 @@ class BaseRegistry:
|
|
|
327
388
|
)
|
|
328
389
|
|
|
329
390
|
@staticmethod
|
|
330
|
-
def _get_registration(mapping, type_str):
|
|
391
|
+
def _get_registration(mapping: PredicateMapping[T], type_str: TypeStr) -> T:
|
|
331
392
|
try:
|
|
332
393
|
value = mapping.find(type_str)
|
|
333
394
|
except ValueError as e:
|
|
@@ -342,19 +403,25 @@ class BaseRegistry:
|
|
|
342
403
|
|
|
343
404
|
|
|
344
405
|
class ABIRegistry(Copyable, BaseRegistry):
|
|
345
|
-
def __init__(self):
|
|
346
|
-
self._encoders = PredicateMapping("encoder registry")
|
|
347
|
-
self._decoders = PredicateMapping("decoder registry")
|
|
406
|
+
def __init__(self) -> None:
|
|
407
|
+
self._encoders: PredicateMapping[Encoder] = PredicateMapping("encoder registry")
|
|
408
|
+
self._decoders: PredicateMapping[Decoder] = PredicateMapping("decoder registry")
|
|
348
409
|
self.get_encoder = functools.lru_cache(maxsize=None)(self._get_encoder_uncached)
|
|
349
410
|
self.get_decoder = functools.lru_cache(maxsize=None)(self._get_decoder_uncached)
|
|
411
|
+
self.get_tuple_encoder = functools.lru_cache(maxsize=None)(
|
|
412
|
+
self._get_tuple_encoder_uncached
|
|
413
|
+
)
|
|
414
|
+
self.get_tuple_decoder = functools.lru_cache(maxsize=None)(
|
|
415
|
+
self._get_tuple_decoder_uncached
|
|
416
|
+
)
|
|
350
417
|
|
|
351
|
-
def _get_registration(self, mapping, type_str):
|
|
418
|
+
def _get_registration(self, mapping: PredicateMapping[T], type_str: TypeStr) -> T:
|
|
352
419
|
coder = super()._get_registration(mapping, type_str)
|
|
353
420
|
|
|
354
421
|
if isinstance(coder, type) and issubclass(coder, BaseCoder):
|
|
355
422
|
return coder.from_type_str(type_str, self)
|
|
356
423
|
|
|
357
|
-
return coder
|
|
424
|
+
return cast(T, coder)
|
|
358
425
|
|
|
359
426
|
@_clear_encoder_cache
|
|
360
427
|
def register_encoder(
|
|
@@ -454,9 +521,16 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
454
521
|
self.unregister_encoder(label)
|
|
455
522
|
self.unregister_decoder(label)
|
|
456
523
|
|
|
457
|
-
def _get_encoder_uncached(self, type_str):
|
|
524
|
+
def _get_encoder_uncached(self, type_str: TypeStr) -> Encoder:
|
|
458
525
|
return self._get_registration(self._encoders, type_str)
|
|
459
526
|
|
|
527
|
+
def _get_tuple_encoder_uncached(
|
|
528
|
+
self,
|
|
529
|
+
*type_strs: TypeStr,
|
|
530
|
+
) -> encoding.TupleEncoder:
|
|
531
|
+
encoders = tuple(map(self.get_encoder, type_strs))
|
|
532
|
+
return encoding.TupleEncoder(encoders=encoders)
|
|
533
|
+
|
|
460
534
|
def has_encoder(self, type_str: TypeStr) -> bool:
|
|
461
535
|
"""
|
|
462
536
|
Returns ``True`` if an encoder is found for the given type string
|
|
@@ -473,7 +547,7 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
473
547
|
|
|
474
548
|
return True
|
|
475
549
|
|
|
476
|
-
def _get_decoder_uncached(self, type_str, strict=True):
|
|
550
|
+
def _get_decoder_uncached(self, type_str: TypeStr, strict: bool = True) -> Decoder:
|
|
477
551
|
decoder = self._get_registration(self._decoders, type_str)
|
|
478
552
|
|
|
479
553
|
if hasattr(decoder, "is_dynamic") and decoder.is_dynamic:
|
|
@@ -484,7 +558,18 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
484
558
|
|
|
485
559
|
return decoder
|
|
486
560
|
|
|
487
|
-
def
|
|
561
|
+
def _get_tuple_decoder_uncached(
|
|
562
|
+
self,
|
|
563
|
+
*type_strs: TypeStr,
|
|
564
|
+
strict: bool = True,
|
|
565
|
+
) -> decoding.TupleDecoder:
|
|
566
|
+
decoders = tuple(
|
|
567
|
+
self.get_decoder(type_str, strict)
|
|
568
|
+
for type_str in type_strs
|
|
569
|
+
)
|
|
570
|
+
return decoding.TupleDecoder(decoders=decoders)
|
|
571
|
+
|
|
572
|
+
def copy(self) -> Self:
|
|
488
573
|
"""
|
|
489
574
|
Copies a registry such that new registrations can be made or existing
|
|
490
575
|
registrations can be unregistered without affecting any instance from
|
|
@@ -495,22 +580,43 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
495
580
|
"""
|
|
496
581
|
cpy = type(self)()
|
|
497
582
|
|
|
498
|
-
cpy._encoders = copy
|
|
499
|
-
cpy._decoders = copy
|
|
583
|
+
cpy._encoders = copy(self._encoders)
|
|
584
|
+
cpy._decoders = copy(self._decoders)
|
|
500
585
|
|
|
501
586
|
return cpy
|
|
502
587
|
|
|
503
588
|
|
|
504
589
|
registry = ABIRegistry()
|
|
505
590
|
|
|
591
|
+
is_int = BaseEquals("int")
|
|
592
|
+
is_int8 = Equals("int8")
|
|
593
|
+
is_int16 = Equals("int16")
|
|
594
|
+
is_uint = BaseEquals("uint")
|
|
595
|
+
is_uint8 = Equals("uint8")
|
|
596
|
+
is_uint16 = Equals("uint16")
|
|
597
|
+
|
|
598
|
+
for size in (8, 16):
|
|
599
|
+
registry.register(
|
|
600
|
+
Equals(f"uint{size}"),
|
|
601
|
+
encoding.UnsignedIntegerEncoder,
|
|
602
|
+
decoding.UnsignedIntegerDecoder,
|
|
603
|
+
label=f"uint{size}",
|
|
604
|
+
)
|
|
605
|
+
registry.register(
|
|
606
|
+
Equals(f"int{size}"),
|
|
607
|
+
encoding.SignedIntegerEncoder,
|
|
608
|
+
decoding.SignedIntegerDecoder,
|
|
609
|
+
label=f"int{size}",
|
|
610
|
+
)
|
|
611
|
+
|
|
506
612
|
registry.register(
|
|
507
|
-
|
|
613
|
+
lambda s: is_uint(s) and not is_uint8(s) and not is_uint16(s),
|
|
508
614
|
encoding.UnsignedIntegerEncoder,
|
|
509
615
|
decoding.UnsignedIntegerDecoder,
|
|
510
616
|
label="uint",
|
|
511
617
|
)
|
|
512
618
|
registry.register(
|
|
513
|
-
|
|
619
|
+
lambda s: is_int(s) and not is_int8(s) and not is_int16(s),
|
|
514
620
|
encoding.SignedIntegerEncoder,
|
|
515
621
|
decoding.SignedIntegerDecoder,
|
|
516
622
|
label="int",
|
|
@@ -578,13 +684,25 @@ registry.register(
|
|
|
578
684
|
|
|
579
685
|
registry_packed = ABIRegistry()
|
|
580
686
|
|
|
687
|
+
for size in (8, 16):
|
|
688
|
+
registry_packed.register_encoder(
|
|
689
|
+
Equals(f"uint{size}"),
|
|
690
|
+
encoding.PackedUnsignedIntegerEncoderCached,
|
|
691
|
+
label=f"uint{size}",
|
|
692
|
+
)
|
|
693
|
+
registry_packed.register_encoder(
|
|
694
|
+
Equals(f"int{size}"),
|
|
695
|
+
encoding.PackedSignedIntegerEncoderCached,
|
|
696
|
+
label=f"int{size}",
|
|
697
|
+
)
|
|
698
|
+
|
|
581
699
|
registry_packed.register_encoder(
|
|
582
|
-
|
|
700
|
+
lambda s: is_uint(s) and not is_uint8(s) and not is_uint16(s),
|
|
583
701
|
encoding.PackedUnsignedIntegerEncoder,
|
|
584
702
|
label="uint",
|
|
585
703
|
)
|
|
586
704
|
registry_packed.register_encoder(
|
|
587
|
-
|
|
705
|
+
lambda s: is_int(s) and not is_int8(s) and not is_int16(s),
|
|
588
706
|
encoding.PackedSignedIntegerEncoder,
|
|
589
707
|
label="int",
|
|
590
708
|
)
|
|
Binary file
|
|
Binary file
|
|
@@ -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,14 @@ 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,
|
|
22
|
+
Arrlist,
|
|
20
23
|
BasicType,
|
|
21
24
|
TupleType,
|
|
22
25
|
normalize,
|
|
26
|
+
)
|
|
27
|
+
from faster_eth_abi.grammar import (
|
|
23
28
|
parse,
|
|
24
29
|
)
|
|
25
30
|
from faster_eth_abi.registry import (
|
|
@@ -81,7 +86,7 @@ class StrategyRegistry(BaseRegistry):
|
|
|
81
86
|
def get_uint_strategy(
|
|
82
87
|
abi_type: BasicType, registry: StrategyRegistry
|
|
83
88
|
) -> st.SearchStrategy:
|
|
84
|
-
bits = abi_type.sub
|
|
89
|
+
bits = cast(int, abi_type.sub)
|
|
85
90
|
|
|
86
91
|
return st.integers(
|
|
87
92
|
min_value=0,
|
|
@@ -92,7 +97,7 @@ def get_uint_strategy(
|
|
|
92
97
|
def get_int_strategy(
|
|
93
98
|
abi_type: BasicType, registry: StrategyRegistry
|
|
94
99
|
) -> st.SearchStrategy:
|
|
95
|
-
bits = abi_type.sub
|
|
100
|
+
bits = cast(int, abi_type.sub)
|
|
96
101
|
|
|
97
102
|
return st.integers(
|
|
98
103
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -107,7 +112,7 @@ bool_strategy: Final = st.booleans()
|
|
|
107
112
|
def get_ufixed_strategy(
|
|
108
113
|
abi_type: BasicType, registry: StrategyRegistry
|
|
109
114
|
) -> st.SearchStrategy:
|
|
110
|
-
bits, places = abi_type.sub
|
|
115
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
111
116
|
|
|
112
117
|
return st.decimals(
|
|
113
118
|
min_value=0,
|
|
@@ -119,7 +124,7 @@ def get_ufixed_strategy(
|
|
|
119
124
|
def get_fixed_strategy(
|
|
120
125
|
abi_type: BasicType, registry: StrategyRegistry
|
|
121
126
|
) -> st.SearchStrategy:
|
|
122
|
-
bits, places = abi_type.sub
|
|
127
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
123
128
|
|
|
124
129
|
return st.decimals(
|
|
125
130
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -150,7 +155,8 @@ def get_array_strategy(
|
|
|
150
155
|
item_type_str = item_type.to_type_str()
|
|
151
156
|
item_strategy = registry.get_strategy(item_type_str)
|
|
152
157
|
|
|
153
|
-
|
|
158
|
+
arrlist = cast(Arrlist, abi_type.arrlist)
|
|
159
|
+
last_dim = cast(Tuple[int, ...], arrlist[-1])
|
|
154
160
|
if len(last_dim) == 0:
|
|
155
161
|
# Is dynamic list. Don't restrict length.
|
|
156
162
|
return st.lists(item_strategy)
|