Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

Toolbox Dev — Ideo-Lab

DeepOps — Deep Get/Set/Del pour structures imbriquĂ©es (dict/list) + Path Compiler

v0.1.0  ‱  Python 3.10+

Pourquoi DeepOps ? (le “utils.py” que tout le monde réécrit)

DeepOps est un mini-utilitaire Python qui rĂ©sout un besoin ultra frĂ©quent : lire / Ă©crire / supprimer une valeur dans une structure imbriquĂ©e (dict, list) en utilisant un “chemin”.

ProblĂšme typique : les JSON, configs, rĂ©ponses API, payloads d’events, settings, etc. deviennent rapidement imbriquĂ©s et pĂ©nibles Ă  manipuler proprement (surtout quand certaines clĂ©s/indices n’existent pas). DeepOps apporte une API stable et “strict” (prĂ©visible) + un path compiler pour les boucles chaudes.

Chemins lisibles

Supporte les chemins sous forme de chaĂźne (a.b[0].c) ou sous forme de tokens (tuple) ("a","b",0,"c") (plus rapide, typable).

Best practice : tuple tokens en interne, string cÎté UX/CLI.

Performance

Le path compiler (compile_path()) permet de parser une fois un chemin string, puis de le réutiliser efficacement dans une boucle (gain net vs parsing répété).

Idéal pour parser des logs, traiter des events, pipelines, etc.

Cas d’usage (rĂ©alistes)

Config / JSON / YAML

Fusion/patch, lecture de valeurs imbriquĂ©es, crĂ©ation d’arbres de config Ă  la volĂ©e.

from deepops import deepget, deepset

cfg = {"app":{"limits":{"rate": 10}}}
rate = deepget(cfg, "app.limits.rate")          # 10
deepset(cfg, "app.limits.burst", 50)            # crée la clé manquante

Data events / pipelines

Extraction de champs imbriqués dans des payloads (API, Kafka, logs, webhooks).

payload = {"user":{"id": 7, "meta":{"geo":{"country":"ES"}}}}
country = deepget(payload, "user.meta.geo.country", default="??")

Fonctionnalités clés

DeepOps se veut volontairement simple, strict et prĂ©visible pour ĂȘtre rĂ©utilisĂ© en prod (sans surprises).

deepget() deepset() deepdel() deephas() compile_path() slice [1:4]

Chemins supportés

FormatExempleRemarque
String patha.b[0].cLisible, pratique cÎté UI/CLI
Tokens tuple("a","b",0,"c")Recommandé (plus rapide, typable)
ClĂ©s “weird”a['x.y']['hello world']Support des points / espaces via crochets + quotes
Slicea.nums[1:4]Lecture slice (écriture slice opt-in)
Path compilercp = compile_path("a.b[0].c")Réutilisation rapide en boucle

Philosophie “strict” (prĂ©dictible)

Strict containers (par dĂ©faut) : pas de “fallback magique” entre dict/list/attrs. Si tu demandes un index sur un dict, ou une clĂ© sur une liste, tu obtiens une exception explicite. Cela Ă©vite des bugs silencieux.

Options avancées (DeepOptions)

from deepops import DeepOptions

opt = DeepOptions(
    create=True,             # créer les containers manquants
    strict_containers=True,  # mode strict
    list_fill=None,          # valeur de remplissage lors d'expansion de list
    allow_slice_set=False,   # assignation de slice off par défaut
)

Distribution Wheel (.whl)

DeepOps est livré sous forme de wheel pour une installation rapide dans un environnement virtuel. Le wheel embarque uniquement le module (pas de dépendances).

Télécharger le Wheel (deepops v0.1.0)

Fichier: deepops-0.1.0-py3-none-any.whl

Installation rapide

# (venv activé)
pip install /static/toolbox/deepops-0.1.0-py3-none-any.whl
Note : sur un serveur Django, tu peux soit copier le wheel dans un rĂ©pertoire local, soit l’installer directement depuis le chemin local (recommandĂ©). L’URL /static/... sert au tĂ©lĂ©chargement, mais pip prĂ©fĂšre un chemin fichier.

Vérification

python -c "from deepops import deepget; print(deepget({'a':{'b':[{'c':1}]}}, 'a.b[0].c'))"

Utilisation & Exemples (prĂȘts Ă  copier-coller)

1) Lecture simple (deepget)

from deepops import deepget

data = {"a": {"b": [{"c": 1}]}}
print(deepget(data, "a.b[0].c"))              # 1
print(deepget(data, "a.b[1].c", default=None)) # None

2) Écriture avec crĂ©ation automatique (deepset)

from deepops import deepset

data = {}
deepset(data, "a.x[0].y", "ok")               # create=True par défaut
print(data)  # {"a":{"x":[{"y":"ok"}]}}

3) Existence (deephas) et suppression (deepdel)

from deepops import deephas, deepdel

data = {"a":{"b":{"c":1}}}
print(deephas(data, "a.b.c"))  # True
deepdel(data, "a.b.c")
print(deephas(data, "a.b.c"))  # False

4) Clés contenant points/espaces (quoted bracket keys)

from deepops import deepget

data = {"a": {"x.y": {"hello world": 123}}}
print(deepget(data, "a['x.y']['hello world']"))  # 123

5) Slice (lecture) : [1:4], [:3], [::2]

from deepops import deepget

data = {"a": {"nums": [0,1,2,3,4,5]}}
print(deepget(data, "a.nums[1:4]"))  # [1,2,3]
print(deepget(data, "a.nums[:3]"))   # [0,1,2]
print(deepget(data, "a.nums[::2]"))  # [0,2,4]

6) Slice (Ă©criture) — opt-in (allow_slice_set=True)

from deepops import DeepOptions, deepset

opt = DeepOptions(allow_slice_set=True)
data = {"a": {"nums": [0,1,2,3,4,5]}}

deepset(data, "a.nums[1:4]", [10,11,12], options=opt)
print(data["a"]["nums"])  # [0,10,11,12,4,5]

7) Path compiler (perf) : compile_path()

Si tu utilises toujours le mĂȘme chemin dans une boucle, compile-le une fois.

from deepops import compile_path, deepget

data = {"a": {"b": [{"c": 123}]}}
cp = compile_path("a.b[0].c")

for _ in range(200_000):
    deepget(data, cp)   # pas de parsing à chaque itération

8) Mini-benchmark (string vs compiled)

# bench/bench_path.py (exemple)
import time
from deepops import compile_path, deepget

data = {"a": {"b": [{"c": 123}]}}
path = "a.b[0].c"
cp = compile_path(path)
iters = 300_000

def bench(label, fn):
    t0 = time.perf_counter()
    for _ in range(iters):
        fn()
    dt = time.perf_counter() - t0
    print(label, dt, "sec", int(iters/dt), "ops/s")

bench("string", lambda: deepget(data, path))
bench("compiled", lambda: deepget(data, cp))
Bonnes pratiques :
  • En prod : utilise tokens tuple ou compiled path si rĂ©pĂ©titif.
  • En UI/CLI : accepte les strings (ergonomie), compile si nĂ©cessaire.
  • Reste en mode strict par dĂ©faut (moins de bugs silencieux).