diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7b87bf9..53a019a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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 @@ -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 @@ -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] diff --git a/ape_vyper/__init__.py b/ape_vyper/__init__.py index 0a78839..290656b 100644 --- a/ape_vyper/__init__.py +++ b/ape_vyper/__init__.py @@ -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", +] diff --git a/ape_vyper/_cli.py b/ape_vyper/_cli.py index bfddd37..5b7efa8 100644 --- a/ape_vyper/_cli.py +++ b/ape_vyper/_cli.py @@ -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 diff --git a/ape_vyper/_utils.py b/ape_vyper/_utils.py index bc58b63..fbdf924 100644 --- a/ape_vyper/_utils.py +++ b/ape_vyper/_utils.py @@ -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", @@ -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) @@ -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: @@ -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 diff --git a/ape_vyper/compiler/_versions/base.py b/ape_vyper/compiler/_versions/base.py index 1c98581..1be11df 100644 --- a/ape_vyper/compiler/_versions/base.py +++ b/ape_vyper/compiler/_versions/base.py @@ -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 @@ -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): @@ -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. @@ -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(): @@ -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) @@ -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. @@ -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: """ @@ -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. @@ -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], @@ -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. """ diff --git a/ape_vyper/compiler/_versions/vyper_02.py b/ape_vyper/compiler/_versions/vyper_02.py index 90db4bd..05d1f86 100644 --- a/ape_vyper/compiler/_versions/vyper_02.py +++ b/ape_vyper/compiler/_versions/vyper_02.py @@ -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): """ @@ -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], diff --git a/ape_vyper/compiler/_versions/vyper_04.py b/ape_vyper/compiler/_versions/vyper_04.py index 9d6632a..6711e59 100644 --- a/ape_vyper/compiler/_versions/vyper_04.py +++ b/ape_vyper/compiler/_versions/vyper_04.py @@ -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 @@ -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: @@ -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 { diff --git a/ape_vyper/compiler/api.py b/ape_vyper/compiler/api.py index 4748347..40e2c7b 100644 --- a/ape_vyper/compiler/api.py +++ b/ape_vyper/compiler/api.py @@ -6,19 +6,15 @@ from functools import cached_property from importlib import import_module from pathlib import Path -from typing import Optional +from typing import TYPE_CHECKING, Optional import vvm # type: ignore from ape.api import CompilerAPI, PluginConfig, TraceAPI -from ape.exceptions import ContractLogicError from ape.logging import logger from ape.managers import ProjectManager from ape.managers.project import LocalProject -from ape.types import ContractSourceCoverage, SourceTraceback from ape.utils import get_full_extension, get_relative_path from ape.utils._github import _GithubClient -from eth_pydantic_types import HexBytes -from ethpm_types import ContractType from ethpm_types.source import Compiler, Content, ContractSource from packaging.specifiers import SpecifierSet from packaging.version import Version @@ -36,6 +32,13 @@ from ape_vyper.imports import ImportMap, ImportResolver from ape_vyper.traceback import SourceTracer +if TYPE_CHECKING: + from ape.exceptions import ContractLogicError + from ape.types.coverage import ContractSourceCoverage + from ape.types.trace import SourceTraceback + from eth_pydantic_types import HexBytes + from ethpm_types.contract_type import ContractType + class VyperCompiler(CompilerAPI): _dependencies_by_project: dict[str, dict[str, ProjectManager]] = {} @@ -245,7 +248,7 @@ def compile( contract_filepaths: Iterable[Path], project: Optional[ProjectManager] = None, settings: Optional[dict] = None, - ) -> Iterator[ContractType]: + ) -> Iterator["ContractType"]: pm = project or self.local_project original_settings = self.compiler_settings self.compiler_settings = {**self.compiler_settings, **(settings or {})} @@ -258,7 +261,7 @@ def _compile( self, contract_filepaths: Iterable[Path], project: Optional[ProjectManager] = None ): pm = project or self.local_project - contract_types: list[ContractType] = [] + contract_types: list["ContractType"] = [] import_map = self._import_resolver.get_imports(pm, contract_filepaths) config = self.get_config(pm) version_map = self._get_version_map_from_import_map( @@ -328,7 +331,7 @@ def _compile( def compile_code( self, code: str, project: Optional[ProjectManager] = None, **kwargs - ) -> ContractType: + ) -> "ContractType": # NOTE: We are unable to use `vvm.compile_code()` because it does not # appear to honor altered VVM install paths, thus always re-installs # Vyper in our tests because of the monkeypatch. Also, their approach @@ -515,18 +518,18 @@ def _get_compiler_settings_from_version_map( return settings def init_coverage_profile( - self, source_coverage: ContractSourceCoverage, contract_source: ContractSource + self, source_coverage: "ContractSourceCoverage", contract_source: ContractSource ): profiler = CoverageProfiler(source_coverage) profiler.initialize(contract_source) - def enrich_error(self, err: ContractLogicError) -> ContractLogicError: + def enrich_error(self, err: "ContractLogicError") -> "ContractLogicError": return enrich_error(err) # TODO: In 0.9, make sure project is a kwarg here. def trace_source( - self, contract_source: ContractSource, trace: TraceAPI, calldata: HexBytes - ) -> SourceTraceback: + self, contract_source: ContractSource, trace: TraceAPI, calldata: "HexBytes" + ) -> "SourceTraceback": return SourceTracer.trace(trace.get_raw_frames(), contract_source, calldata) def _get_compiler_arguments( diff --git a/ape_vyper/coverage.py b/ape_vyper/coverage.py index d1f51bb..deb3e83 100644 --- a/ape_vyper/coverage.py +++ b/ape_vyper/coverage.py @@ -1,19 +1,21 @@ from fnmatch import fnmatch -from typing import Optional +from typing import TYPE_CHECKING, Optional -from ape.types import ContractSourceCoverage from ape.utils import ManagerAccessMixin -from ethpm_types.source import ContractSource from ethpm_types.utils import SourceLocation from ape_vyper.exceptions import RuntimeErrorType +if TYPE_CHECKING: + from ape.types import ContractSourceCoverage + from ethpm_types.source import ContractSource + class CoverageProfiler(ManagerAccessMixin): - def __init__(self, source_coverage: ContractSourceCoverage): + def __init__(self, source_coverage: "ContractSourceCoverage"): self._coverage = source_coverage - def initialize(self, contract_source: ContractSource): + def initialize(self, contract_source: "ContractSource"): exclusions = self.config_manager.get_config("test").coverage.exclude contract_name = contract_source.contract_type.name or "__UnknownContract__" diff --git a/ape_vyper/flattener.py b/ape_vyper/flattener.py index 7b25c6c..1488064 100644 --- a/ape_vyper/flattener.py +++ b/ape_vyper/flattener.py @@ -3,7 +3,6 @@ from typing import TYPE_CHECKING, Optional from ape.logging import logger -from ape.managers import ProjectManager from ape.utils import ManagerAccessMixin, get_relative_path from ethpm_types.source import Content @@ -17,6 +16,8 @@ ) if TYPE_CHECKING: + from ape.managers.project import ProjectManager + from ape_vyper.compiler import VyperCompiler @@ -28,7 +29,7 @@ def vyper(self) -> "VyperCompiler": def flatten( self, path: Path, - project: Optional[ProjectManager] = None, + project: Optional["ProjectManager"] = None, ) -> Content: """ Returns the flattened contract suitable for compilation or verification as a single file @@ -40,7 +41,7 @@ def flatten( def _flatten_source( self, path: Path, - project: Optional[ProjectManager] = None, + project: Optional["ProjectManager"] = None, include_pragma: bool = True, sources_handled: Optional[set[Path]] = None, warn_flattening_modules: bool = True, diff --git a/ape_vyper/imports.py b/ape_vyper/imports.py index 167deb8..7a75228 100644 --- a/ape_vyper/imports.py +++ b/ape_vyper/imports.py @@ -2,15 +2,16 @@ from collections.abc import Iterable, Iterator from functools import cached_property from pathlib import Path -from typing import Optional, Union +from typing import TYPE_CHECKING, Optional, Union from ape.logging import LogLevel, logger -from ape.managers import ProjectManager -from ape.managers.project import Dependency from ape.utils import ManagerAccessMixin, get_relative_path -from ape_vyper import FileType -from ape_vyper._utils import lookup_source_from_site_packages +from ape_vyper._utils import FileType, lookup_source_from_site_packages + +if TYPE_CHECKING: + from ape.managers.project import Dependency, ProjectManager + BUILTIN_PREFIXES = ("vyper", "ethereum") @@ -21,7 +22,7 @@ class Import: def __init__( self, - project: ProjectManager, + project: "ProjectManager", importer: Path, value: str, ): @@ -62,7 +63,7 @@ def is_local(self) -> bool: return bool(self._local_data) @property - def sub_project(self) -> Optional[ProjectManager]: + def sub_project(self) -> Optional["ProjectManager"]: if self.is_builtin: return None elif self.is_local: @@ -88,7 +89,7 @@ def dependency_filestem(self) -> Optional[str]: return self._pathified_value.replace(f"{self.dependency_name}{os.path.sep}", "") @cached_property - def site_package_info(self) -> Optional[tuple[Path, ProjectManager]]: + def site_package_info(self) -> Optional[tuple[Path, "ProjectManager"]]: if not (dependency_name := self.dependency_name): return None elif not (dependency_filestem := self.dependency_filestem): @@ -97,7 +98,7 @@ def site_package_info(self) -> Optional[tuple[Path, ProjectManager]]: return lookup_source_from_site_packages(dependency_name, dependency_filestem) @cached_property - def dependency_info(self) -> Optional[tuple[str, Dependency]]: + def dependency_info(self) -> Optional[tuple[str, "Dependency"]]: dependency_name = self.dependency_name for dependency in self.project.dependencies: if dependency.name != dependency_name: @@ -258,7 +259,7 @@ def _local_absolute_prefix(self) -> Optional[str]: class ImportMap(dict[Path, list[Import]]): - def __init__(self, project: ProjectManager, paths: list[Path]): + def __init__(self, project: "ProjectManager", paths: list[Path]): self.project = project # Even though we build up mappings of all sources, as may be referenced @@ -328,14 +329,16 @@ class ImportResolver(ManagerAccessMixin): _projects: dict[str, ImportMap] = {} _dependency_attempted_compile: set[str] = set() - def get_imports(self, project: ProjectManager, contract_filepaths: Iterable[Path]) -> ImportMap: + def get_imports( + self, project: "ProjectManager", contract_filepaths: Iterable[Path] + ) -> ImportMap: paths = list(contract_filepaths) if project.project_id not in self._projects: self._projects[project.project_id] = ImportMap(project, paths) return self._get_imports(paths, project) - def _get_imports(self, paths: list[Path], project: ProjectManager) -> ImportMap: + def _get_imports(self, paths: list[Path], project: "ProjectManager") -> ImportMap: import_map = self._projects[project.project_id] import_map.paths = list({*import_map.paths, *paths}) for path in paths: @@ -358,7 +361,7 @@ def _get_imports(self, paths: list[Path], project: ProjectManager) -> ImportMap: return import_map def _parse_imports_from_line( - self, line: str, path: Path, project: ProjectManager + self, line: str, path: Path, project: "ProjectManager" ) -> Iterator[Import]: if not (prefix := _parse_import_line(line)): return None @@ -411,7 +414,7 @@ def _parse_imports_from_line( "Could not find it in Ape dependencies or Python's site-packages." ) - def _compile_dependency_if_needed(self, dependency: Dependency): + def _compile_dependency_if_needed(self, dependency: "Dependency"): if ( dependency.name in _KNOWN_PACKAGES_NOT_TO_COMPILE or dependency.project.manifest.contract_types diff --git a/ape_vyper/interface.py b/ape_vyper/interface.py index d59b372..871f919 100644 --- a/ape_vyper/interface.py +++ b/ape_vyper/interface.py @@ -2,10 +2,13 @@ Tools for working with ABI specs and Vyper interface source code """ -from typing import Any, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union from ethpm_types import ABI, MethodABI -from ethpm_types.abi import ABIType + +if TYPE_CHECKING: + from ethpm_types.abi import ABIType + INDENT_SPACES = 4 INDENT = " " * INDENT_SPACES @@ -16,7 +19,7 @@ def indent_line(line: str, level=1) -> str: return f"{INDENT * level}{line}" -def generate_inputs(inputs: list[ABIType]) -> str: +def generate_inputs(inputs: list["ABIType"]) -> str: """Generate the source code input args from ABI inputs""" return ", ".join(f"{i.name}: {i.type}" for i in inputs) diff --git a/ape_vyper/traceback.py b/ape_vyper/traceback.py index 88ad14c..aa38367 100644 --- a/ape_vyper/traceback.py +++ b/ape_vyper/traceback.py @@ -1,8 +1,7 @@ from collections.abc import Iterator from pathlib import Path -from typing import Optional, cast +from typing import TYPE_CHECKING, Optional, cast -from ape.managers import ProjectManager from ape.types import SourceTraceback from ape.utils import ManagerAccessMixin, get_full_extension from eth_pydantic_types import HexBytes @@ -15,6 +14,9 @@ from ape_vyper._utils import DEV_MSG_PATTERN, RETURN_OPCODES, FileType from ape_vyper.exceptions import RuntimeErrorType +if TYPE_CHECKING: + from ape.managers.project import ProjectManager + class SourceTracer(ManagerAccessMixin): """ @@ -28,7 +30,7 @@ def trace( contract: ContractSource, calldata: HexBytes, previous_depth: Optional[int] = None, - project: Optional[ProjectManager] = None, + project: Optional["ProjectManager"] = None, ) -> SourceTraceback: pm = project or cls.local_project method_id = HexBytes(calldata[:4]) @@ -237,7 +239,7 @@ def trace( @classmethod def _create_contract_from_call( - cls, frame: dict, project: Optional[ProjectManager] = None + cls, frame: dict, project: Optional["ProjectManager"] = None ) -> tuple[Optional[ContractSource], HexBytes]: pm = project or cls.local_project evm_frame = TraceFrame(**frame) diff --git a/setup.cfg b/setup.cfg index 1c2ef4d..83a070c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,8 @@ [flake8] max-line-length = 100 +ignore = E704,W503,PYD002,TC003,TC006 exclude = venv* docs build +type-checking-pydantic-enabled = True diff --git a/setup.py b/setup.py index 44fb90f..1599fe7 100644 --- a/setup.py +++ b/setup.py @@ -11,12 +11,14 @@ "snekmate", # Python package-sources integration testing ], "lint": [ - "black>=24.8.0,<25", # Auto-formatter and linter - "mypy>=1.11.2,<2", # Static type analyzer + "black>=24.10.0,<25", # Auto-formatter and linter + "mypy>=1.13.0,<2", # Static type analyzer "types-setuptools", # Needed due to mypy typeshed "flake8>=7.1.1,<8", # Style linter + "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", # Import sorting linter - "mdformat>=0.7.17", # Auto-formatter for markdown + "mdformat>=0.7.18", # Auto-formatter for markdown "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