faster-eth-abi 5.2.22__cp313-cp313-macosx_11_0_arm64.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.
Files changed (46) hide show
  1. faster_eth_abi/__init__.py +12 -0
  2. faster_eth_abi/_codec.cpython-313-darwin.so +0 -0
  3. faster_eth_abi/_codec.py +83 -0
  4. faster_eth_abi/_decoding.cpython-313-darwin.so +0 -0
  5. faster_eth_abi/_decoding.py +299 -0
  6. faster_eth_abi/_encoding.cpython-313-darwin.so +0 -0
  7. faster_eth_abi/_encoding.py +354 -0
  8. faster_eth_abi/_grammar.cpython-313-darwin.so +0 -0
  9. faster_eth_abi/_grammar.py +375 -0
  10. faster_eth_abi/abi.cpython-313-darwin.so +0 -0
  11. faster_eth_abi/abi.py +17 -0
  12. faster_eth_abi/base.py +45 -0
  13. faster_eth_abi/codec.py +2809 -0
  14. faster_eth_abi/constants.cpython-313-darwin.so +0 -0
  15. faster_eth_abi/constants.py +7 -0
  16. faster_eth_abi/decoding.py +584 -0
  17. faster_eth_abi/encoding.py +746 -0
  18. faster_eth_abi/exceptions.py +127 -0
  19. faster_eth_abi/from_type_str.cpython-313-darwin.so +0 -0
  20. faster_eth_abi/from_type_str.py +141 -0
  21. faster_eth_abi/grammar.py +172 -0
  22. faster_eth_abi/io.py +107 -0
  23. faster_eth_abi/packed.cpython-313-darwin.so +0 -0
  24. faster_eth_abi/packed.py +19 -0
  25. faster_eth_abi/py.typed +0 -0
  26. faster_eth_abi/registry.py +758 -0
  27. faster_eth_abi/tools/__init__.cpython-313-darwin.so +0 -0
  28. faster_eth_abi/tools/__init__.py +3 -0
  29. faster_eth_abi/tools/_strategies.cpython-313-darwin.so +0 -0
  30. faster_eth_abi/tools/_strategies.py +243 -0
  31. faster_eth_abi/typing.py +4627 -0
  32. faster_eth_abi/utils/__init__.cpython-313-darwin.so +0 -0
  33. faster_eth_abi/utils/__init__.py +0 -0
  34. faster_eth_abi/utils/numeric.cpython-313-darwin.so +0 -0
  35. faster_eth_abi/utils/numeric.py +117 -0
  36. faster_eth_abi/utils/padding.cpython-313-darwin.so +0 -0
  37. faster_eth_abi/utils/padding.py +22 -0
  38. faster_eth_abi/utils/string.cpython-313-darwin.so +0 -0
  39. faster_eth_abi/utils/string.py +19 -0
  40. faster_eth_abi/utils/validation.cpython-313-darwin.so +0 -0
  41. faster_eth_abi/utils/validation.py +18 -0
  42. faster_eth_abi-5.2.22.dist-info/METADATA +136 -0
  43. faster_eth_abi-5.2.22.dist-info/RECORD +46 -0
  44. faster_eth_abi-5.2.22.dist-info/WHEEL +6 -0
  45. faster_eth_abi-5.2.22.dist-info/top_level.txt +2 -0
  46. faster_eth_abi__mypyc.cpython-313-darwin.so +0 -0
@@ -0,0 +1,127 @@
1
+ # mypy: disable-error-code="misc"
2
+ # cannot subclass `Any`
3
+
4
+ """
5
+ Exception classes for error handling during ABI encoding and decoding operations.
6
+
7
+ faster-eth-abi exceptions always inherit from eth-abi exceptions, so porting to faster-eth-abi
8
+ does not require any change to your existing exception handlers. They will continue to work.
9
+ """
10
+
11
+ import eth_abi.exceptions
12
+
13
+
14
+ class EncodingError(eth_abi.exceptions.EncodingError):
15
+ """
16
+ Base exception for any error that occurs during encoding.
17
+ """
18
+
19
+
20
+ class EncodingTypeError(EncodingError, eth_abi.exceptions.EncodingTypeError):
21
+ """
22
+ Raised when trying to encode a python value whose type is not supported for
23
+ the output ABI type.
24
+ """
25
+
26
+
27
+ class IllegalValue(EncodingError, eth_abi.exceptions.IllegalValue):
28
+ """
29
+ Raised when trying to encode a python value with the correct type but with
30
+ a value that is not considered legal for the output ABI type.
31
+
32
+ .. code-block:: python
33
+
34
+ fixed128x19_encoder(Decimal('NaN')) # cannot encode NaN
35
+
36
+ """
37
+
38
+
39
+ class ValueOutOfBounds(IllegalValue, eth_abi.exceptions.ValueOutOfBounds):
40
+ """
41
+ Raised when trying to encode a python value with the correct type but with
42
+ a value that appears outside the range of valid values for the output ABI
43
+ type.
44
+
45
+ .. code-block:: python
46
+
47
+ ufixed8x1_encoder(Decimal('25.6')) # out of bounds
48
+
49
+ """
50
+
51
+
52
+ class DecodingError(eth_abi.exceptions.DecodingError):
53
+ """
54
+ Base exception for any error that occurs during decoding.
55
+ """
56
+
57
+
58
+ class InsufficientDataBytes(DecodingError, eth_abi.exceptions.InsufficientDataBytes):
59
+ """
60
+ Raised when there are insufficient data to decode a value for a given ABI type.
61
+ """
62
+
63
+
64
+ class NonEmptyPaddingBytes(DecodingError, eth_abi.exceptions.NonEmptyPaddingBytes):
65
+ """
66
+ Raised when the padding bytes of an ABI value are malformed.
67
+ """
68
+
69
+
70
+ class InvalidPointer(DecodingError, eth_abi.exceptions.InvalidPointer):
71
+ """
72
+ Raised when the pointer to a value in the ABI encoding is invalid.
73
+ """
74
+
75
+
76
+ class ParseError(eth_abi.exceptions.ParseError):
77
+ """
78
+ Raised when an ABI type string cannot be parsed.
79
+ """
80
+
81
+ def __str__(self) -> str:
82
+ return (
83
+ f"Parse error at '{self.text[self.pos : self.pos + 5]}' "
84
+ f"(column {self.column()}) in type string '{self.text}'"
85
+ )
86
+
87
+
88
+ class ABITypeError(eth_abi.exceptions.ABITypeError):
89
+ """
90
+ Raised when a parsed ABI type has inconsistent properties; for example,
91
+ when trying to parse the type string ``'uint7'`` (which has a bit-width
92
+ that is not congruent with zero modulo eight).
93
+ """
94
+
95
+
96
+ class PredicateMappingError(eth_abi.exceptions.PredicateMappingError):
97
+ """
98
+ Raised when an error occurs in a registry's internal mapping.
99
+ """
100
+
101
+
102
+ class NoEntriesFound(PredicateMappingError, eth_abi.exceptions.NoEntriesFound):
103
+ """
104
+ Raised when no registration is found for a type string in a registry's
105
+ internal mapping.
106
+
107
+ .. warning::
108
+
109
+ In a future version of ``faster-eth-abi``, this error class will no longer
110
+ inherit from ``ValueError``.
111
+ """
112
+
113
+
114
+ class MultipleEntriesFound(
115
+ PredicateMappingError, eth_abi.exceptions.MultipleEntriesFound
116
+ ):
117
+ """
118
+ Raised when multiple registrations are found for a type string in a
119
+ registry's internal mapping. This error is non-recoverable and indicates
120
+ that a registry was configured incorrectly. Registrations are expected to
121
+ cover completely distinct ranges of type strings.
122
+
123
+ .. warning::
124
+
125
+ In a future version of ``faster-eth-abi``, this error class will no longer
126
+ inherit from ``ValueError``.
127
+ """
@@ -0,0 +1,141 @@
1
+ """Helpers for parsing and normalizing ABI type strings.
2
+
3
+ Provides decorators and utilities for implementing from_type_str methods on coder classes.
4
+ """
5
+ import functools
6
+ from typing import (
7
+ TYPE_CHECKING,
8
+ Any,
9
+ Callable,
10
+ Optional,
11
+ Type,
12
+ TypeVar,
13
+ )
14
+
15
+ from eth_typing import (
16
+ TypeStr,
17
+ )
18
+
19
+ from ._grammar import (
20
+ ABIType,
21
+ BasicType,
22
+ TupleType,
23
+ normalize,
24
+ )
25
+ from .grammar import (
26
+ parse,
27
+ )
28
+
29
+ if TYPE_CHECKING:
30
+ from .base import (
31
+ BaseCoder,
32
+ )
33
+
34
+
35
+ TType = TypeVar("TType", bound=Type["BaseCoder"])
36
+ OldFromTypeStr = Callable[["BaseCoder", ABIType, Any], TType]
37
+ if TYPE_CHECKING:
38
+ NewFromTypeStr = classmethod[TType, [TypeStr, Any], TType]
39
+
40
+
41
+ def parse_type_str(
42
+ expected_base: Optional[str] = None,
43
+ with_arrlist: bool = False,
44
+ ) -> Callable[[OldFromTypeStr[TType]], "NewFromTypeStr[TType]"]:
45
+ """
46
+ Used by BaseCoder subclasses as a convenience for implementing the
47
+ ``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
48
+ then parsing a type string with an (optional) expected base is required in
49
+ that method.
50
+ """
51
+
52
+ def decorator(old_from_type_str: OldFromTypeStr[TType]) -> "NewFromTypeStr[TType]":
53
+ @functools.wraps(old_from_type_str)
54
+ def new_from_type_str(cls: TType, type_str: TypeStr, registry: Any) -> TType:
55
+ normalized_type_str = normalize(type_str)
56
+ abi_type = parse(normalized_type_str)
57
+
58
+ type_str_repr = repr(type_str)
59
+ if type_str != normalized_type_str:
60
+ type_str_repr = (
61
+ f"{type_str_repr} (normalized to {normalized_type_str!r})"
62
+ )
63
+
64
+ if expected_base is not None:
65
+ if not isinstance(abi_type, BasicType):
66
+ raise ValueError(
67
+ "Cannot create {} for non-basic type {}".format(
68
+ cls.__name__,
69
+ type_str_repr,
70
+ )
71
+ )
72
+ if abi_type.base != expected_base:
73
+ raise ValueError(
74
+ "Cannot create {} for type {}: expected type with "
75
+ "base '{}'".format(
76
+ cls.__name__,
77
+ type_str_repr,
78
+ expected_base,
79
+ )
80
+ )
81
+
82
+ if not with_arrlist and abi_type.arrlist is not None:
83
+ raise ValueError(
84
+ "Cannot create {} for type {}: expected type with "
85
+ "no array dimension list".format(
86
+ cls.__name__,
87
+ type_str_repr,
88
+ )
89
+ )
90
+ if with_arrlist and abi_type.arrlist is None:
91
+ raise ValueError(
92
+ "Cannot create {} for type {}: expected type with "
93
+ "array dimension list".format(
94
+ cls.__name__,
95
+ type_str_repr,
96
+ )
97
+ )
98
+
99
+ # Perform general validation of default solidity types
100
+ abi_type.validate()
101
+
102
+ return old_from_type_str(cls, abi_type, registry)
103
+
104
+ return classmethod(new_from_type_str)
105
+
106
+ return decorator
107
+
108
+
109
+ def parse_tuple_type_str(
110
+ old_from_type_str: OldFromTypeStr[TType],
111
+ ) -> "NewFromTypeStr[TType]":
112
+ """
113
+ Used by BaseCoder subclasses as a convenience for implementing the
114
+ ``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
115
+ then parsing a tuple type string is required in that method.
116
+ """
117
+
118
+ @functools.wraps(old_from_type_str)
119
+ def new_from_type_str(cls: TType, type_str: TypeStr, registry: Any) -> TType:
120
+ normalized_type_str = normalize(type_str)
121
+ abi_type = parse(normalized_type_str)
122
+
123
+ if not isinstance(abi_type, TupleType):
124
+ type_str_repr = repr(type_str)
125
+ if type_str != normalized_type_str:
126
+ type_str_repr = "{} (normalized to {})".format(
127
+ type_str_repr,
128
+ repr(normalized_type_str),
129
+ )
130
+ raise ValueError(
131
+ "Cannot create {} for non-tuple type {}".format(
132
+ cls.__name__,
133
+ type_str_repr,
134
+ )
135
+ )
136
+
137
+ abi_type.validate()
138
+
139
+ return old_from_type_str(cls, abi_type, registry)
140
+
141
+ return classmethod(new_from_type_str)
@@ -0,0 +1,172 @@
1
+ """Parsing and normalization logic for ABI type strings.
2
+
3
+ Implements grammar, parsing, and type validation for ABI type strings.
4
+ """
5
+ import functools
6
+ from typing import (
7
+ Any,
8
+ Final,
9
+ final,
10
+ )
11
+
12
+ import parsimonious
13
+ from eth_typing import (
14
+ TypeStr,
15
+ )
16
+ from parsimonious import (
17
+ expressions,
18
+ )
19
+
20
+ from faster_eth_abi._grammar import (
21
+ TYPE_ALIAS_RE,
22
+ TYPE_ALIASES,
23
+ ABIType,
24
+ BasicType,
25
+ TupleType,
26
+ normalize,
27
+ )
28
+ from faster_eth_abi.exceptions import (
29
+ ParseError,
30
+ )
31
+
32
+ grammar: Final = parsimonious.Grammar(
33
+ r"""
34
+ type = tuple_type / basic_type
35
+
36
+ tuple_type = components arrlist?
37
+ components = non_zero_tuple
38
+
39
+ non_zero_tuple = "(" type next_type* ")"
40
+ next_type = "," type
41
+
42
+ basic_type = base sub? arrlist?
43
+
44
+ base = alphas
45
+
46
+ sub = two_size / digits
47
+ two_size = (digits "x" digits)
48
+
49
+ arrlist = (const_arr / dynam_arr)+
50
+ const_arr = "[" digits "]"
51
+ dynam_arr = "[]"
52
+
53
+ alphas = ~"[A-Za-z]+"
54
+ digits = ~"[1-9][0-9]*"
55
+ """
56
+ )
57
+
58
+
59
+ @final
60
+ class NodeVisitor(parsimonious.NodeVisitor):
61
+ """
62
+ Parsimonious node visitor which performs both parsing of type strings and
63
+ post-processing of parse trees. Parsing operations are cached.
64
+ """
65
+
66
+ def __init__(self) -> None:
67
+ self.parse: Final = functools.lru_cache(maxsize=None)(self._parse_uncached)
68
+
69
+ grammar = grammar
70
+
71
+ def visit_non_zero_tuple(self, node, visited_children):
72
+ # Ignore left and right parens
73
+ _, first, rest, _ = visited_children
74
+
75
+ return (first,) + rest
76
+
77
+ def visit_tuple_type(self, node, visited_children):
78
+ components, arrlist = visited_children
79
+
80
+ return TupleType(components, arrlist, node=node)
81
+
82
+ def visit_next_type(self, node, visited_children):
83
+ # Ignore comma
84
+ _, abi_type = visited_children
85
+
86
+ return abi_type
87
+
88
+ def visit_basic_type(self, node, visited_children):
89
+ base, sub, arrlist = visited_children
90
+
91
+ return BasicType(base, sub, arrlist, node=node)
92
+
93
+ def visit_two_size(self, node, visited_children):
94
+ # Ignore "x"
95
+ first, _, second = visited_children
96
+
97
+ return first, second
98
+
99
+ def visit_const_arr(self, node, visited_children):
100
+ # Ignore left and right brackets
101
+ _, int_value, _ = visited_children
102
+
103
+ return (int_value,)
104
+
105
+ def visit_dynam_arr(self, node, visited_children):
106
+ return ()
107
+
108
+ def visit_alphas(self, node, visited_children):
109
+ return node.text
110
+
111
+ def visit_digits(self, node, visited_children):
112
+ return int(node.text)
113
+
114
+ def generic_visit(self, node, visited_children):
115
+ expr = node.expr
116
+ if isinstance(expr, expressions.OneOf):
117
+ # Unwrap value chosen from alternatives
118
+ return visited_children[0]
119
+
120
+ if isinstance(expr, expressions.Quantifier) and expr.min == 0 and expr.max == 1:
121
+ # Unwrap optional value or return `None`
122
+ if len(visited_children) != 0:
123
+ return visited_children[0]
124
+
125
+ return None
126
+
127
+ return tuple(visited_children)
128
+
129
+ def _parse_uncached(self, type_str: TypeStr, **kwargs: Any) -> ABIType:
130
+ """
131
+ Parses a type string into an appropriate instance of
132
+ :class:`~faster_eth_abi.grammar.ABIType`. If a type string cannot be parsed,
133
+ throws :class:`~faster_eth_abi.exceptions.ParseError`.
134
+
135
+ :param type_str: The type string to be parsed.
136
+ :returns: An instance of :class:`~faster_eth_abi.grammar.ABIType` containing
137
+ information about the parsed type string.
138
+ """
139
+ if not isinstance(type_str, str):
140
+ raise TypeError(f"Can only parse string values: got {type(type_str)}")
141
+
142
+ try:
143
+ return super().parse(type_str, **kwargs)
144
+ except parsimonious.ParseError as e:
145
+ # This is a good place to add some better messaging around the type string.
146
+ # If this logic grows any bigger, we should abstract it to its own function.
147
+ if "()" in type_str:
148
+ # validate against zero-sized tuple types
149
+ raise ValueError(
150
+ 'Zero-sized tuple types "()" are not supported.'
151
+ ) from None
152
+
153
+ raise ParseError(e.text, e.pos, e.expr) from e
154
+
155
+
156
+ visitor: Final = NodeVisitor()
157
+
158
+ parse: Final = visitor.parse
159
+
160
+
161
+ __all__ = [
162
+ "NodeVisitor",
163
+ "ABIType",
164
+ "TupleType",
165
+ "BasicType",
166
+ "grammar",
167
+ "parse",
168
+ "normalize",
169
+ "visitor",
170
+ "TYPE_ALIASES",
171
+ "TYPE_ALIAS_RE",
172
+ ]
faster_eth_abi/io.py ADDED
@@ -0,0 +1,107 @@
1
+ """Context-aware byte stream for ABI decoding.
2
+
3
+ Implements a BytesIO subclass that supports contextual frame management for nested ABI decoding.
4
+ """
5
+ from io import (
6
+ BytesIO,
7
+ )
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Final,
12
+ List,
13
+ Tuple,
14
+ final,
15
+ )
16
+
17
+ from mypy_extensions import (
18
+ mypyc_attr,
19
+ )
20
+
21
+ if TYPE_CHECKING:
22
+ from _typeshed import (
23
+ ReadableBuffer,
24
+ )
25
+
26
+
27
+ @final
28
+ @mypyc_attr(allow_interpreted_subclasses=True)
29
+ class ContextFramesBytesIO(BytesIO):
30
+ """
31
+ A byte stream which can track a series of contextual frames in a stack. This
32
+ data structure is necessary to perform nested decodings using the
33
+ :py:class:``HeadTailDecoder`` since offsets present in head sections are
34
+ relative only to a particular encoded object. These offsets can only be
35
+ used to locate a position in a decoding stream if they are paired with a
36
+ contextual offset that establishes the position of the object in which they
37
+ are found.
38
+
39
+ For example, consider the encoding of a value for the following type::
40
+
41
+ type: (int,(int,int[]))
42
+ value: (1,(2,[3,3]))
43
+
44
+ There are two tuples in this type: one inner and one outer. The inner tuple
45
+ type contains a dynamic type ``int[]`` and, therefore, is itself dynamic.
46
+ This means that its value encoding will be placed in the tail section of the
47
+ outer tuple's encoding. Furthermore, the inner tuple's encoding will,
48
+ itself, contain a tail section with the encoding for ``[3,3]``. All
49
+ together, the encoded value of ``(1,(2,[3,3]))`` would look like this (the
50
+ data values are normally 32 bytes wide but have been truncated to remove the
51
+ redundant zeros at the beginnings of their encodings)::
52
+
53
+ offset data
54
+ --------------------------
55
+ ^ 0 0x01
56
+ | 32 0x40 <-- Offset of object A in global frame (64)
57
+ -----|--------------------
58
+ Global frame ^ 64 0x02 <-- Beginning of object A (64 w/offset 0 = 64)
59
+ | | 96 0x40 <-- Offset of object B in frame of object A (64)
60
+ -----|-Object A's frame---
61
+ | | 128 0x02 <-- Beginning of object B (64 w/offset 64 = 128)
62
+ | | 160 0x03
63
+ v v 192 0x03
64
+ --------------------------
65
+
66
+ Note that the offset of object B is encoded as 64 which only specifies the
67
+ beginning of its encoded value relative to the beginning of object A's
68
+ encoding. Globally, object B is located at offset 128. In order to make
69
+ sense out of object B's offset, it needs to be positioned in the context of
70
+ its enclosing object's frame (object A).
71
+ """
72
+
73
+ def __init__(self, initial_bytes: "ReadableBuffer"):
74
+ super().__init__(initial_bytes)
75
+
76
+ self._frames: Final[List[Tuple[int, int]]] = []
77
+ self._total_offset = 0
78
+
79
+ def seek_in_frame(self, pos: int, *args: Any, **kwargs: Any) -> None:
80
+ """
81
+ Seeks relative to the total offset of the current contextual frames.
82
+ """
83
+ self.seek(self._total_offset + pos, *args, **kwargs)
84
+
85
+ def push_frame(self, offset: int) -> None:
86
+ """
87
+ Pushes a new contextual frame onto the stack with the given offset and a
88
+ return position at the current cursor position then seeks to the new
89
+ total offset.
90
+ """
91
+ self._frames.append((offset, self.tell()))
92
+ self._total_offset += offset
93
+
94
+ self.seek_in_frame(0)
95
+
96
+ def pop_frame(self) -> None:
97
+ """
98
+ Pops the current contextual frame off of the stack and returns the
99
+ cursor to the frame's return position.
100
+ """
101
+ try:
102
+ offset, return_pos = self._frames.pop()
103
+ except IndexError:
104
+ raise IndexError("no frames to pop")
105
+ self._total_offset -= offset
106
+
107
+ self.seek(return_pos)
@@ -0,0 +1,19 @@
1
+ """Helpers for packed ABI encoding.
2
+
3
+ Defines functions and registry for packed encoding and encodability checks.
4
+ """
5
+ from typing import (
6
+ Final,
7
+ )
8
+
9
+ from .codec import (
10
+ ABIEncoder,
11
+ )
12
+ from .registry import (
13
+ registry_packed,
14
+ )
15
+
16
+ default_encoder_packed: Final = ABIEncoder(registry_packed)
17
+
18
+ encode_packed: Final = default_encoder_packed.encode
19
+ is_encodable_packed: Final = default_encoder_packed.is_encodable
File without changes