"""Argomenti da riga di comando degli script operativi: un flag ignoto NON e' l'azione di default. PERCHE' ESISTE (2026-09-02). Nessuno degli script di `scripts/live/` usava argparse: leggevano `sys.argv` con `in` e `index`, quindi un flag sbagliato non era un errore — era il ramo `else`. Costo misurato lo stesso giorno, durante una revisione: `trades_db.py --help` non ha stampato l'uso, e' caduto in `sync()` e ha riscritto `meta.ultimo_sync`. Gli altri due sono peggio: `journal.py --help` avrebbe scritto la pagina di oggi e una riga nel DB, `analista.py --help` avrebbe speso una chiamata al modello e mandato un messaggio Telegram. TRE REGOLE, e nient'altro: 1. **Nessun argparse.** Gli script hanno flag posizionali-per-nome (`--report`, `--secco`) e flag con valore (`--giorno 2026-08-21`); argparse cambierebbe i messaggi d'errore, il codice d'uscita e il comportamento di `--help` di 18 script che il cron gia' chiama. Qui serve il contrario: **lasciare intatto cio' che gira** e rifiutare cio' che non e' previsto. 2. **Il cron non deve cambiare.** I flag dichiarati sono quelli che gli script gia' accettano: `valida()` non ne aggiunge e non ne toglie (P15: una regola si prova contro il codice che dovrebbe eseguirla). L'unica novita' e' `--help`, che prima non esisteva. 3. **Si esce PRIMA di qualunque effetto.** `valida()` va chiamata come prima istruzione del blocco `__main__`, prima di `connect()`, prima del sync, prima della rete. Codici d'uscita: 0 per `--help` (l'utente ha chiesto l'uso), 2 per un flag ignoto (errore d'uso, distinto dal 1 con cui gli script segnalano un esito negativo del loro lavoro). """ from __future__ import annotations import sys class UsoSbagliato(Exception): """Flag non previsto da questo script. Portato con l'elenco di cio' che e' previsto (P4).""" def valida(nome: str, uso: str, *, flag: tuple[str, ...] = (), con_valore: tuple[str, ...] = (), argv: list[str] | None = None, esci: bool = True) -> list[str]: """Controlla `argv` contro i flag dichiarati. Ritorna gli argomenti; solleva o esce se ignoti. `flag` sono i booleani (`--quiet`), `con_valore` quelli che consumano l'argomento seguente (`--giorno 2026-08-21`). `--help`/`-h` stampano `uso` ed escono 0. Con `esci=False` non tocca `sys.exit` e solleva `UsoSbagliato`: e' la forma che i test usano. """ args = list(sys.argv[1:] if argv is None else argv) if "--help" in args or "-h" in args: if not esci: return args print(uso.strip()) raise SystemExit(0) noti, ignoti, attesa_valore = set(flag) | set(con_valore), [], False for a in args: if attesa_valore: # e' il valore di un flag noto, non un flag attesa_valore = False continue if not a.startswith("-"): ignoti.append(a); continue # posizionale: nessuno di questi script ne ha if a not in noti: ignoti.append(a); continue attesa_valore = a in con_valore if attesa_valore: ignoti.append(f"{args[-1]} (manca il valore)") if ignoti: msg = (f"{nome}: argomento non previsto: {', '.join(ignoti)}\n" f" previsti: {' '.join(sorted(noti)) or '(nessuno)'}\n\n{uso.strip()}") if not esci: raise UsoSbagliato(msg) print(msg, file=sys.stderr) raise SystemExit(2) return args