refactor(tests): finish shared CLI loader adoption

Test-only refactor continuing #2523. Replaces remaining obvious CLI/script loader boilerplate with tests.helpers.cli_loader.load_script while preserving existing stubs and assertions.
This commit is contained in:
Alexandre Teixeira
2026-06-05 06:00:05 +01:00
committed by GitHub
parent 1f40fbe140
commit 43a101d305
10 changed files with 26 additions and 98 deletions

View File

@@ -1,5 +1,3 @@
import importlib.machinery
import importlib.util
import io import io
import tarfile import tarfile
from pathlib import Path from pathlib import Path
@@ -7,14 +5,11 @@ from types import SimpleNamespace
import pytest import pytest
from tests.helpers.cli_loader import load_script
def _load_backup_cli(): def _load_backup_cli():
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-backup" return load_script("odysseus-backup")
loader = importlib.machinery.SourceFileLoader("odysseus_backup_under_test", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def _patch_repo(module, monkeypatch, root: Path): def _patch_repo(module, monkeypatch, root: Path):

View File

@@ -1,12 +1,8 @@
import importlib.machinery
import importlib.util
import sys import sys
import types import types
from pathlib import Path
from unittest.mock import MagicMock from unittest.mock import MagicMock
from tests.helpers.cli_loader import load_script
ROOT = Path(__file__).resolve().parents[1]
def _load_cli(monkeypatch): def _load_cli(monkeypatch):
@@ -15,12 +11,7 @@ def _load_cli(monkeypatch):
routes._fetch_contacts = MagicMock() routes._fetch_contacts = MagicMock()
routes._create_contact = MagicMock() routes._create_contact = MagicMock()
monkeypatch.setitem(sys.modules, "routes.contacts_routes", routes) monkeypatch.setitem(sys.modules, "routes.contacts_routes", routes)
path = ROOT / "scripts" / "odysseus-contacts" return load_script("odysseus-contacts")
loader = importlib.machinery.SourceFileLoader("odysseus_contacts_cli", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_contact_rows_skips_invalid_rows(monkeypatch): def test_contact_rows_skips_invalid_rows(monkeypatch):

View File

@@ -1,11 +1,10 @@
import importlib.machinery
import importlib.util
import sys import sys
from pathlib import Path
from types import ModuleType, SimpleNamespace from types import ModuleType, SimpleNamespace
import pytest import pytest
from tests.helpers.cli_loader import load_script
class _Conn: class _Conn:
def select(self, folder, readonly=True): def select(self, folder, readonly=True):
@@ -46,12 +45,7 @@ def _load_mail_cli(monkeypatch):
monkeypatch.setitem(sys.modules, "routes.email_pollers", pollers) monkeypatch.setitem(sys.modules, "routes.email_pollers", pollers)
monkeypatch.setitem(sys.modules, "core", core_mod) monkeypatch.setitem(sys.modules, "core", core_mod)
monkeypatch.setitem(sys.modules, "core.database", database_mod) monkeypatch.setitem(sys.modules, "core.database", database_mod)
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-mail" return load_script("odysseus-mail")
loader = importlib.machinery.SourceFileLoader("odysseus_mail_cli_read_test", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_cmd_read_handles_empty_fetch_payload(monkeypatch): def test_cmd_read_handles_empty_fetch_payload(monkeypatch):

View File

@@ -1,9 +1,8 @@
import importlib.machinery
import importlib.util
import sys import sys
from pathlib import Path
from types import ModuleType from types import ModuleType
from tests.helpers.cli_loader import load_script
def _load_mail_cli(monkeypatch): def _load_mail_cli(monkeypatch):
helpers = ModuleType("routes.email_helpers") helpers = ModuleType("routes.email_helpers")
@@ -28,12 +27,7 @@ def _load_mail_cli(monkeypatch):
monkeypatch.setitem(sys.modules, "core", core_mod) monkeypatch.setitem(sys.modules, "core", core_mod)
monkeypatch.setitem(sys.modules, "core.database", database_mod) monkeypatch.setitem(sys.modules, "core.database", database_mod)
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-mail" return load_script("odysseus-mail")
loader = importlib.machinery.SourceFileLoader("odysseus_mail_cli_under_test", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_recipient_list_trims_to_cc_and_bcc(monkeypatch): def test_recipient_list_trims_to_cc_and_bcc(monkeypatch):

View File

@@ -1,16 +1,10 @@
import importlib.machinery
import importlib.util
from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from tests.helpers.cli_loader import load_script
def _load_preset_cli(): def _load_preset_cli():
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-preset" return load_script("odysseus-preset")
loader = importlib.machinery.SourceFileLoader("odysseus_preset_set_corrupt", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_set_replaces_corrupt_existing_entry(monkeypatch): def test_set_replaces_corrupt_existing_entry(monkeypatch):

View File

@@ -3,20 +3,11 @@
`_summarize` did `(data.get("query") or "")[:200]`. A non-string query from a `_summarize` did `(data.get("query") or "")[:200]`. A non-string query from a
legacy/corrupt research JSON is truthy, so `123[:200]` raised TypeError. legacy/corrupt research JSON is truthy, so `123[:200]` raised TypeError.
""" """
import importlib.machinery from tests.helpers.cli_loader import load_script
import importlib.util
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def _load_cli(): def _load_cli():
path = ROOT / "scripts" / "odysseus-research" return load_script("odysseus-research")
loader = importlib.machinery.SourceFileLoader("odysseus_research_cli", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_preview_text_ignores_non_string(): def test_preview_text_ignores_non_string():

View File

@@ -1,20 +1,11 @@
import importlib.machinery
import importlib.util
import json import json
from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from tests.helpers.cli_loader import load_script
ROOT = Path(__file__).resolve().parents[1]
def _load_cli(): def _load_cli():
path = ROOT / "scripts" / "odysseus-research" return load_script("odysseus-research")
loader = importlib.machinery.SourceFileLoader("odysseus_research_cli", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_list_skips_non_object_research_records(tmp_path, monkeypatch): def test_list_skips_non_object_research_records(tmp_path, monkeypatch):

View File

@@ -1,10 +1,9 @@
import importlib.machinery
import importlib.util
import sys import sys
from pathlib import Path
from types import ModuleType from types import ModuleType
from types import SimpleNamespace from types import SimpleNamespace
from tests.helpers.cli_loader import load_script
def _load_sessions_cli(monkeypatch): def _load_sessions_cli(monkeypatch):
core_mod = ModuleType("core") core_mod = ModuleType("core")
@@ -13,13 +12,7 @@ def _load_sessions_cli(monkeypatch):
database_mod.Session = object database_mod.Session = object
monkeypatch.setitem(sys.modules, "core", core_mod) monkeypatch.setitem(sys.modules, "core", core_mod)
monkeypatch.setitem(sys.modules, "core.database", database_mod) monkeypatch.setitem(sys.modules, "core.database", database_mod)
return load_script("odysseus-sessions")
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-sessions"
loader = importlib.machinery.SourceFileLoader("odysseus_sessions_cli_under_test", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_serialize_normalizes_numeric_counters(monkeypatch): def test_serialize_normalizes_numeric_counters(monkeypatch):

View File

@@ -1,9 +1,8 @@
import importlib.machinery
import importlib.util
import sys import sys
from pathlib import Path
from types import ModuleType from types import ModuleType
from tests.helpers.cli_loader import load_script
def _load_signature_cli(monkeypatch): def _load_signature_cli(monkeypatch):
sqlalchemy_mod = ModuleType("sqlalchemy") sqlalchemy_mod = ModuleType("sqlalchemy")
@@ -14,13 +13,7 @@ def _load_signature_cli(monkeypatch):
monkeypatch.setitem(sys.modules, "sqlalchemy", sqlalchemy_mod) monkeypatch.setitem(sys.modules, "sqlalchemy", sqlalchemy_mod)
monkeypatch.setitem(sys.modules, "core", core_mod) monkeypatch.setitem(sys.modules, "core", core_mod)
monkeypatch.setitem(sys.modules, "core.database", database_mod) monkeypatch.setitem(sys.modules, "core.database", database_mod)
return load_script("odysseus-signature")
path = Path(__file__).resolve().parent.parent / "scripts" / "odysseus-signature"
loader = importlib.machinery.SourceFileLoader("odysseus_signature_cli_under_test", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_decode_png_data_accepts_data_url(monkeypatch): def test_decode_png_data_accepts_data_url(monkeypatch):

View File

@@ -4,26 +4,18 @@
description (e.g. a number from a hand-edited/legacy skill store) is truthy, so description (e.g. a number from a hand-edited/legacy skill store) is truthy, so
`123[:200]` raised TypeError. `_preview_text` coerces non-strings to "". `123[:200]` raised TypeError. `_preview_text` coerces non-strings to "".
""" """
import importlib.machinery
import importlib.util
import sys import sys
import types import types
from pathlib import Path
from unittest.mock import MagicMock from unittest.mock import MagicMock
ROOT = Path(__file__).resolve().parents[1] from tests.helpers.cli_loader import load_script
def _load_cli(monkeypatch): def _load_cli(monkeypatch):
mod = types.ModuleType("services.memory.skills") mod = types.ModuleType("services.memory.skills")
mod.SkillsManager = MagicMock() mod.SkillsManager = MagicMock()
monkeypatch.setitem(sys.modules, "services.memory.skills", mod) monkeypatch.setitem(sys.modules, "services.memory.skills", mod)
path = ROOT / "scripts" / "odysseus-skills" return load_script("odysseus-skills")
loader = importlib.machinery.SourceFileLoader("odysseus_skills_cli", str(path))
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
def test_preview_text_ignores_non_string(monkeypatch): def test_preview_text_ignores_non_string(monkeypatch):