Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ApeWorX/ape into feat/0-9
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwise-constructs committed Oct 30, 2024
2 parents 33eff55 + 4fdf8e9 commit df3cb55
Show file tree
Hide file tree
Showing 87 changed files with 1,098 additions and 685 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repos:
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: [flake8-breakpoint, flake8-print, flake8-pydantic]
additional_dependencies: [flake8-breakpoint, flake8-print, flake8-pydantic, flake8-type-checking]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
Expand Down
5 changes: 4 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ exclude =
build
.eggs
tests/integration/cli/projects
ignore = E704,W503,PYD002
ignore = E704,W503,PYD002,TC003,TC006
per-file-ignores =
# Need signal handler before imports
src/ape/__init__.py: E402
# Test data causes long lines
tests/functional/data/python/__init__.py: E501
tests/functional/utils/expected_traces.py: E501

type-checking-pydantic-enabled = True
type-checking-sqlalchemy-enabled = True
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"flake8-breakpoint>=1.1.0,<2", # Detect breakpoints left in code
"flake8-print>=4.0.1,<5", # Detect print statements left in code
"flake8-pydantic", # For detecting issues with Pydantic models
"flake8-type-checking", # Detect imports to move in/out of type-checking blocks
"isort>=5.13.2,<6", # Import sorting linter
"mdformat>=0.7.18", # Auto-formatter for markdown
"mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown
Expand Down
43 changes: 23 additions & 20 deletions src/ape/_cli.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import difflib
import re
import sys
import warnings
from collections.abc import Iterable
from functools import cached_property
from gettext import gettext
from importlib import import_module
from importlib.metadata import entry_points
from pathlib import Path
from typing import Any, Optional
from typing import TYPE_CHECKING, Any, Optional
from warnings import catch_warnings, simplefilter

import click
import rich
import yaml
from click import Context

from ape.cli.options import ape_cli_context
from ape.exceptions import Abort, ApeException, ConfigError, handle_ape_exception
from ape.logging import logger
from ape.utils.basemodel import ManagerAccessMixin as access

if TYPE_CHECKING:
from click import Context

_DIFFLIB_CUT_OFF = 0.6

Expand All @@ -27,6 +29,8 @@ def display_config(ctx, param, value):
if not value or ctx.resilient_parsing:
return

from ape.utils.basemodel import ManagerAccessMixin as access

click.echo("# Current configuration")

# NOTE: Using json-mode as yaml.dump requires JSON-like structure.
Expand All @@ -37,6 +41,8 @@ def display_config(ctx, param, value):


def _validate_config():
from ape.utils.basemodel import ManagerAccessMixin as access

project = access.local_project
try:
_ = project.config
Expand All @@ -47,10 +53,9 @@ def _validate_config():


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

def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
def parse_args(self, ctx: "Context", args: list[str]) -> list[str]:
# Validate the config before any argument parsing,
# as arguments may utilize config.
if "--help" not in args and args != []:
Expand All @@ -60,6 +65,8 @@ def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
return super().parse_args(ctx, args)

def format_commands(self, ctx, formatter) -> None:
from ape.utils.basemodel import ManagerAccessMixin as access

commands = []
for subcommand in self.list_commands(ctx):
cmd = self.get_command(ctx, subcommand)
Expand Down Expand Up @@ -91,7 +98,7 @@ def format_commands(self, ctx, formatter) -> None:

if plugin.in_core:
sections["Core"].append((cli_name, help))
elif plugin.is_installed and not plugin.is_third_party:
elif plugin.check_trusted(use_web=False):
sections["Plugin"].append((cli_name, help))
else:
sections["3rd-Party Plugin"].append((cli_name, help))
Expand Down Expand Up @@ -142,25 +149,21 @@ def _suggest_cmd(usage_error):

raise usage_error

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

_entry_points = entry_points()
eps: Iterable
if select_fn := getattr(_entry_points, "select", None):
# NOTE: Using getattr because mypy.
eps = select_fn(group=self._CLI_GROUP_NAME)
else:
# Python 3.9. Can remove once we drop support.
with warnings.catch_warnings():
warnings.simplefilter("ignore")

try:
eps = _entry_points.select(group=self._CLI_GROUP_NAME)
except AttributeError:
# Fallback for Python 3.9
with catch_warnings():
simplefilter("ignore")
eps = _entry_points.get(self._CLI_GROUP_NAME, []) # type: ignore

commands = {cmd.name.replace("_", "-").replace("ape-", ""): cmd.load for cmd in eps}
self._commands = {k: commands[k] for k in sorted(commands)}
return self._commands
return dict(sorted(commands.items()))

def list_commands(self, ctx) -> list[str]:
return [k for k in self.commands]
Expand Down
5 changes: 3 additions & 2 deletions src/ape/api/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from eip712.messages import SignableMessage as EIP712SignableMessage
from eth_account import Account
from eth_account.messages import encode_defunct
from eth_pydantic_types import HexBytes
from eth_utils import to_hex
from ethpm_types import ContractType

Expand All @@ -31,6 +30,8 @@
from ape.utils.misc import raises_not_implemented

if TYPE_CHECKING:
from eth_pydantic_types import HexBytes

from ape.contracts import ContractContainer, ContractInstance


Expand Down Expand Up @@ -65,7 +66,7 @@ def alias(self) -> Optional[str]:
"""
return None

def sign_raw_msghash(self, msghash: HexBytes) -> Optional[MessageSignature]:
def sign_raw_msghash(self, msghash: "HexBytes") -> Optional[MessageSignature]:
"""
Sign a raw message hash.
Expand Down
4 changes: 2 additions & 2 deletions src/ape/api/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
from ape.exceptions import ConversionError
from ape.types.address import AddressType
from ape.types.units import CurrencyValue
from ape.types.vm import ContractCode
from ape.utils.basemodel import BaseInterface
from ape.utils.misc import log_instead_of_fail

if TYPE_CHECKING:
from ape.api.transactions import ReceiptAPI, TransactionAPI
from ape.managers.chain import AccountHistory
from ape.types.vm import ContractCode


class BaseAddress(BaseInterface):
Expand Down Expand Up @@ -146,7 +146,7 @@ def __setattr__(self, attr: str, value: Any) -> None:
super().__setattr__(attr, value)

@property
def code(self) -> ContractCode:
def code(self) -> "ContractCode":
"""
The raw bytes of the smart-contract code at the address.
"""
Expand Down
36 changes: 18 additions & 18 deletions src/ape/api/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
from pathlib import Path
from typing import TYPE_CHECKING, Optional

from eth_pydantic_types import HexBytes
from ethpm_types import ContractType
from ethpm_types.source import Content, ContractSource
from packaging.version import Version

from ape.api.config import PluginConfig
from ape.api.trace import TraceAPI
from ape.exceptions import APINotImplementedError, ContractLogicError
from ape.types.coverage import ContractSourceCoverage
from ape.types.trace import SourceTraceback
from ape.utils.basemodel import BaseInterfaceModel
from ape.utils.misc import log_instead_of_fail, raises_not_implemented

if TYPE_CHECKING:
from eth_pydantic_types import HexBytes
from ethpm_types import ContractType
from ethpm_types.source import Content, ContractSource
from packaging.version import Version

from ape.api.config import PluginConfig
from ape.api.trace import TraceAPI
from ape.managers.project import ProjectManager
from ape.types.coverage import ContractSourceCoverage
from ape.types.trace import SourceTraceback


class CompilerAPI(BaseInterfaceModel):
Expand All @@ -44,7 +44,7 @@ def name(self) -> str:
The name of the compiler.
"""

def get_config(self, project: Optional["ProjectManager"] = None) -> PluginConfig:
def get_config(self, project: Optional["ProjectManager"] = None) -> "PluginConfig":
"""
The combination of settings from ``ape-config.yaml`` and ``.compiler_settings``.
Expand Down Expand Up @@ -79,7 +79,7 @@ def get_compiler_settings( # type: ignore[empty-body]
contract_filepaths: Iterable[Path],
project: Optional["ProjectManager"] = None,
**overrides,
) -> dict[Version, dict]:
) -> dict["Version", dict]:
"""
Get a mapping of the settings that would be used to compile each of the sources
by the compiler version number.
Expand All @@ -101,7 +101,7 @@ def compile(
contract_filepaths: Iterable[Path],
project: Optional["ProjectManager"],
settings: Optional[dict] = None,
) -> Iterator[ContractType]:
) -> Iterator["ContractType"]:
"""
Compile the given source files. All compiler plugins must implement this function.
Expand All @@ -123,7 +123,7 @@ def compile_code( # type: ignore[empty-body]
project: Optional["ProjectManager"],
settings: Optional[dict] = None,
**kwargs,
) -> ContractType:
) -> "ContractType":
"""
Compile a program.
Expand Down Expand Up @@ -162,7 +162,7 @@ def get_version_map( # type: ignore[empty-body]
self,
contract_filepaths: Iterable[Path],
project: Optional["ProjectManager"] = None,
) -> dict[Version, set[Path]]:
) -> dict["Version", set[Path]]:
"""
Get a map of versions to source paths.
Expand Down Expand Up @@ -218,8 +218,8 @@ def enrich_error(self, err: ContractLogicError) -> ContractLogicError:

@raises_not_implemented
def trace_source( # type: ignore[empty-body]
self, contract_source: ContractSource, trace: TraceAPI, calldata: HexBytes
) -> SourceTraceback:
self, contract_source: "ContractSource", trace: "TraceAPI", calldata: "HexBytes"
) -> "SourceTraceback":
"""
Get a source-traceback for the given contract type.
The source traceback object contains all the control paths taken in the transaction.
Expand All @@ -239,7 +239,7 @@ def trace_source( # type: ignore[empty-body]
@raises_not_implemented
def flatten_contract( # type: ignore[empty-body]
self, path: Path, project: Optional["ProjectManager"] = None, **kwargs
) -> Content:
) -> "Content":
"""
Get the content of a flattened contract via its source path.
Plugin implementations handle import resolution, SPDX de-duplication,
Expand All @@ -259,7 +259,7 @@ def flatten_contract( # type: ignore[empty-body]

@raises_not_implemented
def init_coverage_profile(
self, source_coverage: ContractSourceCoverage, contract_source: ContractSource
self, source_coverage: "ContractSourceCoverage", contract_source: "ContractSource"
): # type: ignore[empty-body]
"""
Initialize an empty report for the given source ID. Modifies the given source
Expand Down
16 changes: 9 additions & 7 deletions src/ape/api/explorers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from abc import abstractmethod
from typing import Optional

from ethpm_types import ContractType
from typing import TYPE_CHECKING, Optional

from ape.api.networks import NetworkAPI
from ape.types.address import AddressType
from ape.utils.basemodel import BaseInterfaceModel

if TYPE_CHECKING:
from ethpm_types import ContractType

from ape.types.address import AddressType


class ExplorerAPI(BaseInterfaceModel):
"""
Expand All @@ -18,7 +20,7 @@ class ExplorerAPI(BaseInterfaceModel):
network: NetworkAPI

@abstractmethod
def get_address_url(self, address: AddressType) -> str:
def get_address_url(self, address: "AddressType") -> str:
"""
Get an address URL, such as for a transaction.
Expand All @@ -42,7 +44,7 @@ def get_transaction_url(self, transaction_hash: str) -> str:
"""

@abstractmethod
def get_contract_type(self, address: AddressType) -> Optional[ContractType]:
def get_contract_type(self, address: "AddressType") -> Optional["ContractType"]:
"""
Get the contract type for a given address if it has been published to this explorer.
Expand All @@ -54,7 +56,7 @@ def get_contract_type(self, address: AddressType) -> Optional[ContractType]:
"""

@abstractmethod
def publish_contract(self, address: AddressType):
def publish_contract(self, address: "AddressType"):
"""
Publish a contract to the explorer.
Expand Down
Loading

0 comments on commit df3cb55

Please sign in to comment.