Skip to content

Commit

Permalink
refactor!: drop 3.8 support (#1983)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Apr 20, 2024
1 parent 601a73f commit 65fc2be
Show file tree
Hide file tree
Showing 30 changed files with 175 additions and 158 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest] # eventually add `windows-latest`
python-version: [3.8, 3.9, "3.10", "3.11"]
python-version: [3.9, "3.10", "3.11"]

env:
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Read our [academic platform](https://academy.apeworx.io/) will help you master A
In the latest release, Ape requires:

- Linux or macOS
- Python 3.8 up to 3.11
- Python 3.9 up to 3.11
- **Windows**: Install Windows Subsystem Linux [(WSL)](https://docs.microsoft.com/en-us/windows/wsl/install)

Check your python version in a terminal with `python3 --version`.
Expand Down
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"packaging>=23.0,<24",
"pandas>=1.3.0,<2",
"pluggy>=1.3,<2",
"pydantic>=2.5.2,<3",
"pydantic>=2.6.4,<3",
"pydantic-settings>=2.0.3,<3",
"pytest>=6.0,<8.0",
"python-dateutil>=2.8.2,<3",
Expand All @@ -127,7 +127,7 @@
"eip712>=0.2.7,<0.3",
"ethpm-types>=0.6.9,<0.7",
"eth_pydantic_types>=0.1.0,<0.2",
"evmchains>=0.0.6,<0.1",
"evmchains>=0.0.7,<0.1",
"evm-trace>=0.1.5,<0.2",
],
entry_points={
Expand All @@ -146,7 +146,7 @@
"ape_pm=ape_pm._cli:cli",
],
},
python_requires=">=3.8,<4",
python_requires=">=3.9,<4",
extras_require=extras_require,
py_modules=packages_data["__modules__"],
license="Apache-2.0",
Expand All @@ -163,7 +163,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",
Expand Down
10 changes: 5 additions & 5 deletions src/ape/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
from gettext import gettext
from importlib.metadata import entry_points
from typing import Any, Dict, Iterable, List, Optional, Tuple
from typing import Any, Iterable, Optional

import click
import yaml
Expand All @@ -30,7 +30,7 @@ def display_config(ctx, param, value):


class ApeCLI(click.MultiCommand):
_commands: Optional[Dict] = None
_commands: Optional[dict] = None
_CLI_GROUP_NAME = "ape_cli_subcommands"

def format_commands(self, ctx, formatter) -> None:
Expand All @@ -47,7 +47,7 @@ def format_commands(self, ctx, formatter) -> None:
limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands)

# Split the commands into 3 sections.
sections: Dict[str, List[Tuple[str, str]]] = {
sections: dict[str, list[tuple[str, str]]] = {
"Core": [],
"Plugin": [],
"3rd-Party Plugin": [],
Expand Down Expand Up @@ -114,15 +114,15 @@ def _suggest_cmd(usage_error):
raise usage_error

@property
def commands(self) -> Dict:
def commands(self) -> dict:
if self._commands:
return self._commands

eps: Iterable = entry_points().get(self._CLI_GROUP_NAME, [])
self._commands = {clean_plugin_name(cmd.name): cmd.load for cmd in eps}
return self._commands

def list_commands(self, ctx) -> List[str]:
def list_commands(self, ctx) -> list[str]:
return list(sorted(self.commands))

def get_command(self, ctx, name) -> Optional[click.Command]:
Expand Down
2 changes: 1 addition & 1 deletion src/ape/api/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def network_choice(self) -> str:
return f"{self.network.choice}:{self.name}"

@abstractmethod
def make_request(self, rpc: str, parameters: Optional[List] = None) -> Any:
def make_request(self, rpc: str, parameters: Optional[Iterable] = None) -> Any:
"""
Make a raw RPC request to the provider.
Advanced featues such as tracing may utilize this to by-pass unnecessary
Expand Down
8 changes: 3 additions & 5 deletions src/ape/api/query.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from functools import lru_cache
from functools import cache
from typing import Any, Dict, Iterator, List, Optional, Sequence, Set, Type, Union

from ethpm_types.abi import BaseModel, EventABI, MethodABI
Expand All @@ -19,8 +19,7 @@
]


# TODO: Replace with `functools.cache` when Py3.8 dropped
@lru_cache(maxsize=None)
@cache
def _basic_columns(Model: Type[BaseInterfaceModel]) -> Set[str]:
columns = set(Model.model_fields)

Expand All @@ -32,8 +31,7 @@ def _basic_columns(Model: Type[BaseInterfaceModel]) -> Set[str]:
return columns


# TODO: Replace with `functools.cache` when Py3.8 dropped
@lru_cache(maxsize=None)
@cache
def _all_columns(Model: Type[BaseInterfaceModel]) -> Set[str]:
columns = _basic_columns(Model)
# NOTE: Iterate down the series of subclasses of `Model` (e.g. Block and BlockAPI)
Expand Down
11 changes: 6 additions & 5 deletions src/ape/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import tempfile
import time
import traceback
from collections.abc import Collection
from inspect import getframeinfo, stack
from pathlib import Path
from types import CodeType, TracebackType
from typing import TYPE_CHECKING, Any, Collection, Dict, List, Optional, Union, cast
from typing import TYPE_CHECKING, Any, Optional, Union, cast

import click
from eth_typing import Hash32
Expand Down Expand Up @@ -103,7 +104,7 @@ class ArgumentsLengthError(ContractDataError):
def __init__(
self,
arguments_length: int,
inputs: Union[MethodABI, ConstructorABI, int, List, None] = None,
inputs: Union[MethodABI, ConstructorABI, int, list, None] = None,
**kwargs,
):
prefix = (
Expand All @@ -114,7 +115,7 @@ def __init__(
super().__init__(f"{prefix}.")
return

inputs_ls: List[Union[MethodABI, ConstructorABI, int]] = (
inputs_ls: list[Union[MethodABI, ConstructorABI, int]] = (
inputs if isinstance(inputs, list) else [inputs]
)
if not inputs_ls:
Expand Down Expand Up @@ -642,7 +643,7 @@ def __init__(
super().__init__(provider, *args, **kwargs)


def handle_ape_exception(err: ApeException, base_paths: List[Path]) -> bool:
def handle_ape_exception(err: ApeException, base_paths: list[Path]) -> bool:
"""
Handle a transaction error by showing relevant stack frames,
including custom contract frames added to the exception.
Expand Down Expand Up @@ -719,7 +720,7 @@ class CustomError(ContractLogicError):
def __init__(
self,
abi: ErrorABI,
inputs: Dict[str, Any],
inputs: dict[str, Any],
txn: Optional[FailedTxn] = None,
trace: Optional["TraceAPI"] = None,
contract_address: Optional["AddressType"] = None,
Expand Down
11 changes: 6 additions & 5 deletions src/ape/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import logging
import sys
import traceback
from collections.abc import Sequence
from enum import IntEnum
from pathlib import Path
from typing import IO, Any, Callable, Dict, Optional, Sequence, Union
from typing import IO, Any, Callable, Optional, Union

import click
from yarl import URL
Expand Down Expand Up @@ -73,8 +74,8 @@ def format(self, record):
if _isatty(sys.stdout) and _isatty(sys.stderr):
# Only color log messages when sys.stdout and sys.stderr are sent to the terminal.
level = LogLevel(record.levelno)
default_dict: Dict[str, Any] = {}
styles: Dict[str, Any] = CLICK_STYLE_KWARGS.get(level, default_dict)
default_dict: dict[str, Any] = {}
styles: dict[str, Any] = CLICK_STYLE_KWARGS.get(level, default_dict)
record.levelname = click.style(record.levelname, **styles)

path = Path(record.pathname)
Expand All @@ -89,7 +90,7 @@ def format(self, record):

class ClickHandler(logging.Handler):
def __init__(
self, echo_kwargs: Dict, handlers: Optional[Sequence[Callable[[str], str]]] = None
self, echo_kwargs: dict, handlers: Optional[Sequence[Callable[[str], str]]] = None
):
super().__init__()
self.echo_kwargs = echo_kwargs
Expand All @@ -112,7 +113,7 @@ def emit(self, record):

class ApeLogger:
_mentioned_verbosity_option = False
_extra_loggers: Dict[str, logging.Logger] = {}
_extra_loggers: dict[str, logging.Logger] = {}

def __init__(
self,
Expand Down
7 changes: 4 additions & 3 deletions src/ape_accounts/accounts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import json
from collections.abc import Iterator
from os import environ
from pathlib import Path
from typing import Any, Dict, Iterator, Optional, Tuple
from typing import Any, Optional

import click
from eip712.messages import EIP712Message
Expand Down Expand Up @@ -32,7 +33,7 @@ def __init__(self):


class AccountContainer(AccountContainerAPI):
loaded_accounts: Dict[str, "KeyfileAccount"] = {}
loaded_accounts: dict[str, "KeyfileAccount"] = {}

@property
def _keyfiles(self) -> Iterator[Path]:
Expand Down Expand Up @@ -292,7 +293,7 @@ def _write_and_return_account(alias: str, passphrase: str, account: LocalAccount

def generate_account(
alias: str, passphrase: str, hd_path: str = ETHEREUM_DEFAULT_PATH, word_count: int = 12
) -> Tuple[KeyfileAccount, str]:
) -> tuple[KeyfileAccount, str]:
"""
Generate a new account.
Expand Down
15 changes: 8 additions & 7 deletions src/ape_cache/query.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections.abc import Iterator
from pathlib import Path
from typing import Any, Dict, Iterator, List, Optional, cast
from typing import Any, Optional, cast

from sqlalchemy import create_engine, func
from sqlalchemy.engine import CursorResult
Expand Down Expand Up @@ -326,7 +327,7 @@ def _perform_block_query(self, query: BlockQuery) -> Iterator[BlockAPI]:
)

@perform_query.register
def _perform_transaction_query(self, query: BlockTransactionQuery) -> Iterator[Dict]:
def _perform_transaction_query(self, query: BlockTransactionQuery) -> Iterator[dict]:
with self.database_connection as conn:
result = conn.execute(
select([Transactions]).where(Transactions.block_hash == query.block_id)
Expand Down Expand Up @@ -395,7 +396,7 @@ def _cache_update_events_clause(self, query: ContractEventQuery) -> Insert:
@singledispatchmethod
def _get_cache_data(
self, query: QueryType, result: Iterator[BaseInterfaceModel]
) -> Optional[List[Dict[str, Any]]]:
) -> Optional[list[dict[str, Any]]]:
raise QueryEngineError(
"""
Not a compatible QueryType. For more details see our docs
Expand All @@ -406,16 +407,16 @@ def _get_cache_data(
@_get_cache_data.register
def _get_block_cache_data(
self, query: BlockQuery, result: Iterator[BaseInterfaceModel]
) -> Optional[List[Dict[str, Any]]]:
) -> Optional[list[dict[str, Any]]]:
return [m.model_dump(mode="json", by_alias=False) for m in result]

@_get_cache_data.register
def _get_block_txns_data(
self, query: BlockTransactionQuery, result: Iterator[BaseInterfaceModel]
) -> Optional[List[Dict[str, Any]]]:
) -> Optional[list[dict[str, Any]]]:
new_result = []
table_columns = [c.key for c in Transactions.__table__.columns] # type: ignore
txns: List[TransactionAPI] = cast(List[TransactionAPI], result)
txns: list[TransactionAPI] = cast(list[TransactionAPI], result)
for val in [m for m in txns]:
new_dict = {
k: v
Expand Down Expand Up @@ -443,7 +444,7 @@ def _get_block_txns_data(
@_get_cache_data.register
def _get_cache_events_data(
self, query: ContractEventQuery, result: Iterator[BaseInterfaceModel]
) -> Optional[List[Dict[str, Any]]]:
) -> Optional[list[dict[str, Any]]]:
return [m.model_dump(mode="json", by_alias=False) for m in result]

def update_cache(self, query: QueryType, result: Iterator[BaseInterfaceModel]):
Expand Down
4 changes: 2 additions & 2 deletions src/ape_compile/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from typing import List, Optional
from typing import Optional

from pydantic import field_validator, model_validator

Expand All @@ -21,7 +21,7 @@ class Config(PluginConfig):
should configure ``include_dependencies`` to be ``True``.
"""

exclude: List[str] = ["*package.json", "*package-lock.json", "*tsconfig.json"]
exclude: list[str] = ["*package.json", "*package-lock.json", "*tsconfig.json"]
"""
Source exclusion globs across all file types.
"""
Expand Down
5 changes: 2 additions & 3 deletions src/ape_compile/_cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from pathlib import Path
from typing import Dict, Set

import click
from ethpm_types import ContractType
Expand Down Expand Up @@ -38,7 +37,7 @@ def _include_dependencies_callback(ctx, param, value):
callback=_include_dependencies_callback,
)
@ape_cli_context()
def cli(cli_ctx, file_paths: Set[Path], use_cache: bool, display_size: bool, include_dependencies):
def cli(cli_ctx, file_paths: set[Path], use_cache: bool, display_size: bool, include_dependencies):
"""
Compiles the manifest for this project and saves the results
back to the manifest.
Expand Down Expand Up @@ -97,7 +96,7 @@ def cli(cli_ctx, file_paths: Set[Path], use_cache: bool, display_size: bool, inc
_display_byte_code_sizes(cli_ctx, contract_types)


def _display_byte_code_sizes(cli_ctx, contract_types: Dict[str, ContractType]):
def _display_byte_code_sizes(cli_ctx, contract_types: dict[str, ContractType]):
# Display bytecode size for *all* contract types (not just ones we compiled)
code_size = []
for contract in contract_types.values():
Expand Down
8 changes: 4 additions & 4 deletions src/ape_console/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from importlib.util import module_from_spec, spec_from_loader
from os import environ, getcwd
from types import ModuleType
from typing import Any, Dict, cast
from typing import Any, cast

import click
import IPython
Expand Down Expand Up @@ -46,7 +46,7 @@ def import_extras_file(file_path) -> ModuleType:
return module


def load_console_extras(**namespace: Any) -> Dict[str, Any]:
def load_console_extras(**namespace: Any) -> dict[str, Any]:
"""load and return namespace updates from ape_console_extras.py files if
they exist"""
global_extras = ManagerAccessMixin.config_manager.DATA_FOLDER.joinpath(CONSOLE_EXTRAS_FILENAME)
Expand All @@ -66,7 +66,7 @@ def load_console_extras(**namespace: Any) -> Dict[str, Any]:
# Figure out the kwargs the func is looking for and assemble
# from the original namespace
func_spec = inspect.getfullargspec(ape_init_extras)
init_kwargs: Dict[str, Any] = {k: namespace.get(k) for k in func_spec.args}
init_kwargs: dict[str, Any] = {k: namespace.get(k) for k in func_spec.args}

# Execute functionality with existing console namespace as
# kwargs.
Expand Down Expand Up @@ -140,7 +140,7 @@ def console(project=None, verbose=None, extra_locals=None, embed=False):
_launch_console(namespace, ipy_config, embed, banner)


def _launch_console(namespace: Dict, ipy_config: IPythonConfig, embed: bool, banner: str):
def _launch_console(namespace: dict, ipy_config: IPythonConfig, embed: bool, banner: str):
ipython_kwargs = {"user_ns": namespace, "config": ipy_config}
if embed:
IPython.embed(**ipython_kwargs, colors="Neutral", banner1=banner)
Expand Down
4 changes: 1 addition & 3 deletions src/ape_console/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from typing import List

from ape.api import PluginConfig


class ConsoleConfig(PluginConfig):
plugins: List[str] = []
plugins: list[str] = []
"""Additional IPython plugins to include in your session."""
Loading

0 comments on commit 65fc2be

Please sign in to comment.