Il client asincrono¶
AsyncNormattiva rispecchia Normattiva metodo per metodo e firma
per firma: cambiano await e async for, e gli argomenti del costruttore sono
gli stessi, salvo http_client, che qui vuole un httpx.AsyncClient, e
sleep, che passa da asyncio.sleep.
Più corutine che condividono lo stesso client condividono anche la sua autolimitazione, quindi si mettono in fila da sole. Quando conviene usarlo lo spiega lavorare in asincrono.
AsyncNormattiva
¶
AsyncNormattiva(
*,
user_agent: str | None = None,
timeout: float = 30.0,
retries: int = 2,
requests_per_second: float = 2.0,
base_url: str = PRODUZIONE,
http_client: AsyncClient | None = None,
sleep: Callable[[float], Awaitable[None]] = sleep,
clock: Callable[[], float] = monotonic,
)
La variante asincrona del client.
Ogni metodo rispecchia il suo gemello su Normattiva, firma compresa;
quelli che iterano restituiscono iteratori asincroni. Anche gli argomenti
del costruttore sono gli stessi, con http_client che qui vuole un
httpx.AsyncClient e sleep che passa da asyncio.sleep.
Le corutine che condividono un client condividono anche la sua autolimitazione, e quindi si mettono in fila da sole.
Ogni metodo che tocca la rete può sollevare ConnectionError se il
servizio non è raggiungibile, UnexpectedResponseError se la risposta non ha
la forma che la libreria sa leggere, e RequestBlockedError se lo strato
di protezione respinge la forma della richiesta. Le sezioni Raises dei
singoli metodi elencano solo le eccezioni specifiche di ciascuno.
Codice sorgente in src/normattiva/client.py
close
async
¶
Rilascia il pool di connessioni, se è stato creato da questo client.
Un client HTTP passato dall'esterno resta aperto: chiuderlo spetta a chi lo ha creato.
Codice sorgente in src/normattiva/client.py
dettaglio
async
¶
dettaglio(
atto: Urn | str | AttoTrovato,
*,
vigenza: Vigenza = None,
se_troncato: SeTroncato = "segnala",
) -> DettaglioAtto
Legge il testo di un atto o di un suo articolo.
atto è un URN, oppure un AttoTrovato uscito da una ricerca. Per i
dodici tipi di atto su trenta la cui forma URN non è verificata la
libreria passa dalle coordinate di Gazzetta, che il servizio accetta
allo stesso modo. Quel percorso però non supporta le date: chiedere una
vigenza per un atto raggiungibile solo così solleva un errore, il
parametro non viene ignorato in silenzio.
Senza vigenza il servizio restituisce il testo vigente oggi, e nella
risposta nulla dichiara a quale data corrisponde: indicarla è l'unico
modo di saperlo. Quando si indica una data, la finestra restituita
viene verificata contro di essa.
Con se_troncato="solleva" un articolo che sembra tagliato solleva
TruncationError invece di limitarsi a segnalarlo in una
proprietà.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
atto
|
Urn | str | AttoTrovato
|
un URN, la sua forma testuale, oppure un |
obbligatorio |
vigenza
|
Vigenza
|
il giorno a cui leggere il testo, |
None
|
se_troncato
|
SeTroncato
|
|
'segnala'
|
Restituisce:
| Tipo | Descrizione |
|---|---|
DettaglioAtto
|
Il testo richiesto, con la finestra di vigenza in cui è valido. |
Esempi:
Il testo dell'articolo 19 della legge 241 com'era nel 2000, con la finestra in cui quel testo è stato in vigore::
atto = normattiva.dettaglio(
"urn:nir:stato:legge:1990-08-07;241~art19",
vigenza=date(2000, 1, 1),
)
print(atto.finestra) # 1994-01-01 → 2005-03-07
Solleva:
| Tipo | Descrizione |
|---|---|
NotFoundError
|
nessun atto risponde a quelle coordinate. |
AmbiguityError
|
l'URN corrisponde a più atti pubblicati; i candidati sono elencati nell'eccezione. |
NotYetInForceError
|
l'articolo non esisteva alla data richiesta. |
ValidityMismatchError
|
il servizio ha risposto con una versione che non copre la data richiesta. |
TruncationError
|
solo con |
InvalidUrnError
|
l'URN è malformato, oppure la forma URN di quel tipo di atto non è verificata. |
InvalidArgumentError
|
la vigenza è indicata due volte, oppure è chiesta per un atto raggiungibile solo dalle coordinate di Gazzetta. |
Codice sorgente in src/normattiva/client.py
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 | |
dettaglio_da_gazzetta
async
¶
dettaglio_da_gazzetta(
codice_redazionale: str,
data: date,
*,
se_troncato: SeTroncato = "segnala",
) -> DettaglioAtto
Legge un atto a partire dalle sue coordinate di Gazzetta.
È il percorso per gli atti la cui forma URN non è verificata: il codice redazionale e la data di Gazzetta arrivano da una ricerca, e il servizio risponde anche per un decreto-legge luogotenenziale del 1917. Questo percorso però non supporta la multivigenza: restituisce sempre il testo vigente oggi, e per una data serve un URN.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
codice_redazionale
|
str
|
l'identificativo di Gazzetta dell'atto, come
arriva da |
obbligatorio |
data
|
date
|
la data di pubblicazione in Gazzetta. |
obbligatorio |
se_troncato
|
SeTroncato
|
come per |
'segnala'
|
Restituisce:
| Tipo | Descrizione |
|---|---|
DettaglioAtto
|
Il testo dell'atto, sempre nella versione vigente oggi. |
Solleva:
| Tipo | Descrizione |
|---|---|
NotFoundError
|
nessun atto per quelle coordinate di Gazzetta. |
InvalidArgumentError
|
il codice redazionale è vuoto. |
Codice sorgente in src/normattiva/client.py
cronologia
async
¶
cronologia(
urn: Urn | str, *, massimo: int | None = None
) -> AsyncIterator[DettaglioAtto]
Percorre tutte le versioni di un articolo, dall'originale a quella in vigore.
Costa una richiesta per versione: le finestre di vigenza sono contigue,
quindi ogni versione viene chiesta al giorno successivo alla fine della
precedente. Con massimo l'iterazione si ferma dopo quel numero di
versioni; senza, arriva all'ultima. Senza massimo la catena si ferma
comunque dopo cinquecento passi: nessun articolo italiano ha
cinquecento versioni, quindi una catena così lunga indica finestre non
contigue.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
urn
|
Urn | str
|
l'articolo di cui percorrere le versioni. |
obbligatorio |
massimo
|
int | None
|
quante versioni al più produrre. Senza, si arriva in fondo. |
None
|
Produce:
| Tipo | Descrizione |
|---|---|
AsyncIterator[DettaglioAtto]
|
Una versione per volta, dalla più vecchia alla più recente. |
Solleva:
| Tipo | Descrizione |
|---|---|
UnexpectedResponseError
|
la catena non si chiude entro cinquecento passi, cioè le finestre di vigenza non sono contigue. |
Codice sorgente in src/normattiva/client.py
ricerca
async
¶
ricerca(
testo: str,
*,
pagina: int = 1,
per_pagina: int = 20,
sort: Sort | str = NEWEST,
tipo: str | None = None,
anno: int | None = None,
emettitore: str | None = None,
) -> EsitoRicerca
Cerca nel testo pieno del corpus.
Le parole vengono combinate in AND dal servizio; non c'è modo di
chiedere un OR. tipo, anno ed emettitore sono le faccette che la
risposta stessa propone, non le coordinate dell'atto: per quelle c'è
ricerca_avanzata.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
testo
|
str
|
le parole da cercare, combinate in AND dal servizio. |
obbligatorio |
pagina
|
int
|
quale pagina di risultati, a partire da 1. |
1
|
per_pagina
|
int
|
quanti risultati per pagina. |
20
|
sort
|
Sort | str
|
|
NEWEST
|
tipo
|
str | None
|
codice della faccetta per tipo di atto, come |
None
|
anno
|
int | None
|
faccetta per anno di provvedimento. |
None
|
emettitore
|
str | None
|
faccetta per amministrazione emanante. |
None
|
Restituisce:
| Tipo | Descrizione |
|---|---|
EsitoRicerca
|
Una pagina di risultati, con il totale e le faccette per restringere. |
Codice sorgente in src/normattiva/client.py
ricerca_avanzata
async
¶
ricerca_avanzata(
*,
denominazione: str | None = None,
anno: int | None = None,
numero: int | str | None = None,
giorno: int | None = None,
mese: int | None = None,
titolo: str | None = None,
testo: str | None = None,
vigente_al: date | None = None,
classe: ClasseProvvedimento | int | None = None,
emanazione: Intervallo | None = None,
pubblicazione: Intervallo | None = None,
sort: Sort | str = NEWEST,
tipo: str | None = None,
emettitore: str | None = None,
pagina: int = 1,
per_pagina: int = 20,
) -> EsitoRicerca
Cerca per coordinate invece che per parole.
Senza nessuna coordinata il servizio risponde con l'intero corpus: è una richiesta ammessa, e la libreria non la rifiuta.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
denominazione
|
str | None
|
il tipo di atto come lo scrive il dizionario, per
esempio |
None
|
anno
|
int | None
|
anno di emanazione. |
None
|
numero
|
int | str | None
|
numero del provvedimento. |
None
|
giorno
|
int | None
|
giorno di emanazione. |
None
|
mese
|
int | None
|
mese di emanazione. |
None
|
titolo
|
str | None
|
parole da cercare nel titolo. |
None
|
testo
|
str | None
|
parole da cercare nel testo. |
None
|
vigente_al
|
date | None
|
tiene solo gli atti in vigore in quel giorno. |
None
|
classe
|
ClasseProvvedimento | int | None
|
la classe redazionale dell'atto (senza aggiornamenti, aggiornato, abrogato). |
None
|
emanazione
|
Intervallo | None
|
intervallo di emanazione, come coppia |
None
|
pubblicazione
|
Intervallo | None
|
intervallo di pubblicazione in Gazzetta, come sopra. |
None
|
sort
|
Sort | str
|
|
NEWEST
|
tipo
|
str | None
|
faccetta per tipo di atto. |
None
|
emettitore
|
str | None
|
faccetta per amministrazione emanante. |
None
|
pagina
|
int
|
quale pagina di risultati, a partire da 1. |
1
|
per_pagina
|
int
|
quanti risultati per pagina. |
20
|
Restituisce:
| Tipo | Descrizione |
|---|---|
EsitoRicerca
|
Una pagina di risultati, nella stessa forma che rende |
Codice sorgente in src/normattiva/client.py
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | |
ricerca_completa
async
¶
ricerca_completa(
testo: str,
*,
massimo: int | None = None,
per_pagina: int = 50,
sort: Sort | str = NEWEST,
tipo: str | None = None,
anno: int | None = None,
emettitore: str | None = None,
) -> AsyncIterator[AttoTrovato]
Scorre tutti gli atti che una ricerca trova, una pagina per volta.
L'iteratore è pigro: ogni pagina viene chiesta solo quando serve,
quindi consumare dieci risultati costa una richiesta sola. Con
massimo ci si ferma dopo quel numero di atti; per sapere quanti ce
n'erano in tutto basta una ricerca e il suo totale.
Quel totale è anche la condizione di uscita: il numero di pagina
restituito dal servizio non è affidabile, e usarlo come condizione
potrebbe rileggere la prima pagina all'infinito.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
testo
|
str
|
le parole da cercare. |
obbligatorio |
massimo
|
int | None
|
quanti atti al più produrre. Senza, si arriva in fondo. |
None
|
per_pagina
|
int
|
quanti risultati chiedere per richiesta. |
50
|
sort
|
Sort | str
|
|
NEWEST
|
tipo
|
str | None
|
faccetta per tipo di atto. |
None
|
anno
|
int | None
|
faccetta per anno di provvedimento. |
None
|
emettitore
|
str | None
|
faccetta per amministrazione emanante. |
None
|
Produce:
| Tipo | Descrizione |
|---|---|
AsyncIterator[AttoTrovato]
|
Un atto per volta, nell'ordine in cui il servizio li rende. |
Codice sorgente in src/normattiva/client.py
atti_aggiornati
async
¶
atti_aggiornati(
dal: date, al: date
) -> AsyncIterator[AttoTrovato]
Elenca gli atti modificati fra due date.
Il flusso contiene solo le modifiche: un atto pubblicato dentro la finestra ma mai modificato dopo non compare. Le finestre più lunghe di un anno vengono spezzate, perché il servizio le rifiuta.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
dal
|
date
|
primo giorno della finestra, compreso. |
obbligatorio |
al
|
date
|
ultimo giorno della finestra, compreso. |
obbligatorio |
Produce:
| Tipo | Descrizione |
|---|---|
AsyncIterator[AttoTrovato]
|
Un atto modificato per volta, finestra dopo finestra. |
Solleva:
| Tipo | Descrizione |
|---|---|
RuleViolationError
|
|
Codice sorgente in src/normattiva/client.py
denominazioni
async
¶
denominazioni(
*, reload: bool = False
) -> tuple[Tipologica, ...]
Elenca i tipi di atto che il corpus contiene, e tiene il risultato in memoria.
Codice sorgente in src/normattiva/client.py
classi_provvedimento
async
¶
classi_provvedimento(
*, reload: bool = False
) -> tuple[Tipologica, ...]
Elenca le classi redazionali a cui un atto può appartenere.
Codice sorgente in src/normattiva/client.py
export_formats
async
¶
export_formats(
*, reload: bool = False
) -> tuple[Tipologica, ...]
Elenca i formati in cui si può chiedere un'esportazione.
Codice sorgente in src/normattiva/client.py
ricerche_predefinite
async
¶
ricerche_predefinite() -> tuple[RicercaPredefinita, ...]
Elenca le ricerche predefinite che il servizio propone.
Codice sorgente in src/normattiva/client.py
collections
async
¶
collections() -> tuple[Collection, ...]
Elenca gli archivi già confezionati che il servizio mette a disposizione.
Codice sorgente in src/normattiva/client.py
download_collection
async
¶
download_collection(
name: str,
*,
format: Format | str = JSON,
mode: ExportMode | str = VIGENTE,
) -> Corpus
Scarica un archivio già confezionato e legge gli atti che contiene.
Solleva:
| Tipo | Descrizione |
|---|---|
InvalidArgumentError
|
il formato chiesto non viene letto in
modelli; usare |
Codice sorgente in src/normattiva/client.py
save_collection
async
¶
save_collection(
name: str,
path: str | Path,
*,
format: Format | str = JSON,
mode: ExportMode | str = VIGENTE,
) -> Path
Scarica su disco un archivio già confezionato, in qualunque formato sia.
Codice sorgente in src/normattiva/client.py
start_export
async
¶
start_export(
*,
format: Format | str = JSON,
mode: ExportMode | str = MULTIVIGENTE,
massimo_atti: int | None = 100,
escludi_testo: str | None = None,
escludi_titolo: str | None = None,
denominazione: str | None = None,
anno: int | None = None,
numero: int | str | None = None,
giorno: int | None = None,
mese: int | None = None,
titolo: str | None = None,
testo: str | None = None,
vigente_al: date | None = None,
classe: ClasseProvvedimento | int | None = None,
emanazione: Intervallo | None = None,
pubblicazione: Intervallo | None = None,
) -> AsyncExport
Chiede l'esportazione completa degli atti che una ricerca trova.
Le coordinate sono le stesse di ricerca_avanzata. Prima di avviare
l'esportazione gli atti vengono contati con una ricerca sincrona,
perché un'esportazione costa minuti di lavoro al servizio e, una volta
partita, non si annulla. Con massimo_atti=None si parte senza
conteggio.
escludi_testo ed escludi_titolo escludono dal risultato gli atti
che contengono quelle parole, e sono l'unico filtro che l'esportazione
supporta e la ricerca no: il conteggio preventivo non ne tiene conto,
quindi può contare più atti di quanti ne arriveranno.
Parametri:
| Nome | Tipo | Descrizione | Predefinito |
|---|---|---|---|
format
|
Format | str
|
in che formato produrre l'archivio. Solo |
JSON
|
mode
|
ExportMode | str
|
quante versioni includere nell'archivio. |
MULTIVIGENTE
|
massimo_atti
|
int | None
|
il tetto oltre il quale l'esportazione non parte.
|
100
|
escludi_testo
|
str | None
|
esclude gli atti che contengono questa parola. |
None
|
escludi_titolo
|
str | None
|
esclude gli atti il cui titolo la contiene. |
None
|
denominazione
|
str | None
|
come in |
None
|
anno
|
int | None
|
anno di emanazione. |
None
|
numero
|
int | str | None
|
numero del provvedimento. |
None
|
giorno
|
int | None
|
giorno di emanazione. |
None
|
mese
|
int | None
|
mese di emanazione. |
None
|
titolo
|
str | None
|
parole da cercare nel titolo. |
None
|
testo
|
str | None
|
parole da cercare nel testo. |
None
|
vigente_al
|
date | None
|
tiene solo gli atti in vigore in quel giorno. |
None
|
classe
|
ClasseProvvedimento | int | None
|
la classe redazionale dell'atto (senza aggiornamenti, aggiornato, abrogato). |
None
|
emanazione
|
Intervallo | None
|
intervallo di emanazione, come coppia |
None
|
pubblicazione
|
Intervallo | None
|
intervallo di pubblicazione in Gazzetta. |
None
|
Restituisce:
| Tipo | Descrizione |
|---|---|
AsyncExport
|
L'esportazione appena avviata, da attendere e poi scaricare. |
Solleva:
| Tipo | Descrizione |
|---|---|
TooManyResultsError
|
i criteri selezionano più atti di
|
ConnectionError
|
il conteggio preventivo non è riuscito. Il messaggio indica come procedere senza. |
Codice sorgente in src/normattiva/client.py
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 | |
export_from_token
async
¶
export_from_token(
token: str, *, format: Format | str = JSON
) -> AsyncExport
Riprende un'esportazione già in corso, dal suo token.