##// END OF EJS Templates
[extensions][tests][autoreload] Remove nose
[extensions][tests][autoreload] Remove nose

File last commit:

r26890:7880f76f
r26910:12d08a51
Show More
test_debugger.py
574 lines | 14.0 KiB | text/x-python | PythonLexer
Fernando Perez
Add simple test for modified repr as per review.
r7087 """Tests for debugging machinery.
"""
Min RK
fix some deprecations...
r22742 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
Fernando Perez
Add simple test for modified repr as per review.
r7087
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 import bdb
import builtins
import os
Itamar Turner-Trauring
Sketch of working interrupt mechanism for Windows. Will need to be implemented in ipykernel.
r25587 import signal
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 import subprocess
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 import sys
Itamar Turner-Trauring
Sketch of working interrupt mechanism for Windows. Will need to be implemented in ipykernel.
r25587 import time
Min RK
fix some deprecations...
r22742 import warnings
Matthias Bussonnier
Expand and Fix PDB skip....
r26824
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 from subprocess import PIPE, CalledProcessError, check_output
Itamar Turner-Trauring
Test for debugger interruption.
r25569 from tempfile import NamedTemporaryFile
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 from textwrap import dedent
Itamar Turner-Trauring
Switch to a much simpler test. Interrupting processes encountered some issues...
r25606 from unittest.mock import patch
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929
Fernando Perez
Add simple test for modified repr as per review.
r7087 from IPython.core import debugger
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
from IPython.testing.decorators import skip_win32
Fernando Perez
Add simple test for modified repr as per review.
r7087
#-----------------------------------------------------------------------------
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 # Helper classes, from CPython's Pdb test suite
#-----------------------------------------------------------------------------
class _FakeInput(object):
"""
A fake input stream for pdb's interactive debugger. Whenever a
line is read, print it (to simulate the user typing it), and then
return it. The set of lines to return is specified in the
constructor; they should not have trailing newlines.
"""
def __init__(self, lines):
self.lines = iter(lines)
def readline(self):
line = next(self.lines)
Thomas Kluyver
Convert print statements to print function calls...
r13348 print(line)
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 return line+'\n'
class PdbTestInput(object):
"""Context manager that makes testing Pdb in doctests easier."""
def __init__(self, input):
self.input = input
def __enter__(self):
self.real_stdin = sys.stdin
sys.stdin = _FakeInput(self.input)
def __exit__(self, *exc):
sys.stdin = self.real_stdin
#-----------------------------------------------------------------------------
Fernando Perez
Add simple test for modified repr as per review.
r7087 # Tests
#-----------------------------------------------------------------------------
def test_longer_repr():
Terry Davis
Remove clearly marked python 2 imports.
r25516 from reprlib import repr as trepr
Fernando Perez
Add simple test for modified repr as per review.
r7087
a = '1234567890'* 7
ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
a_trunc = "'123456789012...8901234567890'"
Samuel Gaist
[core][tests][debugger] Remove nose
r26890 assert trepr(a) == a_trunc
Fernando Perez
Add simple test for modified repr as per review.
r7087 # The creation of our tracer modifies the repr module's repr function
# in-place, since that global is used directly by the stdlib's pdb module.
Min RK
fix some deprecations...
r22742 with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
debugger.Tracer()
Samuel Gaist
[core][tests][debugger] Remove nose
r26890 assert trepr(a) == ar
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929
def test_ipdb_magics():
'''Test calling some IPython magics from ipdb.
First, set up some test functions and classes which we can inspect.
>>> class ExampleClass(object):
... """Docstring for ExampleClass."""
... def __init__(self):
... """Docstring for ExampleClass.__init__"""
... pass
... def __str__(self):
... return "ExampleClass()"
>>> def example_function(x, y, z="hello"):
... """Docstring for example_function."""
... pass
Thomas Kluyver
Fix clashes between debugger tests and coverage.py...
r12286 >>> old_trace = sys.gettrace()
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 Create a function which triggers ipdb.
>>> def trigger_ipdb():
... a = ExampleClass()
... debugger.Pdb().set_trace()
>>> with PdbTestInput([
... 'pdef example_function',
... 'pdoc ExampleClass',
Matthias Bussonnier
Write tests for ipdb...
r21851 ... 'up',
... 'down',
... 'list',
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 ... 'pinfo a',
Matthias Bussonnier
Write tests for ipdb...
r21851 ... 'll',
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 ... 'continue',
... ]):
... trigger_ipdb()
--Return--
None
> <doctest ...>(3)trigger_ipdb()
1 def trigger_ipdb():
2 a = ExampleClass()
----> 3 debugger.Pdb().set_trace()
<BLANKLINE>
ipdb> pdef example_function
example_function(x, y, z='hello')
ipdb> pdoc ExampleClass
MinRK
sentence case...
r15712 Class docstring:
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 Docstring for ExampleClass.
MinRK
sentence case...
r15712 Init docstring:
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 Docstring for ExampleClass.__init__
Matthias Bussonnier
Write tests for ipdb...
r21851 ipdb> up
> <doctest ...>(11)<module>()
Thomas Kluyver
Fix debugger doctest to match atual output
r21945 7 'pinfo a',
8 'll',
Matthias Bussonnier
Write tests for ipdb...
r21851 9 'continue',
10 ]):
---> 11 trigger_ipdb()
<BLANKLINE>
ipdb> down
None
> <doctest ...>(3)trigger_ipdb()
1 def trigger_ipdb():
2 a = ExampleClass()
----> 3 debugger.Pdb().set_trace()
<BLANKLINE>
ipdb> list
1 def trigger_ipdb():
2 a = ExampleClass()
----> 3 debugger.Pdb().set_trace()
<BLANKLINE>
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 ipdb> pinfo a
MinRK
Update signature presentation in pinfo classes...
r15711 Type: ExampleClass
MinRK
sentence case...
r15712 String form: ExampleClass()
MinRK
Update signature presentation in pinfo classes...
r15711 Namespace: Local...
Docstring: Docstring for ExampleClass.
MinRK
sentence case...
r15712 Init docstring: Docstring for ExampleClass.__init__
Matthias Bussonnier
Write tests for ipdb...
r21851 ipdb> ll
1 def trigger_ipdb():
2 a = ExampleClass()
----> 3 debugger.Pdb().set_trace()
<BLANKLINE>
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 ipdb> continue
Thomas Kluyver
Fix clashes between debugger tests and coverage.py...
r12286
Restore previous trace function, e.g. for coverage.py
>>> sys.settrace(old_trace)
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 '''
Bradley M. Froehle
Add test for gh-2697
r8929
Thomas Kluyver
Remove unused imports from IPython.core
r11124 def test_ipdb_magics2():
Bradley M. Froehle
Add test for gh-2697
r8929 '''Test ipdb with a very short function.
Thomas Kluyver
Fix clashes between debugger tests and coverage.py...
r12286
>>> old_trace = sys.gettrace()
Bradley M. Froehle
Add test for gh-2697
r8929
>>> def bar():
... pass
Run ipdb.
>>> with PdbTestInput([
... 'continue',
... ]):
... debugger.Pdb().runcall(bar)
> <doctest ...>(2)bar()
1 def bar():
----> 2 pass
<BLANKLINE>
ipdb> continue
Thomas Kluyver
Fix clashes between debugger tests and coverage.py...
r12286
Restore previous trace function, e.g. for coverage.py
>>> sys.settrace(old_trace)
Bradley M. Froehle
Add test for gh-2697
r8929 '''
Matthias Bussonnier
Add test that quit and exit work in debugger....
r22569
def can_quit():
'''Test that quit work in ipydb
>>> old_trace = sys.gettrace()
>>> def bar():
... pass
>>> with PdbTestInput([
... 'quit',
... ]):
... debugger.Pdb().runcall(bar)
> <doctest ...>(2)bar()
1 def bar():
----> 2 pass
<BLANKLINE>
ipdb> quit
Restore previous trace function, e.g. for coverage.py
>>> sys.settrace(old_trace)
'''
def can_exit():
'''Test that quit work in ipydb
>>> old_trace = sys.gettrace()
>>> def bar():
... pass
>>> with PdbTestInput([
... 'exit',
... ]):
... debugger.Pdb().runcall(bar)
> <doctest ...>(2)bar()
1 def bar():
----> 2 pass
<BLANKLINE>
ipdb> exit
Restore previous trace function, e.g. for coverage.py
>>> sys.settrace(old_trace)
'''
Itamar Turner-Trauring
Test for debugger interruption.
r25569
def test_interruptible_core_debugger():
Itamar Turner-Trauring
Sketch of working interrupt mechanism for Windows. Will need to be implemented in ipykernel.
r25587 """The debugger can be interrupted.
Itamar Turner-Trauring
Switch to a much simpler test. Interrupting processes encountered some issues...
r25606
The presumption is there is some mechanism that causes a KeyboardInterrupt
(this is implemented in ipykernel). We want to ensure the
KeyboardInterrupt cause debugging to cease.
Itamar Turner-Trauring
Sketch of working interrupt mechanism for Windows. Will need to be implemented in ipykernel.
r25587 """
Itamar Turner-Trauring
A maybe better-working interruptible Pdb. Also make separate class so we don't...
r25649 def raising_input(msg="", called=[0]):
called[0] += 1
if called[0] == 1:
raise KeyboardInterrupt()
else:
raise AssertionError("input() should only be called once!")
Itamar Turner-Trauring
Switch to a much simpler test. Interrupting processes encountered some issues...
r25606
with patch.object(builtins, "input", raising_input):
Itamar Turner-Trauring
A maybe better-working interruptible Pdb. Also make separate class so we don't...
r25649 debugger.InterruptiblePdb().set_trace()
Itamar Turner-Trauring
Switch to a much simpler test. Interrupting processes encountered some issues...
r25606 # The way this test will fail is by set_trace() never exiting,
# resulting in a timeout by the test runner. The alternative
# implementation would involve a subprocess, but that adds issues with
# interrupting subprocesses that are rather complex, so it's simpler
# just to do it this way.
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839
@skip_win32
def test_xmode_skip():
"""that xmode skip frames
Not as a doctest as pytest does not run doctests.
"""
import pexpect
env = os.environ.copy()
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
child.expect("IPython")
child.expect("\n")
child.expect_exact("In [1]")
block = dedent(
"""
Matthias Bussonnier
add test
r26594 def f():
__tracebackhide__ = True
g()
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839
Matthias Bussonnier
add test
r26594 def g():
raise ValueError
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839
Matthias Bussonnier
add test
r26594 f()
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 """
)
for line in block.splitlines():
child.sendline(line)
child.expect_exact(line)
child.expect_exact("skipping")
block = dedent(
"""
Matthias Bussonnier
add test
r26594 def f():
__tracebackhide__ = True
g()
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839
Matthias Bussonnier
add test
r26594 def g():
from IPython.core.debugger import set_trace
set_trace()
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839
Matthias Bussonnier
add test
r26594 f()
Matthias Bussonnier
Implement understanding on __tracebackhide__...
r25839 """
)
for line in block.splitlines():
child.sendline(line)
child.expect_exact(line)
child.expect("ipdb>")
child.sendline("w")
child.expect("hidden")
child.expect("ipdb>")
child.sendline("skip_hidden false")
child.sendline("w")
child.expect("__traceba")
child.expect("ipdb>")
child.close()
Matthias Bussonnier
add test
r26594
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 skip_decorators_blocks = (
"""
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 def helpers_helper():
pass # should not stop here except breakpoint
""",
"""
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 def helper_1():
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 helpers_helper() # should not stop here
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 """,
"""
def helper_2():
pass # should not stop here
""",
"""
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 def pdb_skipped_decorator2(function):
def wrapped_fn(*args, **kwargs):
__debuggerskip__ = True
helper_2()
__debuggerskip__ = False
result = function(*args, **kwargs)
__debuggerskip__ = True
helper_2()
return result
return wrapped_fn
""",
"""
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 def pdb_skipped_decorator(function):
def wrapped_fn(*args, **kwargs):
__debuggerskip__ = True
helper_1()
__debuggerskip__ = False
result = function(*args, **kwargs)
__debuggerskip__ = True
helper_2()
return result
return wrapped_fn
""",
"""
@pdb_skipped_decorator
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 @pdb_skipped_decorator2
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 def bar(x, y):
return x * y
""",
"""import IPython.terminal.debugger as ipdb""",
"""
def f():
ipdb.set_trace()
bar(3, 4)
""",
"""
f()
""",
)
def _decorator_skip_setup():
import pexpect
env = os.environ.copy()
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
child.expect("IPython")
child.expect("\n")
dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks]
in_prompt_number = 1
for cblock in dedented_blocks:
child.expect_exact(f"In [{in_prompt_number}]:")
in_prompt_number += 1
for line in cblock.splitlines():
child.sendline(line)
child.expect_exact(line)
child.sendline("")
return child
@skip_win32
def test_decorator_skip():
"""test that decorator frames can be skipped."""
child = _decorator_skip_setup()
child.expect_exact("3 bar(3, 4)")
child.expect("ipdb>")
child.expect("ipdb>")
child.sendline("step")
child.expect_exact("step")
child.expect_exact("1 @pdb_skipped_decorator")
child.sendline("s")
child.expect_exact("return x * y")
child.close()
@skip_win32
def test_decorator_skip_disabled():
"""test that decorator frame skipping can be disabled"""
child = _decorator_skip_setup()
child.expect_exact("3 bar(3, 4)")
for input_, expected in [
("skip_predicates debuggerskip False", ""),
("skip_predicates", "debuggerskip : False"),
("step", "---> 2 def wrapped_fn"),
("step", "----> 3 __debuggerskip__"),
("step", "----> 4 helper_1()"),
("step", "---> 1 def helper_1():"),
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 ("next", "----> 2 helpers_helper()"),
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 ("next", "--Return--"),
("next", "----> 5 __debuggerskip__ = False"),
]:
child.expect("ipdb>")
child.sendline(input_)
child.expect_exact(input_)
child.expect_exact(expected)
child.close()
Matthias Bussonnier
Skip: no pexpect on win32
r26596 @skip_win32
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 def test_decorator_skip_with_breakpoint():
"""test that decorator frame skipping can be disabled"""
import pexpect
env = os.environ.copy()
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
child.expect("IPython")
child.expect("\n")
### we need a filename, so we need to exec the full block with a filename
with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
name = tf.name[:-3].split("/")[-1]
tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
tf.flush()
codeblock = f"from {name} import f"
dedented_blocks = [
codeblock,
"f()",
]
in_prompt_number = 1
for cblock in dedented_blocks:
child.expect_exact(f"In [{in_prompt_number}]:")
in_prompt_number += 1
for line in cblock.splitlines():
child.sendline(line)
child.expect_exact(line)
child.sendline("")
# as the filename does not exists, we'll rely on the filename prompt
child.expect_exact("47 bar(3, 4)")
for input_, expected in [
(f"b {name}.py:3", ""),
("step", "1---> 3 pass # should not stop here except"),
("step", "---> 38 @pdb_skipped_decorator"),
("continue", ""),
]:
child.expect("ipdb>")
child.sendline(input_)
child.expect_exact(input_)
child.expect_exact(expected)
child.close()
@skip_win32
Matthias Bussonnier
add test
r26594 def test_where_erase_value():
Matthias Bussonnier
Update IPython/core/tests/test_debugger.py...
r26595 """Test that `where` does not access f_locals and erase values."""
Matthias Bussonnier
add test
r26594 import pexpect
env = os.environ.copy()
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
child.expect("IPython")
child.expect("\n")
child.expect_exact("In [1]")
block = dedent(
"""
def simple_f():
myvar = 1
print(myvar)
1/0
print(myvar)
simple_f() """
)
for line in block.splitlines():
child.sendline(line)
child.expect_exact(line)
child.expect_exact("ZeroDivisionError")
child.expect_exact("In [2]:")
child.sendline("%debug")
##
child.expect("ipdb>")
child.sendline("myvar")
child.expect("1")
##
child.expect("ipdb>")
child.sendline("myvar = 2")
##
child.expect_exact("ipdb>")
child.sendline("myvar")
child.expect_exact("2")
##
child.expect("ipdb>")
child.sendline("where")
##
child.expect("ipdb>")
child.sendline("myvar")
child.expect_exact("2")
child.expect("ipdb>")
child.close()