##// END OF EJS Templates
Expand and Fix PDB skip....
Matthias Bussonnier -
Show More
@@ -24,8 +24,12 b' By default, frames from readonly files will be hidden, frames containing'
24 24 Frames containing ``__debuggerskip__`` will be stepped over, frames who's parent
25 25 frames value of ``__debuggerskip__`` is ``True`` will be skipped.
26 26
27 >>> def helper_1():
27 >>> def helpers_helper():
28 ... pass
29 ...
30 ... def helper_1():
28 31 ... print("don't step in me")
32 ... helpers_helpers() # will be stepped over unless breakpoint set.
29 33 ...
30 34 ...
31 35 ... def helper_2():
@@ -44,6 +48,7 b' One can define a decorator that wraps a function between the two helpers:'
44 48 ... result = function(*args, **kwargs)
45 49 ... __debuggerskip__ = True
46 50 ... helper_2()
51 ... # setting __debuggerskip__ to False again is not necessary
47 52 ... return result
48 53 ...
49 54 ... return wrapped_fn
@@ -902,12 +907,16 b' class Pdb(OldPdb):'
902 907 stop at any point inside the function
903 908
904 909 """
910
911 sup = super().break_anywhere(frame)
912 if sup:
913 return sup
905 914 if self._predicates["debuggerskip"]:
906 915 if DEBUGGERSKIP in frame.f_code.co_varnames:
907 916 return True
908 917 if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
909 918 return True
910 return super().break_anywhere(frame)
919 return False
911 920
912 921 @skip_doctest
913 922 def _is_in_decorator_internal_and_should_skip(self, frame):
@@ -926,8 +935,12 b' class Pdb(OldPdb):'
926 935 if DEBUGGERSKIP in frame.f_code.co_varnames:
927 936 return True
928 937
929 # if parent frame value set to True skip as well.
930 if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
938 # if one of the parent frame value set to True skip as well.
939
940 cframe = frame
941 while getattr(cframe, "f_back", None):
942 cframe = cframe.f_back
943 if self._get_frame_locals(cframe).get(DEBUGGERSKIP):
931 944 return True
932 945
933 946 return False
@@ -12,6 +12,7 b' import subprocess'
12 12 import sys
13 13 import time
14 14 import warnings
15
15 16 from subprocess import PIPE, CalledProcessError, check_output
16 17 from tempfile import NamedTemporaryFile
17 18 from textwrap import dedent
@@ -325,14 +326,30 b' def test_xmode_skip():'
325 326
326 327 skip_decorators_blocks = (
327 328 """
329 def helpers_helper():
330 pass # should not stop here except breakpoint
331 """,
332 """
328 333 def helper_1():
329 pass # should not stop here
334 helpers_helper() # should not stop here
330 335 """,
331 336 """
332 337 def helper_2():
333 338 pass # should not stop here
334 339 """,
335 340 """
341 def pdb_skipped_decorator2(function):
342 def wrapped_fn(*args, **kwargs):
343 __debuggerskip__ = True
344 helper_2()
345 __debuggerskip__ = False
346 result = function(*args, **kwargs)
347 __debuggerskip__ = True
348 helper_2()
349 return result
350 return wrapped_fn
351 """,
352 """
336 353 def pdb_skipped_decorator(function):
337 354 def wrapped_fn(*args, **kwargs):
338 355 __debuggerskip__ = True
@@ -346,6 +363,7 b' skip_decorators_blocks = ('
346 363 """,
347 364 """
348 365 @pdb_skipped_decorator
366 @pdb_skipped_decorator2
349 367 def bar(x, y):
350 368 return x * y
351 369 """,
@@ -423,7 +441,7 b' def test_decorator_skip_disabled():'
423 441 ("step", "----> 3 __debuggerskip__"),
424 442 ("step", "----> 4 helper_1()"),
425 443 ("step", "---> 1 def helper_1():"),
426 ("next", "----> 2 pass"),
444 ("next", "----> 2 helpers_helper()"),
427 445 ("next", "--Return--"),
428 446 ("next", "----> 5 __debuggerskip__ = False"),
429 447 ]:
@@ -436,6 +454,62 b' def test_decorator_skip_disabled():'
436 454
437 455
438 456 @skip_win32
457 def test_decorator_skip_with_breakpoint():
458 """test that decorator frame skipping can be disabled"""
459
460 import pexpect
461
462 env = os.environ.copy()
463 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
464
465 child = pexpect.spawn(
466 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
467 )
468 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
469
470 child.expect("IPython")
471 child.expect("\n")
472
473 ### we need a filename, so we need to exec the full block with a filename
474 with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
475
476 name = tf.name[:-3].split("/")[-1]
477 tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
478 tf.flush()
479 codeblock = f"from {name} import f"
480
481 dedented_blocks = [
482 codeblock,
483 "f()",
484 ]
485
486 in_prompt_number = 1
487 for cblock in dedented_blocks:
488 child.expect_exact(f"In [{in_prompt_number}]:")
489 in_prompt_number += 1
490 for line in cblock.splitlines():
491 child.sendline(line)
492 child.expect_exact(line)
493 child.sendline("")
494
495 # as the filename does not exists, we'll rely on the filename prompt
496 child.expect_exact("47 bar(3, 4)")
497
498 for input_, expected in [
499 (f"b {name}.py:3", ""),
500 ("step", "1---> 3 pass # should not stop here except"),
501 ("step", "---> 38 @pdb_skipped_decorator"),
502 ("continue", ""),
503 ]:
504 child.expect("ipdb>")
505 child.sendline(input_)
506 child.expect_exact(input_)
507 child.expect_exact(expected)
508
509 child.close()
510
511
512 @skip_win32
439 513 def test_where_erase_value():
440 514 """Test that `where` does not access f_locals and erase values."""
441 515 import pexpect
General Comments 0
You need to be logged in to leave comments. Login now