From 4060753f0a60c6cf24ca9d22a3c1afe0974910a4 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 31 Oct 2024 17:24:46 -0500 Subject: [PATCH 1/4] perf: lazier imports --- src/ape_run/_cli.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ape_run/_cli.py b/src/ape_run/_cli.py index 94e30d361d..345611c72f 100644 --- a/src/ape_run/_cli.py +++ b/src/ape_run/_cli.py @@ -14,13 +14,12 @@ from ape.cli.options import _VERBOSITY_VALUES, _create_verbosity_kwargs, verbosity_option from ape.exceptions import ApeException, handle_ape_exception from ape.logging import logger -from ape.utils.basemodel import ManagerAccessMixin as access -from ape.utils.os import get_relative_path, use_temp_sys_path -from ape_console._cli import console @contextmanager def use_scripts_sys_path(path: Path): + from ape.utils.os import use_temp_sys_path + # First, ensure there is not an existing scripts module. scripts = sys.modules.get("scripts") if scripts: @@ -71,6 +70,8 @@ def __init__(self, *args, **kwargs): self._has_warned_missing_hook: set[Path] = set() def invoke(self, ctx: Context) -> Any: + from ape.utils.basemodel import ManagerAccessMixin as access + try: return super().invoke(ctx) except Exception as err: @@ -95,6 +96,9 @@ def invoke(self, ctx: Context) -> Any: raise def _get_command(self, filepath: Path) -> Union[click.Command, click.Group, None]: + from ape.utils.basemodel import ManagerAccessMixin as access + from ape.utils.os import get_relative_path + relative_filepath = get_relative_path(filepath, access.local_project.path) # First load the code module by compiling it @@ -175,6 +179,8 @@ def call(): @property def commands(self) -> dict[str, Union[click.Command, click.Group]]: + from ape.utils.basemodel import ManagerAccessMixin as access + if not access.local_project.scripts_folder.is_dir(): return {} @@ -223,6 +229,8 @@ def result_callback(self, result, interactive: bool): # type: ignore[override] return result def _launch_console(self): + from ape.utils.basemodel import ManagerAccessMixin as access + trace = inspect.trace() trace_frames = [ x for x in trace if x.filename.startswith(str(access.local_project.scripts_folder)) @@ -247,6 +255,8 @@ def _launch_console(self): if frame: del frame + from ape_console._cli import console + return console(project=access.local_project, extra_locals=extra_locals, embed=True) From 4cf9496a09078a277b18e1f19d3e3c471dbb658c Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 31 Oct 2024 17:30:40 -0500 Subject: [PATCH 2/4] perf: avoid proj access --- src/ape_run/_cli.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ape_run/_cli.py b/src/ape_run/_cli.py index 345611c72f..0c601e7165 100644 --- a/src/ape_run/_cli.py +++ b/src/ape_run/_cli.py @@ -179,12 +179,13 @@ def call(): @property def commands(self) -> dict[str, Union[click.Command, click.Group]]: - from ape.utils.basemodel import ManagerAccessMixin as access - - if not access.local_project.scripts_folder.is_dir(): + # perf: Don't references `.local_project.scripts_folder` here; + # it's too slow when doing just doing `--help`. + scripts_folder = Path.cwd() / "scripts" + if not scripts_folder.is_dir(): return {} - return self._get_cli_commands(access.local_project.scripts_folder) + return self._get_cli_commands(scripts_folder) def _get_cli_commands(self, base_path: Path) -> dict: commands: dict[str, Command] = {} From 0d86278ac5a253e004e533563e3678aa731bc236 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Fri, 1 Nov 2024 08:30:57 -0500 Subject: [PATCH 3/4] chore: forgot --- src/ape_run/_cli.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/ape_run/_cli.py b/src/ape_run/_cli.py index 0c601e7165..ea5eb1b4a2 100644 --- a/src/ape_run/_cli.py +++ b/src/ape_run/_cli.py @@ -8,7 +8,6 @@ from typing import Any, Union import click -from click import Command, Context, Option from ape.cli.commands import ConnectedProviderCommand from ape.cli.options import _VERBOSITY_VALUES, _create_verbosity_kwargs, verbosity_option @@ -69,7 +68,7 @@ def __init__(self, *args, **kwargs): self._command_called = None self._has_warned_missing_hook: set[Path] = set() - def invoke(self, ctx: Context) -> Any: + def invoke(self, ctx: click.Context) -> Any: from ape.utils.basemodel import ManagerAccessMixin as access try: @@ -96,10 +95,8 @@ def invoke(self, ctx: Context) -> Any: raise def _get_command(self, filepath: Path) -> Union[click.Command, click.Group, None]: - from ape.utils.basemodel import ManagerAccessMixin as access - from ape.utils.os import get_relative_path - - relative_filepath = get_relative_path(filepath, access.local_project.path) + scripts_folder = Path.cwd() / "scripts" + relative_filepath = filepath.relative_to(scripts_folder) # First load the code module by compiling it # NOTE: This does not execute the module @@ -126,14 +123,14 @@ def _get_command(self, filepath: Path) -> Union[click.Command, click.Group, None self._namespace[filepath.stem] = cli_ns cli_obj = cli_ns["cli"] - if not isinstance(cli_obj, Command): + if not isinstance(cli_obj, click.Command): logger.warning("Found `cli()` method but it is not a click command.") return None params = [getattr(x, "name", None) for x in cli_obj.params] if "verbosity" not in params: option_kwargs = _create_verbosity_kwargs() - option = Option(_VERBOSITY_VALUES, **option_kwargs) + option = click.Option(_VERBOSITY_VALUES, **option_kwargs) cli_obj.params.append(option) cli_obj.name = filepath.stem if cli_obj.name in ("cli", "", None) else cli_obj.name @@ -188,7 +185,7 @@ def commands(self) -> dict[str, Union[click.Command, click.Group]]: return self._get_cli_commands(scripts_folder) def _get_cli_commands(self, base_path: Path) -> dict: - commands: dict[str, Command] = {} + commands: dict[str, click.Command] = {} for filepath in base_path.iterdir(): if filepath.stem.startswith("_"): @@ -201,6 +198,7 @@ def _get_cli_commands(self, base_path: Path) -> dict: subcommands = self._get_cli_commands(filepath) for subcommand in subcommands.values(): group.add_command(subcommand) + commands[filepath.stem] = group if filepath.suffix == ".py": From f76109bf8c834006a5e3bc9a8b0eaf8a77e963b0 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Fri, 1 Nov 2024 08:32:10 -0500 Subject: [PATCH 4/4] docs: corr --- src/ape_run/_cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ape_run/_cli.py b/src/ape_run/_cli.py index ea5eb1b4a2..6dc0153295 100644 --- a/src/ape_run/_cli.py +++ b/src/ape_run/_cli.py @@ -17,6 +17,7 @@ @contextmanager def use_scripts_sys_path(path: Path): + # perf: avoid importing at top of module so `--help` is faster. from ape.utils.os import use_temp_sys_path # First, ensure there is not an existing scripts module. @@ -176,7 +177,7 @@ def call(): @property def commands(self) -> dict[str, Union[click.Command, click.Group]]: - # perf: Don't references `.local_project.scripts_folder` here; + # perf: Don't reference `.local_project.scripts_folder` here; # it's too slow when doing just doing `--help`. scripts_folder = Path.cwd() / "scripts" if not scripts_folder.is_dir():