Module Loading - Système de Namespaces

Catnip permet de charger des modules Python pour étendre ses fonctionnalités avec un système de namespaces propres.

Philosophie

Les modules sont chargés comme objets namespace (module.function()) au lieu de polluer l'espace global. C'est plus propre, plus pythonique, et évite les conflits.

Les namespaces sont des compartiments pressurisés pour imports.

Syntaxe

catnip -f <target>[:alias] script.cat
Format Description Exemple
-f module Module Python installé -f math
-f ./file.py Fichier Python local -f ./host.py
-f ./file.cat Fichier Catnip local -f ./math.cat
-f module:alias Module avec alias -f math:m
-f ./file.py:alias Fichier avec alias -f ./host.py:api
-f ./file.cat:alias Fichier Catnip avec alias -f ./math.cat:m
-f module:! Injection directe (global) -f math:!

Exemples de Base

Module Python installé

catnip -f math -c "math.sqrt(16)"
# → 4.0

Module avec alias

catnip -f math:m -c "m.sqrt(25)"
# → 5.0

Fichier Python local

Le fichier host.py :

def double(x):
    return x * 2

def greet(name):
    return f"Hello, {name}!"
catnip -f ./host.py -c "host.double(21)"
# → 42

Fichier Catnip local

Le fichier math.cat :

double = (x) => { x * 2 }
triple = (x) => { x * 3 }
catnip -f ./math.cat -c "math.double(21)"
# → 42

Si __all__ est défini dans le module Catnip, seuls ces symboles sont exportés. Sinon, les noms publics ajoutés par le module sont exposés.

Fichier avec alias

catnip -f ./host.py:api -c "api.double(21)"
# → 42

Injection directe (:!)

L'alias spécial ! injecte les symboles du module directement dans le scope global :

catnip -f math:! -c "sqrt(100)"
# → 10.0

Utile pour les scripts courts, mais à éviter en production (pollution du namespace global).

Modules multiples

catnip -f math:m -f random:r -c "m.floor(r.random() * 100)"

Mode mixte (namespace + injection) :

catnip -f math:m -f random:! -c "m.sqrt(random())"
catnip -f ./db.py:db -f ./api.py:api script.cat

Dans le script :

users = db.query("SELECT * FROM users")
data = api.fetch("/endpoint")

Écrire un Module Host

Structure recommandée

# my_module.py

def my_function(x):
    """Cette fonction sera exposée dans le namespace."""
    return x * 2

class MyClass:
    """Les classes sont aussi exposées."""
    def __init__(self):
        self.value = 0

def _private_helper():
    """Fonctions commençant par _ ne sont PAS exposées."""
    return "private"

Règles d'exposition

Exposé dans le namespace :

  • Fonctions publiques (ne commencent pas par _)
  • Classes publiques
  • Constantes publiques
  • Modules importés exposés publiquement

Non exposé :

  • Attributs commençant par _
  • Attributs privés par convention (préfixe _)

Exemple complet

# api.py
import requests  # Import pas exposé

API_BASE = "https://api.example.com"  # Constante exposée

def fetch(endpoint):
    """Fetch data from the API."""
    return requests.get(f"{API_BASE}{endpoint}").json()

class Client:
    """API client wrapper."""
    def __init__(self, token):
        self.token = token

    def get(self, path):
        headers = {"Authorization": f"Bearer {self.token}"}
        return requests.get(f"{API_BASE}{path}", headers=headers).json()

Utilisation :

catnip -f ./api.py:api script.cat
# script.cat
base = api.API_BASE
data = api.fetch("/users")
client = api.Client("secret-token")
profile = client.get("/me")

Mode Verbeux

Le flag -v affiche les détails du chargement :

$ catnip -v -f ./host.py:api script.cat
ℹ Loading Python module: /path/to/host.py
ℹ Module 'host' loaded successfully
ℹ Created namespace 'api' with 3 functions:
ℹ    api.double()    api.greet()    api.fibonacci()

Pragma Feature

Les modules peuvent aussi être chargés depuis le code Catnip via pragma. La syntaxe du spec est identique à la CLI :

pragma("feature", "math")
x = math.sqrt(16)

Avec alias :

pragma("feature", "math:m")
x = m.sqrt(16)

Injection directe :

pragma("feature", "math:!")
x = sqrt(16)

Ou avec l'alias explicite :

pragma("feature", "math", "!")
x = sqrt(16)

Le pragma charge les modules au moment de l'analyse sémantique. Contrairement à -f qui charge avant l'exécution.

Résumé

# Module installé
catnip -f math script.cat              # math.sqrt()

# Module avec alias
catnip -f math:m script.cat            # m.sqrt()

# Injection directe (:!)
catnip -f math:! script.cat            # sqrt()

# Fichier local
catnip -f ./host.py script.cat         # host.function()

# Fichier Catnip local
catnip -f ./math.cat script.cat        # math.double()

# Fichier avec alias
catnip -f ./host.py:api script.cat     # api.function()

# Multiples modules
catnip -f math:m -f random:r script.cat

# Mode mixte
catnip -f math:m -f random:! script.cat

# Mode verbeux
catnip -v -f math:m script.cat

# REPL avec modules
catnip -f math:m