diff --git a/Makefile b/Makefile index e3ff8e455c..e87dd14d1f 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,9 @@ SOLIDITY_FILE_NAME = deposit_contract.json DEPOSIT_CONTRACT_TESTER_DIR = ${SOLIDITY_DEPOSIT_CONTRACT_DIR}/web3_tester CONFIGS_DIR = ./configs +CURRENT_DIR = ${CURDIR} +MYPY_STUBS_DIR = $(CURRENT_DIR)/mypy_stubs + # Collect a list of generator names GENERATORS = $(sort $(dir $(wildcard $(GENERATOR_DIR)/*/.))) # Map this list of generator paths to "gen_{generator name}" entries @@ -44,6 +47,8 @@ export DAPP_SRC:=$(SOLIDITY_DEPOSIT_CONTRACT_DIR) export DAPP_LIB:=$(SOLIDITY_DEPOSIT_CONTRACT_DIR)/lib export DAPP_JSON:=build/combined.json +MYPY_CONFIG_NAME = mypy.ini + .PHONY: clean partial_clean all test citest lint generate_tests pyspec install_test open_cov \ install_deposit_contract_tester test_deposit_contract install_deposit_contract_compiler \ compile_deposit_contract test_compile_deposit_contract check_toc \ @@ -136,6 +141,7 @@ codespell: lint: pyspec . venv/bin/activate; cd $(PY_SPEC_DIR); \ flake8 --config $(LINTER_CONFIG_FILE) ./eth2spec \ + && export MYPYPATH=$(MYPY_STUBS_DIR) \ && pylint --disable=all --enable unused-argument ./eth2spec/phase0 ./eth2spec/altair ./eth2spec/bellatrix \ && mypy --config-file $(LINTER_CONFIG_FILE) -p eth2spec.phase0 -p eth2spec.altair -p eth2spec.bellatrix -p eth2spec.capella diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000000..9c02106de3 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,11 @@ +[mypy] + +disallow_incomplete_defs = True +disallow_untyped_defs = True +disallow_subclassing_any = True + +warn_unused_ignores = True +warn_unused_configs = True +warn_redundant_casts = True + +ignore_missing_imports = True diff --git a/mypy_stubs/__init__.py b/mypy_stubs/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mypy_stubs/__init__.pyi b/mypy_stubs/__init__.pyi new file mode 100644 index 0000000000..a32cfa53c1 --- /dev/null +++ b/mypy_stubs/__init__.pyi @@ -0,0 +1,4 @@ +# Stubs for remerkleable (Python 3) +# +# NOTE: This dynamically typed stub was automatically generated by stubgen. + diff --git a/mypy_stubs/eth2spec/utils/ssz/__init__.pyi b/mypy_stubs/eth2spec/utils/ssz/__init__.pyi new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mypy_stubs/eth2spec/utils/ssz/ssz_impl.pyi b/mypy_stubs/eth2spec/utils/ssz/ssz_impl.pyi new file mode 100644 index 0000000000..36d441ae3e --- /dev/null +++ b/mypy_stubs/eth2spec/utils/ssz/ssz_impl.pyi @@ -0,0 +1,11 @@ +from remerkleable.basic import uint as uint +from remerkleable.byte_arrays import Bytes32 +from remerkleable.core import View +from typing import TypeVar + +def serialize(obj: View) -> bytes: ... +def hash_tree_root(obj: View) -> Bytes32: ... +def uint_to_bytes(n: uint) -> bytes: ... +V = TypeVar('V', bound=View) + +def copy(obj: V) -> V: ... diff --git a/mypy_stubs/eth2spec/utils/ssz/ssz_typing.pyi b/mypy_stubs/eth2spec/utils/ssz/ssz_typing.pyi new file mode 100644 index 0000000000..dbe22d5728 --- /dev/null +++ b/mypy_stubs/eth2spec/utils/ssz/ssz_typing.pyi @@ -0,0 +1,8 @@ +from remerkleable.basic import bit as bit, boolean as boolean, byte as byte, uint as uint, uint128 as uint128, uint16 as uint16, uint256 as uint256, uint32 as uint32, uint64 as uint64, uint8 as uint8 +from remerkleable.bitfields import Bitlist as Bitlist, Bitvector as Bitvector +from remerkleable.byte_arrays import ByteList as ByteList, Bytes1 as Bytes1, Bytes32 as Bytes32, Bytes4 as Bytes4, Bytes48 as Bytes48, Bytes8 as Bytes8, Bytes96 as Bytes96 +from remerkleable.complex import Container as Container, List as List, Vector as Vector +from remerkleable.core import BasicView as BasicView, Path as Path, View as View +from typing import Any + +Bytes20: Any diff --git a/mypy_stubs/remerkleable/__init__.pyi b/mypy_stubs/remerkleable/__init__.pyi new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mypy_stubs/remerkleable/basic.pyi b/mypy_stubs/remerkleable/basic.pyi new file mode 100644 index 0000000000..6c62875425 --- /dev/null +++ b/mypy_stubs/remerkleable/basic.pyi @@ -0,0 +1,100 @@ +from remerkleable.core import BasicView as BasicView, ObjParseException as ObjParseException, ObjType as ObjType, View as View +from typing import Any, Type, TypeVar + +V = TypeVar('V', bound=View) + +class OperationNotSupported(Exception): ... +BoolV = TypeVar('BoolV', bound='boolean') + +class boolean(int, BasicView): + def encode_bytes(self) -> bytes: ... + def __new__(cls: Any, value: int) -> Any: ... + def __add__(self, other: Any) -> None: ... + def __sub__(self, other: Any) -> None: ... + def __mul__(self, other: Any) -> None: ... + def __floordiv__(self, other: Any) -> None: ... + def __truediv__(self, other: Any) -> None: ... + def __bool__(self): ... + @classmethod + def coerce_view(cls: Type[BoolV], v: Any) -> BoolV: ... + @classmethod + def type_byte_length(cls: Any) -> int: ... + @classmethod + def decode_bytes(cls: Type[BoolV], bytez: bytes) -> BoolV: ... + @classmethod + def from_obj(cls: Type[BoolV], obj: ObjType) -> BoolV: ... + def to_obj(self) -> ObjType: ... + @classmethod + def type_repr(cls: Any) -> str: ... +T = TypeVar('T', bound='uint') +W = TypeVar('W', bound=int) + +class uint(int, BasicView): + def __new__(cls: Any, value: int) -> Any: ... + def __add__(self, other: int) -> T: ... + def __radd__(self, other: int) -> T: ... + def __sub__(self, other: int) -> T: ... + def __rsub__(self, other: int) -> T: ... + def __mul__(self, other: Any): ... + def __rmul__(self, other: Any): ... + def __mod__(self, other: int) -> T: ... + def __rmod__(self, other: int) -> T: ... + def __floordiv__(self, other: int) -> T: ... + def __rfloordiv__(self, other: int) -> T: ... + def __truediv__(self, other: Any) -> None: ... + def __rtruediv__(self, other: Any) -> None: ... + def __pow__(self, other: int, modulo: Any=...) -> T: ... + def __rpow__(self, other: Any, modulo: Any=...) -> T: ... + def __lshift__(self, other: int) -> T: ... + def __rlshift__(self, other: W) -> W: ... + def __rshift__(self, other: int) -> T: ... + def __rrshift__(self, other: W) -> W: ... + def __and__(self, other: int) -> T: ... + def __rand__(self, other: int) -> T: ... + def __xor__(self, other: int) -> T: ... + def __rxor__(self, other: int) -> T: ... + def __or__(self, other: int) -> T: ... + def __ror__(self, other: int) -> T: ... + def __neg__(self) -> None: ... + def __invert__(self) -> T: ... + def __pos__(self) -> T: ... + def __abs__(self) -> T: ... + @classmethod + def coerce_view(cls: Type[T], v: Any) -> T: ... + @classmethod + def decode_bytes(cls: Type[T], bytez: bytes) -> T: ... + def encode_bytes(self) -> bytes: ... + @classmethod + def from_obj(cls: Type[T], obj: ObjType) -> T: ... + def to_obj(self) -> ObjType: ... + @classmethod + def type_repr(cls: Any) -> str: ... + +class uint8(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + +class uint16(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + +class uint32(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + +class uint64(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + +class uint128(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + def to_obj(self) -> ObjType: ... + +class uint256(uint): + @classmethod + def type_byte_length(cls: Any) -> int: ... + def to_obj(self) -> ObjType: ... + +class bit(boolean): ... +class byte(uint8): ... diff --git a/mypy_stubs/remerkleable/bitfields.pyi b/mypy_stubs/remerkleable/bitfields.pyi new file mode 100644 index 0000000000..8d77aa5d07 --- /dev/null +++ b/mypy_stubs/remerkleable/bitfields.pyi @@ -0,0 +1,88 @@ +from collections.abc import Sequence as ColSequence +from remerkleable.basic import boolean as boolean, uint256 as uint256 +from remerkleable.core import BackedView as BackedView, FixedByteLengthViewHelper as FixedByteLengthViewHelper, ObjParseException as ObjParseException, ObjType as ObjType, View as View, pack_bits_to_chunks as pack_bits_to_chunks +from remerkleable.readonly_iters import BitfieldIter as BitfieldIter +from remerkleable.tree import Gindex as Gindex, Link as Link, NavigationError as NavigationError, Node as Node, PairNode as PairNode, Root as Root, RootNode as RootNode, get_depth as get_depth, subtree_fill_to_contents as subtree_fill_to_contents, subtree_fill_to_length as subtree_fill_to_length, to_gindex as to_gindex, zero_node as zero_node +from typing import Any, BinaryIO, Type, TypeVar + +V = TypeVar('V', bound=View) + +class BitsView(BackedView, ColSequence): + @classmethod + def coerce_view(cls: Type[V], v: Any) -> V: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + def length(self) -> int: ... + def get(self, i: int) -> boolean: ... + def set(self, i: int, v: boolean) -> None: ... + def __len__(self): ... + def __getitem__(self, k: Any): ... + def __setitem__(self, k: Any, v: Any) -> None: ... + def encode_bytes(self) -> bytes: ... + @classmethod + def decode_bytes(cls: Type[V], bytez: bytes) -> V: ... + @classmethod + def from_obj(cls: Type[V], obj: ObjType) -> V: ... + def to_obj(self) -> ObjType: ... + def navigate_view(self, key: Any) -> View: ... + +class Bitlist(BitsView): + def __new__(cls, *args: Any, **kwargs: Any): ... + def __class_getitem__(cls: Any, limit: Any) -> Type[Bitlist]: ... + def __iter__(self) -> Any: ... + @classmethod + def contents_depth(cls: Any) -> int: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def limit(cls: Any) -> int: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + def length(self) -> int: ... + def append(self, v: boolean) -> Any: ... + def pop(self) -> None: ... + def get(self, i: int) -> boolean: ... + def set(self, i: int, v: boolean) -> None: ... + def value_byte_length(self) -> int: ... + @classmethod + def decode_bytes(cls: Type[V], bytez: bytes) -> V: ... + @classmethod + def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V: ... + def serialize(self, stream: BinaryIO) -> int: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + +class Bitvector(BitsView, FixedByteLengthViewHelper): + def __new__(cls, *args: Any, **kwargs: Any): ... + def __class_getitem__(cls: Any, length: Any) -> Type[Bitvector]: ... + def __iter__(self) -> Any: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def vector_length(cls: Any) -> int: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def type_byte_length(cls: Any) -> int: ... + def length(self) -> int: ... + def get(self, i: int) -> boolean: ... + def set(self, i: int, v: boolean) -> None: ... + @classmethod + def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V: ... + def serialize(self, stream: BinaryIO) -> int: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... diff --git a/mypy_stubs/remerkleable/byte_arrays.pyi b/mypy_stubs/remerkleable/byte_arrays.pyi new file mode 100644 index 0000000000..174c2033b7 --- /dev/null +++ b/mypy_stubs/remerkleable/byte_arrays.pyi @@ -0,0 +1,81 @@ +from remerkleable.basic import byte as byte, uint256 as uint256 +from remerkleable.core import FixedByteLengthViewHelper as FixedByteLengthViewHelper, ObjParseException as ObjParseException, ObjType as ObjType, View as View, ViewHook as ViewHook, pack_bytes_to_chunks as pack_bytes_to_chunks, zero_node as zero_node +from remerkleable.tree import Gindex as Gindex, Node as Node, PairNode as PairNode, Root as Root, RootNode as RootNode, get_depth as get_depth, subtree_fill_to_contents as subtree_fill_to_contents, subtree_fill_to_length as subtree_fill_to_length, to_gindex as to_gindex +from typing import Any, BinaryIO, Optional, Type, TypeVar + +RV = TypeVar('RV', bound='RawBytesView') + +class RawBytesView(bytes, View): + def __new__(cls, *args: Any, **kwargs: Any): ... + @classmethod + def default_bytes(cls: Any) -> bytes: ... + @classmethod + def coerce_view(cls: Type[RV], v: Any) -> RV: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + def set_backing(self, value: Any) -> None: ... + @classmethod + def decode_bytes(cls: Type[RV], bytez: bytes) -> RV: ... + def encode_bytes(self) -> bytes: ... + @classmethod + def from_obj(cls: Type[RV], obj: ObjType) -> RV: ... + def to_obj(self) -> ObjType: ... + def navigate_view(self, key: Any) -> View: ... +BV = TypeVar('BV', bound='ByteVector') + +class ByteVector(RawBytesView, FixedByteLengthViewHelper, View): + def __new__(cls, *args: Any, **kwargs: Any): ... + def __class_getitem__(cls: Any, length: Any) -> Type[ByteVector]: ... + @classmethod + def vector_length(cls): ... + @classmethod + def default_bytes(cls: Any) -> bytes: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def view_from_backing(cls: Type[BV], node: Node, hook: Optional[ViewHook]=...) -> BV: ... + def get_backing(self) -> Node: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + +Bytes1: Any +Bytes4: Any +Bytes8: Any +Bytes32: Any +Bytes48: Any +Bytes96: Any +BL = TypeVar('BL', bound='ByteList') + +class ByteList(RawBytesView, FixedByteLengthViewHelper, View): + def __new__(cls, *args: Any, **kwargs: Any): ... + def __class_getitem__(cls: Any, limit: Any) -> Type[ByteList]: ... + @classmethod + def limit(cls: Any) -> int: ... + @classmethod + def default_bytes(cls: Any) -> bytes: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def view_from_backing(cls: Type[BL], node: Node, hook: Optional[ViewHook]=...) -> BL: ... + def get_backing(self) -> Node: ... + @classmethod + def contents_depth(cls: Any) -> int: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + @classmethod + def deserialize(cls: Type[BL], stream: BinaryIO, scope: int) -> BL: ... + def value_byte_length(self) -> int: ... diff --git a/mypy_stubs/remerkleable/complex.pyi b/mypy_stubs/remerkleable/complex.pyi new file mode 100644 index 0000000000..9fc43b6b5e --- /dev/null +++ b/mypy_stubs/remerkleable/complex.pyi @@ -0,0 +1,172 @@ +from collections.abc import Sequence as ColSequence +from remerkleable.basic import uint256 as uint256, uint32 as uint32, uint8 as uint8 +from remerkleable.core import BasicView as BasicView, OFFSET_BYTE_LENGTH as OFFSET_BYTE_LENGTH, ObjParseException as ObjParseException, ObjType as ObjType, View as View, ViewHook as ViewHook +from remerkleable.readonly_iters import ComplexElemIter as ComplexElemIter, ComplexFreshElemIter as ComplexFreshElemIter, ContainerElemIter as ContainerElemIter, PackedIter as PackedIter +from remerkleable.subtree import SubtreeView as SubtreeView +from remerkleable.tree import Gindex as Gindex, NavigationError as NavigationError, Node as Node, PairNode as PairNode, get_depth as get_depth, subtree_fill_to_contents as subtree_fill_to_contents, subtree_fill_to_length as subtree_fill_to_length, to_gindex as to_gindex, zero_node as zero_node +from typing import Any, BinaryIO, Dict, List as PyList, NamedTuple, Optional, Type, TypeVar + +V = TypeVar('V', bound=View) + +def decode_offset(stream: BinaryIO) -> uint32: ... +def encode_offset(stream: BinaryIO, offset: int) -> Any: ... + +class ComplexView(SubtreeView): + def encode_bytes(self) -> bytes: ... + @classmethod + def decode_bytes(cls: Type[V], bytez: bytes) -> V: ... +M = TypeVar('M', bound='MonoSubtreeView') + +class MonoSubtreeView(ColSequence, ComplexView): + def length(self) -> int: ... + @classmethod + def coerce_view(cls: Type[M], v: Any) -> M: ... + @classmethod + def element_cls(cls: Any) -> Type[View]: ... + @classmethod + def item_elem_cls(cls: Any, i: int) -> Type[View]: ... + @classmethod + def to_chunk_length(cls: Any, elems_length: int) -> int: ... + @classmethod + def views_into_chunks(cls: Any, views: PyList[View]) -> PyList[Node]: ... + @classmethod + def is_valid_count(cls: Any, count: int) -> bool: ... + def __iter__(self) -> Any: ... + def readonly_iter(self): ... + @classmethod + def deserialize(cls: Type[M], stream: BinaryIO, scope: int) -> M: ... + def serialize(self, stream: BinaryIO) -> int: ... + @classmethod + def from_obj(cls: Type[M], obj: ObjType) -> M: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + def navigate_view(self, key: Any) -> View: ... + def __len__(self): ... + def __add__(self, other: Any): ... + def __getitem__(self, k: Any): ... + def __setitem__(self, k: Any, v: Any) -> None: ... + +class List(MonoSubtreeView): + def __new__(cls: Any, *args: Any, backing: Optional[Node]=..., hook: Optional[ViewHook]=..., **kwargs: Any) -> Any: ... + def __class_getitem__(cls: Any, params: Any) -> Type[List]: ... + def length(self) -> int: ... + def value_byte_length(self) -> int: ... + def append(self, v: View) -> Any: ... + def pop(self) -> None: ... + def get(self, i: int) -> View: ... + def set(self, i: int, v: View) -> None: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def is_packed(cls: Any) -> bool: ... + @classmethod + def contents_depth(cls: Any) -> int: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def item_elem_cls(cls: Any, i: int) -> Type[View]: ... + @classmethod + def limit(cls: Any) -> int: ... + @classmethod + def is_valid_count(cls: Any, count: int) -> bool: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + def to_obj(self) -> ObjType: ... + +class Vector(MonoSubtreeView): + def __new__(cls: Any, *args: Any, backing: Optional[Node]=..., hook: Optional[ViewHook]=..., **kwargs: Any) -> Any: ... + def __class_getitem__(cls: Any, params: Any) -> Type[Vector]: ... + def get(self, i: int) -> View: ... + def set(self, i: int, v: View) -> None: ... + def length(self) -> int: ... + def value_byte_length(self) -> int: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def vector_length(cls: Any) -> int: ... + @classmethod + def is_valid_count(cls: Any, count: int) -> bool: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + def to_obj(self) -> ObjType: ... +Fields = Dict[str, Type[View]] + +class FieldOffset(NamedTuple): + key: str + typ: Type[View] + offset: int + +class _ContainerLike: + @classmethod + def fields(cls: Any) -> Fields: ... +CV = TypeVar('CV', bound='Container') + +class _ContainerBase(ComplexView): + def __new__(cls: Any, *args: Any, backing: Optional[Node]=..., hook: Optional[ViewHook]=..., append_nodes: Optional[PyList[Node]]=..., **kwargs: Any) -> Any: ... + @classmethod + def fields(cls: Any) -> Fields: ... + +class Container(_ContainerBase): + def __new__(cls: Any, *args: Any, backing: Optional[Node]=..., hook: Optional[ViewHook]=..., append_nodes: Optional[PyList[Node]]=..., **kwargs: Any) -> Any: ... + def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: ... + @classmethod + def coerce_view(cls: Type[CV], v: Any) -> CV: ... + @classmethod + def fields(cls: Any) -> Fields: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def type_byte_length(cls: Any) -> int: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + @classmethod + def is_packed(cls: Any) -> bool: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def item_elem_cls(cls: Any, i: int) -> Type[View]: ... + @classmethod + def default_node(cls: Any) -> Node: ... + def value_byte_length(self) -> int: ... + def __getattr__(self, item: Any): ... + def __setattr__(self, key: Any, value: Any) -> None: ... + @classmethod + def type_repr(cls: Any) -> str: ... + def __iter__(self) -> Any: ... + @classmethod + def decode_bytes(cls: Type[V], bytez: bytes) -> V: ... + @classmethod + def deserialize(cls: Type[CV], stream: BinaryIO, scope: int) -> CV: ... + def serialize(self, stream: BinaryIO) -> int: ... + @classmethod + def from_obj(cls: Type[CV], obj: ObjType) -> CV: ... + def to_obj(self) -> ObjType: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + def navigate_view(self, key: Any) -> View: ... diff --git a/mypy_stubs/remerkleable/core.pyi b/mypy_stubs/remerkleable/core.pyi new file mode 100644 index 0000000000..eeba1aa39d --- /dev/null +++ b/mypy_stubs/remerkleable/core.pyi @@ -0,0 +1,109 @@ +from remerkleable.tree import Gindex as Gindex, Node as Node, Root as Root, RootNode as RootNode, concat_gindices as concat_gindices, zero_node as zero_node +from typing import Any, BinaryIO, Callable, Iterable, List as PyList, Optional, Tuple, Type, TypeVar, Union, _ProtocolMeta + +OFFSET_BYTE_LENGTH: int +V = TypeVar('V', bound='View') + +class ViewMeta(_ProtocolMeta): + def __truediv__(self, other: Any) -> Path: ... +ObjType = Union[dict, list, tuple, str, int, bool, None] + +class ObjParseException(Exception): ... + +class Path: + anchor: Type[View] + path: PyList[Tuple[Any, Type[View]]] + def __init__(self, anchor: Type[View], path: Optional[PyList[Tuple[Any, Type[View]]]]=...) -> None: ... + @staticmethod + def from_raw_path(anchor: Type[View], path: PyList[Any]) -> Path: ... + def __truediv__(self, other: Any) -> Path: ... + def gindex(self, view: Optional[View]=...) -> Gindex: ... + def navigate_type(self) -> Type[View]: ... + def navigate_view(self, v: View) -> View: ... +HV = TypeVar('HV', bound='View') +ViewHook = Callable[[HV], None] + +class View(metaclass=ViewMeta): + @classmethod + def coerce_view(cls: Type[V], v: Any) -> V: ... + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def view_from_backing(cls: Type[V], node: Node, hook: Optional[ViewHook[V]]=...) -> V: ... + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + @classmethod + def decode_bytes(cls: Type[V], bytez: bytes) -> V: ... + @classmethod + def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V: ... + @classmethod + def from_obj(cls: Type[V], obj: ObjType) -> V: ... + @classmethod + def type_repr(cls: Any) -> str: ... + @classmethod + def navigate_type(cls: Any, key: Any) -> Type[View]: ... + @classmethod + def key_to_static_gindex(cls: Any, key: Any) -> Gindex: ... + @classmethod + def default(cls: Type[V], hook: Optional[ViewHook[V]]) -> V: ... + def get_backing(self) -> Node: ... + def set_backing(self, value: Any) -> None: ... + def copy(self) -> V: ... + @classmethod + def type_byte_length(cls: Any) -> int: ... + def value_byte_length(self) -> int: ... + def __bytes__(self): ... + def encode_bytes(self) -> bytes: ... + def serialize(self, stream: BinaryIO) -> int: ... + def to_obj(self) -> ObjType: ... + def navigate_view(self, key: Any) -> View: ... + def key_to_dynamic_gindex(self, key: Any) -> Gindex: ... + def hash_tree_root(self) -> Root: ... + def __eq__(self, other: Any) -> Any: ... + def __hash__(self) -> Any: ... + +class FixedByteLengthViewHelper(View): + @classmethod + def is_fixed_byte_length(cls: Any) -> bool: ... + @classmethod + def min_byte_length(cls: Any) -> int: ... + @classmethod + def max_byte_length(cls: Any) -> int: ... + @classmethod + def deserialize(cls: Type[V], stream: BinaryIO, scope: int) -> V: ... + def value_byte_length(self) -> int: ... +BackedV = TypeVar('BackedV', bound='BackedView') + +class BackedView(View): + @classmethod + def view_from_backing(cls: Type[BackedV], node: Node, hook: Optional[ViewHook]=...) -> BackedV: ... + def __new__(cls: Any, backing: Optional[Node]=..., hook: Optional[ViewHook]=..., **kwargs: Any) -> Any: ... + def get_backing(self) -> Node: ... + def set_backing(self, value: Any) -> None: ... +BV = TypeVar('BV', bound='BasicView') + +class BasicView(FixedByteLengthViewHelper): + @classmethod + def default_node(cls: Any) -> Node: ... + @classmethod + def view_from_backing(cls: Type[BV], node: Node, hook: Optional[ViewHook[BV]]=...) -> BV: ... + @classmethod + def basic_view_from_backing(cls: Type[BV], node: Node, i: int) -> BV: ... + @classmethod + def pack_views(cls: Type[BV], views: PyList[BV]) -> PyList[Node]: ... + def copy(self) -> V: ... + def backing_from_base(self, base: Node, i: int) -> Node: ... + def get_backing(self) -> Node: ... + def set_backing(self, value: Any) -> None: ... + +def grouper(items: Iterable, n: int, fillvalue: Any=...) -> Iterable[Tuple]: ... +def pack_ints_to_chunks(items: Iterable[int], items_per_chunk: int) -> PyList[Node]: ... +def bits_to_byte_int(byte: Tuple[bool, bool, bool, bool, bool, bool, bool, bool]) -> int: ... +def byte_int_to_byte(b: int) -> bytes: ... +def pack_bits_to_chunks(items: Iterable[bool]) -> PyList[Node]: ... +def pack_byte_ints_to_chunks(items: Iterable[int]) -> PyList[Node]: ... +def pack_bytes_to_chunks(bytez: bytes) -> PyList[Node]: ... diff --git a/mypy_stubs/remerkleable/history.pyi b/mypy_stubs/remerkleable/history.pyi new file mode 100644 index 0000000000..d8b7fd81e4 --- /dev/null +++ b/mypy_stubs/remerkleable/history.pyi @@ -0,0 +1,7 @@ +from remerkleable.tree import Gindex as Gindex, Node as Node, ROOT_GINDEX as ROOT_GINDEX, get_anchor_gindex as get_anchor_gindex +from typing import List, Tuple, TypeVar + +K = TypeVar('K') +History = List[Tuple[K, Node]] + +def get_target_history(history: History, target: Gindex) -> History: ... diff --git a/mypy_stubs/remerkleable/readonly_iters.pyi b/mypy_stubs/remerkleable/readonly_iters.pyi new file mode 100644 index 0000000000..7eb271c1a8 --- /dev/null +++ b/mypy_stubs/remerkleable/readonly_iters.pyi @@ -0,0 +1,58 @@ +from remerkleable.core import BasicView as BasicView, View as View +from remerkleable.tree import Node as Node, Root as Root, RootNode as RootNode, ZERO_ROOT as ZERO_ROOT +from typing import Any, List as PyList, Optional, Sequence, Type + +class BitfieldIter: + anchor: Node + depth: int + i: int + j: int + rootIndex: int + length: int + currentRoot: Root + stack: PyList[Optional[Node]] + def __init__(self, anchor: Node, depth: int, length: int) -> None: ... + def __iter__(self) -> Any: ... + def __next__(self): ... + +class PackedIter: + anchor: Node + depth: int + i: int + j: int + rootIndex: int + length: int + per_node: int + currentRoot: RootNode + elem_type: Type[BasicView] + stack: PyList[Optional[Node]] + def __init__(self, anchor: Node, depth: int, length: int, elem_type: Type[BasicView]) -> None: ... + def __iter__(self) -> Any: ... + def __next__(self): ... + +class NodeIter: + anchor: Node + depth: int + i: int + length: int + per_node: int + stack: PyList[Optional[Node]] + currentRoot: Any = ... + def __init__(self, anchor: Node, depth: int, length: int) -> None: ... + def __iter__(self) -> Any: ... + def __next__(self): ... + +class ComplexElemIter(NodeIter): + reused_view: View + def __init__(self, anchor: Node, depth: int, length: int, elem_type: Type[View]) -> None: ... + def __next__(self): ... + +class ComplexFreshElemIter(NodeIter): + elem_type: Type[View] + def __init__(self, anchor: Node, depth: int, length: int, elem_type: Type[View]) -> None: ... + def __next__(self): ... + +class ContainerElemIter(NodeIter): + elem_types: Sequence[Type[View]] + def __init__(self, anchor: Node, depth: int, elem_types: Sequence[Type[View]]) -> None: ... + def __next__(self): ... diff --git a/mypy_stubs/remerkleable/subtree.pyi b/mypy_stubs/remerkleable/subtree.pyi new file mode 100644 index 0000000000..22eb028a3e --- /dev/null +++ b/mypy_stubs/remerkleable/subtree.pyi @@ -0,0 +1,13 @@ +from remerkleable.core import BackedView as BackedView, BasicView as BasicView, View as View +from remerkleable.tree import Link as Link, to_gindex as to_gindex +from typing import Any, Type + +class SubtreeView(BackedView): + @classmethod + def is_packed(cls: Any) -> bool: ... + @classmethod + def tree_depth(cls: Any) -> int: ... + @classmethod + def item_elem_cls(cls: Any, i: int) -> Type[View]: ... + def get(self, i: int) -> View: ... + def set(self, i: int, v: View) -> None: ... diff --git a/mypy_stubs/remerkleable/tree.pyi b/mypy_stubs/remerkleable/tree.pyi new file mode 100644 index 0000000000..c01c335069 --- /dev/null +++ b/mypy_stubs/remerkleable/tree.pyi @@ -0,0 +1,75 @@ +from typing import Any, Callable, Iterable, Iterator, List, Tuple, TypeVar + +def get_depth(elem_count: int) -> int: ... + +Gindex: Any +ROOT_GINDEX: Any +LEFT_GINDEX: Any +RIGHT_GINDEX: Any + +def to_gindex(index: int, depth: int) -> Gindex: ... +def get_anchor_gindex(gindex: Gindex) -> Gindex: ... +def gindex_bit_iter(gindex: Gindex) -> Tuple[Iterator[bool], int]: ... +def concat_gindices(steps: Iterable[Gindex]) -> Gindex: ... + +Root: Any +MerkleFn = Callable[[Root, Root], Root] +ZERO_ROOT: Root + +def merkle_hash(left: Root, right: Root) -> Root: ... + +Link: Any +SummaryLink: Any + +class Node: + def get_left(self) -> Node: ... + def get_right(self) -> Node: ... + def getter(self, target: Gindex) -> Node: ... + def is_leaf(self) -> bool: ... + def rebind_left(self, v: Node) -> Node: ... + def rebind_right(self, v: Node) -> Node: ... + def setter(self, target: Gindex, expand: bool=...) -> Link: ... + def summarize_into(self, target: Gindex) -> SummaryLink: ... + @property + def root(self) -> Root: ... + def merkle_root(self) -> Root: ... + +zero_hashes: List[Root] + +def zero_node(depth: int) -> RootNode: ... +def identity(v: Node) -> Node: ... +def compose(inner: Link, outer: Link) -> Link: ... + +class NavigationError(RuntimeError): ... +V = TypeVar('V', bound=Node) + +class RebindableNode(Node): + def combine(self, left: Node, right: Node) -> Node: ... + def rebind_left(self, v: Node) -> Node: ... + def rebind_right(self, v: Node) -> Node: ... + def setter(self, target: Gindex, expand: bool=...) -> Link: ... + +class PairNode(RebindableNode, Node): + left: Node + right: Node + def __init__(self, left: Node, right: Node) -> None: ... + def get_left(self) -> Node: ... + def get_right(self) -> Node: ... + def is_leaf(self) -> bool: ... + def merkle_root(self) -> Root: ... + +def subtree_fill_to_depth(bottom: Node, depth: int) -> Node: ... +def subtree_fill_to_length(bottom: Node, depth: int, length: int) -> Node: ... +def subtree_fill_to_contents(nodes: List[Node], depth: int) -> Node: ... + +class RootNode(Node): + def __init__(self, root: Root) -> None: ... + def getter(self, target: Gindex) -> Node: ... + def is_leaf(self) -> bool: ... + def setter(self, target: Gindex, expand: bool=...) -> Link: ... + @property + def root(self) -> Root: ... + def merkle_root(self) -> Root: ... + +def leaf_iter(node: Node) -> Iterator[Node]: ... +def get_diff(a: Node, b: Node) -> Iterator[Tuple[Node, Node]]: ... diff --git a/mypy_stubs/remerkleable/virtual.pyi b/mypy_stubs/remerkleable/virtual.pyi new file mode 100644 index 0000000000..a86d4763bd --- /dev/null +++ b/mypy_stubs/remerkleable/virtual.pyi @@ -0,0 +1,15 @@ +from remerkleable.tree import NavigationError as NavigationError, Node as Node, RebindableNode as RebindableNode, Root as Root + +class VirtualSource: + def get_left(self, key: Root) -> Node: ... + def get_right(self, key: Root) -> Node: ... + def is_leaf(self, key: Root) -> bool: ... + +class VirtualNode(RebindableNode, Node): + def __init__(self, root: Root, src: VirtualSource) -> None: ... + def get_left(self) -> Node: ... + def get_right(self) -> Node: ... + def is_leaf(self) -> bool: ... + @property + def root(self) -> Root: ... + def merkle_root(self) -> Root: ... diff --git a/setup.py b/setup.py index 35b1a2c8a3..b42618af28 100644 --- a/setup.py +++ b/setup.py @@ -1040,7 +1040,7 @@ def run(self): python_requires=">=3.8, <4", extras_require={ "test": ["pytest>=4.4", "pytest-cov", "pytest-xdist"], - "lint": ["flake8==3.7.7", "mypy==0.812", "pylint==2.12.2"], + "lint": ["flake8==3.7.7", "mypy==0.812", "pylint==2.12.2", "mypy-extensions==0.4.3"], "generator": ["python-snappy==0.5.4"], }, install_requires=[