-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
gh-136057: Allow step and next to step over for loops #136160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
24857e4
83cd3b3
e47731e
99837fd
6ad8598
21d2783
4094efc
1d3f1b3
d7ad5d4
553f715
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -306,7 +306,12 @@ def dispatch_line(self, frame): | |
| self.user_line(). Raise BdbQuit if self.quitting is set. | ||
| Return self.trace_dispatch to continue tracing in this scope. | ||
| """ | ||
| if self.stop_here(frame) or self.break_here(frame): | ||
| # GH-136057 | ||
| # For line events, we don't want to stop at the same line where | ||
| # we issue the previous next/step command. | ||
|
||
| if (self.stop_here(frame) or self.break_here(frame)) and not ( | ||
| self.cmdframe == frame and self.cmdlineno == frame.f_lineno | ||
| ): | ||
| self.user_line(frame) | ||
| self.restart_events() | ||
| if self.quitting: raise BdbQuit | ||
|
|
@@ -535,7 +540,8 @@ def _set_trace_opcodes(self, trace_opcodes): | |
| if self.monitoring_tracer: | ||
| self.monitoring_tracer.update_local_events() | ||
|
|
||
| def _set_stopinfo(self, stopframe, returnframe, stoplineno=0, opcode=False): | ||
| def _set_stopinfo(self, stopframe, returnframe, stoplineno=0, opcode=False, | ||
| cmdframe=None, cmdlineno=None): | ||
| """Set the attributes for stopping. | ||
|
|
||
| If stoplineno is greater than or equal to 0, then stop at line | ||
|
|
@@ -548,6 +554,11 @@ def _set_stopinfo(self, stopframe, returnframe, stoplineno=0, opcode=False): | |
| # stoplineno >= 0 means: stop at line >= the stoplineno | ||
| # stoplineno -1 means: don't stop at all | ||
| self.stoplineno = stoplineno | ||
| # cmdframe/cmdlineno is the frame/line number when the user issues | ||
| # step/next commands. We don't want to stop at the same line for | ||
| # those commands. | ||
gaogaotiantian marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self.cmdframe = cmdframe | ||
| self.cmdlineno = cmdlineno | ||
| self._set_trace_opcodes(opcode) | ||
|
|
||
| def _set_caller_tracefunc(self, current_frame): | ||
|
|
@@ -573,15 +584,17 @@ def set_until(self, frame, lineno=None): | |
|
|
||
| def set_step(self): | ||
| """Stop after one line of code.""" | ||
| self._set_stopinfo(None, None) | ||
| # set_step() could be called from signal handler so enterframe might be None | ||
| self._set_stopinfo(None, None, cmdframe=self.enterframe, | ||
| cmdlineno=getattr(self.enterframe, 'f_lineno', None)) | ||
|
|
||
| def set_stepinstr(self): | ||
| """Stop before the next instruction.""" | ||
| self._set_stopinfo(None, None, opcode=True) | ||
|
|
||
| def set_next(self, frame): | ||
| """Stop on the next line in or below the given frame.""" | ||
| self._set_stopinfo(frame, None) | ||
| self._set_stopinfo(frame, None, cmdframe=frame, cmdlineno=frame.f_lineno) | ||
|
|
||
| def set_return(self, frame): | ||
| """Stop when returning from the given frame.""" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3232,6 +3232,37 @@ def test_pdb_issue_gh_127321(): | |
| """ | ||
|
|
||
|
|
||
| def test_pdb_issue_gh_136057(): | ||
| """See GH-136057 | ||
| "step" and "next" commands should be able to get over list comprehensions | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it be that next steps over the list comp but step executes every iteration?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not according to our documentation
I mean we can have different interpretation of the phrase "first possible occasion". Technically we can do this at bytecode level - but that's probably not we really want. I think we should stick to the explanation in the parenthesis. |
||
| >>> def test_function(): | ||
| ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() | ||
| ... lst = [i for i in range(10)] | ||
| ... for i in lst: pass | ||
|
|
||
| >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE | ||
| ... 'next', | ||
| ... 'next', | ||
| ... 'step', | ||
| ... 'continue', | ||
| ... ]): | ||
| ... test_function() | ||
| > <doctest test.test_pdb.test_pdb_issue_gh_136057[0]>(2)test_function() | ||
| -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() | ||
| (Pdb) next | ||
| > <doctest test.test_pdb.test_pdb_issue_gh_136057[0]>(3)test_function() | ||
| -> lst = [i for i in range(10)] | ||
| (Pdb) next | ||
| > <doctest test.test_pdb.test_pdb_issue_gh_136057[0]>(4)test_function() | ||
| -> for i in lst: pass | ||
| (Pdb) step | ||
| --Return-- | ||
| > <doctest test.test_pdb.test_pdb_issue_gh_136057[0]>(4)test_function()->None | ||
| -> for i in lst: pass | ||
| (Pdb) continue | ||
| """ | ||
|
|
||
|
|
||
| def test_pdb_issue_gh_80731(): | ||
| """See GH-80731 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Fixed the bug in :mod:`pdb` and :mod:`bdb` where ``next`` and ``step`` can't go over the line if a loop exists in the line. |
Uh oh!
There was an error while loading. Please reload this page.