Skip to content

feat(layout): scoperta sezioni dati per convenzione — zero mappa repo - #462

Merged
Gabrymi93 merged 3 commits into
mainfrom
feat/discover-dataset-sections
Aug 9, 2026
Merged

feat(layout): scoperta sezioni dati per convenzione — zero mappa repo#462
Gabrymi93 merged 3 commits into
mainfrom
feat/discover-dataset-sections

Conversation

@Gabrymi93

Copy link
Copy Markdown
Member

Tipo

root fix / refactor — sostituisce la mappa hardcoded REPO_DATASET_DIRS (repo→dirs) con una scoperta per convenzione: zero dichiarazioni per repo, scalabile a qualsiasi layout presente e futuro.

Problema reale

REPO_DATASET_DIRS era una mappa {repo: (dirs,)}: ogni repo nuovo con layout custom richiedeva una riga in più nel toolkit. L'arrivo di open-conto-annuale (layout datasets/ + support/ nella PR open-conto-annuale#3) avrebbe richiesto l'ennesima aggiunta — punto e a capo a ogni repo. Inoltre open-siope (già datasets/+support/) non era dichiarato affatto.

Soluzione — risoluzione univoca

Una dir di primo livello del repo è una sezione dati se contiene {slug}/dataset.yml. La convenzione è la fonte unica: datasets/, support/, candidates/, compose/, support_datasets/, anagrafica/ — qualunque layout — vengono scoperte senza dichiararle.

Esclusioni (falsi positivi verificati): dir nascoste (.github/ISSUE_TEMPLATE/dataset.yml, .git) e templates/ (candidate seed).

Contratto riusato/sostituito

  • Sostituito: REPO_DATASET_DIRS + repo_dataset_dirs(repo_name) (mappa) → repo_dataset_dirs(repo_dir) (scoperta).
  • Riusato: la firma di chiamata nei consumer (catalog.py scan configs, discovery.py Stage 3) — cambia solo l'argomento da repo.name a repo_dir.

Implementazione

File Cosa
toolkit/registry/layout.py repo_dataset_dirs(repo_dir): scopre le sezioni da {section}/*/dataset.yml, esclude nascoste+templates, default ("datasets",) se nessuna
toolkit/domain/catalog.py _scan_workspace_configs passa repo_dir; docstring aggiornata
toolkit/core/discovery.py resolve_config_path Stage 3 passa repo_dir
tests/test_registry_builder.py 5 test contract di scoperta (flat, multi-sezione, DI, esclusioni, default) — sostituiscono i 2 della vecchia mappa

Verifica

  • open-conto-annuale → scopre ('datasets', 'support') senza dichiarazione
  • open-siope → scopre ('datasets', 'support') (prima non dichiarato)
  • dataset-incubator('candidates', 'compose', 'support_datasets') scoperto
  • eurostat/dcl-bologna('datasets',) invariato
  • Scan configs: 191 dataset cross-repo, inclusi open-conto/open-siope
  • 1334 test verdi, ruff + mypy puliti

Rischio residuo

  • Il fallback ("datasets",) per repo senza sezioni mantiene la compat con il vecchio default — un repo senza dataset.yml ma con dir datasets/ vuota lo usa comunque.
  • open-conto-annuale è su branch pre-migrazione (layout anagrafica/): la scoperta lo vede già; dopo il merge della sua PR Ridurre il surface area del toolkit e consolidare il contract runtime #3 sarà datasets/+support/nessuna modifica al toolkit necessaria (è il punto della PR).

Follow-up

Nessuno obbligatorio. Con questa PR, il toolkit scopre i layout senza conoscerli — il pattern si applica a qualsiasi repo futuro.

Sostituisce REPO_DATASET_DIRS (mappa hardcoded repo→dirs) con una
scoperta per convenzione: una dir di primo livello del repo è una sezione
dati se contiene {slug}/dataset.yml. Vale per qualsiasi layout presente
e futuro (datasets/, support/, candidates/, compose/, ...) — un nuovo repo
con layout custom non richiede più modifiche al toolkit.

- layout.py: repo_dataset_dirs(repo_dir) scopre le sezioni, esclude dir
  nascoste (.github, .git) e templates/ (falsi positivi verificati)
- catalog.py/discovery.py: passano repo_dir invece di repo.name
- Test: 5 contract di scoperta (flat, multi-sezione, DI, esclusioni,
  default compat) — sostituiscono i 2 della vecchia mappa

Verifica: open-conto-annuale e open-siope scoprono ('datasets','support')
senza dichiarazione; 1334 test verdi, ruff+mypy puliti.
…dati

Review finding (fix-required): la scoperta per convenzione esponeva
toolkit/smoke/ come sezione dati — 6 fixture di test (bdap_ckan_csv,
bdap_http_csv, ...) comparivano nel find workspace (224 totali invece
di 218 reali).

- _EXCLUDED_SECTION_DIRS: aggiunto smoke/ (fixture di test)
- rimosso il fallback a ('datasets',): un repo senza sezioni scoperte
  NON è un repo dati → tuple vuota, il chiamante lo salta (prima 35 repo
  non-dati ricevevano il default e venivano scanditi inutilmente)
- DEFAULT_DATASET_DIRS resta solo come default del dataclass RepoLayout
  (builder con layout esplicito)

Test: test_excludes_templates_and_hidden ora include smoke/;
test_no_sections_returns_default → test_no_sections_returns_empty.
Verificato: find workspace 224→218 (6 smoke rimossi), 1334 verdi,
ruff+mypy puliti.
…overy

Due fix collegati, chiudono il finding monthly HDD:

1. _scan_workspace_configs: slug da dataset.name (chiave canonica, come
   load_manifest) invece di data['slug'] or dir_slug — 22/188 dataset
   avevano slug dalla dir (es. 'precipitazioni' vs 'precipitazioni_bologna',
   'anag-enti' vs 'ca_anag_enti_seed'). data['slug'] top-level è morto (0 usi).

2. resolve_config_path Stage 4: fallback alla mappa slug→config_path di
   _scan_workspace_configs quando la ricerca per dir fallisce (dir
   totalmente diversa dallo slug, o senza dir locale — monthly HDD).

Test: +3 (slug da dataset.name, fallback dir senza name, resolve dir≠slug
via mappa). Verificato: tutti i casi risolvono (precipitazioni_bologna,
ca_anag_enti_seed, siope_anag_enti_seed, chddr2_m senza dir locale).
1337 verdi, ruff+mypy puliti.
@Gabrymi93

Copy link
Copy Markdown
Member Author

Completamento finding monthly HDD (commit 1fd7ecb)

La review aveva sollevato: il fix #460 copriva solo dir=slug-hyphen, non dir totalmente diverse dallo slug (monthly HDD, seed anag-*).

Fix root in 2 punti (unico contratto: dataset.name è la chiave canonica):

  1. _scan_workspace_configs: slug da dataset.name (come load_manifest) invece di data['slug'] or dir_slug. Prima 22/188 dataset avevano slug dalla dir (es. precipitazioni vs precipitazioni_bologna, anag-enti vs ca_anag_enti_seed). Il campo top-level slug era morto (0 utilizzi nel workspace).

  2. resolve_config_path Stage 4: fallback alla mappa slug→config_path dello scan quando la ricerca per dir fallisce — copre dir completamente diverse (seed) e slug senza dir locale (monthly HDD).

Verificato (tutti risolvono):

  • precipitazioni_bologna (dir precipitazioni) ✅
  • ca_anag_enti_seed (dir anag-enti) ✅
  • siope_anag_enti_seed (dir anag-enti) ✅
  • eurostat_nrg_chddr2_m_nuts3 (senza dir locale nel workspace) ✅ via mappa scan

Test: +3 (slug da dataset.name, fallback dir senza name, resolve dir≠slug via mappa). 1337 verdi, ruff+mypy puliti, CI completa verde.

Risponde alla domanda architetturale: lo slug del dataset (dataset.name) è la fonte, la cartella è solo un contenitore — ora entrambi i percorsi (scan + discovery CLI) usano lo stesso contratto.

@Gabrymi93
Gabrymi93 merged commit a288837 into main Aug 9, 2026
3 checks passed
@Gabrymi93
Gabrymi93 deleted the feat/discover-dataset-sections branch August 9, 2026 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant