Skip to content

Commit

Permalink
chore: lazify CLI loading (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Oct 29, 2024
1 parent f26db86 commit d1f0176
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 90 deletions.
11 changes: 6 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: check-yaml

Expand All @@ -10,7 +10,7 @@ repos:
- id: isort

- repo: https://github.com/psf/black
rev: 24.8.0
rev: 24.10.0
hooks:
- id: black
name: black
Expand All @@ -19,15 +19,16 @@ repos:
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: [flake8-breakpoint, flake8-print, flake8-pydantic, flake8-type-checking]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.2
rev: v1.13.0
hooks:
- id: mypy
additional_dependencies: [types-setuptools, pydantic==1.10.4]
additional_dependencies: [types-setuptools, pydantic]

- repo: https://github.com/executablebooks/mdformat
rev: 0.7.17
rev: 0.7.18
hooks:
- id: mdformat
additional_dependencies: [mdformat-gfm, mdformat-frontmatter, mdformat-pyproject]
Expand Down
38 changes: 34 additions & 4 deletions ape_vyper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,45 @@
from ape import plugins
from typing import Any

from ._utils import FileType
from .compiler import VyperCompiler
from .config import VyperConfig
from ape import plugins


@plugins.register(plugins.Config)
def config_class():
from .config import VyperConfig

return VyperConfig


@plugins.register(plugins.CompilerPlugin)
def register_compiler():
from ._utils import FileType
from .compiler import VyperCompiler

return tuple(e.value for e in FileType), VyperCompiler


def __getattr__(name: str) -> Any:
if name == "FileType":
from ._utils import FileType

return FileType

elif name == "VyperCompiler":
from .compiler import VyperCompiler

return VyperCompiler

elif name == "VyperConfig":
from .config import VyperConfig

return VyperConfig

else:
raise AttributeError(name)


__all__ = [
"FileType",
"VyperCompiler",
"VyperConfig",
]
2 changes: 1 addition & 1 deletion ape_vyper/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ape
import click
from ape.cli import ape_cli_context, project_option
from ape.cli.options import ape_cli_context, project_option


@click.group
Expand Down
18 changes: 11 additions & 7 deletions ape_vyper/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@
from collections.abc import Iterable
from enum import Enum
from pathlib import Path
from typing import Any, Optional, Union
from typing import TYPE_CHECKING, Any, Optional, Union

import vvm # type: ignore
from ape.exceptions import ProjectError
from ape.logging import logger
from ape.managers import ProjectManager
from ape.types import SourceTraceback
from ape.utils import get_relative_path
from eth_utils import is_0x_prefixed
from ethpm_types import ASTNode, PCMap, SourceMapItem
from ethpm_types.source import Function
from packaging.specifiers import InvalidSpecifier, SpecifierSet
from packaging.version import Version

from ape_vyper.exceptions import RuntimeErrorType, VyperInstallError

if TYPE_CHECKING:
from ape.types.trace import SourceTraceback
from ethpm_types.source import Function
from packaging.version import Version

Optimization = Union[str, bool]
EVM_VERSION_DEFAULT = {
"0.2.15": "berlin",
Expand Down Expand Up @@ -54,7 +56,7 @@ def __str__(self) -> str:
return self.value


def install_vyper(version: Version):
def install_vyper(version: "Version"):
for attempt in range(MAX_INSTALL_RETRIES):
try:
vvm.install_vyper(version, show_progress=True)
Expand Down Expand Up @@ -255,7 +257,7 @@ def seek() -> Optional[Path]:
return None


def safe_append(data: dict, version: Union[Version, SpecifierSet], paths: Union[Path, set]):
def safe_append(data: dict, version: Union["Version", SpecifierSet], paths: Union[Path, set]):
if isinstance(paths, Path):
paths = {paths}
if version in data:
Expand Down Expand Up @@ -478,7 +480,9 @@ def is_immutable_member_load(opcodes: list[str]):
return not is_code_copy and opcodes and is_0x_prefixed(opcodes[0])


def extend_return(function: Function, traceback: SourceTraceback, last_pc: int, source_path: Path):
def extend_return(
function: "Function", traceback: "SourceTraceback", last_pc: int, source_path: Path
):
return_ast_result = [x for x in function.ast.children if x.ast_type == "Return"]
if not return_ast_result:
return
Expand Down
34 changes: 19 additions & 15 deletions ape_vyper/compiler/_versions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
from typing import TYPE_CHECKING, Any, Optional

from ape.logging import logger
from ape.managers.project import ProjectManager
from ape.utils import ManagerAccessMixin, clean_path, get_relative_path
from ethpm_types import ASTNode, ContractType, SourceMap
from ethpm_types.ast import ASTClassification
from ethpm_types.source import Content
from packaging.version import Version
from vvm import compile_standard as vvm_compile_standard # type: ignore
from vvm.exceptions import VyperError # type: ignore

Expand All @@ -25,10 +23,13 @@
get_pcmap,
)
from ape_vyper.exceptions import VyperCompileError
from ape_vyper.imports import ImportMap

if TYPE_CHECKING:
from ape.managers.project import ProjectManager
from packaging.version import Version

from ape_vyper.compiler.api import VyperCompiler
from ape_vyper.imports import ImportMap


class BaseVyperCompiler(ManagerAccessMixin):
Expand All @@ -39,7 +40,7 @@ class BaseVyperCompiler(ManagerAccessMixin):
def __init__(self, api: "VyperCompiler"):
self.api = api

def get_import_remapping(self, project: Optional[ProjectManager] = None) -> dict[str, dict]:
def get_import_remapping(self, project: Optional["ProjectManager"] = None) -> dict[str, dict]:
# Overridden on 0.4 to not use.
# Import remappings are for Vyper versions 0.2 - 0.3 to
# create the interfaces dict.
Expand All @@ -48,11 +49,11 @@ def get_import_remapping(self, project: Optional[ProjectManager] = None) -> dict

def compile(
self,
vyper_version: Version,
vyper_version: "Version",
settings: dict,
import_map: ImportMap,
import_map: "ImportMap",
compiler_data: dict,
project: Optional[ProjectManager] = None,
project: Optional["ProjectManager"] = None,
):
pm = project or self.local_project
for settings_key, settings_set in settings.items():
Expand Down Expand Up @@ -155,10 +156,10 @@ def compile(

def get_settings(
self,
version: Version,
version: "Version",
source_paths: Iterable[Path],
compiler_data: dict,
project: Optional[ProjectManager] = None,
project: Optional["ProjectManager"] = None,
) -> dict:
pm = project or self.local_project
default_optimization = self._get_default_optimization(version)
Expand Down Expand Up @@ -210,7 +211,7 @@ def _classify_ast(self, _node: ASTNode):
self._classify_ast(child)

def _get_sources_dictionary(
self, source_ids: Iterable[str], project: Optional[ProjectManager] = None, **kwargs
self, source_ids: Iterable[str], project: Optional["ProjectManager"] = None, **kwargs
) -> dict[str, dict]:
"""
Generate input for the "sources" key in the input JSON.
Expand All @@ -225,7 +226,7 @@ def _get_sources_dictionary(
def _get_selection_dictionary(
self,
selection: Iterable[str],
project: Optional[ProjectManager] = None,
project: Optional["ProjectManager"] = None,
**kwargs,
) -> dict:
"""
Expand All @@ -238,7 +239,10 @@ def _get_selection_dictionary(
return {s: ["*"] for s in selection if (pm.path / s).is_file() if "interfaces" not in s}

def _get_compile_kwargs(
self, vyper_version: Version, compiler_data: dict, project: Optional[ProjectManager] = None
self,
vyper_version: "Version",
compiler_data: dict,
project: Optional["ProjectManager"] = None,
) -> dict:
"""
Generate extra kwargs to pass to Vyper.
Expand All @@ -249,14 +253,14 @@ def _get_compile_kwargs(
comp_kwargs["base_path"] = pm.path
return comp_kwargs

def _get_base_compile_kwargs(self, vyper_version: Version, compiler_data: dict):
def _get_base_compile_kwargs(self, vyper_version: "Version", compiler_data: dict):
vyper_binary = compiler_data[vyper_version]["vyper_binary"]
comp_kwargs = {"vyper_version": vyper_version, "vyper_binary": vyper_binary}
return comp_kwargs

def _get_pcmap(
self,
vyper_version: Version,
vyper_version: "Version",
ast: Any,
src_map: list,
opcodes: list[str],
Expand All @@ -274,7 +278,7 @@ def _parse_source_map(self, raw_source_map: Any) -> SourceMap:
# All versions < 0.4 use this one
return SourceMap(root=raw_source_map)

def _get_default_optimization(self, vyper_version: Version) -> Optimization:
def _get_default_optimization(self, vyper_version: "Version") -> Optimization:
"""
The default value for "optimize" in the settings for input JSON.
"""
Expand Down
9 changes: 5 additions & 4 deletions ape_vyper/compiler/_versions/vyper_02.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import Any

from packaging.version import Version
from typing import TYPE_CHECKING, Any

from ape_vyper._utils import get_legacy_pcmap
from ape_vyper.compiler._versions.base import BaseVyperCompiler

if TYPE_CHECKING:
from packaging.version import Version


class Vyper02Compiler(BaseVyperCompiler):
"""
Expand All @@ -15,7 +16,7 @@ class Vyper02Compiler(BaseVyperCompiler):

def _get_pcmap(
self,
vyper_version: Version,
vyper_version: "Version",
ast: Any,
src_map: list,
opcodes: list[str],
Expand Down
25 changes: 15 additions & 10 deletions ape_vyper/compiler/_versions/vyper_04.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import os
from collections.abc import Iterable
from pathlib import Path
from typing import Optional
from typing import TYPE_CHECKING, Optional

from ape.managers import ProjectManager
from ape.utils import get_full_extension, get_relative_path
from ethpm_types import SourceMap
from packaging.version import Version

from ape_vyper._utils import FileType, Optimization
from ape_vyper.compiler._versions.base import BaseVyperCompiler
from ape_vyper.imports import ImportMap

if TYPE_CHECKING:
from ape.managers.project import ProjectManager
from packaging.version import Version


class Vyper04Compiler(BaseVyperCompiler):
"""
Compiler for Vyper>=0.4.0.
"""

def get_import_remapping(self, project: Optional[ProjectManager] = None) -> dict[str, dict]:
def get_import_remapping(self, project: Optional["ProjectManager"] = None) -> dict[str, dict]:
# Import remappings are not used in 0.4.
# You always import via module or package name.
return {}

def get_settings(
self,
version: Version,
version: "Version",
source_paths: Iterable[Path],
compiler_data: dict,
project: Optional[ProjectManager] = None,
project: Optional["ProjectManager"] = None,
) -> dict:
pm = project or self.local_project

Expand All @@ -43,7 +45,7 @@ def get_settings(
return settings

def _get_sources_dictionary(
self, source_ids: Iterable[str], project: Optional[ProjectManager] = None, **kwargs
self, source_ids: Iterable[str], project: Optional["ProjectManager"] = None, **kwargs
) -> dict[str, dict]:
pm = project or self.local_project
if not source_ids:
Expand Down Expand Up @@ -83,18 +85,21 @@ def _get_sources_dictionary(
return src_dict

def _get_compile_kwargs(
self, vyper_version: Version, compiler_data: dict, project: Optional[ProjectManager] = None
self,
vyper_version: "Version",
compiler_data: dict,
project: Optional["ProjectManager"] = None,
) -> dict:
return self._get_base_compile_kwargs(vyper_version, compiler_data)

def _get_default_optimization(self, vyper_version: Version) -> Optimization:
def _get_default_optimization(self, vyper_version: "Version") -> Optimization:
return "gas"

def _parse_source_map(self, raw_source_map: dict) -> SourceMap:
return SourceMap(root=raw_source_map["pc_pos_map_compressed"])

def _get_selection_dictionary(
self, selection: Iterable[str], project: Optional[ProjectManager] = None, **kwargs
self, selection: Iterable[str], project: Optional["ProjectManager"] = None, **kwargs
) -> dict:
pm = project or self.local_project
return {
Expand Down
Loading

0 comments on commit d1f0176

Please sign in to comment.