diff -r d7aa625147f7 Lib/pydoc.py --- a/Lib/pydoc.py Sat Apr 06 20:26:53 2013 -0500 +++ b/Lib/pydoc.py Thu Sep 26 16:54:52 2013 +0530 @@ -53,6 +53,8 @@ # path will be displayed. import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings +import tokenize, ast +from token import tok_name from repr import Repr from string import expandtabs, find, join, lower, split, strip, rfind, rstrip from traceback import extract_tb @@ -192,22 +194,15 @@ return True return False -def source_synopsis(file): - line = file.readline() - while line[:1] == '#' or not strip(line): - line = file.readline() - if not line: break - line = strip(line) - if line[:4] == 'r"""': line = line[1:] - if line[:3] == '"""': - line = line[3:] - if line[-1:] == '\\': line = line[:-1] - while not strip(line): - line = file.readline() - if not line: break - result = strip(split(line, '"""')[0]) - else: result = None - return result +def source_synopsis(file_): + # generate_tokens always atleast returns ENDMARKER + for token in tokenize.generate_tokens(file_.readline): + token_name = tok_name[token[0]] + if token_name not in ['COMMENT', 'NL']: + break + if token_name == 'STRING': + return ast.literal_eval(token[1]).strip().split('\n')[0].strip() + return None def synopsis(filename, cache={}): """Get the one-line summary out of a module file.""" diff -r d7aa625147f7 Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py Sat Apr 06 20:26:53 2013 -0500 +++ b/Lib/test/test_pydoc.py Thu Sep 26 16:54:52 2013 +0530 @@ -12,7 +12,8 @@ from collections import namedtuple from test.script_helper import assert_python_ok from test.test_support import ( - TESTFN, rmtree, reap_children, captured_stdout) + TESTFN, rmtree, reap_children, captured_stdout, unlink) +import StringIO from test import pydoc_mod @@ -281,6 +282,31 @@ self.assertEqual(expected, result, "documentation for missing module found") + def test_synopsis(self): + # issue 1185124 + # summary is returned even for single triple quote docstrings + self.addCleanup(unlink, TESTFN) + with open(TESTFN, 'w') as f: + f.write('#!/usr/bin/python\n') + f.write("'''\nline 1: h\xe9\n") + f.write("line 2: hi'''\n") + synopsis = pydoc.synopsis(TESTFN, {}) + self.assertEqual(synopsis, 'line 1: h\xe9') + + def test_source_synopsis(self): + # extension to issue 1185124 + # source_synopsis should work in all cases where __doc__ works + + # single quotes + example_string = "#!/usr/bin/python\n\n'Module summary'\nprint('hello')" + synopsis = pydoc.source_synopsis(StringIO.StringIO(example_string)) + self.assertEqual(synopsis, 'Module summary') + + # double quotes + example_string = '"summary"' + synopsis = pydoc.source_synopsis(StringIO.StringIO(example_string)) + self.assertEqual(synopsis, 'summary') + def test_input_strip(self): missing_module = " test.i_am_not_here " result = run_pydoc(missing_module)