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â.
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é manquanteData 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).
Chemins supportés
| Format | Exemple | Remarque |
|---|---|---|
| String path | a.b[0].c | Lisible, 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 |
| Slice | a.nums[1:4] | Lecture slice (écriture slice opt-in) |
| Path compiler | cp = compile_path("a.b[0].c") | Réutilisation rapide en boucle |
Philosophie âstrictâ (prĂ©dictible)
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).
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/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)) # None2) Ă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")) # False4) 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']")) # 1235) 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ération8) 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))- 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).
