From abbe2100a5e7d8d0913e83632fffd77ea2ab75a1 Mon Sep 17 00:00:00 2001 From: pacrob <5199899+pacrob@users.noreply.github.com> Date: Tue, 6 Feb 2024 09:38:15 -0700 Subject: [PATCH] type codec.py and exceptions, change mypy ignore from files to error types, add py.typed back at top level --- .pre-commit-config.yaml | 2 +- eth_abi/base.py | 8 +------- eth_abi/codec.py | 3 ++- eth_abi/decoding.py | 13 +++++++++++-- eth_abi/encoding.py | 6 ++++++ eth_abi/exceptions.py | 4 ++-- eth_abi/grammar.py | 2 +- eth_abi/{tools => }/py.typed | 0 eth_abi/registry.py | 21 +++++++++++++-------- eth_abi/utils/py.typed | 0 newsfragments/221.internal.rst | 1 + pyproject.toml | 3 ++- 12 files changed, 40 insertions(+), 23 deletions(-) rename eth_abi/{tools => }/py.typed (100%) delete mode 100644 eth_abi/utils/py.typed create mode 100644 newsfragments/221.internal.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8303db6c..d435ab36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,4 +48,4 @@ repos: hooks: - id: mypy args: [--follow-imports=silent, --disable-error-code=no-untyped-call] - exclude: tests\/|eth_abi\/(base\.py|registry\.py|grammar\.py|packed\.py|decoding\.py|encoding\.py|exceptions\.py|codec\.py|constants\.py) + exclude: tests/ diff --git a/eth_abi/base.py b/eth_abi/base.py index 9bb5c51f..309cd1d2 100644 --- a/eth_abi/base.py +++ b/eth_abi/base.py @@ -1,9 +1,5 @@ import functools -from eth_typing.abi import ( - TypeStr, -) - from .grammar import ( BasicType, TupleType, @@ -142,9 +138,7 @@ def validate(self): pass @classmethod - def from_type_str( - cls, type_str: TypeStr, registry - ) -> "BaseCoder": # pragma: no cover + def from_type_str(cls, type_str, registry): # pragma: no cover """ Used by :any:`ABIRegistry` to get an appropriate encoder or decoder instance for the given type string and type registry. diff --git a/eth_abi/codec.py b/eth_abi/codec.py index 0e311d61..6b495d2d 100644 --- a/eth_abi/codec.py +++ b/eth_abi/codec.py @@ -2,6 +2,7 @@ Any, Iterable, Tuple, + cast, ) from eth_typing.abi import ( @@ -158,7 +159,7 @@ def decode( decoder = TupleDecoder(decoders=decoders) stream = self.stream_class(data) - return decoder(stream) + return cast(Tuple[Any, ...], decoder(stream)) class ABICodec(ABIEncoder, ABIDecoder): diff --git a/eth_abi/decoding.py b/eth_abi/decoding.py index 7b544eff..118a73c4 100644 --- a/eth_abi/decoding.py +++ b/eth_abi/decoding.py @@ -3,6 +3,7 @@ import io from typing import ( Any, + Generator, ) from eth_utils import ( @@ -144,6 +145,8 @@ def decode(self, stream): start_pos = decode_uint_256(stream) stream.push_frame(start_pos) + if self.tail_decoder is None: + raise AssertionError("`tail_decoder` is None") value = self.tail_decoder(stream) stream.pop_frame() @@ -169,8 +172,8 @@ def validate(self): if self.decoders is None: raise ValueError("No `decoders` set") - @to_tuple - def decode(self, stream): + @to_tuple # type: ignore[misc] # untyped decorator + def decode(self, stream: ContextFramesBytesIO) -> Generator[Any, None, None]: for decoder in self.decoders: yield decoder(stream) @@ -198,6 +201,8 @@ def validate_padding_bytes(self, value, padding_bytes): def decode(self, stream): raw_data = self.read_data_from_stream(stream) data, padding_bytes = self.split_data_and_padding(raw_data) + if self.decoder_fn is None: + raise AssertionError("`decoder_fn` is None") value = self.decoder_fn(data) self.validate_padding_bytes(value, padding_bytes) @@ -254,6 +259,8 @@ def __init__(self, **kwargs): @to_tuple def decode(self, stream): + if self.item_decoder is None: + raise AssertionError("`item_decoder` is None") for _ in range(self.array_size): yield self.item_decoder(stream) @@ -266,6 +273,8 @@ class DynamicArrayDecoder(BaseArrayDecoder): def decode(self, stream): array_size = decode_uint_256(stream) stream.push_frame(32) + if self.item_decoder is None: + raise AssertionError("`item_decoder` is None") for _ in range(array_size): yield self.item_decoder(stream) stream.pop_frame() diff --git a/eth_abi/encoding.py b/eth_abi/encoding.py index d582ac03..8cf90da6 100644 --- a/eth_abi/encoding.py +++ b/eth_abi/encoding.py @@ -193,6 +193,8 @@ def validate_value(self, value): def encode(self, value): self.validate_value(value) + if self.encode_fn is None: + raise AssertionError("`encode_fn` is None") base_encoded_value = self.encode_fn(value) if self.is_big_endian: @@ -249,6 +251,8 @@ def validate(self): raise ValueError("`type_check_fn` cannot be null") def validate_value(self, value): + if self.type_check_fn is None: + raise AssertionError("`type_check_fn` is None") if not self.type_check_fn(value): self.invalidate_value(value) @@ -586,6 +590,8 @@ def encode_elements(self, value): self.validate_value(value) item_encoder = self.item_encoder + if item_encoder is None: + raise AssertionError("`item_encoder` is None") tail_chunks = tuple(item_encoder(i) for i in value) items_are_dynamic = getattr(item_encoder, "is_dynamic", False) diff --git a/eth_abi/exceptions.py b/eth_abi/exceptions.py index 0e1692a1..2ab204ad 100644 --- a/eth_abi/exceptions.py +++ b/eth_abi/exceptions.py @@ -58,12 +58,12 @@ class NonEmptyPaddingBytes(DecodingError): """ -class ParseError(parsimonious.ParseError): +class ParseError(parsimonious.ParseError): # type: ignore[misc] # subclasses Any """ Raised when an ABI type string cannot be parsed. """ - def __str__(self): + def __str__(self) -> str: return ( f"Parse error at '{self.text[self.pos : self.pos + 5]}' " f"(column {self.column()}) in type string '{self.text}'" diff --git a/eth_abi/grammar.py b/eth_abi/grammar.py index 01925220..b7a937ce 100644 --- a/eth_abi/grammar.py +++ b/eth_abi/grammar.py @@ -38,7 +38,7 @@ ) -class NodeVisitor(parsimonious.NodeVisitor): +class NodeVisitor(parsimonious.NodeVisitor): # type: ignore[misc] # subclasses Any """ Parsimonious node visitor which performs both parsing of type strings and post-processing of parse trees. Parsing operations are cached. diff --git a/eth_abi/tools/py.typed b/eth_abi/py.typed similarity index 100% rename from eth_abi/tools/py.typed rename to eth_abi/py.typed diff --git a/eth_abi/registry.py b/eth_abi/registry.py index 13f078e7..221aaeaf 100644 --- a/eth_abi/registry.py +++ b/eth_abi/registry.py @@ -4,6 +4,7 @@ from typing import ( Any, Callable, + Optional, Type, Union, ) @@ -276,18 +277,18 @@ def is_base_tuple(type_str): return isinstance(abi_type, grammar.TupleType) and abi_type.arrlist is None -def _clear_encoder_cache(old_method): +def _clear_encoder_cache(old_method: Callable[..., None]) -> Callable[..., None]: @functools.wraps(old_method) - def new_method(self, *args, **kwargs): + def new_method(self: "ABIRegistry", *args: Any, **kwargs: Any) -> None: self.get_encoder.cache_clear() return old_method(self, *args, **kwargs) return new_method -def _clear_decoder_cache(old_method): +def _clear_decoder_cache(old_method: Callable[..., None]) -> Callable[..., None]: @functools.wraps(old_method) - def new_method(self, *args, **kwargs): + def new_method(self: "ABIRegistry", *args: Any, **kwargs: Any) -> None: self.get_decoder.cache_clear() return old_method(self, *args, **kwargs) @@ -354,7 +355,7 @@ def _get_registration(self, mapping, type_str): @_clear_encoder_cache def register_encoder( - self, lookup: Lookup, encoder: Encoder, label: str = None + self, lookup: Lookup, encoder: Encoder, label: Optional[str] = None ) -> None: """ Registers the given ``encoder`` under the given ``lookup``. A unique @@ -377,7 +378,7 @@ def unregister_encoder(self, lookup_or_label: Lookup) -> None: @_clear_decoder_cache def register_decoder( - self, lookup: Lookup, decoder: Decoder, label: str = None + self, lookup: Lookup, decoder: Decoder, label: Optional[str] = None ) -> None: """ Registers the given ``decoder`` under the given ``lookup``. A unique @@ -399,7 +400,11 @@ def unregister_decoder(self, lookup_or_label: Lookup) -> None: self._unregister(self._decoders, lookup_or_label) def register( - self, lookup: Lookup, encoder: Encoder, decoder: Decoder, label: str = None + self, + lookup: Lookup, + encoder: Encoder, + decoder: Decoder, + label: Optional[str] = None, ) -> None: """ Registers the given ``encoder`` and ``decoder`` under the given @@ -438,7 +443,7 @@ def register( self.register_encoder(lookup, encoder, label=label) self.register_decoder(lookup, decoder, label=label) - def unregister(self, label: str) -> None: + def unregister(self, label: Optional[str]) -> None: """ Unregisters the entries in the encoder and decoder registries which have the label ``label``. diff --git a/eth_abi/utils/py.typed b/eth_abi/utils/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/newsfragments/221.internal.rst b/newsfragments/221.internal.rst new file mode 100644 index 00000000..88b0b22d --- /dev/null +++ b/newsfragments/221.internal.rst @@ -0,0 +1 @@ +Clear mypy ``misc``-type errors and add top-level ``py.typed`` file back diff --git a/pyproject.toml b/pyproject.toml index d8036d58..6caae5d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ profile = "black" [tool.mypy] check_untyped_defs = true disallow_incomplete_defs = true -disallow_untyped_defs = true +disallow_untyped_defs = false disallow_any_generics = true disallow_untyped_calls = true disallow_untyped_decorators = true @@ -27,6 +27,7 @@ warn_redundant_casts = true warn_return_any = true warn_unused_configs = true warn_unused_ignores = true +disable_error_code = ["arg-type", "call-arg", "call-overload", "assignment", "operator", "var-annotated", "attr-defined", "has-type", "union-attr"] [tool.pydocstyle]