I modelli¶
Tutti i modelli sono dataclass congelate: non si modificano dopo la
costruzione, si hashano e si confrontano per valore. Nessuno di questi va
costruito a mano nell'uso normale: arrivano dalle risposte del servizio.
Quale oggetto arriva da quale chiamata¶
| Chiamata | Restituisce | Contiene |
|---|---|---|
dettaglio |
DettaglioAtto |
il testo di un atto o articolo in una finestra di vigenza |
cronologia |
iteratore di DettaglioAtto |
una versione per volta, dalla più vecchia |
ricerca, ricerca_avanzata |
EsitoRicerca |
una pagina di AttoTrovato, più totale e faccette |
ricerca_completa |
iteratore di AttoTrovato |
gli atti di tutte le pagine, uno per volta |
atti_aggiornati |
iteratore di AttoTrovato |
gli atti modificati nel periodo |
start_export |
Export |
il lavoro in corso, con il suo token |
Export.download |
Corpus |
un AttoStorico per atto, con tutte le versioni |
denominazioni e le altre tipologiche |
tupla di Tipologica |
i codici che i criteri accettano |
collections |
tupla di Collection |
gli archivi già confezionati |
classDiagram
direction LR
class DettaglioAtto {
+str titolo
+str testo
+tuple~Comma~ commi
+str note_aggiornamento
+bool possibile_troncamento
+str permalink
}
class EstremiAtto {
+str denominazione
+date data
+str numero
+str citazione
}
class PubblicazioneGazzetta {
+date data
+int numero
+str codice_redazionale
}
class FinestraVigenza {
+date inizio
+date fine
+bool aperta
+contiene(giorno) bool
}
class Comma {
+str numero
+str testo
}
class EsitoRicerca {
+int totale
+int pagina
+bool ultima_pagina
}
class AttoTrovato {
+str titolo
+bool ha_urn
+Urn urn
}
class Faccette {
+tuple per_anno
+tuple per_tipo
+tuple per_emettitore
}
DettaglioAtto *-- "1" EstremiAtto : estremi
DettaglioAtto *-- "1" PubblicazioneGazzetta : gazzetta
DettaglioAtto *-- "1" FinestraVigenza : finestra
DettaglioAtto *-- "0..n" Comma : commi
EsitoRicerca *-- "0..n" AttoTrovato : atti
EsitoRicerca *-- "1" Faccette : faccette
AttoTrovato *-- "1" EstremiAtto : estremi
AttoTrovato *-- "1" PubblicazioneGazzetta : gazzetta
Dall'esportazione arriva invece un albero, dove Partizione contiene sé stessa:
classDiagram
direction LR
class Corpus {
+tuple~AttoStorico~ atti
+save(path)
+from_zip(path)$ Corpus
}
class AttoStorico {
+Urn urn
+bool abrogato
+date pubblicato_il
+alla_data(giorno) VersioneAtto
+originale VersioneAtto
+vigente VersioneAtto
}
class VersioneAtto {
+date vigente_dal
+bool originale
+articoli() Iterator
}
class Partizione {
+str tipo
+str numero
+str rubrica
+str testo
}
class Aggiornamento {
+date data
+str testo
}
Corpus *-- "1..n" AttoStorico : atti
AttoStorico *-- "1..n" VersioneAtto : versioni
AttoStorico *-- "0..n" Aggiornamento : aggiornamenti
VersioneAtto *-- "0..n" Partizione : articolato
VersioneAtto *-- "0..n" Partizione : annessi
Partizione *-- "0..n" Partizione : figli
I due percorsi producono modelli diversi perché le due risposte del servizio
sono strutturalmente diverse: DettaglioAtto porta testo e commi di una
versione, AttoStorico porta l'albero dell'articolato di tutte. Il
confronto sta in
com'è fatto il servizio.
Il testo di un atto o di un articolo¶
DettaglioAtto
dataclass
¶
DettaglioAtto(
estremi: EstremiAtto,
gazzetta: PubblicazioneGazzetta,
titolo: str,
sottotitolo: str | None,
testo_html: str,
finestra: FinestraVigenza | None,
)
Il testo di un atto o di un articolo a un punto nel tempo.
Porta il testo già separato dalle note redazionali, i commi numerati, la finestra di vigenza in cui quel testo è valido, le coordinate di Gazzetta e il permalink alla pagina pubblica. Le proprietà che leggono l'HTML del servizio lo fanno alla prima richiesta e tengono il risultato.
note_aggiornamento
property
¶
note_aggiornamento: str | None
Le note redazionali sulle modifiche a questo testo, se presenti.
commi_presenti
property
¶
commi_presenti: int | None
Quanti commi sono arrivati, o None se il testo non ne ha.
ultimo_comma_numerato
property
¶
ultimo_comma_numerato: int | None
L'etichetta dell'ultimo comma numerato, o None se non ce n'è nessuno.
Non coincide con commi_presenti: un articolo può avere commi con
etichette non numeriche, e sono le etichette a indicare dove il testo
si ferma.
possibile_troncamento
property
¶
possibile_troncamento: bool
Indica se questo testo sembra troncato.
Il servizio conserva gli articoli lunghi a blocchi di cento commi e ne restituisce solo il primo, senza segnalarlo. Un articolo il cui ultimo comma numerato cade esattamente su un multiplo di cento è quindi sospetto. Un articolo che finisce davvero lì resta indistinguibile da uno troncato: per questo il valore esprime un sospetto, non una certezza.
Le coordinate di un atto¶
EstremiAtto
dataclass
¶
EstremiAtto(
denominazione: str,
data: date,
numero: str | None = None,
codice_tipo: str | None = None,
)
Gli estremi che identificano un provvedimento: tipo, data e numero.
ha_urn
property
¶
ha_urn: bool
Indica se per questo tipo di atto si sa comporre l'URN.
Da verificare prima di leggere urn scorrendo risultati di ricerca:
dodici tipi di atto su trenta, quasi tutti storici, non hanno una forma
NIR verificata, e per quelli urn solleva un'eccezione invece di
indovinare.
urn
property
¶
urn: Urn
L'URN che identifica questo atto.
Solleva InvalidUrnError per i tipi di atto la cui forma URN non è
stata verificata: un URN inventato otterrebbe un 404 dal servizio, e
chi lo riceve non avrebbe modo di capire che il difetto è nell'URN.
ha_urn permette di verificarlo in anticipo, senza sollevare.
Solleva:
| Tipo | Descrizione |
|---|---|
InvalidUrnError
|
la forma URN di questo tipo di atto non è verificata. |
PubblicazioneGazzetta
dataclass
¶
PubblicazioneGazzetta(
data: date,
numero: int | None = None,
codice_redazionale: str | None = None,
supplemento: str | None = None,
numero_supplemento: int | None = None,
)
Dove e quando un atto è stato pubblicato in Gazzetta Ufficiale.
numero è opzionale perché il servizio non lo fornisce ovunque: gli atti
aggiornanti citati dentro un'esportazione hanno la data di Gazzetta ma non
il numero, e in quel caso il campo resta None.
FinestraVigenza
dataclass
¶
Intervallo di tempo in cui una versione di un testo è stata in vigore.
contiene
¶
Indica se il giorno indicato cade dentro questa finestra.
Una finestra aperta, cioè senza fine, contiene ogni giorno a partire dal suo inizio.
Codice sorgente in src/normattiva/modelli.py
I risultati di una ricerca¶
EsitoRicerca
dataclass
¶
EsitoRicerca(
atti: tuple[AttoTrovato, ...],
totale: int,
pagina: int = 1,
pagine: int = 1,
faccette: Faccette = Faccette(),
)
Una pagina di risultati di ricerca.
Non definisce __len__: non sarebbe chiaro se conta i risultati di questa
pagina o quelli dell'intera ricerca, e un esito con la pagina vuota ma
cinquemila atti in totale risulterebbe falso dentro un if. Si iterano gli
atti di questa pagina, e si legge totale per il conteggio complessivo.
AttoTrovato
dataclass
¶
AttoTrovato(
estremi: EstremiAtto,
gazzetta: PubblicazioneGazzetta,
titolo: str,
descrizione: str | None = None,
ultima_modifica: date | None = None,
atti_modificanti: tuple[str, ...] = (),
evidenziazioni: tuple[Evidenziazione, ...] = (),
)
Un atto come restituito da una ricerca.
atti_modificanti
class-attribute
instance-attribute
¶
I codici redazionali degli ultimi atti che hanno modificato questo, come 26G00129.
Non sono URN né titoli: sono gli identificativi di Gazzetta degli atti modificanti, e per risalire all'atto serve anche la loro data, che il servizio qui non fornisce. Osservati il 2026-08-24 nel flusso degli atti aggiornati.
ha_urn
property
¶
ha_urn: bool
Indica se per questo atto si sa comporre l'URN: da verificare prima di leggerlo.
Evidenziazione
dataclass
¶
Il punto in cui un termine di ricerca è stato trovato dentro un atto.
Faccette
dataclass
¶
Faccette(
per_anno: tuple[Faccetta, ...] = (),
per_tipo: tuple[Faccetta, ...] = (),
per_emettitore: tuple[Faccetta, ...] = (),
)
Le tre faccette che la ricerca restituisce.
Faccetta
dataclass
¶
Un valore di una faccetta di ricerca, con quanti atti lo portano.
L'atto intero, dall'esportazione¶
AttoStorico
dataclass
¶
AttoStorico(
urn: Urn,
estremi: EstremiAtto,
versioni: tuple[VersioneAtto, ...],
eli: str | None = None,
gazzetta: PubblicazioneGazzetta | None = None,
abrogato: bool = False,
aggiornamenti: tuple[Aggiornamento, ...] = (),
)
Un atto intero con tutte le versioni incluse nell'esportazione.
pubblicato_il
property
¶
pubblicato_il: date
La data da cui l'atto esiste: la data di Gazzetta, o in mancanza quella di emanazione.
originale
property
¶
originale: VersioneAtto | None
La versione originale dell'atto, se inclusa nell'export.
vigente
property
¶
vigente: VersioneAtto | None
La versione più recente inclusa nell'export.
Per un atto mai modificato è l'originale: non esiste un testo più recente di quello di pubblicazione.
alla_data
¶
alla_data(giorno: date) -> VersioneAtto
Restituisce la versione dell'atto in vigore nel giorno indicato.
Prima della prima modifica vale il testo originale, che nell'export non ha una data di inizio: vale la data di pubblicazione dell'atto. Un atto mai modificato ha solo quella versione, valida senza limite di tempo.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
giorno
|
date
|
il giorno di cui si vuole il testo. |
obbligatorio |
Restituisce:
| Tipo | Descrizione |
|---|---|
VersioneAtto
|
La versione in vigore quel giorno, con il suo articolato. |
Solleva:
| Tipo | Descrizione |
|---|---|
VersionNotFoundError
|
nessuna versione copre quel giorno, tipicamente perché è anteriore alla pubblicazione. |
Codice sorgente in src/normattiva/modelli.py
VersioneAtto
dataclass
¶
VersioneAtto(
vigente_dal: date | None,
articolato: tuple[Partizione, ...] = (),
annessi: tuple[Partizione, ...] = (),
)
Una versione dell'atto, in vigore da una certa data in poi.
originale
property
¶
originale: bool
Indica se questa è la versione originale, come pubblicata la prima volta.
articoli
¶
articoli() -> Iterator[Partizione]
Itera gli articoli di questa versione, in ordine.
Scende solo nell'articolato: gli allegati stanno in annessi, che è un
ramo separato dell'atto.
Produce:
| Tipo | Descrizione |
|---|---|
Partizione
|
Un articolo per volta, in ordine di lettura. |
Codice sorgente in src/normattiva/modelli.py
Partizione
dataclass
¶
Partizione(
tipo: str | None,
numero: str,
testo: str,
rubrica: str | None = None,
finestre: tuple[FinestraVigenza, ...] = (),
figli: tuple[Partizione, ...] = (),
)
Un nodo della struttura di un atto: un capo, un articolo, un allegato.
tipo contiene il nome NIR del nodo così come lo dichiara il servizio; per
gli articoli vale la costante ARTICOLO.
articoli
¶
articoli() -> Iterator[Partizione]
Itera gli articoli a partire da questo nodo, incluso il nodo stesso.
Produce:
| Tipo | Descrizione |
|---|---|
Partizione
|
Ogni nodo il cui |
Codice sorgente in src/normattiva/modelli.py
Aggiornamento
dataclass
¶
Aggiornamento(
data: date,
testo: str,
riferimenti: tuple[RiferimentoAggiornamento, ...] = (),
)
Una modifica subita dall'atto, come descritta dal servizio.
RiferimentoAggiornamento
dataclass
¶
RiferimentoAggiornamento(
gazzetta: PubblicazioneGazzetta,
articolo: str | None = None,
)
L'articolo che ha introdotto una modifica.
I dizionari del servizio¶
Tipologica
dataclass
¶
Una voce di uno dei dizionari (tipologiche) del servizio.
Collection
dataclass
¶
Collection(
name: str,
format: str,
total_atti: int,
description: str | None = None,
created_at: date | None = None,
)
Un archivio già confezionato messo a disposizione dal servizio.
RicercaPredefinita
dataclass
¶
Una ricerca predefinita suggerita dal servizio.
Le enumerazioni¶
ClasseProvvedimento
¶
Sort
¶
Le costanti¶
ATTRIBUZIONE
module-attribute
¶
ATTRIBUZIONE = "Fonte: Normattiva (https://www.normattiva.it), Istituto Poligrafico e Zecca dello Stato, in licenza CC BY 4.0. Testo non autentico e gratuito: l'unico testo ufficiale è quello pubblicato sulla Gazzetta Ufficiale a mezzo stampa."
La riga di attribuzione che la licenza dei dati richiede.
L'avviso legale del portale richiede tre menzioni: «La riproduzione dei
testi forniti nel formato elettronico è consentita purché venga menzionata la
fonte, il carattere non autentico e gratuito». La riga le contiene tutte e tre,
e tests/test_licenza.py lo verifica, perché è facile accorciare
un'attribuzione senza accorgersi di aver perso una menzione.
DENOMINAZIONI_URN
module-attribute
¶
DENOMINAZIONI_URN = {
"COSTITUZIONE": "costituzione",
"DECRETO": "decreto",
"DECRETO DEL CAPO PROVVISORIO DELLO STATO": "decreto.del.capo.provvisorio.dello.status",
"DECRETO DEL PRESIDENTE DEL CONSIGLIO DEI MINISTRI": "decreto.del.presidente.del.consiglio.dei.ministri",
"DECRETO DEL PRESIDENTE DELLA REPUBBLICA": "decreto.del.presidente.della.repubblica",
"DECRETO LEGISLATIVO": "decreto.legislativo",
"DECRETO LEGISLATIVO LUOGOTENENZIALE": "decreto.legislativo.luogotenenziale",
"DECRETO LEGISLATIVO PRESIDENZIALE": "decreto.legislativo.presidenziale",
"DECRETO LUOGOTENENZIALE": "decreto.luogotenenziale",
"DECRETO MINISTERIALE": "decreto.ministeriale",
"DECRETO PRESIDENZIALE": "decreto.presidenziale",
"DECRETO-LEGGE": "decreto.legge",
"DELIBERAZIONE": "deliberazione",
"LEGGE": "legge",
"LEGGE COSTITUZIONALE": "legge.costituzionale",
"ORDINANZA": "ordinanza",
"REGIO DECRETO": "regio.decreto",
"REGIO DECRETO LEGISLATIVO": "regio.decreto.legislativo",
}
Forma di ogni tipo di atto dentro un URN, verificata contro il servizio.
Sono le diciotto denominazioni su trenta per cui un URN così composto risponde
davvero. Per le altre, quasi tutte tipologie storiche come «DECRETO DEL DUCE» o
«REGOLAMENTO», la forma NIR non è nota: indovinarla porta a un 404 che sembra un
difetto dell'atto e invece è un URN composto male. EstremiAtto.ha_urn permette
di verificarlo in anticipo.
ABBREVIAZIONI
module-attribute
¶
ABBREVIAZIONI = {
"COSTITUZIONE": "Cost.",
"LEGGE": "L.",
"LEGGE COSTITUZIONALE": "L. cost.",
"DECRETO-LEGGE": "D.L.",
"DECRETO LEGISLATIVO": "D.Lgs.",
"DECRETO DEL PRESIDENTE DELLA REPUBBLICA": "D.P.R.",
"DECRETO DEL PRESIDENTE DEL CONSIGLIO DEI MINISTRI": "D.P.C.M.",
"DECRETO MINISTERIALE": "D.M.",
"REGIO DECRETO": "R.D.",
"REGIO DECRETO-LEGGE": "R.D.L.",
"REGIO DECRETO LEGISLATIVO": "R.D.Lgs.",
}
Abbreviazione di ogni tipo di atto nelle citazioni.
Non coincide con DENOMINAZIONI_URN, e la differenza è voluta: abbreviare è
una convenzione editoriale applicabile anche a un atto che questa libreria non
sa indirizzare, come il regio decreto-legge, mentre comporre un URN richiede di
conoscere la forma esatta che il servizio accetta.
Un tipo che qui non compare si cita per esteso, quindi
EstremiAtto.citazione risponde per tutti.
ARTICOLO
module-attribute
¶
Valore del campo tipo di Partizione per i nodi di tipo articolo.