Skip to content

Commit b7c42ea

Browse files
Handle concatenated string, parentheses, newlines, and add more tests.
1 parent 835fea2 commit b7c42ea

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

Lib/pydoc.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,18 +387,27 @@ def ispackage(path):
387387
def source_synopsis(file):
388388
"""Return the one-line summary of a file object, if present"""
389389

390+
string = ''
390391
try:
391392
tokens = tokenize.generate_tokens(file.readline)
392393
for tok_type, tok_string, _, _, _ in tokens:
393394
if tok_type == tokenize.STRING:
394-
docstring = ast.literal_eval(tok_string)
395-
if isinstance(docstring, str):
396-
return docstring.strip().split('\n')[0].strip()
397-
return None
395+
string += tok_string
396+
elif tok_type == tokenize.NEWLINE:
397+
with warnings.catch_warnings():
398+
# Ignore the "invalid escape sequence" warning.
399+
warnings.simplefilter("ignore", SyntaxWarning)
400+
docstring = ast.literal_eval(string)
401+
if not isinstance(docstring, str):
402+
return None
403+
return docstring.strip().split('\n')[0].strip()
404+
elif tok_type == tokenize.OP and tok_string in ('(', ')'):
405+
string += tok_string
398406
elif tok_type not in (tokenize.COMMENT, tokenize.NL, tokenize.ENCODING):
399407
return None
400-
except (tokenize.TokenError, UnicodeDecodeError, SyntaxError, ValueError) as e:
408+
except (tokenize.TokenError, UnicodeDecodeError, SyntaxError):
401409
return None
410+
return None
402411

403412
def synopsis(filename, cache={}):
404413
"""Get the one-line summary out of a module file."""

Lib/test/test_pydoc/test_pydoc.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import contextlib
55
import importlib.util
66
import inspect
7+
import io
78
import pydoc
89
import py_compile
910
import keyword
@@ -921,6 +922,12 @@ def test_source_synopsis(self):
921922
('""""""',
922923
''),
923924

925+
('"""Embedded\0null byte"""',
926+
None),
927+
928+
('"""Embedded null byte"""\0',
929+
None),
930+
924931
('"""Café and résumé."""',
925932
'Café and résumé.'),
926933

@@ -933,8 +940,32 @@ def test_source_synopsis(self):
933940
("'Single single quotes'",
934941
'Single single quotes'),
935942

943+
('"""split\\\nline"""',
944+
'splitline'),
945+
946+
('"""Unrecognized escape \\sequence"""',
947+
'Unrecognized escape \\sequence'),
948+
949+
('"""Invalid escape seq\\uence"""',
950+
None),
951+
952+
('r"""Raw \\string"""',
953+
'Raw \\string'),
954+
955+
('b"""Bytes literal"""',
956+
None),
957+
958+
('f"""f-string"""',
959+
None),
960+
936961
('"""Concatenated""" \\\n"string" \'literals\'',
937962
'Concatenatedstringliterals'),
963+
964+
('("""In """\n"""parentheses""")',
965+
'In parentheses'),
966+
967+
('()', # tuple
968+
None),
938969
]
939970

940971
for source, expected in test_cases:
@@ -943,6 +974,12 @@ def test_source_synopsis(self):
943974
result = pydoc.source_synopsis(source_file)
944975
self.assertEqual(result, expected)
945976

977+
# Encoding error.
978+
source = b'"""\xff"""'
979+
with io.TextIOWrapper(io.BytesIO(source), encoding='utf-8') as source_file:
980+
result = pydoc.source_synopsis(source_file)
981+
self.assertIsNone(result)
982+
946983
with tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8') as temp_file:
947984
temp_file.write('"""Real file test."""\n')
948985
temp_file.flush()

0 commit comments

Comments
 (0)