diff --git a/tools/check_nfalle.py b/tools/check_nfalle.py new file mode 100644 index 0000000..ce08b66 --- /dev/null +++ b/tools/check_nfalle.py @@ -0,0 +1,153 @@ +"""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.") + + +# ── 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"(? `${x.grund} ${pc(x.n)} %`).join(" · "); blkEl.textContent = `⛔ heute ${pc(bm.frei)} % ohne Block` + (top ? ` · ${top}` : ""); + // ⚠ Schliessendes Anführungszeichen als „ “ (U+201C), NICHT über eine + // Konkatenation mit '"' — die war valide, aber schwer lesbar und lässt + // jeden Quote-Zähler auflaufen (der \n-Scan hat sie als offenes Literal + // gemeldet). blkEl.title = "Welches Gate hält die Empfehlung gerade zurück — über den " + "heutigen Tag gezählt. Ohne diese Zeile war „warum gab es so wenige " - + "Empfehlungen?" + '"' + " nur per Datenbank-Abfrage zu beantworten."; + + "Empfehlungen?“ nur per Datenbank-Abfrage zu beantworten."; } else { blkEl.textContent = ""; }