Libreria Python, sincrona e asincrona, per accedere ai dati del registro elettronico DiDUP / Argo Famiglia: voti, assenze, registro di classe, bacheca, promemoria e altro, restituiti come modelli tipizzati Pydantic v2.
Important
Progetto non ufficiale, sviluppato in modo indipendente e non affiliato, approvato o supportato da Argo Software S.r.l. Le API utilizzate non sono pubbliche né documentate: sono state ricostruite osservando il traffico dell'app ufficiale e possono cambiare in qualsiasi momento senza preavviso. Leggi la sezione Note legali prima dell'uso.
- Caratteristiche
- Requisiti e installazione
- Guida rapida
- Versione del client
- Account con più figli
- Riferimento API
- Gestione degli errori
- Notifiche sulle novità
- Sviluppo
- Note legali
- Contatti e richieste di rimozione
- Licenza
- Client asincrono (
DiDUPClient) e sincrono (DiDUPClientSync) con la stessa interfaccia. - Login completo OAuth2/PKCE, identico a quello dell'app ufficiale.
- Risposte validate e tipizzate con Pydantic v2, tolleranti a campi
mancanti,
nulle campi aggiunti in futuro dal server. - Cache della dashboard: più chiamate consecutive generano una sola richiesta.
- Eccezioni dedicate per autenticazione, rate limit, risorse non trovate e versione del client superata.
DashboardPollerper ricevere callback solo quando compaiono nuovi dati.- Pacchetto completamente tipizzato (
py.typed).
Serve Python 3.10 o successivo.
pip install didupwrapperPer il login servono il codice scuola (es. SC12345), lo username e la
password, gli stessi usati nell'app DiDUP Famiglia.
import asyncio
import os
from didupwrapper import DiDUPClient
async def main() -> None:
async with DiDUPClient(
os.environ["DIDUP_SCUOLA"],
os.environ["DIDUP_USERNAME"],
os.environ["DIDUP_PASSWORD"],
) as didup:
print("Media generale:", await didup.get_media_generale())
for voto in await didup.get_voti():
print(voto.des_materia, voto.cod_codice)
asyncio.run(main())import os
from didupwrapper import DiDUPClientSync
with DiDUPClientSync(
os.environ["DIDUP_SCUOLA"],
os.environ["DIDUP_USERNAME"],
os.environ["DIDUP_PASSWORD"],
) as didup:
for voto in didup.get_voti():
print(voto.des_materia, voto.cod_codice)Tip
Non inserire mai le credenziali nel codice sorgente: usa variabili d'ambiente o un gestore di segreti, come negli esempi.
Per essere accettato dal server, ogni richiesta include l'header
argo-client-version, che deve corrispondere a una versione recente dell'app
pubblicata sugli store (il default attuale è 1.29.2). Se la versione è
troppo vecchia il server risponde 410 e la libreria solleva un DiDUPError
che lo spiega.
Ci sono tre modi per gestirla:
# 1. Default della libreria
DiDUPClient("SC12345", "user", "pwd")
# 2. Versione fissata a mano
DiDUPClient("SC12345", "user", "pwd", version="1.29.2")
# 3. Versione letta dall'App Store al momento del login (consigliato)
DiDUPClient("SC12345", "user", "pwd", auto_versione=True)Per conoscere solo l'ultima versione pubblicata:
from didupwrapper import recupera_versione_app
print(await recupera_versione_app()) # es. "1.29.2", oppure None se non raggiungibileCon un account genitore collegato a più figli, Argo restituisce un profilo per ogni figlio. Di default il client usa il primo; per consultare gli altri:
with DiDUPClientSync("SC12345", "mario.rossi", "password") as didup:
for profilo in didup.get_profili():
print(profilo.indice, profilo.nome_completo)
didup.seleziona_profilo("Beatrice") # oppure l'indice, o un Profilo
print(didup.get_voti())seleziona_profilo() accetta il nome, nome e cognome in qualsiasi ordine o una
parola del nominativo; se il nome corrisponde a nessuno o a più profili solleva
DiDUPError. Cambiando profilo la cache della dashboard viene svuotata, e il
profilo scelto resta attivo anche quando il client rifà il login per una
sessione scaduta.
Disponibili sia su DiDUPClient (con await) sia su DiDUPClientSync.
| Metodo | Restituisce |
|---|---|
get_dashboard(forza_refresh=False) |
Tutti i dati aggregati (DashboardResponse) |
get_voti() |
Voti (list[Voto]) |
get_assenze() |
Assenze, ritardi e uscite (list[EventoAppello]) |
get_registro() |
Registro delle lezioni (list[RegistroLezione]) |
get_bacheca() |
Comunicazioni in bacheca (list[ComunicazioneBacheca]) |
get_bacheca_alunno() |
File della bacheca alunno (list[FileBachecaAlunno]) |
get_promemoria() |
Promemoria dei docenti (list[Promemoria]) |
get_fuori_classe() |
Attività fuori classe (list[FuoriClasse]) |
get_note_disciplinari() |
Note disciplinari (list[NotaDisciplinare]) |
get_materie() |
Materie (list[Materia]) |
get_docenti() |
Docenti della classe (list[Docente]) |
get_periodi() |
Periodi / quadrimestri (list[Periodo]) |
get_prenotazioni() |
Colloqui prenotati (list[Prenotazione]) |
get_media_generale() |
Media complessiva (float | None) |
invalida_cache() |
Svuota la cache della dashboard |
get_profili() |
Profili dell'account, uno per figlio (list[Profilo]) |
seleziona_profilo(profilo) |
Rende attivo un profilo per nome, indice o Profilo |
La dashboard viene scaricata una volta e riutilizzata dalle chiamate
successive. Per dati aggiornati usa get_dashboard(forza_refresh=True) oppure
invalida_cache().
await didup.voti.per_materia(pk_materia) # pk_materia è una stringa, es. voto.pk_materia
await didup.voti.media_per_materia(pk_materia)
await didup.voti.scritti()
await didup.assenze.da_giustificare()
await didup.bacheca.da_leggere()
await didup.registro.compiti()
await didup.fuori_classe.online()Le chiavi primarie restituite da Argo (pk_materia, pk_periodo, ...) sono
stringhe, non numeri.
Tutte le eccezioni derivano da DiDUPError, che espone status_code,
payload e request_url.
| Eccezione | Quando |
|---|---|
AuthError |
Credenziali errate, sessione scaduta (HTTP 401/403) |
RateLimitError |
Troppe richieste (HTTP 429); vedi retry_after |
NotFoundError |
Risorsa inesistente (HTTP 404) |
DiDUPError |
Qualsiasi altro errore, incluso il 410 per versione superata |
from didupwrapper import AuthError, DiDUPError
try:
async with DiDUPClient(scuola, username, password) as didup:
voti = await didup.get_voti()
except AuthError:
print("Credenziali non valide")
except DiDUPError as errore:
print("Errore:", errore)DashboardPoller interroga la dashboard a intervalli regolari e chiama le
callback (normali funzioni o coroutine) solo per gli elementi nuovi. Al primo
giro registra lo stato iniziale senza notificare nulla, a meno di passare
emetti_al_primo_giro=True.
from didupwrapper import DashboardPoller
async def on_nuovi_voti(nuovi):
for voto in nuovi:
print("Nuovo voto:", voto.des_materia, voto.cod_codice)
poller = DashboardPoller(didup, intervallo=600, on_nuovi_voti=on_nuovi_voti)
await poller.start() # blocca finché non viene chiamato poller.stop()Sono disponibili anche on_nuove_assenze, on_nuove_comunicazioni,
on_nuove_note, on_nuovi_promemoria e on_evento (riceve un EventoPoller
con tutte le novità del giro).
Usa intervalli ragionevoli (almeno qualche minuto): il servizio è pensato per l'uso da parte di famiglie e studenti, non per interrogazioni continue.
git clone https://github.com/Rocciadura/didupAPI-wrapper.git
cd didupAPI-wrapper
pip install -e ".[dev]"
pytest # test (HTTP simulato con respx, nessuna richiesta reale)
ruff check . # lint
mypy didupwrapper # type checkingGli stessi controlli girano in automatico con GitHub Actions su Python
3.10–3.13 a ogni push su main e a ogni pull request.
- Aggiorna
versioninpyproject.tomle__version__indidupwrapper/__init__.py(un test controlla che coincidano). - Fai il commit e crea un tag con lo stesso numero, es.
git tag v0.1.3. git push --tags: il workflowpublish.ymlfa la build e la carica su PyPI con il Trusted Publishing (va configurato una volta sola su PyPI, indicando questo repository, il workflowpublish.ymle l'environmentpypi).
Contributi e segnalazioni sono benvenuti tramite issue e pull request.
- Nessuna affiliazione. Questo progetto non è affiliato, approvato né sostenuto da Argo Software S.r.l. "Argo", "DiDUP" e "Argo Famiglia" sono marchi dei rispettivi titolari e sono citati solo per indicare il servizio con cui la libreria è compatibile.
- Uso consentito. La libreria è pensata per accedere esclusivamente ai propri dati (o a quelli dei propri figli), con le proprie credenziali. Non usarla per accedere ad account altrui, raccogliere dati di terzi o sovraccaricare i server.
- Termini del servizio. L'utente è responsabile del rispetto dei termini d'uso di Argo e della normativa sulla protezione dei dati personali (GDPR).
- Nessuna garanzia. Il software è fornito "così com'è", senza garanzie di alcun tipo, come previsto dalla licenza MIT.
Se sei un rappresentante di Argo Software e ritieni che questo progetto non debba essere pubblico, o vuoi che venga modificato, contattami: il repository e il pacchetto su PyPI verranno rimossi o modificati subito, senza bisogno di ulteriori formalità.
Puoi scrivermi:
- in privato, tramite una segnalazione riservata su GitHub;
- in pubblico, aprendo una issue.
Lo stesso vale per eventuali problemi di sicurezza: segnalali in privato tramite il primo canale, non con una issue pubblica.
Distribuito con licenza MIT. Vedi LICENSE.