Toolkit Python per pipeline dati riproducibili RAW -> CLEAN -> MART, con approccio SQL-first, audit degli artefatti e run tracking persistente.
Questa repo e' il motore tecnico della pipeline dati di DataCivicLab.
Ruoli delle repo correlate:
.github: policy condivise, community health, template issue/PR, onboarding GitHubdataciviclab: hub pubblico e minimale dell'organizzazionetoolkit: runtime, CLI, contract di config/path/output, documentazione tecnica del motoreproject-template: template operativo dei repo dataset- repo dataset: progetti concreti che usano il toolkit
Questa repo non e' l'hub dell'organizzazione e non replica la documentazione org-wide: resta focalizzata sul motore e sul suo contratto tecnico.
Il toolkit espone un perimetro volutamente stretto:
- core runtime:
raw,clean,mart,run,validate,status,inspect - advanced tooling:
resume,profile raw, run parziali per layer - compatibility only: alias legacy e shim deprecati
Regola pratica:
- nuovi repo dataset: resta nel workflow canonico
- recovery o diagnostica: usa gli strumenti advanced
- bootstrap o compatibilita': non trattarli come parte del contratto stabile
- mantenere una struttura progetto semplice:
dataset.yml+sql/ - eseguire trasformazioni riproducibili con DuckDB
- tenere separati i layer
raw,clean,mart - produrre output auditabili con metadata, manifest e validation report
- rendere la CLI scriptabile senza introdurre logica dataset-specifica nel core
Il toolkit include:
- pipeline
raw,clean,mart - validation gate post-layer integrato in
run - run tracking persistente in
data/_runs/... - comandi CLI
run,resume,status,validate,profile,inspect project-example/offline per smoke test locale
git clone https://github.com/dataciviclab/toolkit.git
cd toolkit
pip install -e .[dev]Richiede Python 3.10+.
Il comando CLI canonico del progetto e' toolkit.
Se nel tuo ambiente c'e' una collisione di nome o il console script non e' nel PATH, puoi usare direttamente il modulo Python:
python -m toolkit.cli.app run all --config dataset.ymlIl percorso canonico per i repo dataset clonati dal template e':
toolkit run all --config dataset.ymltoolkit validate all --config dataset.ymltoolkit status --dataset <dataset> --year <year> --latest --config dataset.yml- notebook locali che leggono gli output reali sotto
root/data/...
Giro offline completo con il progetto di esempio, eseguibile in pochi minuti su una macchina pulita.
Windows PowerShell:
$env:TOOLKIT_OUTDIR = Join-Path $env:TEMP "dataciviclab-toolkit-quickstart"
py -m pip install -e ".[dev]"
py -m toolkit.cli.app run all -c project-example/dataset.yml
py -m toolkit.cli.app validate all -c project-example/dataset.yml
py -m toolkit.cli.app status --dataset project_example --year 2022 --config project-example/dataset.ymlLinux/macOS:
export TOOLKIT_OUTDIR="$(mktemp -d)/dataciviclab-toolkit-quickstart"
python -m pip install -e ".[dev]"
python -m toolkit.cli.app run all -c project-example/dataset.yml
python -m toolkit.cli.app validate all -c project-example/dataset.yml
python -m toolkit.cli.app status --dataset project_example --year 2022 --config project-example/dataset.ymlValidazione rapida della config prima di eseguire la pipeline:
toolkit run all --config dataset.yml --dry-runInterpretazione errori config:
Config validation failed: output.<campo>: Extra inputs are not permitted-> campo non supportatoConfig validation failed: raw.sources: Input should be a valid list-> tipo YAML sbagliatoConfig validation failed: clean.validate.primary_key: ... string or a list of strings-> forma del valore non valida- warning di deprecazione -> config ancora accettata, ma in forma legacy da migrare
Schema completo e legacy supportato: docs/config-schema.md
Flow avanzati e tooling secondario: docs/advanced-workflows.md
Matrice di stabilita: [docs/feature-stability.md](docs/feature-stability.md) Contratto notebook/output: [docs/notebook-contract.md](docs/notebook-contract.md) Confini runtime e superfici non-core: [docs/runtime-boundaries.md](docs/runtime-boundaries.md) Per policy condivise e community health organizzativa, fai riferimento alla repo .github` dell'organizzazione.
Artefatti attesi:
$TOOLKIT_OUTDIR/data/raw/project_example/2022/manifest.json$TOOLKIT_OUTDIR/data/clean/project_example/2022/project_example_2022_clean.parquet$TOOLKIT_OUTDIR/data/mart/project_example/2022/rd_by_regione.parquet$TOOLKIT_OUTDIR/data/_runs/project_example/2022/<run_id>.json
Configurazione minima:
root: "./_smoke_out"
dataset:
name: "project_example"
years: [2022]
raw:
sources:
- name: "local_csv"
type: "local_file"
args:
path: "data/raw_sample.csv"
filename: "ispra_dettaglio_comunale_{year}.csv"
clean:
sql: "sql/clean.sql"
read_mode: "fallback"
read:
mode: "explicit"
include: ["ispra_dettaglio_comunale_*.csv"]
delim: ";"
encoding: "utf-8"
mart:
tables:
- name: "rd_by_regione"
sql: "sql/mart/mart_regione_anno.sql"
validation:
fail_on_error: trueI path relativi in dataset.yml sono risolti rispetto alla directory del dataset.yml, non rispetto al cwd.
La directory di output effettiva segue questa precedenza:
rootdichiarato indataset.ymlDCL_ROOT- fallback sulla directory che contiene
dataset.yml
Convenzioni:
dataset.ymldescrive dataset, anni, sorgenti, SQL e validazionisql/clean.sqldefinisce il layer CLEANsql/mart/*.sqldefinisce le tabelle MART- per esempi pronti, vedi examples/dataset_min.yml e examples/dataset_full.yml
Caso utile per CSV pubblici multi-anno quasi stabili ma non identici:
clean:
sql: "sql/clean.sql"
read:
source: config_only
header: false
skip: 1
delim: ";"
encoding: "utf-8"
columns:
column00: "VARCHAR"
column01: "VARCHAR"
column02: "VARCHAR"
normalize_rows_to_columns: trueUsa normalize_rows_to_columns: true quando:
- vuoi un layout posizionale canonico
- alcuni file o anni hanno righe piu corte del numero di colonne atteso
- vuoi evitare che una colonna aggiunta o mancante faccia saltare il
clean
Non usarlo come default. Ha senso quando stai deliberatamente gestendo una fonte instabile con schema posizionale dichiarato.
Workflow canonico:
toolkit run all --config dataset.yml
toolkit validate all --config dataset.ymlPer il percorso base:
run allesegue RAW -> CLEAN -> MARTvalidate allesegue i quality checks su CLEAN e MARTstatuslegge il run record e mostra lo stato piu` recenteinspect pathsespone i path stabili per notebook e script locali, insieme ai principali hints del RAWinspect schema-diffconfronta i principali segnali di schema RAW tra gli anni configurati--dry-runvalida config e SQL senza eseguire la pipeline
Esempi:
toolkit run all --config dataset.yml --strict-config
toolkit validate all --config dataset.yml --strict-config
toolkit status --dataset my_dataset --year 2024 --latest --config dataset.yml
toolkit inspect paths --config dataset.yml --year 2024 --json
toolkit inspect schema-diff --config dataset.yml --json
toolkit run all --config dataset.yml --dry-run --strict-configresume, profile raw, run raw|clean|mart e la policy completa degli artifacts restano disponibili, ma sono tooling avanzato: vedi docs/advanced-workflows.md.
Nei repo dataset clonati dal template, i notebook dovrebbero leggere gli output reali gia` scritti dal toolkit, non ricostruire logica di path.
In pratica:
- RAW:
root/data/raw/<dataset>/<year>/ - CLEAN:
root/data/clean/<dataset>/<year>/ - MART:
root/data/mart/<dataset>/<year>/ - run records:
root/data/_runs/<dataset>/<year>/ - hints RAW:
root/data/raw/<dataset>/<year>/_profile/suggested_read.yml
Helper ufficiale per evitare path logic duplicata nei notebook:
toolkit inspect paths --config dataset.yml --year 2024 --jsonRuoli stabili degli output:
metadata.json: payload ricco del layermanifest.json: summary stabile del layer con puntatori a metadata e validationdata/_runs/.../<run_id>.json: stato del run usato dastatuseresumeinspect paths --json: discovery helper read-only per notebook e script locali, con bloccoraw_hints
Questo mantiene il contratto semplice tra toolkit e repo dataset:
- il toolkit produce artefatti e metadata stabili
- i notebook li ispezionano localmente
dataset.ymlresta la fonte di verita` per dataset, anni e path relativi
Run tracking:
- ogni
runeresumescrive un record indata/_runs/<dataset>/<year>/<run_id>.json statuslegge questi recordinspect pathsespone i path stabili da usare in notebook e script
Validation gate:
toolkit run ...valida automaticamente dopo ogni layer completato- con
validation.fail_on_error: truela pipeline si ferma - con
validation.fail_on_error: falseil run puoterminare comeSUCCESS_WITH_WARNINGS`
Per dettagli completi su layer, validazioni, plugin, artifact policy e flow avanzati, vedi:
Vedi docs/conventions.md per:
- policy RAW
- policy di selezione input CLEAN
- precedence del read config
- metadata, manifest e validation contracts
- workflow avanzati e tooling secondario: docs/advanced-workflows.md
Suite rapida:
py -m pytestLint:
py -m ruff check .La suite include:
- test unitari su config, registry, extractors e validazioni
- test su CLI
run,status,resume,dry-run - golden path E2E su
project-example
Gli output generati non devono mai essere committati.
- tieni artefatti e cache solo in directory locali gia
ignorate come_smoke_out/,_test_out/,.pytest_cache/,.ruff_cache/e*.egg-info/` - usa un
rootesplicito neldataset.ymloDCL_ROOTper tenere gli output fuori dal codice sorgente quando lavori su smoke test o progetti locali - se un output e
giatracciato da git, rimuovilo dall'index congit rm -r --cached <path>senza cancellarlo dal filesystem
Questo repository non contiene dataset reali di produzione.
Contiene:
- il motore
- le convenzioni
- un progetto esempio minimo