#!/usr/bin/env python3 """Controllo statico dell'azione sulla copertina (P8 del piano). Verifica le regole che la documentazione Silica pone sulle azioni di copertina, e che il componente sia usato come va usato: - il `CoverActionList` sta come figlio diretto della copertina (qui la radice e' `CoverBackground`, che eredita da `Cover`: e' li' che va dichiarato). Un elenco annidato dentro un altro elemento non si attaccherebbe; - al massimo una azione: la documentazione dice che due si possono avere, ma che lo stile delle app di sistema ne mostra una; - l'icona si dichiara con `iconSource` (non `icon.source`, che e' del pulsante Button: sbagliarlo qui non da' errore, l'icona semplicemente non compare); - l'icona esiste davvero, risolta rispetto al file QML che definisce la copertina; - il comando che l'azione invia esiste nella tabella dei comandi del bridge (un id sbagliato lo scoprirebbe solo il telefono, con un 400). Non serve il kit Silica: legge i file. Uscita 0 = tutto a posto. """ import pathlib import re import sys RADICE = pathlib.Path(__file__).resolve().parent.parent COPERTINA = RADICE / "qml" / "cover" / "CoverPage.qml" BRIDGE = RADICE / "bridge" / "aira_bridge.py" def main(): if not COPERTINA.exists(): print("ESITO: manca %s" % COPERTINA) return 1 testo = COPERTINA.read_text(encoding="utf-8") righe = testo.splitlines() problemi = [] radice = next((r.strip() for r in righe if re.match(r"^[A-Z][A-Za-z]*\s*\{", r)), "") if not re.match(r"CoverBackground|Cover\s*\{", radice): problemi.append("la radice della copertina e' %r: le azioni vanno dentro " "un Cover (CoverBackground eredita da Cover)" % radice[:40]) # il CoverActionList deve stare al primo livello dentro la radice elenchi = [(i, r) for i, r in enumerate(righe) if re.match(r"^\s*CoverActionList\s*\{", r)] if not elenchi: print("nessuna azione sulla copertina: niente da controllare (0.6.8 e prima)") return 0 for i, r in elenchi: rientro = len(r) - len(r.lstrip()) if rientro != 4: problemi.append("riga %d: il CoverActionList e' rientrato di %d spazi, " "deve essere figlio diretto della copertina" % (i + 1, rientro)) azioni = [r for r in righe if re.match(r"^\s*CoverAction\s*\{", r)] if len(azioni) > 1: problemi.append("%d azioni: la documentazione Silica ne ammette piu' di una " "ma lo stile delle app di sistema ne mostra una" % len(azioni)) if re.search(r"^\s*icon\.source\s*:", testo, re.M): problemi.append("usa `iconSource`, non `icon.source`: `icon.source` e' del " "pulsante Button e qui non darebbe errore, solo nessuna icona") for m in re.finditer(r'iconSource\s*:\s*"([^"]+)"', testo): icona = (COPERTINA.parent / m.group(1)).resolve() if not icona.exists(): problemi.append("l'icona %s non esiste (risolta da %s)" % (m.group(1), COPERTINA.name)) else: print("icona: %s -> %s" % (m.group(1), icona.relative_to(RADICE))) comandi = re.findall(r'sendCommand\("([^"]+)"', testo) if not comandi: problemi.append("l'azione non invia nessun comando: a che serve?") for c in comandi: if not BRIDGE.exists(): print("salto il controllo del comando %r: manca %s" % (c, BRIDGE)) continue ponte = BRIDGE.read_text(encoding="utf-8") if not re.search(r'"%s"\s*:' % re.escape(c), ponte): problemi.append("il comando %r non e' nella tabella del bridge: " "il telefono riceverebbe un 400" % c) else: print("comando: %s -> presente nel bridge" % c) if problemi: for p in problemi: print("PROBLEMA: %s" % p) print("ESITO: %d problemi sull'azione di copertina" % len(problemi)) return 1 print("ESITO: azione di copertina a posto") return 0 if __name__ == "__main__": sys.exit(main())