From 6b7ad5dcdbafce8ceb4accddefd8ba132ad92ef3 Mon Sep 17 00:00:00 2001 From: antazoey Date: Mon, 3 Jun 2024 19:26:33 -0500 Subject: [PATCH] feat!: py3.8 drop and py3.12 support add (#59) --- .github/workflows/commitlint.yaml | 4 ++-- .github/workflows/prtitle.yaml | 4 ++-- .github/workflows/publish.yaml | 4 ++-- .github/workflows/test.yaml | 18 ++++++++-------- .pre-commit-config.yaml | 6 +++--- evm_trace/base.py | 4 ++-- evm_trace/display.py | 3 ++- evm_trace/gas.py | 4 ++-- evm_trace/geth.py | 25 +++++++++++----------- evm_trace/parity.py | 12 +++++------ evm_trace/vmtrace.py | 35 ++++++++++++++++--------------- setup.py | 7 +++---- tests/test_gas.py | 4 +--- 13 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/workflows/commitlint.yaml b/.github/workflows/commitlint.yaml index 021b990..3b8de5e 100644 --- a/.github/workflows/commitlint.yaml +++ b/.github/workflows/commitlint.yaml @@ -9,12 +9,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" diff --git a/.github/workflows/prtitle.yaml b/.github/workflows/prtitle.yaml index a6cd3b0..6e8999f 100644 --- a/.github/workflows/prtitle.yaml +++ b/.github/workflows/prtitle.yaml @@ -12,10 +12,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 2c88013..081d138 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7aacc21..be904b3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" @@ -42,10 +42,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" @@ -63,13 +63,13 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] # eventually add `windows-latest` - python-version: [3.8, 3.9, "3.10", "3.11", "3.12"] + python-version: [3.9, "3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -89,10 +89,10 @@ jobs: # fail-fast: true # # steps: -# - uses: actions/checkout@v2 +# - uses: actions/checkout@v4 # # - name: Setup Python -# uses: actions/setup-python@v2 +# uses: actions/setup-python@v5 # with: # python-version: "3.10" # diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a7a4502..ba0b688 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,18 +10,18 @@ repos: - id: isort - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 24.3.0 hooks: - id: black name: black - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.9.0 hooks: - id: mypy additional_dependencies: [types-PyYAML, types-requests, types-setuptools, pydantic] diff --git a/evm_trace/base.py b/evm_trace/base.py index be562dc..e32eb3d 100644 --- a/evm_trace/base.py +++ b/evm_trace/base.py @@ -1,5 +1,5 @@ from functools import cached_property, singledispatchmethod -from typing import List, Optional +from typing import Optional from eth_pydantic_types import HexBytes from pydantic import BaseModel as _BaseModel @@ -50,7 +50,7 @@ class CallTreeNode(BaseModel): returndata: HexBytes = HexBytes("") """Transaction returndata (outputs).""" - calls: List["CallTreeNode"] = [] + calls: list["CallTreeNode"] = [] """The list of external sub-calls this call makes.""" selfdestruct: bool = False diff --git a/evm_trace/display.py b/evm_trace/display.py index 1be1b86..fb53d9d 100644 --- a/evm_trace/display.py +++ b/evm_trace/display.py @@ -1,4 +1,5 @@ -from typing import TYPE_CHECKING, Iterator, Optional, cast +from collections.abc import Iterator +from typing import TYPE_CHECKING, Optional, cast from eth_typing import ChecksumAddress from eth_utils import to_checksum_address diff --git a/evm_trace/gas.py b/evm_trace/gas.py index 7680efc..452a4a3 100644 --- a/evm_trace/gas.py +++ b/evm_trace/gas.py @@ -1,11 +1,11 @@ import copy -from typing import Dict, List, TypeVar +from typing import TypeVar from evm_trace.base import CallTreeNode ContractID = TypeVar("ContractID") MethodID = TypeVar("MethodID") -GasReport = Dict[ContractID, Dict[MethodID, List[int]]] +GasReport = dict[ContractID, dict[MethodID, list[int]]] def get_gas_report(calltree: CallTreeNode) -> GasReport: diff --git a/evm_trace/geth.py b/evm_trace/geth.py index 64b9747..15b8ea8 100644 --- a/evm_trace/geth.py +++ b/evm_trace/geth.py @@ -1,5 +1,6 @@ import math -from typing import Dict, Iterator, List, Optional +from collections.abc import Iterator +from typing import Optional from eth_pydantic_types import HashBytes20, HexBytes from eth_utils import to_int @@ -9,8 +10,8 @@ from evm_trace.enums import CALL_OPCODES, CallType -class TraceMemory(RootModel[List[HexBytes]]): - root: List[HexBytes] = [] +class TraceMemory(RootModel[list[HexBytes]]): + root: list[HexBytes] = [] def get(self, offset: HexBytes, size: HexBytes): return extract_memory(offset, size, self.root) @@ -39,13 +40,13 @@ class TraceFrame(BaseModel): The number of external jumps away the initially called contract (starts at 0). """ - stack: List[HexBytes] = [] + stack: list[HexBytes] = [] """Execution stack.""" memory: TraceMemory = TraceMemory() """Execution memory.""" - storage: Dict[HexBytes, HexBytes] = {} + storage: dict[HexBytes, HexBytes] = {} """Contract storage.""" contract_address: Optional[HashBytes20] = None @@ -70,7 +71,7 @@ def address(self) -> Optional[HashBytes20]: return self.contract_address -def create_trace_frames(data: Iterator[Dict]) -> Iterator[TraceFrame]: +def create_trace_frames(data: Iterator[dict]) -> Iterator[TraceFrame]: """ Get trace frames from ``debug_traceTransaction`` response items. Sets the ``contract_address`` for CREATE and CREATE2 frames by @@ -99,7 +100,7 @@ def create_trace_frames(data: Iterator[Dict]) -> Iterator[TraceFrame]: yield TraceFrame(**frame) -def _get_create_frames(frame: TraceFrame, frames: Iterator[Dict]) -> List[TraceFrame]: +def _get_create_frames(frame: TraceFrame, frames: Iterator[dict]) -> list[TraceFrame]: create_frames = [frame] start_depth = frame.depth for next_frame in frames: @@ -126,7 +127,7 @@ def _get_create_frames(frame: TraceFrame, frames: Iterator[Dict]) -> List[TraceF return create_frames -def get_calltree_from_geth_call_trace(data: Dict) -> CallTreeNode: +def get_calltree_from_geth_call_trace(data: dict) -> CallTreeNode: """ Creates a CallTreeNode from a given transaction call trace. @@ -173,7 +174,7 @@ def get_calltree_from_geth_trace( ) -def create_call_node_data(frame: TraceFrame) -> Dict: +def create_call_node_data(frame: TraceFrame) -> dict: """ Parse a CALL-opcode frame into an address and calldata. @@ -184,7 +185,7 @@ def create_call_node_data(frame: TraceFrame) -> Dict: Tuple[str, HexBytes]: A tuple of the address str and the calldata. """ - data: Dict = {"address": frame.address, "depth": frame.depth} + data: dict = {"address": frame.address, "depth": frame.depth} if frame.op == CallType.CALL.value: data["call_type"] = CallType.CALL data["value"] = int(frame.stack[-3].hex(), 16) @@ -208,7 +209,7 @@ def create_call_node_data(frame: TraceFrame) -> Dict: return data -def extract_memory(offset: HexBytes, size: HexBytes, memory: List[HexBytes]) -> HexBytes: +def extract_memory(offset: HexBytes, size: HexBytes, memory: list[HexBytes]) -> HexBytes: """ Extracts memory from the EVM stack. @@ -333,7 +334,7 @@ def _create_node( return node -def _validate_data_from_call_tracer(data: Dict) -> Dict: +def _validate_data_from_call_tracer(data: dict) -> dict: # Handle renames if "receiver" in data: data["address"] = data.pop("receiver") diff --git a/evm_trace/parity.py b/evm_trace/parity.py index 1b384ce..fb66858 100644 --- a/evm_trace/parity.py +++ b/evm_trace/parity.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Union, cast +from typing import Any, Optional, Union, cast from pydantic import Field, RootModel, field_validator @@ -93,7 +93,7 @@ class ParityTrace(BaseModel): call_type: CallType = Field(alias="type") result: Optional[ParityTraceResult] = None subtraces: int - trace_address: List[int] = Field(alias="traceAddress") + trace_address: list[int] = Field(alias="traceAddress") transaction_hash: str = Field(alias="transactionHash") @field_validator("call_type", mode="before") @@ -108,7 +108,7 @@ def convert_call_type(cls, value, info) -> CallType: return CallType(value) -ParityTraceList = RootModel[List[ParityTrace]] +ParityTraceList = RootModel[list[ParityTrace]] def get_calltree_from_parity_trace( @@ -133,7 +133,7 @@ def get_calltree_from_parity_trace( """ root = root or traces.root[0] failed = root.error is not None - node_kwargs: Dict[Any, Any] = { + node_kwargs: dict[Any, Any] = { "call_type": root.call_type, "failed": failed, } @@ -181,8 +181,8 @@ def get_calltree_from_parity_trace( address=selfdestruct_action.address, ) - trace_list: List[ParityTrace] = traces.root - subtraces: List[ParityTrace] = [ + trace_list: list[ParityTrace] = traces.root + subtraces: list[ParityTrace] = [ sub for sub in trace_list if len(sub.trace_address) == len(root.trace_address) + 1 diff --git a/evm_trace/vmtrace.py b/evm_trace/vmtrace.py index 7b6d84b..9ee6d91 100644 --- a/evm_trace/vmtrace.py +++ b/evm_trace/vmtrace.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Dict, Iterator, List, Optional, Type, Union +from collections.abc import Iterator +from typing import Any from eth.vm.memory import Memory from eth.vm.stack import Stack @@ -33,7 +34,7 @@ class uint256(int): class VMTrace(Struct): code: HexBytes """The code to be executed.""" - ops: List[VMOperation] + ops: list[VMOperation] """The operations executed.""" @@ -42,9 +43,9 @@ class VMOperation(Struct): """The program counter.""" cost: int """The gas cost for this instruction.""" - ex: Optional[VMExecutedOperation] + ex: VMExecutedOperation | None """Information concerning the execution of the operation.""" - sub: Optional[VMTrace] + sub: VMTrace | None """Subordinate trace of the CALL/CREATE if applicable.""" op: str """Opcode that is being called.""" @@ -55,11 +56,11 @@ class VMOperation(Struct): class VMExecutedOperation(Struct): used: int """The amount of remaining gas.""" - push: List[HexBytes] + push: list[HexBytes] """The stack item placed, if any.""" - mem: Optional[MemoryDiff] + mem: MemoryDiff | None """If altered, the memory delta.""" - store: Optional[StorageDiff] + store: StorageDiff | None """The altered storage value, if any.""" @@ -86,9 +87,9 @@ class VMTraceFrame(Struct): pc: int op: str depth: int - stack: List[int] - memory: Union[bytes, memoryview] - storage: Dict[int, int] + stack: list[int] + memory: bytes | memoryview + storage: dict[int, int] def to_trace_frames( @@ -119,7 +120,7 @@ def to_trace_frames( """ memory = Memory() stack = Stack() - storage: Dict[int, int] = {} + storage: dict[int, int] = {} call_address = "" read_memory = memory.read_bytes if copy_memory else memory.read @@ -166,26 +167,26 @@ def to_trace_frames( class RPCResponse(Struct): - result: Union[RPCTraceResult, List[RPCTraceResult]] + result: RPCTraceResult | list[RPCTraceResult] class RPCTraceResult(Struct): - trace: Optional[List] + trace: list | None vmTrace: VMTrace - stateDiff: Optional[Dict] + stateDiff: dict | None -def dec_hook(type: Type, obj: Any) -> Any: +def dec_hook(type: type, obj: Any) -> Any: if type is uint256: return uint256(obj, 16) elif type is HexBytes: return HexBytes(obj) -def from_rpc_response(buffer: bytes) -> Union[VMTrace, List[VMTrace]]: +def from_rpc_response(buffer: bytes) -> VMTrace | list[VMTrace]: """ Decode structured data from a raw `trace_replayTransaction` or `trace_replayBlockTransactions`. """ response = Decoder(RPCResponse, dec_hook=dec_hook).decode(buffer) - result: Union[List[RPCTraceResult], RPCTraceResult] = response.result + result: list[RPCTraceResult] | RPCTraceResult = response.result return [i.vmTrace for i in result] if isinstance(result, list) else result.vmTrace diff --git a/setup.py b/setup.py index d5f62be..6f7cba9 100644 --- a/setup.py +++ b/setup.py @@ -10,10 +10,10 @@ "eth-hash[pysha3]", # For eth-utils address checksumming ], "lint": [ - "black>=23.11.0,<24", # Auto-formatter and linter - "mypy>=1.7.1,<2", # Static type analyzer + "black>=24.3.0,<25", # Auto-formatter and linter + "mypy>=1.9.0,<2", # Static type analyzer "types-setuptools", # Needed for mypy type shed - "flake8>=6.1.0,<7", # Style linter + "flake8>=7.0.0,<8", # Style linter "flake8-breakpoint>=1.1.0,<2", # Detect breakpoints left in code "flake8-print>=5.0.0,<6", # Detect print statements left in code "isort>=5.10.1,<6", # Import sorting linter @@ -82,7 +82,6 @@ "Operating System :: MacOS", "Operating System :: POSIX", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", diff --git a/tests/test_gas.py b/tests/test_gas.py index 7a15c06..54f92f1 100644 --- a/tests/test_gas.py +++ b/tests/test_gas.py @@ -1,5 +1,3 @@ -from typing import List - from eth_pydantic_types import HexBytes from evm_trace import CallTreeNode @@ -13,7 +11,7 @@ METHOD_B = HexBytes("0xc7cee1b7") METHOD_C = HexBytes("0xd76d0659") -reports: List[GasReport] = [ +reports: list[GasReport] = [ { CONTRACT_A: {METHOD_A: [100, 101, 100, 102]}, CONTRACT_B: {METHOD_B: [200, 202, 202, 200, 200]},