File: docstring-dedent.patch

package info (click to toggle)
jupyter-client 8.6.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,604 kB
  • sloc: python: 9,025; makefile: 168; sh: 33
file content (93 lines) | stat: -rw-r--r-- 2,966 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
Description: Fix handling of docstring dedenting in Python 3.13
Forwarded: https://github.com/jupyter/jupyter_client/pull/1052
Bug-Debian: https://bugs.debian.org/1092533
Author: Julian Gilbey <jdg@debian.org>
Last-Update: 2025-01-13

--- a/jupyter_client/client.py	2024-07-29 09:27:07.000000000 +0100
+++ b/jupyter_client/client.py	2025-01-13 20:23:42.392822889 +0000
@@ -3,7 +3,9 @@
 # Distributed under the terms of the Modified BSD License.
 import asyncio
 import inspect
+import re
 import sys
+import textwrap
 import time
 import typing as t
 from functools import partial
@@ -35,6 +37,24 @@
             raise ValueError("value %r in dict must be a string" % v)
 
 
+def get_docstring_indent(doc: str) -> str:
+    # Python 3.13 dedents docstrings automatically.
+    # In this module, the docstring indent is the indent of the
+    # first non-blank line after the initial line, which is returned
+    # as a whitespace string.
+    # This is not a general method for determining the indent of a docstring!
+    # See the source code of textwrap.dedent() for that.
+    doclines = doc.split("\n")
+    for line in doclines[1:]:
+        if re.match(r"\s*$", line):
+            continue
+        linematch = re.match(r"(\s*)\S", line)
+        assert linematch is not None
+        return linematch.group(1)
+    # If there was no content in the docstring beyond the initial line
+    return ""
+
+
 def reqrep(wrapped: t.Callable, meth: t.Callable, channel: str = "shell") -> t.Callable:
     wrapped = wrapped(meth, channel)
     if not meth.__doc__:
@@ -42,31 +61,34 @@
         # so don't bother building the wrapped docstring
         return wrapped
 
-    basedoc, _ = meth.__doc__.split("Returns\n", 1)
-    parts = [basedoc.strip()]
-    if "Parameters" not in basedoc:
-        parts.append(
-            """
+    params_header = """\
         Parameters
         ----------
         """
-        )
-    parts.append(
-        """
-        reply: bool (default: False)
+    returns_doc = """\
+        reply : bool (default: False)
             Whether to wait for and return reply
-        timeout: float or None (default: None)
+
+        timeout : float or None (default: None)
             Timeout to use when waiting for a reply
 
         Returns
         -------
-        msg_id: str
+        msg_id : str
             The msg_id of the request sent, if reply=False (default)
-        reply: dict
+
+        reply : dict
             The reply message for this request, if reply=True
-    """
-    )
-    wrapped.__doc__ = "\n".join(parts)
+        """
+
+    basedoc, _ = meth.__doc__.split("Returns\n", 1)
+    parts = [basedoc.strip()]
+    indent = get_docstring_indent(basedoc)
+    if "Parameters" not in basedoc:
+        parts.append(textwrap.indent(textwrap.dedent(params_header), indent))
+    parts.append(textwrap.indent(textwrap.dedent(returns_doc), indent))
+
+    wrapped.__doc__ = "\n\n".join(parts)
     return wrapped