Skip to main content

Noria

SQL-first data pipeline framework
Jinja2 templating · multi-base de données · monitoring intégré

PyPI Python MIT


"Noria" — la roue hydraulique qui fait circuler l'eau avec précision et régularité.
Ici, vos données circulent avec la même fiabilité.


Pourquoi Noria ?

Besoin Solution Noria
Écrire du SQL, pas du Python ORM Templates Jinja2 directement dans vos fichiers .sql
Changer de BDD sans tout réécrire Macros cross-DB compilées selon le dialecte cible
Orchestrer des dépendances entre requêtes DAG déclaratif en YAML, exécution parallèle
Voir ce qui se passe Dashboard de monitoring intégré, historique SQLite
Démarrer en 2 minutes pip install noria && noria init mon_projet && noria run

Installation

Noria s'installe dans un environnement Python : un dossier de travail qui contiendra Noria et vos projets.

# Installer uv (une seule fois sur votre machine)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Créer votre espace de travail et y installer Noria
mkdir data_projets && cd data_projets
uv venv                          # crée l'environnement Python (.venv)
source .venv/bin/activate        # l'active (à refaire à chaque nouveau terminal)
uv pip install noria

noria version                    # vérification : affiche la version installée

Sans uv : python3 -m venv .venv && source .venv/bin/activate && pip install noria fait exactement la même chose.

« noria : commande introuvable » ? L'environnement n'est pas activé : relancez source .venv/bin/activate depuis le dossier data_projets.


Démarrage rapide

noria init mon_pipeline          # Noria pose quelques questions (base de données…)
                                 # Entrée pour garder les valeurs par défaut
cd mon_pipeline
noria run                        # exécute le pipeline d'exemple

Organisation générée :

data_projets/            ← espace de travail (environnement Python)
├── .venv/               ← Noria installé ici
└── mon_pipeline/        ← votre projet Noria
    ├── noria.yml
    ├── envs/
    └── sql/

Pour un deuxième projet : revenez dans data_projets, puis noria init autre_projet.


Structure d'un projet Noria

mon_pipeline/
├── noria.yml                  # Configuration du pipeline
├── sql/
│   ├── macros/                # Macros Jinja2 réutilisables
│   │   └── utils.sql.j2
│   ├── 01_clients.sql         # Requêtes SQL avec templates Jinja2
│   └── 02_rapport.sql
├── params/
│   └── prod.yml               # Paramètres par environnement
└── .noria/
    ├── data.db                # Base DuckDB locale (développement)
    └── tracking.db            # Historique des exécutions

Configuration — noria.yml

name: mon_pipeline
description: "Pipeline de données clients"

database:
  dialect: duckdb          # duckdb | postgresql
  database: .noria/data.db

params:
  date_min: "2024-01-01"
  schema: main

monitoring:
  enabled: true
  port: 7070

tasks:
  clients_actifs:
    sql: sql/01_clients.sql
    target: "{{ params.schema }}.clients_actifs"
    write_mode: replace        # replace | append | truncate | merge
    active: true
    description: "Clients avec au moins une commande"

  rapport:
    sql: sql/02_rapport.sql
    target: "{{ params.schema }}.rapport"
    write_mode: replace
    depends_on:
      - clients_actifs          # exécuté après clients_actifs
    pre_hook:
      file: sql/hooks/pre_rapport.sql
    post_hook:
      file: sql/hooks/post_rapport.sql

Écrire du SQL avec Jinja2

-- sql/01_clients.sql

SELECT
    {{ cast('id', 'VARCHAR') }}             AS id_client,  -- adapté au dialecte
    first_name || ' ' || last_name          AS nom,
    {{ date_trunc('month', 'created_at') }} AS mois_inscription,
    {{ coalesce('phone', "'N/A'") }}        AS telephone

FROM source_schema.customers
WHERE created_at >= '{{ params.date_min }}'

{% if params.actif_only %}
  AND actif = TRUE
{% endif %}

Macros cross-base de données

Macro Jinja2 PostgreSQL compilé DuckDB compilé
{{ cast('id', 'TEXT') }} id::TEXT CAST(id AS TEXT)
{{ date_trunc('month', 'ts') }} DATE_TRUNC('month', ts) DATE_TRUNC('month', ts)
{{ current_timestamp() }} NOW() CURRENT_TIMESTAMP
{{ concat('a', 'b') }} CONCAT(a, b) CONCAT(a, b)
{{ coalesce('a', '0') }} COALESCE(a, 0) COALESCE(a, 0)
{{ safe_divide('num', 'den') }} CASE WHEN den=0 THEN NULL... CASE WHEN den=0 THEN NULL...
{{ to_char('ts', 'YYYY-MM') }} TO_CHAR(ts, 'YYYY-MM') STRFTIME(ts, 'YYYY-MM')
{{ limit(10) }} LIMIT 10 LIMIT 10
{{ schema_table('s', 't') }} s.t s.t

Macros personnalisées

Créez vos propres macros dans sql/macros/*.sql.j2 :

{# sql/macros/utils.sql.j2 #}
{% macro panier_moyen(montant, quantite) %}
  {{ safe_divide(montant, quantite) }}
{% endmacro %}

Puis utilisez-les dans n'importe quel fichier SQL :

{% from 'utils.sql.j2' import panier_moyen %}
SELECT {{ panier_moyen('SUM(amount)', 'COUNT(id)') }} AS panier_moyen
FROM orders

Modes d'écriture (write_mode)

Mode Comportement
replace DROP TABLE + CREATE TABLE AS SELECT
append INSERT INTO ... SELECT
truncate TRUNCATE + INSERT
merge INSERT ON CONFLICT (nécessite merge_key)
create_if_not_exists Crée seulement si absente

CLI — Commandes

noria init <nom>          # Initialiser un projet
noria validate            # Valider config + DAG (sans connexion BDD)
noria compile             # Prévisualiser le SQL compilé
noria compile -t ma_tache # Compiler une seule tâche
noria run                 # Lancer tout le pipeline
noria run -t tache_a      # Lancer une tâche spécifique
noria run --dry-run       # Compiler sans exécuter
noria run --workers 8     # Parallélisme (défaut: 4)
noria run --param date_min=2024-06-01  # Surcharger un paramètre
noria tasks               # Lister les tâches et dépendances
noria status              # Voir l'historique des exécutions
noria monitor             # Ouvrir le dashboard web

Paramétrage par environnement

# Développement (défaut)
noria run

# Production via surcharge CLI
noria run --param schema=prod --param date_min=2023-01-01

# Variables d'environnement dans noria.yml
# database.password: ${DB_PASSWORD}

Hooks pre/post

tasks:
  ma_tache:
    sql: sql/ma_tache.sql
    pre_hook:
      file: sql/hooks/pre.sql     # Exécuté avant la tâche
      ignore_on_error: false
    post_hook:
      file: sql/hooks/post.sql    # Exécuté après
      ignore_on_error: true       # Erreur non bloquante

Monitoring

Le dashboard web est inclus par défaut :

noria monitor             # Ouvre http://localhost:7070
  • Historique de toutes les exécutions
  • Détail par tâche : statut, durée, lignes écrites, erreurs
  • Rafraîchissement automatique (HTMX)

L'historique est stocké localement dans .noria/tracking.db (SQLite, zéro config).


API Python

from noria.core.pipeline import Pipeline

# Lancer le pipeline
pipeline = Pipeline("./mon_projet", params_override={"schema": "staging"})
results = pipeline.run()

# Compilation uniquement
compiled_sql = pipeline.compile(task_name="ma_tache")
print(compiled_sql["ma_tache"])

# Historique
history = pipeline.history(limit=5)

Ajouter un dialecte personnalisé

from noria.adapters import register_adapter
from noria.adapters.base import BaseAdapter
from sqlalchemy import create_engine

class MyAdapter(BaseAdapter):
    dialect_name = "mydb"
    
    def create_engine(self, db_config):
        return create_engine(f"mydb://...")
    
    # ... implémenter les méthodes abstraites

register_adapter("mydb", MyAdapter)

Tests

make install-dev
make test
make test-cov   # avec rapport de couverture HTML

Contribuer

  1. Fork le dépôt
  2. make install-dev
  3. Créer une branche feature
  4. make test + make lint avant de soumettre

Licence

MIT © Noria Contributors

Metadata

Release files for noria 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for noria 0.1.2
File Size Uploaded
noria-0.1.2.tar.gz 1.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for noria 0.1.2
File Interpreter ABI Platform
noria-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 1.8 MB

Release files / noria-0.1.2.tar.gz

Download URL noria-0.1.2.tar.gz
Size 1.7 MB
Tags Source
SHA-256 checksum
How to use checksums
105e89014006e489b66bb7da2fea514b270b86a53b8f05fb7e2f121bf972a4ab
BLAKE2b-256 checksum
How to use checksums
0bdcba226ab0080421ee1cd4e3c91fc1cd72976f27a429735f6ec81aae814a9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / noria-0.1.2-py3-none-any.whl

Download URL noria-0.1.2-py3-none-any.whl
Size 98.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83a336bf0c20f2945181b38375dde23cffd7e1003f1e6ba9d7d34337eb1026d2
BLAKE2b-256 checksum
How to use checksums
414154cfc792968c81446dfcb3c10b2c230db1f0ef22945c6e669ebe7c14d474
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.0

2 release files

0.1.3

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page