Skip to content

Commit

Permalink
Merge branch 'main' into poll-methods-redux
Browse files Browse the repository at this point in the history
  • Loading branch information
z80dev authored Oct 25, 2023
2 parents ab57454 + e3cb2c8 commit 9175bcd
Show file tree
Hide file tree
Showing 97 changed files with 2,448 additions and 999 deletions.
3 changes: 2 additions & 1 deletion build_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def build_docs(path: Path) -> Path:
try:
subprocess.check_call(["sphinx-build", "docs", str(path)])
except subprocess.SubprocessError as err:
raise ApeDocsBuildError(f"Command 'sphinx-build docs {path}' failed.") from err
message = f"Command 'sphinx-build docs {path}' failed.\nErr:{err}"
raise ApeDocsBuildError(message) from err

return path

Expand Down
10 changes: 10 additions & 0 deletions docs/userguides/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ This is helpful when:
- When there is not a suitable `DependencyAPI` implementation available for downloading your dependency.
- Testing the framework.

You can also reference local project manifests and use those as dependencies.
To do this, use a local value pointing to the manifest file, like this:

```yaml
dependencies:
- name: MyDependency
local: ./my-dependency.json
version: 1.0.0
```

### NPM

You can use dependencies from NPM.
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exclude =
docs
build
.eggs
tests/integration/cli/projects
per-file-ignores =
# Need signal handler before imports
src/ape/__init__.py: E402
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown
"mdformat-frontmatter>=0.4.1", # Needed for frontmatters-style headers in issue templates
"mdformat-pyproject>=0.0.1", # Allows configuring in pyproject.toml
"pydantic<2.0", # Needed for successful type check. TODO: Remove after full v2 support.
],
"doc": [
"myst-parser>=1.0.0,<2", # Parse markdown docs
Expand Down Expand Up @@ -101,7 +102,7 @@
"packaging>=23.0,<24",
"pandas>=1.3.0,<2",
"pluggy>=1.3,<2",
"pydantic>=1.10.8,<2",
"pydantic>=1.10.8,<3",
"PyGithub>=1.59,<2",
"pytest>=6.0,<8.0",
"python-dateutil>=2.8.2,<3",
Expand All @@ -123,7 +124,7 @@
"web3[tester]>=6.7.0,<7",
# ** Dependencies maintained by ApeWorX **
"eip712>=0.2.1,<0.3",
"ethpm-types>=0.5.6,<0.6",
"ethpm-types>=0.5.8,<0.6",
"evm-trace>=0.1.0a23",
],
entry_points={
Expand Down
43 changes: 20 additions & 23 deletions src/ape/_cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import difflib
import re
import sys
from typing import Any, Dict
from typing import Any, Dict, List, Optional

import click
import importlib_metadata as metadata
Expand Down Expand Up @@ -29,7 +29,8 @@ def display_config(ctx, param, value):


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

def invoke(self, ctx) -> Any:
try:
Expand All @@ -48,11 +49,14 @@ def _suggest_cmd(usage_error):
if usage_error.message is None:
raise usage_error

match = re.match("No such command '(.*)'.", usage_error.message)
if not match:
elif not (match := re.match("No such command '(.*)'.", usage_error.message)):
raise usage_error

bad_arg = match.groups()[0]
groups = match.groups()
if len(groups) < 1:
raise usage_error

bad_arg = groups[0]
suggested_commands = difflib.get_close_matches(
bad_arg, list(usage_error.ctx.command.commands.keys()), cutoff=_DIFFLIB_CUT_OFF
)
Expand All @@ -66,30 +70,22 @@ def _suggest_cmd(usage_error):

@property
def commands(self) -> Dict:
group_name = "ape_cli_subcommands"
if not self._commands:
try:
entry_points = metadata.entry_points(group=group_name)
except TypeError:
entry_points = metadata.entry_points()
entry_points = (
entry_points[group_name] if group_name in entry_points else [] # type: ignore
)

if not entry_points:
raise Abort("Missing registered cli subcommands")
if self._commands:
return self._commands

self._commands = {
clean_plugin_name(entry_point.name): entry_point.load
for entry_point in entry_points
}
entry_points = metadata.entry_points(group=self._CLI_GROUP_NAME)
if not entry_points:
raise Abort("Missing registered CLI subcommands.")

self._commands = {
clean_plugin_name(entry_point.name): entry_point.load for entry_point in entry_points
}
return self._commands

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

def get_command(self, ctx, name):
def get_command(self, ctx, name) -> Optional[click.Command]:
if name in self.commands:
try:
return self.commands[name]()
Expand All @@ -99,6 +95,7 @@ def get_command(self, ctx, name):
)

# NOTE: don't return anything so Click displays proper error
return None


@click.command(cls=ApeCLI, context_settings=dict(help_option_names=["-h", "--help"]))
Expand Down
47 changes: 47 additions & 0 deletions src/ape/_pydantic_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# support both pydantic v1 and v2

try:
from pydantic.v1 import ( # type: ignore
BaseModel,
BaseSettings,
Extra,
Field,
FileUrl,
HttpUrl,
NonNegativeInt,
PositiveInt,
ValidationError,
root_validator,
validator,
)
from pydantic.v1.dataclasses import dataclass # type: ignore
except ImportError:
from pydantic import ( # type: ignore
BaseModel,
BaseSettings,
Extra,
Field,
FileUrl,
HttpUrl,
NonNegativeInt,
PositiveInt,
ValidationError,
root_validator,
validator,
)
from pydantic.dataclasses import dataclass # type: ignore

__all__ = (
"BaseModel",
"BaseSettings",
"dataclass",
"Extra",
"Field",
"FileUrl",
"HttpUrl",
"NonNegativeInt",
"PositiveInt",
"ValidationError",
"root_validator",
"validator",
)
3 changes: 1 addition & 2 deletions src/ape/api/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from ape.exceptions import ConversionError
from ape.types import AddressType, ContractCode
from ape.utils import BaseInterface, abstractmethod, cached_property
from ape.utils.abi import _convert_kwargs

if TYPE_CHECKING:
from ape.api.transactions import ReceiptAPI, TransactionAPI
Expand Down Expand Up @@ -167,7 +166,7 @@ def history(self) -> "AccountHistory":
return self.chain_manager.history[self.address]

def as_transaction(self, **kwargs) -> "TransactionAPI":
converted_kwargs = _convert_kwargs(kwargs, self.conversion_manager.convert)
converted_kwargs = self.conversion_manager.convert_method_kwargs(kwargs)
return self.provider.network.ecosystem.create_transaction(
receiver=self.address, **converted_kwargs
)
Expand Down
4 changes: 2 additions & 2 deletions src/ape/api/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum
from typing import Any, Dict, Optional, TypeVar

from pydantic import BaseModel, BaseSettings
from ape._pydantic_compat import BaseModel, BaseSettings

T = TypeVar("T")

Expand Down Expand Up @@ -40,7 +40,7 @@ def update(root: Dict, value_map: Dict):
return cls(**update(default_values, overrides))

def __getattr__(self, attr_name: str) -> Any:
# allow hyphens in plugin config files
# Allow hyphens in plugin config files.
attr_name = attr_name.replace("-", "_")
return super().__getattribute__(attr_name)

Expand Down
Loading

0 comments on commit 9175bcd

Please sign in to comment.