Skip to content

Normattiva Download API

italy

Italy-specific downloader built on the Normattiva API.

Classes:

Name Description
ItalyDownloaderConfig

Configuration for the Italy-specific downloader.

ExportMode

An export mode that defines an API request and optional time caps.

SearchWindow

A simple window of dates to pass as search parameters.

ItalyDownloader

Replicate the entire Normattiva dataset (AKN + JSON).

ItalyDownloaderConfig dataclass

ItalyDownloaderConfig(
    output_dir: Path,
    richiesta_export: str = "M",
    modalita: str = "R",
    tipo_ricerca: str = "A",
    overlap_days: int = 2,
    history_start_year: int = 1861,
    recent_window_years: int = 5,
    multivigente_start_year: int | None = 2020,
    skip_history_bulk: bool = True,
    vigente_richiesta_export: str = "V",
    originario_richiesta_export: str = "O",
    checkpoint_chunks: int = 0,
    checkpoint_interval_seconds: float = 0.0,
    origin_source: str = "normattiva",
    owner_alias_kind: str = NORMATTIVA_ALIAS_KIND,
)

Configuration for the Italy-specific downloader.

Attributes: output_dir: Root directory where downloaded payloads are written. richiesta_export: Default export request code (eg. 'M'). modalita: Data access mode code (eg. 'R'). tipo_ricerca: Search type code (eg. 'A'). overlap_days: Days to overlap when computing incremental windows. history_start_year: Earliest year to include in historical syncs. recent_window_years: Size of the rolling recent window. multivigente_start_year: Optional override for multivigente history start. skip_history_bulk: Skip historical V/O bulk windows when True. vigente_richiesta_export: Export code for vigente historic mode. originario_richiesta_export: Export code for originario historic mode. checkpoint_chunks: Deprecated legacy JSON checkpoint setting. checkpoint_interval_seconds: Deprecated legacy JSON checkpoint setting.

ExportMode dataclass

ExportMode(
    richiesta_export: str,
    label: str,
    start_floor: date | None = None,
    end_cap: date | None = None,
)

An export mode that defines an API request and optional time caps.

Attributes: richiesta_export: The export code to send to Normattiva. label: Short label used for logging and manifest entries. start_floor: Optional earliest date to include in the mode. end_cap: Optional latest date to include in the mode.

SearchWindow dataclass

SearchWindow(
    filtro: AdvancedSearchFilter,
    start_date: date,
    end_date: date,
)

A simple window of dates to pass as search parameters.

Attributes: filtro: Prebuilt filter model describing the search parameters. start_date: Inclusive start of the window. end_date: Inclusive end of the window.

Methods:

Name Description
build

Create a :class:SearchWindow using ISO format dates.

build classmethod

build(
    *,
    start_date: date,
    end_date: date,
    order_type: str = "DESC",
) -> SearchWindow

Create a :class:SearchWindow using ISO format dates.

Args: start_date: Inclusive start of the window. end_date: Inclusive end of the window. order_type: Normattiva order type (defaults to DESC).

Source code in src/law_graph/pipelines/normattiva/download/italy.py
@classmethod
def build(cls, *, start_date: date, end_date: date, order_type: str = "DESC") -> SearchWindow:
    """Create a :class:`SearchWindow` using ISO format dates.

    Args:
        start_date: Inclusive start of the window.
        end_date: Inclusive end of the window.
        order_type: Normattiva order type (defaults to DESC).
    """
    filtro = AdvancedSearchFilter(
        data_inizio_pubblicazione=start_date.isoformat(),
        data_fine_pubblicazione=end_date.isoformat(),
        order_type=order_type,
    )
    return cls(filtro=filtro, start_date=start_date, end_date=end_date)

ItalyDownloader

ItalyDownloader(
    config: ItalyDownloaderConfig,
    *,
    datastore: DataStore,
    client: AsyncExportExtensionsClient,
    inventory_store: DownloadManifestDbStore,
    run_id: str,
    dedupe_by_sha: bool = True,
)

Bases: BaseDownloader

Replicate the entire Normattiva dataset (AKN + JSON).

Initialise a new downloader bound to the provided datastore and manifest store.

Methods:

Name Description
run

Execute a full downloader run.

Source code in src/law_graph/pipelines/normattiva/download/italy.py
def __init__(
    self,
    config: ItalyDownloaderConfig,
    *,
    datastore: DataStore,
    client: AsyncExportExtensionsClient,
    inventory_store: DownloadManifestDbStore,
    run_id: str,
    dedupe_by_sha: bool = True,
) -> None:
    """Initialise a new downloader bound to the provided datastore and
    manifest store.
    """
    super().__init__(config.output_dir)
    self.config = config
    self.datastore = datastore
    self.client = client
    self.inventory_store = inventory_store
    self.run_id = run_id
    self.dedupe_by_sha = dedupe_by_sha
    self.log = get_logger(
        component="downloader.italy",
        modalita=self.config.modalita,
        output_dir=str(self.config.output_dir),
    )
    self._identity_resolver = NormattivaArchiveIdentityResolver(
        owner_alias_kind=self.config.owner_alias_kind,
    )
    self._persistence_port = NormattivaArchivePersistencePort(
        origin_source=self.config.origin_source,
        owner_alias_kind=self.config.owner_alias_kind,
    )

run async

run() -> None

Execute a full downloader run.

Retrieves the extensions supported by Normattiva, computes the set of date windows to fetch and writes found payloads to the configured datastore. The inventory database is updated with file and event records.

Source code in src/law_graph/pipelines/normattiva/download/italy.py
async def run(self) -> None:
    """Execute a full downloader run.

    Retrieves the extensions supported by Normattiva, computes the
    set of date windows to fetch and writes found payloads to the
    configured datastore. The inventory database is updated with file and
    event records.
    """
    self.log.info("Starting Italy downloader run")
    extensions = await self.client.get_extensions()
    specs = self._resolve_specs(extensions)
    self.log.debug(
        "Resolved format specs keys={keys}",
        keys=[spec.key for spec in specs],
    )
    modes = self._export_modes()
    for mode in modes:
        for spec in specs:
            stats = await self._download_format(spec, mode)
            if stats is None:
                continue
    self.log.info("Downloader run completed")