diff options
author | Srinivas Reddy Thatiparthy (తాటిపర్తి శ్రీనివాస్ రెడ్డి) <thatiparthysreenivas@gmail.com> | 2025-01-08 10:32:07 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-08 10:32:07 (GMT) |
commit | 474e419792484d1c16e7d9c99b7bf144136b9307 (patch) | |
tree | 3ec41062488693a5296ccc867ce786a04152d802 /Lib/pydoc.py | |
parent | cdfb8bc93a4d8c06d2404ba2d243937ba209438c (diff) | |
download | cpython-474e419792484d1c16e7d9c99b7bf144136b9307.zip cpython-474e419792484d1c16e7d9c99b7bf144136b9307.tar.gz cpython-474e419792484d1c16e7d9c99b7bf144136b9307.tar.bz2 |
gh-41872: Fix quick extraction of module docstrings from a file in pydoc (GH-127520)
It now supports docstrings with single quotes, escape sequences,
raw string literals, and other Python syntax.
Co-authored-by: Éric <merwok@netwok.org>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Lib/pydoc.py')
-rw-r--r-- | Lib/pydoc.py | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py index c863794..9e84292 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -53,6 +53,7 @@ Richard Chamberlain, for the first implementation of textdoc. # the current directory is changed with os.chdir(), an incorrect # path will be displayed. +import ast import __future__ import builtins import importlib._bootstrap @@ -384,21 +385,29 @@ def ispackage(path): return False def source_synopsis(file): - line = file.readline() - while line[:1] == '#' or not line.strip(): - line = file.readline() - if not line: break - line = line.strip() - if line[:4] == 'r"""': line = line[1:] - if line[:3] == '"""': - line = line[3:] - if line[-1:] == '\\': line = line[:-1] - while not line.strip(): - line = file.readline() - if not line: break - result = line.split('"""')[0].strip() - else: result = None - return result + """Return the one-line summary of a file object, if present""" + + string = '' + try: + tokens = tokenize.generate_tokens(file.readline) + for tok_type, tok_string, _, _, _ in tokens: + if tok_type == tokenize.STRING: + string += tok_string + elif tok_type == tokenize.NEWLINE: + with warnings.catch_warnings(): + # Ignore the "invalid escape sequence" warning. + warnings.simplefilter("ignore", SyntaxWarning) + docstring = ast.literal_eval(string) + if not isinstance(docstring, str): + return None + return docstring.strip().split('\n')[0].strip() + elif tok_type == tokenize.OP and tok_string in ('(', ')'): + string += tok_string + elif tok_type not in (tokenize.COMMENT, tokenize.NL, tokenize.ENCODING): + return None + except (tokenize.TokenError, UnicodeDecodeError, SyntaxError): + return None + return None def synopsis(filename, cache={}): """Get the one-line summary out of a module file.""" |