[Python-checkins] cpython (2.7): Issue #16638: Include up to 5 docstring header lines (before first blank) in

terry.reedy python-checkins at python.org
Wed Jan 22 02:45:59 CET 2014


http://hg.python.org/cpython/rev/6b62c923c0ef
changeset:   88627:6b62c923c0ef
branch:      2.7
user:        Terry Jan Reedy <tjreedy at udel.edu>
date:        Tue Jan 21 20:45:03 2014 -0500
summary:
  Issue #16638: Include up to 5 docstring header lines (before first blank) in
Idle calltips. This is needed for builtins, such 3.x bytes (which is why 5).
Based on patch by Serhiy Storchaka.

files:
  Lib/idlelib/CallTips.py                |  40 +++++++++----
  Lib/idlelib/idle_test/test_calltips.py |  15 ++++-
  2 files changed, 40 insertions(+), 15 deletions(-)


diff --git a/Lib/idlelib/CallTips.py b/Lib/idlelib/CallTips.py
--- a/Lib/idlelib/CallTips.py
+++ b/Lib/idlelib/CallTips.py
@@ -130,14 +130,24 @@
             if rc is not None: return rc
     return None
 
+# The following are used in get_arg_text
+_MAX_COLS = 79
+_MAX_LINES = 5  # enough for bytes
+
 def get_arg_text(ob):
-    """Get a string describing the arguments for the given object,
-       only if it is callable."""
-    arg_text = ""
+    '''Return a string describing the signature of a callable object, or ''.
+
+    For Python-coded functions and methods, the first line is introspected.
+    Delete 'self' parameter for classes (.__init__) and bound methods.
+    The next lines are the first lines of the doc string up to the first
+    empty line or _MAX_LINES.    For builtins, this typically includes
+    the arguments in addition to the return value.
+    '''
+    argspec = ""
     try:
         ob_call = ob.__call__
     except BaseException:
-        return arg_text
+        return argspec
 
     arg_offset = 0
     if type(ob) in (types.ClassType, types.TypeType):
@@ -171,22 +181,24 @@
             items.append("*args")
         if fob.func_code.co_flags & 0x8:
             items.append("**kwds")
-        arg_text = ", ".join(items)
-        arg_text = "(%s)" % re.sub("(?<!\d)\.\d+", "<tuple>", arg_text)
+        argspec = ", ".join(items)
+        argspec = "(%s)" % re.sub("(?<!\d)\.\d+", "<tuple>", argspec)
     # See if we can use the docstring
     if isinstance(ob_call, types.MethodType):
         doc = ob_call.__doc__
     else:
         doc = getattr(ob, "__doc__", "")
     if doc:
-        doc = doc.lstrip()
-        pos = doc.find("\n")
-        if pos < 0 or pos > 70:
-            pos = 70
-        if arg_text:
-            arg_text += "\n"
-        arg_text += doc[:pos]
-    return arg_text
+        lines = [argspec] if argspec else []
+        for line in doc.split('\n', 5)[:_MAX_LINES]:
+            line = line.strip()
+            if not line:
+                break
+            if len(line) > _MAX_COLS:
+                line = line[: _MAX_COLS - 3] + '...'
+            lines.append(line)
+        argspec = '\n'.join(lines)
+    return argspec
 
 if __name__ == '__main__':
     from unittest import main
diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py
--- a/Lib/idlelib/idle_test/test_calltips.py
+++ b/Lib/idlelib/idle_test/test_calltips.py
@@ -53,7 +53,6 @@
         def gtest(obj, out):
             self.assertEqual(signature(obj), out)
 
-        gtest(list, "()\nlist() -> new empty list")
         gtest(List, '()\n' + List.__doc__)
         gtest(list.__new__,
                'T.__new__(S, ...) -> a new object with type S, a subtype of T')
@@ -67,6 +66,20 @@
         gtest(types.MethodType, '()\ninstancemethod(function, instance, class)')
         gtest(SB(), default_tip)
 
+    def test_multiline_docstring(self):
+        # Test fewer lines than max.
+        self.assertEqual(signature(list),
+                "()\nlist() -> new empty list\n"
+                "list(iterable) -> new list initialized from iterable's items")
+
+        # Test max lines and line (currently) too long.
+        def f():
+            pass
+        s = 'a\nb\nc\nd\n'
+        f.__doc__ = s + 300 * 'e' + 'f'
+        self.assertEqual(signature(f),
+                         '()\n' + s + (ct._MAX_COLS - 3) * 'e' + '...')
+
     def test_functions(self):
         def t1(): 'doc'
         t1.tip = "()"

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list