https://github.com/python/cpython/commit/16f71bda3f6cdd9ff013ffba4d29c863bb2c6a2e
commit: 16f71bda3f6cdd9ff013ffba4d29c863bb2c6a2e
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-06-10T13:44:35+03:00
summary:
gh-150285: Wrap long single-line summary in text output in pydoc (GH-151081)
files:
A Lib/test/test_pydoc/longsummary.py
A Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst
M Lib/pydoc.py
M Lib/test/test_pydoc/test_pydoc.py
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 497cc7d90a42456..ca4eb1001981681 100644
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -1240,6 +1240,17 @@ def indent(self, text, prefix=' '):
lines = [(prefix + line).rstrip() for line in text.split('\n')]
return '\n'.join(lines)
+ def _format_doc(self, text, width=68):
+ """Wraps the single-line summary if it is too long."""
+ if not text: return ''
+ lines = text.split('\n', 2)
+ if len(lines) > 1 and lines[1]:
+ return text
+ lines[:1] = textwrap.wrap(lines[0], width,
+ break_long_words=False,
+ break_on_hyphens=False)
+ return '\n'.join(lines)
+
def section(self, title, contents):
"""Format a section with a given heading."""
clean_contents = self.indent(contents).rstrip()
@@ -1390,6 +1401,7 @@ def makename(c, m=object.__module__):
doc = getdoc(object)
if doc:
+ doc = self._format_doc(doc)
push(doc + '\n')
# List the mro, if non-trivial.
@@ -1590,6 +1602,7 @@ def docroutine(self, object, name=None, mod=None,
cl=None, homecls=None):
return decl + '\n'
else:
doc = getdoc(object) or ''
+ doc = self._format_doc(doc)
return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
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):
push('\n')
doc = getdoc(object) or ''
if doc:
+ doc = self._format_doc(doc)
push(self.indent(doc))
push('\n')
return ''.join(results)
@@ -1620,7 +1634,8 @@ def docother(self, object, name=None, mod=None,
parent=None, *ignored,
if not doc:
doc = getdoc(object)
if doc:
- line += '\n' + self.indent(str(doc)) + '\n'
+ doc = self._format_doc(str(doc))
+ line += '\n' + self.indent(doc) + '\n'
return line
class _PlainTextDoc(TextDoc):
diff --git a/Lib/test/test_pydoc/longsummary.py
b/Lib/test/test_pydoc/longsummary.py
new file mode 100644
index 000000000000000..0e566d33454119b
--- /dev/null
+++ b/Lib/test/test_pydoc/longsummary.py
@@ -0,0 +1,29 @@
+class C:
+ """This is a class summary that consists of a very long single line,
exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+ """
+ def meth(self):
+ """This is a method summary that consists of a very long single line,
exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+ """
+
+ @property
+ def prop(self):
+ """This is a property summary that consists of a very long single
line, exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+ """
+
+def func(self):
+ """This is a function summary that consists of a very long single line,
exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+ """
+
+data = C()
+data.__doc__ = """This is a data summary that consists of a very long single
line, exceeding the recommended PEP 8 limit.
+
+The rest of the docstring body, separated from the summary by a blank line,
can also contain very long lines.
+"""
diff --git a/Lib/test/test_pydoc/test_pydoc.py
b/Lib/test/test_pydoc/test_pydoc.py
index 5cd26923f75c311..5543c664528e6c8 100644
--- a/Lib/test/test_pydoc/test_pydoc.py
+++ b/Lib/test/test_pydoc/test_pydoc.py
@@ -1245,6 +1245,71 @@ def
function_with_really_long_name_so_annotations_can_be_rather_small(
<lambda> lambda
very_long_parameter_name_that_should_not_fit_into_a_single_line,
second_very_long_parameter_name
''' % __name__)
+ @requires_docstrings
+ def test_long_summaries(self):
+ from . import longsummary
+ doc = pydoc.render_doc(longsummary)
+ doc = clean_text(doc)
+ self.assertEqual(doc, '''Python Library Documentation: module
test.test_pydoc.longsummary in test.test_pydoc
+
+NAME
+ test.test_pydoc.longsummary
+
+CLASSES
+ builtins.object
+ C
+
+ class C(builtins.object)
+ | This is a class summary that consists of a very long single line,
+ | exceeding the recommended PEP 8 limit.
+ |
+ | The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+ |
+ | Methods defined here:
+ |
+ | meth(self)
+ | This is a method summary that consists of a very long single line,
+ | exceeding the recommended PEP 8 limit.
+ |
+ | The rest of the docstring body, separated from the summary by a
blank line, can also contain very long lines.
+ |
+ | ----------------------------------------------------------------------
+ | Readonly properties defined here:
+ |
+ | prop
+ | This is a property summary that consists of a very long single
line,
+ | exceeding the recommended PEP 8 limit.
+ |
+ | The rest of the docstring body, separated from the summary by a
blank line, can also contain very long lines.
+ |
+ | ----------------------------------------------------------------------
+ | Data descriptors defined here:
+ |
+ | __dict__
+ | dictionary for instance variables
+ |
+ | __weakref__
+ | list of weak references to the object
+
+FUNCTIONS
+ func(self)
+ This is a function summary that consists of a very long single line,
+ exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+
+DATA
+ data = <test.test_pydoc.longsummary.C object>
+ This is a data summary that consists of a very long single line,
+ exceeding the recommended PEP 8 limit.
+
+ The rest of the docstring body, separated from the summary by a blank
line, can also contain very long lines.
+
+FILE
+ %s
+
+''' % inspect.getabsfile(longsummary))
+
def test__future__imports(self):
# __future__ features are excluded from module help,
# except when it's the __future__ module itself
diff --git
a/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst
b/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst
new file mode 100644
index 000000000000000..60b1f3e0a71f5bb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst
@@ -0,0 +1 @@
+:mod:`pydoc` now wraps long single-line summary in text output.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]