"""Utilita' condivise dei test. `tests/` e' su sys.path (c'e' un conftest), quindi si importa con `from helpers import carica_script`. PERCHE' ESISTE (2026-09-02). `scripts/` non e' un package importabile per nome, quindi ogni test che tocca uno script si caricava il modulo a mano con `importlib.util.spec_from_file_location`: **15 copie della stessa dozzina di righe**, con nomi di modulo diversi per lo stesso file e differenze silenziose (chi registra in `sys.modules` e chi no — e chi non lo fa rompe `pickle`, `dataclasses` e i decoratori che risolvono per nome). Una funzione sola, con la registrazione fatta sempre. """ from __future__ import annotations import importlib.util import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def carica_script(rel: str, nome: str | None = None): """Carica per PERCORSO uno script del repo (es. "scripts/live/trades_db.py"). `nome` e' il nome sotto cui il modulo viene registrato in `sys.modules`; il default e' il nome del file. Registrare PRIMA di eseguire e' voluto: un modulo che si auto-importa o usa `dataclasses` durante l'esecuzione deve trovarsi. """ p = (ROOT / rel).resolve() assert p.exists(), f"script inesistente: {rel}" nome = nome or p.stem spec = importlib.util.spec_from_file_location(nome, p) mod = importlib.util.module_from_spec(spec) sys.modules[nome] = mod spec.loader.exec_module(mod) return mod