Context managers (with)
with x as y: guarantees cleanup (closing files, releasing locks) even if an exception is raised.
Code example
with open('data.csv') as f:
rows = f.read().splitlines()
# f is closed here even if read() threw
with session.lock:
session.namespace['x'] = 42
How it works
A context manager implements `__enter__` and `__exit__`. The `with` statement calls `__enter__`, runs the block, and always calls `__exit__` — even on exception. This is the right way to acquire locks (the notebook session lock), open files, or hold DB transactions. The notebook uses `with session.lock:` to ensure only one cell runs at a time per user.
🔍 Where this is used in OpenBenchML
app/routes/notebook.py — `with session.lock:` guards the namespace dict.