mirror of
https://github.com/mvt-project/mvt.git
synced 2026-09-03 08:30:51 +02:00
Keep the start of mvt-ios and mvt-android cheap for shell completion
Each console script imports its CLI module before Click can answer a shell completion request, and the completion scripts run the program on every keystroke. Importing mvt.ios.cli or mvt.android.cli took ~230 ms, of which building the command tree needed almost nothing: cli_plugins imported one constant from module_loader, which pulled in MVTModule, the indicators, the pydantic settings, requests and rich; the command implementations pulled in the same, and the iOS CLI imported iOSbackup (pycryptodome) for decrypt-backup. The two platform CLI modules now only build the command tree: each command imports what it runs when it is invoked. cli_plugins owns the custom command prefix instead of importing it from module_loader, and exec_or_profile() loads the settings when it runs. Completion of mvt-ios and mvt-android drops from ~260 ms to ~85 ms per keystroke on a clean install, and every command starts that much sooner. A test fails as soon as a CLI module imports the module machinery again.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2026 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import pytest
|
||||
|
||||
from .plugin_fixtures import run_isolated_python
|
||||
|
||||
# Importing a platform CLI must only build its command tree: the console
|
||||
# scripts import it before Click can answer a shell completion request, which
|
||||
# the completion scripts make on every keystroke. Every command imports what
|
||||
# it runs when it is invoked. Each of these costs tens of milliseconds to
|
||||
# import and is the sign that a command implementation is imported too early.
|
||||
HEAVY_MODULES = ("pydantic", "requests", "Crypto", "mvt.common.module")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cli_module", ("mvt.ios.cli", "mvt.android.cli"))
|
||||
def test_importing_a_cli_does_not_import_the_module_machinery(cli_module, tmp_path):
|
||||
result = run_isolated_python(
|
||||
"import sys\n"
|
||||
f"import {cli_module}\n"
|
||||
f"print(','.join(name for name in {HEAVY_MODULES!r} if name in sys.modules))\n",
|
||||
home=tmp_path / "home",
|
||||
)
|
||||
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert result.stdout.strip() == "", f"{cli_module} imported {result.stdout.strip()}"
|
||||
Reference in New Issue
Block a user