"""Sucht die \\n-Falle in allen Projektdateien — in BEIDE Richtungen. Die Falle: beim Schreiben ueber ein Shell-Heredoc wird aus einem gemeinten `\\n` ein ECHTER Zeilenumbruch mitten im String-Literal. In Python bricht das den Compile (zweimal heute passiert), in JS ebenso — aber nicht ueberall faellt es sofort auf. Geprueft wird: A) Python: kompiliert jede Datei. Ein zerrissenes Literal faellt hier auf. B) JS: Zeilen mit ungerader Zahl UNMASKIERTER Anfuehrungszeichen ausserhalb von Kommentaren = angefangenes, nicht geschlossenes String-Literal. C) Umgekehrter Fall: literales `\\n` als TEXT dort, wo es niemand lesen will (HTML-Attribute, Markdown-Fliesstext) — das entsteht, wenn ein `\\\\n` zu viel escaped wurde. D) Verdaechtige Zeilenpaare: eine Zeile endet mit oeffnendem Quote, die naechste besteht nur aus einem Quote — die Signatur der beiden heutigen Faelle. """ import pathlib import py_compile import re import sys import tempfile WURZEL = pathlib.Path(r"c:\Users\ah\Downloads\tradingrobot") SKIP = {".git", "__pycache__", ".reminders", "node_modules", ".removed_backup"} befunde = [] def dateien(*endungen): for p in WURZEL.rglob("*"): if any(s in p.parts for s in SKIP): continue if p.is_file() and p.suffix in endungen: yield p # ── A) Python ──────────────────────────────────────────────────────────── print("=" * 88) print(" A) PYTHON — kompiliert jede Datei (ein zerrissenes Literal faellt hier auf)") print("=" * 88) npy = 0 tmp = tempfile.mkdtemp() for p in dateien(".py"): npy += 1 try: py_compile.compile(str(p), cfile=f"{tmp}/x.pyc", doraise=True) except py_compile.PyCompileError as e: msg = str(e).strip().splitlines()[-1][:110] befunde.append(f"PY {p.relative_to(WURZEL)}: {msg}") print(f" FEHLER {p.relative_to(WURZEL)}") print(f" {msg}") print(f" {npy} Dateien geprueft.") # ── A2) pyflakes: was py_compile NICHT sieht ───────────────────────────── # ⚠⚠ WARUM DIESE STUFE NOETIG IST. `py_compile` prueft nur die SYNTAX. Ein # Tippfehler in einem Namen ist syntaktisch einwandfrei und fliegt erst zur # Laufzeit — und dieses Projekt hat sehr viele breite `except Exception`-Bloecke # (bewusst, als Fail-safe im Trading-Betrieb). Ein `NameError` darin ist damit # UNSICHTBAR: keine Meldung, kein Logeintrag, nur ein Zweig, der nichts tut. # Real gefunden beim ERSTEN Lauf ueberhaupt (2026-08-07): # · `core/trader.py` nutzte zweimal `log.` — den Namen gibt es dort nicht # (nur `log_trade`/`log_hist`). Einer davon seit dem Initial-Commit. # · Folge 1 (`_broker_offset_s`): der NameError lief in ein `except: pass` # und nahm die Zuweisung `self._boff = int(off)` mit → ein echter # Broker-Zeitzonen-Wechsel waere nie uebernommen worden. # · Folge 2 (`modify_sltp`): kein try drumherum → der Fehler lief bis in # `/api/sltp`; der Broker hatte SL/TP schon geaendert, der User bekam # trotzdem einen Fehler, und `trail.deactivate()` wurde uebersprungen. # GETRENNT NACH SCHWEREGRAD: eine Pruefung, die dauerhaft 100 harmlose Zeilen # ausgibt, wird ignoriert — und dann auch die eine wichtige. # ⚠ `redefinition of unused` steht BEWUSST NICHT hier drin. pyflakes meldet damit # auch das voellig legitime Muster `hook = None` gefolgt von einem bedingten # `def hook(...)` — real in `backtest_flipclose2.py` und # `backtest_adverse15_squeeze.py`, beide geprueft und korrekt. Zwei unvermeidbare # Dauer-Treffer sind genau der Weg, auf dem eine Pruefung ignoriert wird, und mit # ihr dann auch die eine echte Meldung. Wer die Klasse doch sehen will, ruft # `python -m pyflakes ` direkt auf. SCHWER = ("undefined name", "undefined local", "syntax error") print() print("=" * 88) print(" A2) PYFLAKES — undefinierte Namen (was py_compile nicht sieht)") print("=" * 88) try: import io from pyflakes.api import checkPath from pyflakes.reporter import Reporter aus, err = io.StringIO(), io.StringIO() rep = Reporter(aus, err) for p in dateien(".py"): checkPath(str(p), rep) zeilen = [z for z in (aus.getvalue() + err.getvalue()).splitlines() if z.strip()] schwer = [z for z in zeilen if any(s in z for s in SCHWER)] for z in schwer: kurz = z.replace(str(WURZEL) + "\\", "").replace(str(WURZEL) + "/", "") befunde.append(f"PF {kurz}") print(f" FEHLER {kurz}") if not schwer: print(" keine undefinierten Namen.") print(f" ({len(zeilen) - len(schwer)} kosmetische Hinweise unterdrueckt — " f"ungenutzte Importe, f-Strings ohne Platzhalter)") except ImportError: print(" ⚠ pyflakes nicht installiert — Stufe uebersprungen.") print(" Installation: python -m pip install pyflakes") # ── B) JavaScript ──────────────────────────────────────────────────────── def js_offene_strings(text: str): """Zeilen mit angefangenem, nicht geschlossenem ' oder " (Template-Literale duerfen mehrzeilig sein und werden uebersprungen).""" treffer = [] in_tmpl = False for nr, z in enumerate(text.splitlines(), 1): # Backticks zaehlen -> Template-Literal-Zustand fortschreiben bt = len(re.findall(r"(?