##// END OF EJS Templates
DEBUG: on pexpect failure show 1000 chars buffer
DEBUG: on pexpect failure show 1000 chars buffer

File last commit:

r27626:5b6f01c3
r27626:5b6f01c3
Show More
test_debugger.py
580 lines | 14.2 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
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 import bdb
import builtins
import os
Matthias Bussonnier
Backport PR #12168: Make IPython.core.debugger interruptible by KeyboardInterrupt
r25661 import signal
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 import subprocess
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 import sys
Matthias Bussonnier
Backport PR #12168: Make IPython.core.debugger interruptible by KeyboardInterrupt
r25661 import time
Min RK
fix some deprecations...
r22742 import warnings
Matthias Bussonnier
Backport PR #13175: Expand and Fix PDB skip.
r26834
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 from subprocess import PIPE, CalledProcessError, check_output
Matthias Bussonnier
Backport PR #12168: Make IPython.core.debugger interruptible by KeyboardInterrupt
r25661 from tempfile import NamedTemporaryFile
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 from textwrap import dedent
Matthias Bussonnier
Backport PR #12168: Make IPython.core.debugger interruptible by KeyboardInterrupt
r25661 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 import nose.tools as nt
from IPython.core import debugger
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 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():
Thomas Kluyver
Fix tests for core
r13375 try:
from reprlib import repr as trepr # Py 3
except ImportError:
from repr import repr as trepr # Py 2
Fernando Perez
Add simple test for modified repr as per review.
r7087
a = '1234567890'* 7
ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
a_trunc = "'123456789012...8901234567890'"
Bradley M. Froehle
s/nt.assert_equals/nt.assert_equal/
r7875 nt.assert_equal(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()
Bradley M. Froehle
s/nt.assert_equals/nt.assert_equal/
r7875 nt.assert_equal(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)
'''
Matthias Bussonnier
Backport PR #12168: Make IPython.core.debugger interruptible by KeyboardInterrupt
r25661
def test_interruptible_core_debugger():
"""The debugger can be interrupted.
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.
"""
def raising_input(msg="", called=[0]):
called[0] += 1
if called[0] == 1:
raise KeyboardInterrupt()
else:
raise AssertionError("input() should only be called once!")
with patch.object(builtins, "input", raising_input):
debugger.InterruptiblePdb().set_trace()
# 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
Backport PR #12359: Implement understanding on __tracebackhide__
r25844
@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
Backport PR #13021: Don't access current_frame f_locals
r26598 def f():
__tracebackhide__ = True
g()
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 def g():
raise ValueError
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 f()
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 """
)
for line in block.splitlines():
child.sendline(line)
child.expect_exact(line)
child.expect_exact("skipping")
block = dedent(
"""
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 def f():
__tracebackhide__ = True
g()
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 def g():
from IPython.core.debugger import set_trace
set_trace()
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 f()
Matthias Bussonnier
Backport PR #12359: Implement understanding on __tracebackhide__
r25844 """
)
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
Backport PR #13021: Don't access current_frame f_locals
r26598
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 skip_decorators_blocks = (
"""
Matthias Bussonnier
Backport PR #13175: Expand and Fix PDB skip.
r26834 def helpers_helper():
pass # should not stop here except breakpoint
""",
"""
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 def helper_1():
Matthias Bussonnier
Backport PR #13175: Expand and Fix PDB skip.
r26834 helpers_helper() # should not stop here
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 """,
"""
def helper_2():
pass # should not stop here
""",
"""
Matthias Bussonnier
Backport PR #13175: Expand and Fix PDB skip.
r26834 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
Backport PR #13142: Pdbskip #13136...
r26817 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
Backport PR #13175: Expand and Fix PDB skip.
r26834 @pdb_skipped_decorator2
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 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
)
Matthias Bussonnier
DEBUG: on pexpect failure show 1000 chars buffer
r27626 child.str_last_chars = 1000
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 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
Backport PR #13175: Expand and Fix PDB skip.
r26834 ("next", "----> 2 helpers_helper()"),
Matthias Bussonnier
Backport PR #13142: Pdbskip #13136...
r26817 ("next", "--Return--"),
("next", "----> 5 __debuggerskip__ = False"),
]:
child.expect("ipdb>")
child.sendline(input_)
child.expect_exact(input_)
child.expect_exact(expected)
child.close()
Matthias Bussonnier
Backport PR #13021: Don't access current_frame f_locals
r26598 @skip_win32
Matthias Bussonnier
Backport PR #13175: Expand and Fix PDB skip.
r26834 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
Backport PR #13021: Don't access current_frame f_locals
r26598 def test_where_erase_value():
"""Test that `where` does not access f_locals and erase values."""
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()