Repository: spyder-ide/spyder

Issue:
Namespace is not set correctly while debugging
## Problem Description
Setting a breakpoint inside the function for debugging,
Looking at the value of the function's input parameter in variable explorer, it is not expected

### What steps reproduce the problem?
![debug](https://user-images.githubusercontent.com/1759365/78227221-854b2b80-74ff-11ea-96da-49818c454251.gif)
### What is the expected output? What do you see instead?
Normally, the value of a variable is not printed using "print", but viewed directly through variable explorer.
I think ,when debugging,the value of the variable "a" should be 5,not 10

### code

```python
def test(a):
    print('a:',a)
    print()#Set a breakpoint on this line
a = 10
test(5)
```

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: 4.1.1
* Python version: 3.7.5
* Qt version: 5.9.6
* PyQt version: 5.9.2
* Operating System name/version: win 10




Discussion:
Thanks for reporting. It seems the user namespace is shadowing the pdb namespace and that's why `a` is shown as `10` and not as `5`.

@impact27, could you take a look at this one?
Fixed in https://github.com/spyder-ide/spyder-kernels/pull/212
Thanks for the quick response @impact27! Could you add a test for this? (I don't know if it's necessary to do it here or in spyder-kernels).

Resolving patch:
diff --git a/external-deps/spyder-kernels/spyder_kernels/console/kernel.py b/external-deps/spyder-kernels/spyder_kernels/console/kernel.py
--- a/external-deps/spyder-kernels/spyder_kernels/console/kernel.py
+++ b/external-deps/spyder-kernels/spyder_kernels/console/kernel.py
@@ -419,16 +419,16 @@ def _get_current_namespace(self, with_magics=False):
         both locals() and globals() for current frame when debugging
         """
         ns = {}
-        glbs = self._mglobals()
-
-        if self._pdb_frame is None:
-            ns.update(glbs)
+        if self._running_namespace is None:
+            ns.update(self._mglobals())
         else:
-            ns.update(glbs)
-            ns.update(self._pdb_locals)
+            running_globals, running_locals = self._running_namespace
+            ns.update(running_globals)
+            if running_locals is not None:
+                ns.update(running_locals)
 
-        if self._running_namespace is not None:
-            ns.update(self._running_namespace)
+        if self._pdb_frame is not None:
+            ns.update(self._pdb_locals)
 
         # Add magics to ns so we can show help about them on the Help
         # plugin
diff --git a/external-deps/spyder-kernels/spyder_kernels/customize/namespace_manager.py b/external-deps/spyder-kernels/spyder_kernels/customize/namespace_manager.py
--- a/external-deps/spyder-kernels/spyder_kernels/customize/namespace_manager.py
+++ b/external-deps/spyder-kernels/spyder_kernels/customize/namespace_manager.py
@@ -80,7 +80,8 @@ def __enter__(self):
                 self._reset_main = True
 
         # Save current namespace for access by variable explorer
-        get_ipython().kernel._running_namespace = self.ns_globals
+        get_ipython().kernel._running_namespace = (
+            self.ns_globals, self.ns_locals)
 
         if (self._file_code is not None
                 and not PY2
diff --git a/external-deps/spyder-kernels/spyder_kernels/utils/nsview.py b/external-deps/spyder-kernels/spyder_kernels/utils/nsview.py
--- a/external-deps/spyder-kernels/spyder_kernels/utils/nsview.py
+++ b/external-deps/spyder-kernels/spyder_kernels/utils/nsview.py
@@ -123,7 +123,13 @@ def get_size(item):
     elif isinstance(item, Image):
         return item.size
     if isinstance(item, (DataFrame, Index, Series)):
-        return item.shape
+        try:
+            return item.shape
+        except RecursionError:
+            # This is necessary to avoid an error when trying to
+            # get the shape of these objects.
+            # Fixes spyder-ide/spyder-kernels#217
+            return (-1, -1)
     else:
         return 1
 


Test patch:
diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py
--- a/spyder/app/tests/test_mainwindow.py
+++ b/spyder/app/tests/test_mainwindow.py
@@ -3094,5 +3094,59 @@ def test_ipython_magic(main_window, qtbot, tmpdir, ipython, test_cell_magic):
             os.remove(to_text_string(write_file))
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_running_namespace(main_window, qtbot, tmpdir):
+    """
+    Test that the running namespace is correctly sent when debugging in a
+    new namespace.
+    """
+    code = ("def test(a):\n    print('a:',a)\na = 10\ntest(5)")
+
+    # Wait until the window is fully up
+    shell = main_window.ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Main variables
+    debug_action = main_window.debug_toolbar_actions[0]
+    debug_button = main_window.debug_toolbar.widgetForAction(debug_action)
+
+    # Clear all breakpoints
+    main_window.editor.clear_all_breakpoints()
+
+    # create new file
+    main_window.editor.new()
+    code_editor = main_window.editor.get_focus_widget()
+    code_editor.set_text(code)
+    code_editor.debugger.toogle_breakpoint(line_number=2)
+
+    # Write b in the namespace
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('b = 10')
+
+    nsb = main_window.variableexplorer.get_focus_widget()
+    qtbot.waitUntil(lambda: 'b' in nsb.editor.source_model._data)
+    assert nsb.editor.source_model._data['b']['view'] == '10'
+
+    # Start debugging
+    with qtbot.waitSignal(shell.executed):
+        qtbot.mouseClick(debug_button, Qt.LeftButton)
+
+    # b should not be there (running namespace) and the local a should be 5
+    qtbot.waitUntil(lambda: 'a' in nsb.editor.source_model._data and
+                    nsb.editor.source_model._data['a']['view'] == '5',
+                    timeout=3000)
+    assert 'b' not in nsb.editor.source_model._data
+    assert nsb.editor.source_model._data['a']['view'] == '5'
+
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('c')
+
+    # At the end, b should be back and a should be 10
+    qtbot.waitUntil(lambda: 'b' in nsb.editor.source_model._data)
+    assert nsb.editor.source_model._data['a']['view'] == '10'
+    assert nsb.editor.source_model._data['b']['view'] == '10'
+
 if __name__ == "__main__":
     pytest.main()