From a37a6de71faffa8108574f20231c3b0a6dc9af57 2020-07-14 17:38:42
From: Matthias Bussonnier <bussonniermatthias@gmail.com>
Date: 2020-07-14 17:38:42
Subject: [PATCH] Backport PR #12437: PR: Move extraction of local scope to a method

---

diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
index ddb1b64..f2eec1c 100644
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -2321,11 +2321,21 @@ class InteractiveShell(SingletonConfigurable):
             kwargs = {}
             # Grab local namespace if we need it:
             if getattr(fn, "needs_local_scope", False):
-                kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
+                kwargs['local_ns'] = self.get_local_scope(stack_depth)
             with self.builtin_trap:
                 result = fn(*args, **kwargs)
             return result
 
+    def get_local_scope(self, stack_depth):
+        """Get local scope at given stack depth.
+
+        Parameters
+        ----------
+        stack_depth : int
+          Depth relative to calling frame
+        """
+        return sys._getframe(stack_depth + 1).f_locals
+
     def run_cell_magic(self, magic_name, line, cell):
         """Execute the given cell magic.