bpo-30211: bdb: add docstrings#1350
Conversation
|
@csabella, thanks for your PR! By analyzing the history of the files in this pull request, we identified @tim-one, @birkenfeld and @avassalotti to be potential reviewers. |
terryjreedy
left a comment
There was a problem hiding this comment.
This is the start I wanted. Thank you. Good catch on the typos. This review is incomplete in that some comments mark a place to change without yet saying exactly how.
- Maybe add docstring for _set_stopinfo, moving comment into docstring. (Can't seem to add this inline.)
Lib/bdb.py
Outdated
| self.frame_returning = None | ||
|
|
||
| def canonic(self, filename): | ||
| """Get a filename into a canonical form. |
There was a problem hiding this comment.
"""Return canonical form of filename.
There was a problem hiding this comment.
Thanks! Three questions on this function:
- It seems like this helper function would be valuable in os.path, but maybe not if it hasn't been needed before. Are there times when helper functions like this are moved?
- This function also caches this results. Would there be any point in using a decorator or does that add unnecessary overhead?
- os.path.abspath says that it returns a normalized absolutized version of the path. So why call both here?
There was a problem hiding this comment.
This function is not really a method, as it does not use 'self'. But is was written before 'staticmethod' and the original author(s) must have not wanted to expose it at module level. We are here documenting the API and will next test the current implementation. Once tested, we could possibly revise.
-
canonicdoes 2 things different from os function(s).
1A. Leave angle bracketed names alone. This following part of the doc, copied in your patch, "stripped of surrounding angle brackets" does not match the code. Either way, I don't know what bracketed ''s are about or when, if ever, they occur. I also don't know if the existing test is the fastest possible.
1B. Cache the mapping of non-bracketed names to absolute name. This must be for speed as the same abbreviated name is used repeatedly. -
It does not cache bracketed name. If it did, I would say 'test alternatives for speed'.
-
normcaseis notnormpathand latter, called byabspath, does not callnormcase.
There was a problem hiding this comment.
Thanks for that explanation. Looking through the patch history, canonic was added later. I'll try to find it again and maybe the commit comment will help. I have no idea how the old commits were ported to git, but it is just one more cool thing -- to have all the history available. :-)
Edit
Found it - November 28, 2001 -
canonic(): don't use abspath() for filenames looking like <...>; this
fixes the problem reported in SF bug #477023 (Jonathan Mark): "pdb:
unexpected path confuses Emacs".
There was a problem hiding this comment.
https://bugs.python.org/issue477023 works. The bracketed path names are from interactive mode.
Lib/bdb.py
Outdated
| return self.trace_dispatch | ||
|
|
||
| def dispatch_line(self, frame): | ||
| """Trace function when a new line of code is executed. |
There was a problem hiding this comment.
Hmm. Just saying "Return trace function." does not really help much. It is really an implementation detail in that communicating a tracer change could have been differently. setting self.tracer, for instance, could have been the linking mechanism. Describing the 'side-effect', which is actually the main effect is awkward. "Return trace function after calling user_line if debugger stops here." is fairly accurate and descriptive. But I am open to other ideas for the wording. Ditto for other 3 event handlers.
There was a problem hiding this comment.
You're probably not going to like what I changed it to, but maybe it will help come up with something else. :-)
| @@ -323,6 +438,10 @@ def clear_all_file_breaks(self, filename): | |||
| del self.breaks[filename] | |||
There was a problem hiding this comment.
When there is an explicit non-None return in a function, then any None return should be explicit. (This is somewhere in PEP 8.) So add 'return None' on new line after this.
There was a problem hiding this comment.
I hadn't changed any code, so I wasn't sure about this when I saw it. I've now added None to all the similar set_* functions that had another return and no return None. Question -- if there are no returns, should I add return None?
Another question: there is some code like this - "if self.quitting: raise BdbQuit". Should I put that on two lines?
There was a problem hiding this comment.
Clarification: add 'return None' at the end of the function ;-). I missed 'set_break' and any others because of the folding; thank you for checking. The relevant PEP8 section begins "Be consistent in return statements." It is standard to omit 'return None' at the end and leave it implicit when there are no other return statements.
For 'if cond: statement', PEP8 says both 'Rather not:' and 'While sometimes it's okay'. I think we should leave them alone.
|
|
||
|
|
||
| def set_trace(): | ||
| """Start debugging with a Bdb instance from the caller's frame.""" |
There was a problem hiding this comment.
I presume you copied this, but I am not sure I understand it.
There was a problem hiding this comment.
Yes, it's from the docs. There are three functions defined outside of the classes - set_trace(), effective(), and checkfuncname(). effective() and checkfuncname() already had docstrings, so I didn't change them. set_trace() has one line - Bdb.set_trace().
louisom
left a comment
There was a problem hiding this comment.
Some small point could change.
Lib/bdb.py
Outdated
| that originate in a module that matches one of these patterns. | ||
| Whether a frame is considered to originate in a certain module | ||
| is determined by the __name__ in the frame globals. | ||
|
|
There was a problem hiding this comment.
No need for this blank line
There was a problem hiding this comment.
Thanks! I wasn't sure on that one. PEP-8 doesn't have it, but existing strings in this module did. Probably a good time to remove them all.
|
|
||
| A canonical form is a case-normalized (on case insenstive filesystems) | ||
| absolute path, stripped of surrounding angle brackets. | ||
|
|
Lib/bdb.py
Outdated
| See sys.settrace() for more information on the trace function. For | ||
| more information on code and frame objects, refer to The Standard | ||
| Type Hierarchy. | ||
|
|
Lib/bdb.py
Outdated
| self._set_stopinfo(None, None) | ||
|
|
||
| def trace_dispatch(self, frame, event, arg): | ||
| """Trace function of debugged frames. |
There was a problem hiding this comment.
Dispatch routine for debugged frames' event.
There was a problem hiding this comment.
Made a slight change to yours to make it a verb, but thank you for suggesting to put 'dispatch' first. I had struggled with this yesterday.
| method. Raise a BdbQuit exception if the Bdb.quitting flag is set. | ||
| Return a reference to the trace_dispatch() method for further | ||
| tracing in that scope. | ||
|
|
| method. Raise a BdbQuit exception if the Bdb.quitting flag is set. | ||
| Return a reference to the trace_dispatch() method for further | ||
| tracing in that scope. | ||
|
|
| user_exception() method. Raise a BdbQuit exception if the | ||
| Bdb.quitting flag is set. Return a reference to the trace_dispatch() | ||
| method for further tracing in that scope. | ||
|
|
| Check if there is a breakpoint in the filename and lineno | ||
| belonging to the frame or in the current function. If the breakpoint | ||
| is a temporary one, delete it. | ||
|
|
Lib/bdb.py
Outdated
| funcname=None): | ||
| """Set a new breakpoint for the filename:lineno. | ||
|
|
||
| If lineno doesn't exist for the filename, return error. The |
There was a problem hiding this comment.
return an error message.
for consistent.
Lib/bdb.py
Outdated
| def clear_break(self, filename, lineno): | ||
| """Delete breakpoints in filename:lineno. | ||
|
|
||
| If none were set, return an error message. |
There was a problem hiding this comment.
I think if none were set should be more clearly. But not sure how to change it.
There was a problem hiding this comment.
Changed to 'If no breakpoints were set"
|
As far as documenting _set_stopinfo, I didn't know if the _ functions should get docstrings or not. Looked at some other modules and it didn't seem like they were, so I left it out. Changed that for this and for _prune_breaks. Is it standard to include docstrings for the functions defined with _? Terry, I'm sure you've seen this, but this is marked as a 'gotcha' in the Breakpoint class. Not sure if I need to docstring it somehow: |
Whoever wrote that considers it a bug, which we could try to fix in a follow-on issue. |
|
The class comment was added January 25, 1999 by GvR. :-) |
Lib/bdb.py
Outdated
|
|
||
| If the debugger stops on this function return, invoke the | ||
| user_exception() method. Raise a BdbQuit exception if the | ||
| Bdb.quitting flag is set. Return a reference to the trace_dispatch() |
There was a problem hiding this comment.
There is a missing whitespace after the period.
Lib/bdb.py
Outdated
| def _set_stopinfo(self, stopframe, returnframe, stoplineno=0): | ||
| """Set the attributes for stopping. | ||
|
|
||
| If `stoplineno` is greater than or equal to 0, then stop at line |
There was a problem hiding this comment.
In this doctstring you are wrapping the argument stoplineno with `, while in all the other doctstrings you are not. I think to be consistent you have to remove the `` around stoplineno.
There was a problem hiding this comment.
Thanks. I've removed the backticks on the ones I added. There is still one set of backticks that I didn't add. Do you think I should remove those too?
There was a problem hiding this comment.
I think we can also remove the backticks in checkfuncname(), so we'll have all the docstrings formatted consistently.
There was a problem hiding this comment.
Done. I've also changed checkfuncname() to match the doc page.
|
Refreshing the patch was required for 'import re' (in patchcheck and IDLE) to run in pr_1350 with a current build. I am now editing the docstrings themselves. Please wait before committing anything more. |
Many reduce wordiness. Only a few intend to change meaning.
|
Thanks for reviewing and making those changes. I'm sorry there was so much left for you to work on. |
| # definition of stopping and breakpoints. | ||
|
|
||
| def is_skipped_module(self, module_name): | ||
| "Return True if module_name matches any skip pattern." |
There was a problem hiding this comment.
What this is difference between single quotes and triple quotes?
There was a problem hiding this comment.
Triple quotes are only needed for multiple lines. For single lines, single quotes are commonly used, in spite of what PEP257 says. I only changed your additions where line length was an issue.
There was a problem hiding this comment.
Thank you for explaining. Makes sense to use single quotes for simple lines that might need to wrap.
Lib/bdb.py
Outdated
|
|
||
| This must be implemented by derived classes otherwise it raises | ||
| a NotImplementedError. | ||
| If not implemented in derived classe, raise NotImplementedError. |
There was a problem hiding this comment.
Fixed with revision of sentence.
Lib/bdb.py
Outdated
|
|
||
| def break_anywhere(self, frame): | ||
| """Return True if there is a breakpoint in the filename for the frame. | ||
| """Return True if there any breakpoint for frame's filename. |
|
|
||
| Get a list of records for a frame and all higher (calling) and | ||
| lower frames, and the size of the higher part. | ||
| List starts with original calling frame, if there is one. |
There was a problem hiding this comment.
Does the return value start with the original calling frame? With the stack.reverse(), I thought it first traversed in one direction from f (backwards - which would put f first), but then reversed the list so f was no longer first and then continued to append the traceback frames.
There was a problem hiding this comment.
By 'original calling frame', I meant self.botframe. Initial loop breaks after appending botframe, then reverse makes botframe first.
There was a problem hiding this comment.
Got it. Thanks. I think I need to figure out a call to get_stack to really understand it.
| Get a list of records for a frame and all higher (calling) and | ||
| lower frames, and the size of the higher part. | ||
| List starts with original calling frame, if there is one. | ||
| Size may be number of frames above or below f. |
There was a problem hiding this comment.
For the size, the line 'if f is None: i = max()', but I don't see why f wouldn't be None here. It could come in as None or the 'while f is not None:' loop changes it until it is None. So, the size would either be 0 (if there isn't a stack) or the size of the stack - 1. It wouldn't be just the above part or below part. I realize I'm probably missing something, but I don't see it. Thanks.
There was a problem hiding this comment.
f is either None or self.botframe (the break condition). The latter might or might not be None. The length calculation makes no sense to me. So I put something vague that should be accurate.
|
This may be followed by an additional PR for the same issue, but it is good enough for now. |


No description provided.