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]

Reply via email to