Skip to content

Commit 16f71bd

Browse files
gh-150285: Wrap long single-line summary in text output in pydoc (GH-151081)
1 parent ca32ebf commit 16f71bd

4 files changed

Lines changed: 111 additions & 1 deletion

File tree

Lib/pydoc.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,17 @@ def indent(self, text, prefix=' '):
12401240
lines = [(prefix + line).rstrip() for line in text.split('\n')]
12411241
return '\n'.join(lines)
12421242

1243+
def _format_doc(self, text, width=68):
1244+
"""Wraps the single-line summary if it is too long."""
1245+
if not text: return ''
1246+
lines = text.split('\n', 2)
1247+
if len(lines) > 1 and lines[1]:
1248+
return text
1249+
lines[:1] = textwrap.wrap(lines[0], width,
1250+
break_long_words=False,
1251+
break_on_hyphens=False)
1252+
return '\n'.join(lines)
1253+
12431254
def section(self, title, contents):
12441255
"""Format a section with a given heading."""
12451256
clean_contents = self.indent(contents).rstrip()
@@ -1390,6 +1401,7 @@ def makename(c, m=object.__module__):
13901401

13911402
doc = getdoc(object)
13921403
if doc:
1404+
doc = self._format_doc(doc)
13931405
push(doc + '\n')
13941406

13951407
# List the mro, if non-trivial.
@@ -1590,6 +1602,7 @@ def docroutine(self, object, name=None, mod=None, cl=None, homecls=None):
15901602
return decl + '\n'
15911603
else:
15921604
doc = getdoc(object) or ''
1605+
doc = self._format_doc(doc)
15931606
return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
15941607

15951608
def docdata(self, object, name=None, mod=None, cl=None, *ignored):
@@ -1602,6 +1615,7 @@ def docdata(self, object, name=None, mod=None, cl=None, *ignored):
16021615
push('\n')
16031616
doc = getdoc(object) or ''
16041617
if doc:
1618+
doc = self._format_doc(doc)
16051619
push(self.indent(doc))
16061620
push('\n')
16071621
return ''.join(results)
@@ -1620,7 +1634,8 @@ def docother(self, object, name=None, mod=None, parent=None, *ignored,
16201634
if not doc:
16211635
doc = getdoc(object)
16221636
if doc:
1623-
line += '\n' + self.indent(str(doc)) + '\n'
1637+
doc = self._format_doc(str(doc))
1638+
line += '\n' + self.indent(doc) + '\n'
16241639
return line
16251640

16261641
class _PlainTextDoc(TextDoc):

Lib/test/test_pydoc/longsummary.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class C:
2+
"""This is a class summary that consists of a very long single line, exceeding the recommended PEP 8 limit.
3+
4+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
5+
"""
6+
def meth(self):
7+
"""This is a method summary that consists of a very long single line, exceeding the recommended PEP 8 limit.
8+
9+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
10+
"""
11+
12+
@property
13+
def prop(self):
14+
"""This is a property summary that consists of a very long single line, exceeding the recommended PEP 8 limit.
15+
16+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
17+
"""
18+
19+
def func(self):
20+
"""This is a function summary that consists of a very long single line, exceeding the recommended PEP 8 limit.
21+
22+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
23+
"""
24+
25+
data = C()
26+
data.__doc__ = """This is a data summary that consists of a very long single line, exceeding the recommended PEP 8 limit.
27+
28+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
29+
"""

Lib/test/test_pydoc/test_pydoc.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,71 @@ def function_with_really_long_name_so_annotations_can_be_rather_small(
12451245
<lambda> lambda very_long_parameter_name_that_should_not_fit_into_a_single_line, second_very_long_parameter_name
12461246
''' % __name__)
12471247

1248+
@requires_docstrings
1249+
def test_long_summaries(self):
1250+
from . import longsummary
1251+
doc = pydoc.render_doc(longsummary)
1252+
doc = clean_text(doc)
1253+
self.assertEqual(doc, '''Python Library Documentation: module test.test_pydoc.longsummary in test.test_pydoc
1254+
1255+
NAME
1256+
test.test_pydoc.longsummary
1257+
1258+
CLASSES
1259+
builtins.object
1260+
C
1261+
1262+
class C(builtins.object)
1263+
| This is a class summary that consists of a very long single line,
1264+
| exceeding the recommended PEP 8 limit.
1265+
|
1266+
| The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
1267+
|
1268+
| Methods defined here:
1269+
|
1270+
| meth(self)
1271+
| This is a method summary that consists of a very long single line,
1272+
| exceeding the recommended PEP 8 limit.
1273+
|
1274+
| The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
1275+
|
1276+
| ----------------------------------------------------------------------
1277+
| Readonly properties defined here:
1278+
|
1279+
| prop
1280+
| This is a property summary that consists of a very long single line,
1281+
| exceeding the recommended PEP 8 limit.
1282+
|
1283+
| The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
1284+
|
1285+
| ----------------------------------------------------------------------
1286+
| Data descriptors defined here:
1287+
|
1288+
| __dict__
1289+
| dictionary for instance variables
1290+
|
1291+
| __weakref__
1292+
| list of weak references to the object
1293+
1294+
FUNCTIONS
1295+
func(self)
1296+
This is a function summary that consists of a very long single line,
1297+
exceeding the recommended PEP 8 limit.
1298+
1299+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
1300+
1301+
DATA
1302+
data = <test.test_pydoc.longsummary.C object>
1303+
This is a data summary that consists of a very long single line,
1304+
exceeding the recommended PEP 8 limit.
1305+
1306+
The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines.
1307+
1308+
FILE
1309+
%s
1310+
1311+
''' % inspect.getabsfile(longsummary))
1312+
12481313
def test__future__imports(self):
12491314
# __future__ features are excluded from module help,
12501315
# except when it's the __future__ module itself
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:mod:`pydoc` now wraps long single-line summary in text output.

0 commit comments

Comments
 (0)