Source code for arsenal.debug

[docs]def extract(source=None): """Copies the variables of the caller up to iPython. Useful for debugging. In a Jupyter notebook, create a cell after an exception has occurred with .. code-block:: python %%debug from arsenal.debug import extract; extract() Args: source: A method or module from which to extract local variables. If not specified the current scope's locals will be used. Notes: Taken from Andy Jones' personal library https://github.com/andyljones/aljpy/blob/master/aljpy/debugging.py All rights go to him. See Also: Andy wrote a blog post explaining how he uses this code: https://andyljones.com/posts/post-mortem-plotting.html .. code-block:: python def f(): x = 'hello world' extract() f() # raises an error print(x) # prints 'hello world' """ import inspect import ctypes if source is None: frames = inspect.stack() caller = frames[1].frame name, ls, gs = caller.f_code.co_name, caller.f_locals, caller.f_globals elif hasattr(source, "__func__"): func = source.__func__ name, ls, gs = func.__qualname__, (func.__closure__ or {}), func.__globals__ elif hasattr(source, "__init__"): func = source.__init__.__func__ name, ls, gs = func.__qualname__, (func.__closure__ or {}), func.__globals__ else: raise ValueError(f"Don't support source {source}") ipython = [f for f in inspect.stack() if f.filename.startswith("<ipython-input")][ -1 ].frame ipython.f_locals.update({k: v for k, v in gs.items() if k[:2] != "__"}) ipython.f_locals.update({k: v for k, v in ls.items() if k[:2] != "__"}) # Magic call to make the updates to f_locals 'stick'. # More info: http://pydev.blogspot.co.uk/2014/02/changing-locals-of-frame-frameflocals.html ctypes.pythonapi.PyFrame_LocalsToFast(ctypes.py_object(ipython), ctypes.c_int(0)) message = "Copied {}'s variables to {}".format(name, ipython.f_code.co_name) raise RuntimeError(message)