"""Angriffsfaelle fuer --ibkr-python von abendkontrolle_wsl.py (Nachtrag zu Paket DH, IB2), in WSL, ohne Netz. Koordinator-Werkzeug, nicht fuers Repo. Auf dem Docker-Host laeuft der Teil ibkr im Abbild; dort gibt es das Venv aus WSL nicht, und ibkr_pruefen.py lesen laeuft mit dem python des Containers (abendkontrolle-host.sh: --ibkr-python python). Die Faelle pruefen den Schalter, die Vorgabe, den Aufruf mit dem genannten Interpreter gegen ein Ersatzskript in einem Wegwerf-Ordner und die Weitergabe im Ablauf. Das Ersatzskript druckt den Interpreter, der es startet; so faellt ein Aufruf mit dem festen Venv-Pfad auf, auch wenn es den Pfad gibt. Aufruf (WSL, Venv): python abendkontrolle_ibkr_python_angriffe.py Exit 0 ohne Abweichung, 2 mit Abweichung. """ import importlib.util import sys import tempfile from datetime import datetime from pathlib import Path HIER = Path(__file__).resolve().parent ERSATZ = ( "import sys\n" "print('Interpreter: ' + sys.executable)\n" "print('Positionen: 0')\n" "print('Offene Orders: 0')\n" ) FAELLE = [] def fall(funktion): FAELLE.append(funktion) return funktion def lade(): spec = importlib.util.spec_from_file_location("abendkontrolle_wsl_unter_angriff", HIER / "abendkontrolle_wsl.py") modul = importlib.util.module_from_spec(spec) spec.loader.exec_module(modul) # Zweite Sperre (Pruefung DH-Nachtrag, 2026-09-26): Die Faelle geben den Ordner mit dem # Ersatzskript ausdruecklich mit. Nimmt ein Mutant stattdessen die Vorgabe, zeigt sie ins Leere # und nicht auf den Betriebsordner mit dem echten ibkr_pruefen.py. modul.IBKR_ORDNER = "/nicht-vorhanden/trading-ibkr-betrieb" return modul @fall def der_schalter_nennt_den_interpreter(): argumente = lade().parse_args(["--tag", "2026-10-05", "--teil", "ibkr", "--ibkr-python", "/usr/local/bin/python"]) assert argumente.ibkr_python == "/usr/local/bin/python", argumente @fall def ohne_schalter_bleibt_das_venv_aus_wsl(): modul = lade() argumente = modul.parse_args(["--tag", "2026-10-05", "--teil", "ibkr"]) assert argumente.ibkr_python == modul.IBKR_PY, argumente assert modul.IBKR_PY == "/home/claude/venvs/trading-ibkr/bin/python", modul.IBKR_PY @fall def lesen_laeuft_mit_dem_genannten_interpreter(): modul = lade() with tempfile.TemporaryDirectory() as ordner: wurzel = Path(ordner) (wurzel / "scripts").mkdir() (wurzel / "scripts" / "ibkr_pruefen.py").write_text(ERSATZ, encoding="utf-8") code, text = modul.lies_konto_ibkr(wurzel, None, sys.executable) assert code == 0, (code, text) assert f"Interpreter: {sys.executable}" in text, text assert "Positionen: 0" in text and "Offene Orders: 0" in text, text @fall def der_ablauf_gibt_den_schalter_weiter(): quelle = (HIER / "abendkontrolle_wsl.py").read_text(encoding="utf-8") assert "lies_konto_ibkr, ordner, argumente.ibkr_konto, argumente.ibkr_python)" in quelle assert '[python, "scripts/ibkr_pruefen.py", "lesen"], cwd=ordner,' in quelle def main() -> int: abweichungen = 0 for funktion in FAELLE: try: funktion() except (Exception, SystemExit) as ausnahme: abweichungen += 1 print(f"ABWEICHUNG {funktion.__name__}: {type(ausnahme).__name__}: {ausnahme}") else: print(f"OK {funktion.__name__}") print(f"{len(FAELLE)} Faelle, {abweichungen} Abweichung(en) ({datetime.now():%Y-%m-%d %H:%M})") return 2 if abweichungen else 0 if __name__ == "__main__": sys.exit(main())