Repository: spyder-ide/spyder

Issue:
Debug mode not working on win10 for any code
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [Y] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [Y] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [Y] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [Y] Tried basic troubleshooting (if a bug/error)
    * [ ] Restarted Spyder
    * [ ] Reset preferences with ``spyder --reset``
    * [ ] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [ ] Tried the other applicable steps from the Troubleshooting Guide
* [ ] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description
any code, such as
 `a = 1 # you can see the traceback follow, the spyder hanging at the first line of the code`
`b = 1`
`c = a + b`
All operations (such as step F10, continue to next breakpoint F12) not responding when spyder in debug mode. it seems like the IDE is hanging, all I can do is click the "Stop the current command" to exit the debug mode.

### What steps reproduce the problem?

1. debug any code and try to step inside

### What is the expected output? What do you see instead?

the spyder can stop at the pre-setted break points, and can step the code

### Paste Traceback/Error Below (if applicable)
<!--- Copy from error dialog or View > Panes > Internal Console --->

```python-traceback

debugfile('E:/Public2/paper/universalLAIEstimation/test.py', wdir='E:/Public2/paper/universalLAIEstimation')
> e:\public2\paper\universallaiestimation\test.py(6)<module>()
      4 
      5 @author: WIN
----> 6 """
      7 
      8 a = 1


--KeyboardInterrupt--

KeyboardInterrupt: Interrupted by user

```

## 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.2
* Python version: 3.7.7
* Qt version: 
* PyQt version: 
* Operating System name/version: win10 1909

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
NO DEPENDENCIES
```



Discussion:

![debug2](https://user-images.githubusercontent.com/23078349/101341784-92a18c80-38bc-11eb-85db-d80916d23695.gif)

@yellowpuppy, thanks for reporting.

@impact27, could you take a look at this one?

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole/plugin.py b/spyder/plugins/ipythonconsole/plugin.py
--- a/spyder/plugins/ipythonconsole/plugin.py
+++ b/spyder/plugins/ipythonconsole/plugin.py
@@ -833,12 +833,7 @@ def stop_debugging(self):
         """Stop debugging"""
         sw = self.get_current_shellwidget()
         if sw is not None:
-            if not sw.is_waiting_pdb_input():
-                sw.interrupt_kernel()
-            try:
-                sw.pdb_execute_command("exit")
-            except AttributeError:
-                pass
+            sw.stop_debugging()
 
     def get_pdb_state(self):
         """Get debugging state of the current console."""
diff --git a/spyder/plugins/ipythonconsole/widgets/debugging.py b/spyder/plugins/ipythonconsole/widgets/debugging.py
--- a/spyder/plugins/ipythonconsole/widgets/debugging.py
+++ b/spyder/plugins/ipythonconsole/widgets/debugging.py
@@ -21,6 +21,7 @@
 from pygments.util import ClassNotFound
 from qtconsole.rich_jupyter_widget import RichJupyterWidget
 from qtpy.QtCore import Qt
+from qtpy.QtGui import QTextCursor
 
 from spyder.config.base import _, get_conf_path
 from spyder.config.manager import CONF
@@ -237,7 +238,8 @@ def set_debug_state(self, is_debugging):
     def _pdb_cmd_prefix(self):
         """Return the command prefix"""
         prefix = ''
-        if self.is_pdb_using_exclamantion_mark():
+        if (self.spyder_kernel_comm.is_open() and
+                self.is_pdb_using_exclamantion_mark()):
             prefix = '!'
         return prefix
 
@@ -249,6 +251,21 @@ def pdb_execute_command(self, command):
             self._pdb_cmd_prefix() + command, hidden=False,
             echo_stack_entry=False, add_history=False)
 
+    def _handle_input_request(self, msg):
+        """Process an input request."""
+        if (not self.spyder_kernel_comm.is_open() and
+                msg['content']['prompt'] == "ipdb> "):
+            # Check if we can guess a path from the shell content:
+            self._flush_pending_stream()
+            cursor = self._get_end_cursor()
+            cursor.setPosition(self._prompt_pos, QTextCursor.KeepAnchor)
+            text = cursor.selection().toPlainText()
+            match = re.search(r"> (.*\.py)\((\d+)\)", text)
+            if match:
+                fname, lineno = match.groups()
+                self.sig_pdb_step.emit(fname, int(lineno))
+        return super(DebuggingWidget, self)._handle_input_request(msg)
+
     def pdb_execute(self, line, hidden=False, echo_stack_entry=True,
                     add_history=True):
         """
@@ -268,6 +285,14 @@ def pdb_execute(self, line, hidden=False, echo_stack_entry=True,
         add_history: bool
             If not hidden, wether the line should be added to history
         """
+        # Send line to input if no comm
+        if not self.spyder_kernel_comm.is_open():
+            if not hidden:
+                self._append_plain_text(line + '\n')
+            self._finalize_input_request()
+            self.kernel_client.input(line)
+            return
+
         if not self.is_debugging():
             return
 
@@ -334,6 +359,13 @@ def get_pdb_settings(self):
         }
 
     # --- To Sort --------------------------------------------------
+    def stop_debugging(self):
+        """Stop debugging."""
+        if (self.spyder_kernel_comm.is_open() and
+                not self.is_waiting_pdb_input()):
+            self.interrupt_kernel()
+        self.pdb_execute_command("exit")
+
     def set_spyder_breakpoints(self):
         """Set Spyder breakpoints into a debugging session"""
         self.call_kernel(interrupt=True).set_breakpoints(


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
@@ -3805,5 +3805,36 @@ def test_outline_no_init(main_window, qtbot):
     assert len(treewidget.editor_tree_cache[editor_id]) > 0
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_pdb_without_comm(main_window, qtbot):
+    """Check if pdb works without comm."""
+    ipyconsole = main_window.ipyconsole
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+    control = ipyconsole.get_focus_widget()
+
+    with qtbot.waitSignal(shell.executed):
+        shell.execute("get_ipython().kernel.frontend_comm.close()")
+    shell.execute("%debug print()")
+    qtbot.waitUntil(
+        lambda: shell._control.toPlainText().split()[-1] == 'ipdb>')
+    qtbot.keyClicks(control, "print('Two: ' + str(1+1))")
+    qtbot.keyClick(control, Qt.Key_Enter)
+    qtbot.waitUntil(
+        lambda: shell._control.toPlainText().split()[-1] == 'ipdb>')
+
+    assert "Two: 2" in control.toPlainText()
+
+    # Press step button and expect a sig_pdb_step signal
+    with qtbot.waitSignal(shell.sig_pdb_step):
+        main_window.editor.debug_command("step")
+
+    # Stop debugging and expect an executed signal
+    with qtbot.waitSignal(shell.executed):
+        main_window.editor.stop_debugging()
+
+
 if __name__ == "__main__":
     pytest.main()
diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
--- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
@@ -1797,27 +1797,6 @@ def test_pdb_eventloop(ipyconsole, qtbot, backend):
     assert "Two: 2" in control.toPlainText()
 
 
-@flaky(max_runs=3)
-def test_pdb_without_comm(ipyconsole, qtbot):
-    """Check if pdb works without comm."""
-    shell = ipyconsole.get_current_shellwidget()
-    qtbot.waitUntil(lambda: shell._prompt_html is not None,
-                    timeout=SHELL_TIMEOUT)
-    control = ipyconsole.get_focus_widget()
-
-    with qtbot.waitSignal(shell.executed):
-        shell.execute("get_ipython().kernel.frontend_comm.close()")
-    shell.execute("%debug print()")
-    qtbot.waitUntil(
-        lambda: shell._control.toPlainText().split()[-1] == 'ipdb>')
-    qtbot.keyClicks(control, "print('Two: ' + str(1+1))")
-    qtbot.keyClick(control, Qt.Key_Enter)
-    qtbot.waitUntil(
-        lambda: shell._control.toPlainText().split()[-1] == 'ipdb>')
-
-    assert "Two: 2" in control.toPlainText()
-
-
 @flaky(max_runs=3)
 def test_recursive_pdb(ipyconsole, qtbot):
     """Check commands and code are separted."""