Repository: spyder-ide/spyder

Issue:
can't run doctest - unexpected keyword argument 'nosigint'
_From [RyanSKin...@gmail.com](https://code.google.com/u/110207151280343061731/) on 2014-06-17T13:17:05Z_

Hello, I'm unable to run doctests from spyder's IPthyon interpreter. The tests execute properly using a standard python console or a standalone IPython3 shell. Thanks for your help in solving this issue.

Spyder Version:  2.3.0rc
Python Version:  3.4.0
Qt Version    :  4.8.6, PyQt4 (API v2) 4.10.4 on Linux
IPython >=0.13  :  1.2.1 (OK)
matplotlib >=1.0:  1.3.1 (OK)
pep8 >=0.6      :  None (OK)
psutil >=0.3    :  None (OK)
pyflakes >=0.6.0:  0.8.1 (OK)
pygments >=1.6  :  1.6 (OK)
pylint >=0.25   :  1.1.0 (OK)
rope >=0.9.2    :  None (NOK)
sphinx >=0.6.6  :  None (OK)
sympy >=0.7.0   :  None (OK) 

What steps will reproduce the problem?
1. open spyder's IPython console
2. In [1]: import doctest
    In [2]: doctest.testmod() 

What is the expected output? What do you see instead?

Expected: tests complete successfuly.

Actual:

```python-traceback
Traceback (most recent call last):

  File "<ipython-input-2-aa223a5ff88d>", line 1, in <module>
    doctest.testmod()

  File "/usr/lib/python3.4/doctest.py", line 1945, in testmod
    runner.run(test)

  File "/usr/lib/python3.4/doctest.py", line 1456, in run
    self.debugger = _OutputRedirectingPdb(save_stdout)

  File "/usr/lib/python3.4/doctest.py", line 357, in **init**
    pdb.Pdb.**init**(self, stdout=out, nosigint=True)

TypeError: **init**() got an unexpected keyword argument 'nosigint'
```

_Original issue: http://code.google.com/p/spyderlib/issues/detail?id=1855_



Discussion:
_From [ccordoba12](https://code.google.com/u/ccordoba12/) on 2014-08-26T08:02:51Z_

**Labels:** Cat-IPythonConsole MS-v2.4  

_From [MartinMo...@gmail.com](https://code.google.com/u/102642118397971510645/) on 2014-12-05T13:15:30Z_

For a shoddy quick fix you can remove the 'nosigint=True' argument from the pdb.Pdb.**init** in doctest, and change the default value of nosigint to True in pdb.py.

The underlying problem seems to be that pdb.Pdb is actually the derived class SpyderPdb in sitecustomize.py. SpyderPdb does not have a **init** method defined and Python does not automatically call the parent's **init** for derived classes. So the SpyderPdb **init** needs to be written to handle nosigint.

This is still an issue in Spyder 2.3.8, can someone please state the status of this bug? The workaround kind of seems like I need to change a default library, and that is a little out of my comfort zone.

Current workaround for me is to use the Python console, instead of the IPython console. And I do want to use the IPython console.

No one has worked on this, sorry. I'll take a look at it for Spyder 3.1 (yes, still several months away because 3.0 is in beta :-)

The thing is this is not a critical bug, so I decided to not make it block 3.0.

Any update on this? It is still an ongoing bug it seems.
We'll take a look at it in Spyder 3.2.
Just ran into this issue as well.  Stopped me briefly from participating in a training session that used doctests for their coding exercises.  For anyone looking for a workaround until it's fixed:  http://stackoverflow.com/questions/37669435/python-3-5-typeerror-init-got-an-unexpected-keyword-argument-nosigint.  While this does change core libraries, the change is small and fairly isolated.
The solution seems simple enough, thanks for letting us know about it.
It would be better to modify spyder? http://stackoverflow.com/a/42660766/125507
Yes, that's our plan. This will be fixed in Spyder 3.1.4

Resolving patch:
diff --git a/spyder/utils/site/sitecustomize.py b/spyder/utils/site/sitecustomize.py
--- a/spyder/utils/site/sitecustomize.py
+++ b/spyder/utils/site/sitecustomize.py
@@ -511,6 +511,7 @@ def in_qtconsole():
 # Pdb adjustments
 #==============================================================================
 class SpyderPdb(pdb.Pdb):
+
     send_initial_notification = True
 
     def set_spyder_breakpoints(self):
@@ -556,8 +557,10 @@ def notify_spyder(self, frame):
                     monitor.notify_pdb_step(fname, lineno)
                     time.sleep(0.1)
 
+
 pdb.Pdb = SpyderPdb
 
+
 #XXX: I know, this function is now also implemented as is in utils/misc.py but
 #     I'm kind of reluctant to import spyder in sitecustomize, even if this
 #     import is very clean.
@@ -591,6 +594,13 @@ def decorator(func):
         return func
     return decorator
 
+
+@monkeypatch_method(pdb.Pdb, 'Pdb')
+def __init__(self, completekey='tab', stdin=None, stdout=None,
+             skip=None, nosigint=False):
+    self._old_Pdb___init__()
+
+
 @monkeypatch_method(pdb.Pdb, 'Pdb')
 def user_return(self, frame, return_value):
     """This function is called when a return trap is set here."""
@@ -603,6 +613,7 @@ def user_return(self, frame, return_value):
         self._wait_for_mainpyfile = 0
     self._old_Pdb_user_return(frame, return_value)
 
+
 @monkeypatch_method(pdb.Pdb, 'Pdb')
 def interaction(self, frame, traceback):
     self.setup(frame, traceback)
@@ -612,6 +623,7 @@ def interaction(self, frame, traceback):
     self.cmdloop()
     self.forget()
 
+
 @monkeypatch_method(pdb.Pdb, 'Pdb')
 def reset(self):
     self._old_Pdb_reset()
@@ -624,6 +636,7 @@ def reset(self):
         monitor.register_pdb_session(self)
     self.set_spyder_breakpoints()
 
+
 #XXX: notify spyder on any pdb command (is that good or too lazy? i.e. is more
 #     specific behaviour desired?)
 @monkeypatch_method(pdb.Pdb, 'Pdb')
@@ -631,6 +644,7 @@ def postcmd(self, stop, line):
     self.notify_spyder(self.curframe)
     return self._old_Pdb_postcmd(stop, line)
 
+
 # Breakpoints don't work for files with non-ascii chars in Python 2
 # Fixes Issue 1484
 if PY2:


Test patch:
diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py
--- a/spyder/plugins/tests/test_ipythonconsole.py
+++ b/spyder/plugins/tests/test_ipythonconsole.py
@@ -8,6 +8,7 @@
 import os.path as osp
 import shutil
 import tempfile
+from textwrap import dedent
 
 from flaky import flaky
 import pytest
@@ -59,6 +60,42 @@ def close_widget():
 #==============================================================================
 # Tests
 #==============================================================================
+@flaky(max_runs=10)
+@pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows")
+def test_run_doctest(ipyconsole, qtbot):
+    """
+    Test that doctests can be run without problems
+    """
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT)
+
+    code = dedent('''
+    def add(x, y):
+        """
+        >>> add(1, 2)
+        3
+        >>> add(5.1, 2.2)
+        7.3
+        """
+        return x + y
+    ''')
+
+    # Run code
+    with qtbot.waitSignal(shell.executed):
+        shell.execute(code)
+
+    # Import doctest
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('import doctest')
+
+    # Run doctest
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('doctest.testmod()')
+
+    # Assert that doctests were run correctly
+    assert "TestResults(failed=0, attempted=2)" in shell._control.toPlainText()
+
+
 @flaky(max_runs=10)
 @pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows")
 def test_mpl_backend_change(ipyconsole, qtbot):
@@ -67,7 +104,6 @@ def test_mpl_backend_change(ipyconsole, qtbot):
     using the %matplotlib magic
     """
     shell = ipyconsole.get_current_shellwidget()
-    client = ipyconsole.get_current_client()
     qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT)
 
     # Import Matplotlib