noria 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- noria-0.1.0/.github/copilot-instructions.md +61 -0
- noria-0.1.0/.github/prompts/1_create_task.prompt.md +39 -0
- noria-0.1.0/.github/prompts/2_analyse_pipeline.prompt.md +27 -0
- noria-0.1.0/.github/prompts/3_debug_erreur.prompt.md +22 -0
- noria-0.1.0/.github/prompts/4_migration_etl.prompt.md +148 -0
- noria-0.1.0/.github/workflows/ci.yml +67 -0
- noria-0.1.0/.gitignore +39 -0
- noria-0.1.0/CHANGELOG.md +29 -0
- noria-0.1.0/LICENSE +21 -0
- noria-0.1.0/Makefile +35 -0
- noria-0.1.0/PKG-INFO +361 -0
- noria-0.1.0/README.md +306 -0
- noria-0.1.0/docs/adapters/bigquery.md +107 -0
- noria-0.1.0/docs/adapters/custom.md +70 -0
- noria-0.1.0/docs/adapters/duckdb.md +113 -0
- noria-0.1.0/docs/adapters/postgres.md +113 -0
- noria-0.1.0/docs/advanced/assertions.md +56 -0
- noria-0.1.0/docs/advanced/dag.md +124 -0
- noria-0.1.0/docs/advanced/freshness.md +95 -0
- noria-0.1.0/docs/advanced/notifications.md +56 -0
- noria-0.1.0/docs/advanced/scd2.md +51 -0
- noria-0.1.0/docs/advanced/seeds.md +43 -0
- noria-0.1.0/docs/index.md +60 -0
- noria-0.1.0/docs/migration/alteryx.md +104 -0
- noria-0.1.0/docs/migration/index.md +30 -0
- noria-0.1.0/docs/migration/powercenter.md +93 -0
- noria-0.1.0/docs/migration/sas.md +150 -0
- noria-0.1.0/docs/na/303/257a/analyse_pipeline.md +111 -0
- noria-0.1.0/docs/na/303/257a/create_task.md +128 -0
- noria-0.1.0/docs/na/303/257a/debug.md +192 -0
- noria-0.1.0/docs/na/303/257a/index.md +68 -0
- noria-0.1.0/docs/quickstart.md +109 -0
- noria-0.1.0/docs/reference/cli.md +78 -0
- noria-0.1.0/docs/reference/config.md +238 -0
- noria-0.1.0/docs/reference/loops.md +183 -0
- noria-0.1.0/docs/reference/macros.md +207 -0
- noria-0.1.0/docs/reference/write_modes.md +82 -0
- noria-0.1.0/examples/demo_project/noria.yml +136 -0
- noria-0.1.0/examples/demo_project/params/prod.yml +5 -0
- noria-0.1.0/examples/demo_project/sql/01_raw_customers.sql +18 -0
- noria-0.1.0/examples/demo_project/sql/02_raw_orders.sql +19 -0
- noria-0.1.0/examples/demo_project/sql/03_clients_actifs.sql +20 -0
- noria-0.1.0/examples/demo_project/sql/04_stats_mensuelles.sql +25 -0
- noria-0.1.0/examples/demo_project/sql/05_rapport_final.sql +25 -0
- noria-0.1.0/examples/demo_project/sql/06_rapport_par_region.sql +24 -0
- noria-0.1.0/examples/demo_project/sql/07_rapport_par_client.sql +21 -0
- noria-0.1.0/examples/demo_project/sql/hooks/loop_pre_region.sql +15 -0
- noria-0.1.0/examples/demo_project/sql/hooks/post_rapport.sql +15 -0
- noria-0.1.0/examples/demo_project/sql/macros/utils.sql.j2 +41 -0
- noria-0.1.0/mkdocs.yml +73 -0
- noria-0.1.0/pyproject.toml +83 -0
- noria-0.1.0/schemas/noria.schema.json +428 -0
- noria-0.1.0/site/404.html +1465 -0
- noria-0.1.0/site/adapters/bigquery/index.html +1924 -0
- noria-0.1.0/site/adapters/custom/index.html +1743 -0
- noria-0.1.0/site/adapters/duckdb/index.html +1878 -0
- noria-0.1.0/site/adapters/postgres/index.html +1880 -0
- noria-0.1.0/site/advanced/assertions/index.html +1706 -0
- noria-0.1.0/site/advanced/dag/index.html +1855 -0
- noria-0.1.0/site/advanced/freshness/index.html +1816 -0
- noria-0.1.0/site/advanced/notifications/index.html +1683 -0
- noria-0.1.0/site/advanced/scd2/index.html +1755 -0
- noria-0.1.0/site/advanced/seeds/index.html +1681 -0
- noria-0.1.0/site/assets/images/favicon.png +0 -0
- noria-0.1.0/site/assets/javascripts/bundle.d7400e89.min.js +16 -0
- noria-0.1.0/site/assets/javascripts/bundle.d7400e89.min.js.map +7 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
- noria-0.1.0/site/assets/javascripts/lunr/tinyseg.js +206 -0
- noria-0.1.0/site/assets/javascripts/lunr/wordcut.js +6708 -0
- noria-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
- noria-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
- noria-0.1.0/site/assets/stylesheets/main.ec1eaa64.min.css +1 -0
- noria-0.1.0/site/assets/stylesheets/main.ec1eaa64.min.css.map +1 -0
- noria-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
- noria-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
- noria-0.1.0/site/index.html +1698 -0
- noria-0.1.0/site/migration/alteryx/index.html +2040 -0
- noria-0.1.0/site/migration/index.html +1694 -0
- noria-0.1.0/site/migration/powercenter/index.html +1976 -0
- noria-0.1.0/site/migration/sas/index.html +2070 -0
- noria-0.1.0/site/na/303/257a/analyse_pipeline/index.html +1890 -0
- noria-0.1.0/site/na/303/257a/create_task/index.html +1830 -0
- noria-0.1.0/site/na/303/257a/debug/index.html +2066 -0
- noria-0.1.0/site/na/303/257a/index.html +1855 -0
- noria-0.1.0/site/quickstart/index.html +1795 -0
- noria-0.1.0/site/reference/cli/index.html +1828 -0
- noria-0.1.0/site/reference/config/index.html +2300 -0
- noria-0.1.0/site/reference/loops/index.html +1966 -0
- noria-0.1.0/site/reference/macros/index.html +2132 -0
- noria-0.1.0/site/reference/write_modes/index.html +1801 -0
- noria-0.1.0/site/search/search_index.json +1 -0
- noria-0.1.0/site/sitemap.xml +103 -0
- noria-0.1.0/site/sitemap.xml.gz +0 -0
- noria-0.1.0/src/noria/__init__.py +5 -0
- noria-0.1.0/src/noria/_version.py +1 -0
- noria-0.1.0/src/noria/adapters/__init__.py +45 -0
- noria-0.1.0/src/noria/adapters/base.py +170 -0
- noria-0.1.0/src/noria/adapters/bigquery_adapter.py +172 -0
- noria-0.1.0/src/noria/adapters/duckdb_adapter.py +221 -0
- noria-0.1.0/src/noria/adapters/postgres_adapter.py +202 -0
- noria-0.1.0/src/noria/cli/__init__.py +3 -0
- noria-0.1.0/src/noria/cli/app.py +570 -0
- noria-0.1.0/src/noria/config/__init__.py +14 -0
- noria-0.1.0/src/noria/config/loader.py +82 -0
- noria-0.1.0/src/noria/config/models.py +220 -0
- noria-0.1.0/src/noria/core/__init__.py +24 -0
- noria-0.1.0/src/noria/core/compiler.py +167 -0
- noria-0.1.0/src/noria/core/connection.py +89 -0
- noria-0.1.0/src/noria/core/dag.py +177 -0
- noria-0.1.0/src/noria/core/dag_view.py +186 -0
- noria-0.1.0/src/noria/core/docs_generator.py +136 -0
- noria-0.1.0/src/noria/core/executor.py +323 -0
- noria-0.1.0/src/noria/core/freshness.py +57 -0
- noria-0.1.0/src/noria/core/lineage.py +69 -0
- noria-0.1.0/src/noria/core/node.py +451 -0
- noria-0.1.0/src/noria/core/pipeline.py +226 -0
- noria-0.1.0/src/noria/core/seeds.py +83 -0
- noria-0.1.0/src/noria/core/task.py +8 -0
- noria-0.1.0/src/noria/core/tracking.py +243 -0
- noria-0.1.0/src/noria/monitoring/__init__.py +3 -0
- noria-0.1.0/src/noria/monitoring/server.py +272 -0
- noria-0.1.0/src/noria/scaffold/__init__.py +3 -0
- noria-0.1.0/src/noria/scaffold/generator.py +210 -0
- noria-0.1.0/src/noria/utils/__init__.py +29 -0
- noria-0.1.0/src/noria/utils/exceptions.py +39 -0
- noria-0.1.0/src/noria/utils/logger.py +70 -0
- noria-0.1.0/src/noria/utils/notifications.py +63 -0
- noria-0.1.0/src/noria/utils/run_status.py +47 -0
- noria-0.1.0/tests/__init__.py +0 -0
- noria-0.1.0/tests/conftest.py +82 -0
- noria-0.1.0/tests/test_compiler.py +259 -0
- noria-0.1.0/tests/test_config.py +76 -0
- noria-0.1.0/tests/test_dag.py +101 -0
- noria-0.1.0/tests/test_executor.py +276 -0
- noria-0.1.0/tests/test_loop.py +295 -0
- noria-0.1.0/tests/test_new_features.py +372 -0
- noria-0.1.0/tests/test_pipeline.py +82 -0
- noria-0.1.0/tests/test_tracking.py +73 -0
- noria-0.1.0/uv.lock +2941 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Instructions NAÏA (Noria AI Assistant) — Framework Noria
|
|
2
|
+
|
|
3
|
+
## Contexte
|
|
4
|
+
|
|
5
|
+
Ce projet utilise le framework **Noria**, un pipeline SQL-first basé sur Jinja2, DuckDB, SQLAlchemy et Typer.
|
|
6
|
+
|
|
7
|
+
## Structure d'un projet Noria
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
mon_projet/
|
|
11
|
+
├── noria.yml # configuration principale
|
|
12
|
+
├── sql/
|
|
13
|
+
│ ├── macros/ # macros Jinja2 auto-chargées
|
|
14
|
+
│ ├── seeds/ # fichiers CSV/Parquet (task_type: seed)
|
|
15
|
+
│ └── *.sql # requêtes des tâches
|
|
16
|
+
└── .noria/
|
|
17
|
+
├── .env # secrets (auto-chargé)
|
|
18
|
+
└── tracking.db # historique des exécutions
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Règles importantes
|
|
22
|
+
|
|
23
|
+
1. **Macros cross-DB** : utiliser `{{ cast() }}`, `{{ date_trunc() }}`, `{{ safe_divide() }}` plutôt que SQL dialectal.
|
|
24
|
+
2. **Paramètres** : accéder via `{{ params.nom }}` dans le SQL.
|
|
25
|
+
3. **Macros utilisateur** : définies dans `sql/macros/*.sql` ou `*.sql.j2`, auto-importées.
|
|
26
|
+
4. **Cible dynamique** : `target: "{{ params.schema }}.{{ params.table }}"` est compilé par tâche.
|
|
27
|
+
5. **Types de tâches** : `sql` (défaut), `assert` (qualité — échoue si SELECT retourne des lignes), `seed` (chargement fichier).
|
|
28
|
+
6. **Boucles** : `loop:` (liste statique), `loop_from_query:` (SQL), contexte `{{ loop.index }}`, `{{ loop.first }}`, `{{ loop.last }}`.
|
|
29
|
+
|
|
30
|
+
## Commandes utiles
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
noria validate # valider la config
|
|
34
|
+
noria compile --task nom # prévisualiser le SQL compilé
|
|
35
|
+
noria run --dry-run # simuler sans exécuter
|
|
36
|
+
noria dag # cartographie visuelle
|
|
37
|
+
noria docs # documentation HTML
|
|
38
|
+
noria run --only-tags daily # filtrer par tag
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Réécriture ETL → Noria
|
|
42
|
+
|
|
43
|
+
L'architecture Noria (tâches SQL, modes d'écriture, boucles, dépendances, paramètres) couvre nativement les mêmes besoins que les outils ETL graphiques. Un développeur peut réécrire un traitement existant en Noria sans changer de paradigme.
|
|
44
|
+
|
|
45
|
+
| Concept ETL | Équivalent Noria |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Mapping / Workflow | Tâche SQL + `depends_on:` |
|
|
48
|
+
| Update Strategy (I/U/D) | `write_mode: replace / merge / update / scd2` |
|
|
49
|
+
| Parameter File | `params:` + `--params-file` |
|
|
50
|
+
| Boucle / Batch Macro | `loop:` ou `loop_from_query:` |
|
|
51
|
+
| Pre/Post SQL | `pre_hook:` / `post_hook:` |
|
|
52
|
+
| Reprise sur erreur | `retry: N` + `retry_delay_s: N` |
|
|
53
|
+
|
|
54
|
+
Pour réécrire un traitement, utilise le prompt NAÏA : `.github/prompts/4_migration_etl.prompt.md`
|
|
55
|
+
Documentation complète : `docs/migration/`
|
|
56
|
+
|
|
57
|
+
## Ne pas faire
|
|
58
|
+
|
|
59
|
+
- Ne pas utiliser `CAST(col AS TYPE)` directement — utiliser `{{ cast('col', 'TYPE') }}`.
|
|
60
|
+
- Ne pas hardcoder les noms de schéma — utiliser `{{ params.schema }}`.
|
|
61
|
+
- Ne pas créer de tâche sans `description:` (bonne pratique).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# NAÏA — Créer une tâche Noria
|
|
2
|
+
|
|
3
|
+
Tu es NAÏA (Noria AI Assistant), un assistant expert du framework Noria. Aide l'utilisateur à créer une nouvelle tâche dans `noria.yml`.
|
|
4
|
+
|
|
5
|
+
## Contexte Noria
|
|
6
|
+
|
|
7
|
+
- Chaque tâche a un nom unique, un fichier SQL (`sql:`), une table cible (`target:`), et un mode d'écriture (`write_mode:`).
|
|
8
|
+
- Les modes d'écriture disponibles : `replace`, `append`, `truncate`, `merge`, `create_if_not_exists`, `safe_replace`, `incremental`, `scd2`, `update`.
|
|
9
|
+
- Les types de tâches : `sql` (défaut), `assert` (qualité), `seed` (load_orders fichier), `snapshot`.
|
|
10
|
+
- Les macros SQL cross-DB : `{{ cast('col', 'TYPE') }}`, `{{ date_trunc('month', 'col') }}`, `{{ safe_divide(a, b) }}`, `{{ current_timestamp() }}`.
|
|
11
|
+
- Les boucles permettent de répéter une tâche sur une liste ou une requête SQL (`loop:` / `loop_from_query:`).
|
|
12
|
+
- Les dépendances s'expriment avec `depends_on: [tâche1, tâche2]`.
|
|
13
|
+
|
|
14
|
+
## Instruction
|
|
15
|
+
|
|
16
|
+
L'utilisateur va décrire ce qu'il veut faire. Tu dois :
|
|
17
|
+
1. Poser les questions nécessaires pour compléter la configuration.
|
|
18
|
+
2. Générer le bloc YAML de la tâche.
|
|
19
|
+
3. Générer le fichier SQL associé avec les macros appropriées.
|
|
20
|
+
|
|
21
|
+
## Format de réponse
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
# noria.yml — section tasks
|
|
25
|
+
tasks:
|
|
26
|
+
nom_de_la_tache:
|
|
27
|
+
sql: sql/nom_de_la_tache.sql
|
|
28
|
+
target: "{{ params.schema }}.nom_de_la_tache"
|
|
29
|
+
write_mode: replace
|
|
30
|
+
description: "Description claire de ce que fait la tâche"
|
|
31
|
+
tags: [tag1, tag2]
|
|
32
|
+
depends_on: []
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
-- sql/nom_de_la_tache.sql
|
|
37
|
+
SELECT ...
|
|
38
|
+
FROM {{ params.schema }}.table_source
|
|
39
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# NAÏA — Analyser un pipeline Noria
|
|
2
|
+
|
|
3
|
+
Tu es NAÏA (Noria AI Assistant), un assistant expert du framework Noria. Analyse le pipeline décrit par l'utilisateur.
|
|
4
|
+
|
|
5
|
+
## Ce que tu peux analyser
|
|
6
|
+
|
|
7
|
+
1. **DAG et dépendances** : identifier les tâches racines, les chemins critiques, les tâches orphelines.
|
|
8
|
+
2. **Modes d'écriture** : vérifier la cohérence (ex: merge sans merge_key, incremental sans incremental_key).
|
|
9
|
+
3. **SQL qualité** : repérer les JOINs sans condition, les SELECT *, les divisions sans protection.
|
|
10
|
+
4. **Performance** : tâches pouvant être parallélisées, loops qui pourraient bénéficier de `loop_parallel: true`.
|
|
11
|
+
5. **Robustesse** : tâches sans retry, sans timeout, sans ignore_on_error sur des tâches non critiques.
|
|
12
|
+
|
|
13
|
+
## Instructions
|
|
14
|
+
|
|
15
|
+
1. Lis le `noria.yml` fourni.
|
|
16
|
+
2. Pour chaque problème trouvé, donne : la tâche concernée, le problème, et la correction proposée.
|
|
17
|
+
3. Propose les améliorations en priorité : critique > important > suggestion.
|
|
18
|
+
|
|
19
|
+
## Format de réponse
|
|
20
|
+
|
|
21
|
+
### Analyse du pipeline `{nom}`
|
|
22
|
+
|
|
23
|
+
| Priorité | Tâche | Problème | Correction |
|
|
24
|
+
|----------|-------|----------|------------|
|
|
25
|
+
| 🔴 Critique | ... | ... | ... |
|
|
26
|
+
| 🟡 Important | ... | ... | ... |
|
|
27
|
+
| 🟢 Suggestion | ... | ... | ... |
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# NAÏA — Déboguer une erreur Noria
|
|
2
|
+
|
|
3
|
+
Tu es NAÏA (Noria AI Assistant), un assistant expert du framework Noria. Aide l'utilisateur à diagnostiquer et résoudre une erreur.
|
|
4
|
+
|
|
5
|
+
## Erreurs fréquentes et solutions
|
|
6
|
+
|
|
7
|
+
| Erreur | Cause probable | Solution |
|
|
8
|
+
|--------|---------------|----------|
|
|
9
|
+
| `CompilationError: undefined variable` | Variable Jinja2 non définie | Ajouter la variable dans `params:` ou vérifier le nom |
|
|
10
|
+
| `ExecutionError: safe_replace guard` | SELECT renvoie moins de lignes que `safe_replace_min_rows` | Vérifier la requête ou baisser `safe_replace_min_rows` |
|
|
11
|
+
| `DependencyError: cycle detected` | Cycle dans `depends_on` | Visualiser avec `noria dag` et corriger |
|
|
12
|
+
| `TaskError: timed out` | Tâche dépasse `timeout:` secondes | Augmenter `timeout:` ou optimiser la requête |
|
|
13
|
+
| `ExecutionError: assert FAILED` | Assertion qualité échouée | Vérifier les données — des violations ont été trouvées |
|
|
14
|
+
| `ConfigError: merge_key required` | `write_mode: merge` sans `merge_key` | Ajouter `merge_key: [col1]` |
|
|
15
|
+
| `Seed file not found` | `seed_file:` pointe vers un fichier absent | Vérifier le chemin relatif depuis la racine du projet |
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
1. Demande à l'utilisateur de coller le message d'erreur complet.
|
|
20
|
+
2. Identifie la cause dans le tableau ci-dessus ou par analyse.
|
|
21
|
+
3. Propose une solution concrète avec le code corrigé.
|
|
22
|
+
4. Si le problème est dans le SQL, propose de vérifier avec `noria compile --task nom_tache`.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# NAÏA — Réécrire un traitement ETL en Noria
|
|
2
|
+
|
|
3
|
+
Tu es NAÏA (Noria AI Assistant). Tu aides le développeur à **réécrire** un traitement ETL existant (PowerCenter, Alteryx, SAS, Talend) en tâches Noria.
|
|
4
|
+
|
|
5
|
+
> **Principe** : Noria ne migre pas automatiquement. C'est son architecture (tâches SQL, modes d'écriture, boucles, dépendances, paramètres) qui est conçue pour couvrir nativement les mêmes besoins que les outils ETL graphiques. Le développeur garde le contrôle du SQL — il remplace les boîtes graphiques par des requêtes lisibles et versionnables.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Correspondances PowerCenter → Noria
|
|
10
|
+
|
|
11
|
+
| Concept PowerCenter | Équivalent Noria | Notes |
|
|
12
|
+
|---------------------|-----------------|-------|
|
|
13
|
+
| Mapping | Fichier SQL + tâche `sql:` | 1 mapping = 1 à N tâches selon la complexité |
|
|
14
|
+
| Session | Tâche avec `write_mode:` | La stratégie de load_orders est dans `write_mode` |
|
|
15
|
+
| Workflow | Pipeline (`noria.yml`) | L'ordonnancement = `depends_on:` |
|
|
16
|
+
| Source Qualifier | `FROM {{ params.schema }}.table` | Le filtre source va dans `WHERE` |
|
|
17
|
+
| Expression Transformation | Colonnes calculées dans `SELECT` | Utiliser `{{ cast() }}`, `{{ safe_divide() }}` |
|
|
18
|
+
| Aggregator | `GROUP BY` | Direct en SQL |
|
|
19
|
+
| Lookup Transformation | `LEFT JOIN` ou sous-requête | Pas de cache lookup séparé |
|
|
20
|
+
| Router | Plusieurs tâches avec `WHERE` différents | 1 branche = 1 tâche |
|
|
21
|
+
| Joiner | `JOIN` | Standard SQL |
|
|
22
|
+
| Filter | `WHERE` | Standard SQL |
|
|
23
|
+
| Union | `UNION ALL` | Standard SQL |
|
|
24
|
+
| Sorter | `ORDER BY` | Standard SQL |
|
|
25
|
+
| Update Strategy (Insert only) | `write_mode: replace` ou `append` | |
|
|
26
|
+
| Update Strategy (Update) | `write_mode: update` + `update_key:` | |
|
|
27
|
+
| Update Strategy (Upsert) | `write_mode: merge` + `merge_key:` | |
|
|
28
|
+
| Update Strategy (Delete+Insert) | `write_mode: incremental` + `incremental_key:` | |
|
|
29
|
+
| SCD Type 2 | `write_mode: scd2` + `scd2_key:` | Colonnes _valid_from/_valid_to/_is_current gérées |
|
|
30
|
+
| Sequence Generator | `ROW_NUMBER() OVER (...)` en SQL | |
|
|
31
|
+
| Parameter ($Param) | `{{ params.nom }}` dans le SQL | |
|
|
32
|
+
| Parameter File | `--params-file prod.yml` en CLI | |
|
|
33
|
+
| Mapping Parameter | `params:` dans la tâche | |
|
|
34
|
+
| Pre/Post SQL | `pre_hook:` / `post_hook:` | |
|
|
35
|
+
| Worklet | Groupe de tâches avec `depends_on:` | |
|
|
36
|
+
| Concurrent sessions | `loop_parallel: true` ou DAG parallèle | |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Correspondances Alteryx → Noria
|
|
41
|
+
|
|
42
|
+
| Outil Alteryx | Équivalent Noria | Notes |
|
|
43
|
+
|---------------|-----------------|-------|
|
|
44
|
+
| Input Data Tool | `FROM {{ params.schema }}.table` | |
|
|
45
|
+
| Select Tool | Colonnes dans `SELECT`, alias | |
|
|
46
|
+
| Filter Tool | `WHERE` | |
|
|
47
|
+
| Join Tool | `INNER JOIN` / `LEFT JOIN` | |
|
|
48
|
+
| Union Tool | `UNION ALL` | |
|
|
49
|
+
| Summarize Tool | `GROUP BY` + fonctions d'agrégat | |
|
|
50
|
+
| Formula Tool | Colonnes calculées | `{{ cast() }}`, `CASE WHEN`, etc. |
|
|
51
|
+
| Multi-Row Formula | `LAG()`, `LEAD()`, `ROW_NUMBER() OVER (...)` | |
|
|
52
|
+
| Running Total | `SUM() OVER (ORDER BY ...)` | |
|
|
53
|
+
| Sort Tool | `ORDER BY` | |
|
|
54
|
+
| Sample Tool | `LIMIT N` ou `{{ limit(n) }}` | |
|
|
55
|
+
| Unique Tool | `SELECT DISTINCT` | |
|
|
56
|
+
| Transpose | `UNPIVOT` (DuckDB) | |
|
|
57
|
+
| Cross Tab | `PIVOT` (DuckDB) | |
|
|
58
|
+
| Output Data Tool | `target:` + `write_mode:` | |
|
|
59
|
+
| Macro (Standard) | Macro Jinja2 dans `sql/macros/` | |
|
|
60
|
+
| App Parameter | `{{ params.nom }}` | |
|
|
61
|
+
| Batch Macro | `loop:` ou `loop_from_query:` | |
|
|
62
|
+
| Container (groupement) | Tags (`tags:`) + `depends_on:` | |
|
|
63
|
+
| Test Tool | `task_type: assert` | |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Correspondances SAS → Noria
|
|
68
|
+
|
|
69
|
+
| Concept SAS | Équivalent Noria | Notes |
|
|
70
|
+
|-------------|-----------------|-------|
|
|
71
|
+
| LIBNAME | `{{ params.schema }}.` | |
|
|
72
|
+
| DATA step (SET) | `SELECT * FROM source` | |
|
|
73
|
+
| DATA step (calculs) | Colonnes calculées dans `SELECT` | |
|
|
74
|
+
| DATA step (IF/THEN) | `CASE WHEN` | |
|
|
75
|
+
| DATA step (RETAIN) | Fonctions fenêtre `SUM() OVER (...)` | |
|
|
76
|
+
| PROC SQL | SQL direct (natif dans Noria) | |
|
|
77
|
+
| PROC SORT | `ORDER BY` | |
|
|
78
|
+
| PROC MEANS | `SELECT AVG(), MIN(), MAX(), ...` + `GROUP BY` | |
|
|
79
|
+
| PROC FREQ | `SELECT col, COUNT(*) GROUP BY col` | |
|
|
80
|
+
| PROC TRANSPOSE | `PIVOT` (DuckDB) ou CASE WHEN | |
|
|
81
|
+
| PROC APPEND | `write_mode: append` | |
|
|
82
|
+
| PROC DELETE | `write_mode: replace` (vide puis recharge) | |
|
|
83
|
+
| Macro variable (¶m) | `{{ params.nom }}` | |
|
|
84
|
+
| %LET / %GLOBAL | `params:` dans noria.yml | |
|
|
85
|
+
| %INCLUDE | Macro Jinja2 ou `{% include %}` | |
|
|
86
|
+
| %DO %TO (boucle) | `loop:` (liste) ou `loop_from_query:` | |
|
|
87
|
+
| Formats | `CASE WHEN` ou macro utilisateur | |
|
|
88
|
+
| BY group processing | `PARTITION BY` dans les fonctions fenêtre | |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Instructions pour la réécriture
|
|
93
|
+
|
|
94
|
+
1. L'utilisateur décrit ou colle le traitement source (pseudocode, description métier, ou extrait du code/mapping).
|
|
95
|
+
2. Tu identifies :
|
|
96
|
+
- Les **sources** (tables, fichiers)
|
|
97
|
+
- Les **transformations** (calculs, jointures, agrégations, filtres)
|
|
98
|
+
- La **stratégie de load_orders** (insert, update, upsert, historisation)
|
|
99
|
+
- Le **séquencement** (étapes dépendantes ou parallélisables)
|
|
100
|
+
3. Tu génères :
|
|
101
|
+
- Le bloc YAML des tâches dans `noria.yml`
|
|
102
|
+
- Les fichiers SQL avec macros cross-DB
|
|
103
|
+
- Les macros métier réutilisables dans `sql/macros/` si pertinent
|
|
104
|
+
4. Tu signales ce qui nécessite attention (logique métier complexe, connecteurs propriétaires non reproductibles en SQL pur).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Format de réponse
|
|
109
|
+
|
|
110
|
+
### Analyse du traitement source
|
|
111
|
+
|
|
112
|
+
**Outil d'origine :** PowerCenter / Alteryx / SAS
|
|
113
|
+
**Sources :** liste des tables/fichiers en entrée
|
|
114
|
+
**Cible :** table résultat
|
|
115
|
+
**Stratégie de load_orders :** replace / merge / scd2 / etc.
|
|
116
|
+
**Étapes identifiées :** N
|
|
117
|
+
|
|
118
|
+
### Tâches Noria
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
tasks:
|
|
122
|
+
etape_1:
|
|
123
|
+
sql: sql/etape_1.sql
|
|
124
|
+
target: "{{ params.schema }}.etape_1"
|
|
125
|
+
write_mode: replace
|
|
126
|
+
description: "..."
|
|
127
|
+
|
|
128
|
+
resultat_final:
|
|
129
|
+
sql: sql/resultat_final.sql
|
|
130
|
+
target: "{{ params.schema }}.resultat"
|
|
131
|
+
write_mode: merge
|
|
132
|
+
merge_key: [id]
|
|
133
|
+
depends_on: [etape_1]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```sql
|
|
137
|
+
-- sql/etape_1.sql
|
|
138
|
+
SELECT
|
|
139
|
+
id,
|
|
140
|
+
{{ cast('montant', 'DECIMAL(18,2)') }} AS montant,
|
|
141
|
+
{{ date_trunc('month', 'date_op') }} AS mois
|
|
142
|
+
FROM {{ params.schema }}.source_brute
|
|
143
|
+
WHERE statut = 'actif'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Points d'attention
|
|
147
|
+
- Ce qui a été simplifié ou adapté par rapport à l'original
|
|
148
|
+
- Ce qui nécessite une vérification manuelle (règles métier complexes, etc.)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Tests (${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
run: pip install uv
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv pip install -e ".[dev]" --system
|
|
31
|
+
|
|
32
|
+
- name: Lint (ruff)
|
|
33
|
+
run: ruff check src/ tests/
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: pytest -q --cov=src/noria --cov-report=xml
|
|
37
|
+
|
|
38
|
+
- name: Upload coverage
|
|
39
|
+
if: matrix.python-version == '3.12'
|
|
40
|
+
uses: codecov/codecov-action@v4
|
|
41
|
+
with:
|
|
42
|
+
file: coverage.xml
|
|
43
|
+
|
|
44
|
+
publish:
|
|
45
|
+
name: Publish to PyPI
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
needs: test
|
|
48
|
+
if: github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'release:')
|
|
49
|
+
permissions:
|
|
50
|
+
id-token: write
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- name: Set up Python
|
|
56
|
+
uses: actions/setup-python@v5
|
|
57
|
+
with:
|
|
58
|
+
python-version: "3.12"
|
|
59
|
+
|
|
60
|
+
- name: Install build tools
|
|
61
|
+
run: pip install build
|
|
62
|
+
|
|
63
|
+
- name: Build package
|
|
64
|
+
run: python -m build
|
|
65
|
+
|
|
66
|
+
- name: Publish to PyPI
|
|
67
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
noria-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
*.egg
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# Noria runtime
|
|
17
|
+
.noria/
|
|
18
|
+
*.db
|
|
19
|
+
|
|
20
|
+
# Tests
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.ruff_cache/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
|
|
27
|
+
# Editors
|
|
28
|
+
.idea/
|
|
29
|
+
.vscode/
|
|
30
|
+
*.swp
|
|
31
|
+
*.swo
|
|
32
|
+
|
|
33
|
+
# OS
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
|
|
37
|
+
# Env
|
|
38
|
+
.env
|
|
39
|
+
.env.*
|
noria-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Noria are documented here.
|
|
4
|
+
|
|
5
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
6
|
+
Versioning: [Semantic Versioning](https://semver.org/)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.1.0] — 2026-09-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial release of the Noria framework
|
|
14
|
+
- **SQL-first pipeline engine** — Jinja2 templating in `.sql` files
|
|
15
|
+
- **Multi-database adapters** — DuckDB (default) and PostgreSQL
|
|
16
|
+
- **Cross-DB macro system** — `cast`, `date_trunc`, `current_timestamp`, `concat`, `coalesce`, `safe_divide`, `to_char`, `limit`, `schema_table`
|
|
17
|
+
- **DAG orchestrator** — topological sort, parallel task execution (configurable thread pool)
|
|
18
|
+
- **Write modes** — `replace`, `append`, `truncate`, `merge`, `create_if_not_exists`
|
|
19
|
+
- **Pre/post hooks** — SQL files executed before/after each task
|
|
20
|
+
- **Built-in monitoring dashboard** — FastAPI + HTMX, auto-refresh, run history
|
|
21
|
+
- **SQLite run tracker** — embedded, zero-config execution history
|
|
22
|
+
- **Pydantic v2 config** — strict validation of `noria.yml`
|
|
23
|
+
- **CLI** (`typer`) — `init`, `validate`, `compile`, `run`, `run-task`, `tasks`, `status`, `monitor`
|
|
24
|
+
- **Project scaffolding** — `noria init <name>` generates a ready-to-use project
|
|
25
|
+
- **Parameter system** — global params, task-level overrides, CLI overrides, env vars
|
|
26
|
+
- **Comprehensive test suite** — pytest, 40+ tests covering all components
|
|
27
|
+
- **Demo project** — e-commerce pipeline with 5 tasks and macros examples
|
|
28
|
+
|
|
29
|
+
[0.1.0]: https://github.com/your-org/noria/releases/tag/v0.1.0
|
noria-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Noria Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
noria-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.PHONY: install install-dev test lint format typecheck demo clean
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
pip install -e .
|
|
5
|
+
|
|
6
|
+
install-dev:
|
|
7
|
+
pip install -e ".[dev]"
|
|
8
|
+
pre-commit install
|
|
9
|
+
|
|
10
|
+
test:
|
|
11
|
+
pytest tests/ -v
|
|
12
|
+
|
|
13
|
+
test-cov:
|
|
14
|
+
pytest tests/ --cov=src/noria --cov-report=html --cov-report=term-missing
|
|
15
|
+
|
|
16
|
+
lint:
|
|
17
|
+
ruff check src/ tests/
|
|
18
|
+
|
|
19
|
+
format:
|
|
20
|
+
ruff format src/ tests/
|
|
21
|
+
|
|
22
|
+
typecheck:
|
|
23
|
+
mypy src/noria/
|
|
24
|
+
|
|
25
|
+
demo:
|
|
26
|
+
cd examples/demo_project && noria run --verbose
|
|
27
|
+
|
|
28
|
+
demo-monitor:
|
|
29
|
+
cd examples/demo_project && noria monitor --open
|
|
30
|
+
|
|
31
|
+
clean:
|
|
32
|
+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
|
33
|
+
find . -type d -name .noria -exec rm -rf {} + 2>/dev/null || true
|
|
34
|
+
find . -name "*.db" -delete 2>/dev/null || true
|
|
35
|
+
rm -rf build/ dist/ *.egg-info/ .coverage htmlcov/
|