##// END OF EJS Templates
misc headers fixes
misc headers fixes

File last commit:

r28828:2e34c770
r28964:a8810c6c
Show More
test_debugger.py
592 lines | 15.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 builtins
import os
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 import sys
Matthias Bussonnier
Skip problemtic test on PyPy
r27325 import platform
Matthias Bussonnier
Expand and Fix PDB skip....
r26824
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
Matthias Bussonnier
Skip problemtic test on PyPy
r27325 import pytest
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
#-----------------------------------------------------------------------------
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.
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 In [1]: class ExampleClass(object):
...: """Docstring for ExampleClass."""
...: def __init__(self):
...: """Docstring for ExampleClass.__init__"""
...: pass
...: def __str__(self):
...: return "ExampleClass()"
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 In [2]: def example_function(x, y, z="hello"):
...: """Docstring for example_function."""
...: pass
Thomas Kluyver
Fix clashes between debugger tests and coverage.py...
r12286
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 In [3]: old_trace = sys.gettrace()
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 Create a function which triggers ipdb.
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 In [4]: def trigger_ipdb():
...: a = ExampleClass()
...: debugger.Pdb().set_trace()
Run ipdb with faked input & check output. Because of a difference between
Python 3.13 & older versions, the first bit of the output is inconsistent.
We need to use ... to accommodate that, so the examples have to use IPython
prompts so that ... is distinct from the Python PS2 prompt.
In [5]: with PdbTestInput([
...: 'pdef example_function',
...: 'pdoc ExampleClass',
...: 'up',
...: 'down',
...: 'list',
...: 'pinfo a',
...: 'll',
...: 'continue',
...: ]):
...: trigger_ipdb()
...> <doctest ...>(3)trigger_ipdb()
Bradley M. Froehle
Add basic tests for calling pdef/pdoc/pinfo from ipdb.
r7929 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>
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 ipdb> down...
Matthias Bussonnier
Write tests for ipdb...
r21851 > <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 test_ipdb_magics doctest for Python 3.13
r28825
Thomas Kluyver
Autoformat with darker
r28828 Restore previous trace function, e.g. for coverage.py
Thomas Kluyver
Fix test_ipdb_magics doctest for Python 3.13
r28825 In [6]: 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
Nikita Kniazev
Rewrite bunch of `raise AssertionError` and `assert False` tests
r27087 assert called[0] == 1, "input() should only be called once!"
raise KeyboardInterrupt()
Itamar Turner-Trauring
Switch to a much simpler test. Interrupting processes encountered some issues...
r25606
Nikita Kniazev
TST: Restore original trace function
r26957 tracer_orig = sys.gettrace()
try:
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.
finally:
# restore the original trace function
sys.settrace(tracer_orig)
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"
Matthias Bussonnier
no CPR
r27691 env["PROMPT_TOOLKIT_NO_CPR"] = "1"
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
Nikita Kniazev
Tweak tests for PyPy and add CI runner...
r27235 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810
child.expect("IPython")
child.expect("\n")
Nikita Kniazev
Tweak tests for PyPy and add CI runner...
r27235 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
Matthias Bussonnier
extend buffer len
r27690 child.str_last_chars = 500
Nikita Kniazev
Tweak tests for PyPy and add CI runner...
r27235
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 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
Matthias Bussonnier
always skip
r27695 @pytest.mark.skip(reason="recently fail for unknown reason on CI")
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 @skip_win32
def test_decorator_skip():
"""test that decorator frames can be skipped."""
child = _decorator_skip_setup()
Matthias Bussonnier
debug
r27694 child.expect_exact("ipython-input-8")
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 child.expect_exact("3 bar(3, 4)")
child.expect("ipdb>")
child.expect("ipdb>")
child.sendline("step")
child.expect_exact("step")
Matthias Bussonnier
debug
r27694 child.expect_exact("--Call--")
child.expect_exact("ipython-input-6")
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810
child.expect_exact("1 @pdb_skipped_decorator")
child.sendline("s")
child.expect_exact("return x * y")
child.close()
Matthias Bussonnier
always skip
r27695 @pytest.mark.skip(reason="recently fail for unknown reason on CI")
Matthias Bussonnier
replace skip by skipif
r27357 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="issues on PyPy")
Matthias Bussonnier
Allow decorator frames to be marked as skippable....
r26810 @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()
M Bussonnier
MAINT: mark 3.13.dev failing test as xfail
r28798 @pytest.mark.xfail(
sys.version_info.releaselevel not in ("final", "candidate"),
reason="fails on 3.13.dev",
M Bussonnier
stricted but no doctests
r28800 strict=True,
M Bussonnier
MAINT: mark 3.13.dev failing test as xfail
r28798 )
Matthias Bussonnier
replace skip by skipif
r27357 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="issues on PyPy")
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"
Matthias Bussonnier
try to fix tests
r27692 env["PROMPT_TOOLKIT_NO_CPR"] = "1"
Matthias Bussonnier
Expand and Fix PDB skip....
r26824
child = pexpect.spawn(
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
)
Nikita Kniazev
Tweak tests for PyPy and add CI runner...
r27235 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
Matthias Bussonnier
try to fix tests
r27692 child.str_last_chars = 500
Matthias Bussonnier
Expand and Fix PDB skip....
r26824
child.expect("IPython")
child.expect("\n")
Nikita Kniazev
Tweak tests for PyPy and add CI runner...
r27235 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 ### 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("")
Thomas Kluyver
Fix test_decorator_skip_with_breakpoint() on Python 3.13
r28826 # From 3.13, set_trace()/breakpoint() stop on the line where they're
# called, instead of the next line.
if sys.version_info >= (3, 13):
child.expect_exact("--> 46 ipdb.set_trace()")
extra_step = [("step", "--> 47 bar(3, 4)")]
else:
child.expect_exact("--> 47 bar(3, 4)")
extra_step = []
Matthias Bussonnier
Expand and Fix PDB skip....
r26824
Thomas Kluyver
Autoformat with darker
r28828 for input_, expected in (
[
(f"b {name}.py:3", ""),
]
+ extra_step
+ [
("step", "1---> 3 pass # should not stop here except"),
("step", "---> 38 @pdb_skipped_decorator"),
("continue", ""),
]
):
Matthias Bussonnier
Expand and Fix PDB skip....
r26824 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()