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

terry.reedy python-checkins at python.org
Wed Jan 22 02:46:01 CET 2014


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

files:
  Lib/idlelib/CallTips.py                |  26 ++++++++-----
  Lib/idlelib/idle_test/test_calltips.py |  22 +++++++++--
  2 files changed, 34 insertions(+), 14 deletions(-)


diff --git a/Lib/idlelib/CallTips.py b/Lib/idlelib/CallTips.py
--- a/Lib/idlelib/CallTips.py
+++ b/Lib/idlelib/CallTips.py
@@ -116,17 +116,21 @@
             # exception, especially if user classes are involved.
             return None
 
-# The following are used in both get_argspec and tests
+# The following are used in get_argspec and some in tests
+_MAX_COLS = 79
+_MAX_LINES = 5  # enough for bytes
 _first_param = re.compile('(?<=\()\w*\,?\s*')
 _default_callable_argspec = "See source or doc"
 
+
 def get_argspec(ob):
     '''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 last line is the first line of the doc string.  For builtins, this typically
-    includes the arguments in addition to the return value.
+    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:
@@ -150,13 +154,15 @@
     else:
         doc = getattr(ob, "__doc__", "")
     if doc:
-        doc = doc.lstrip()
-        pos = doc.find("\n")
-        if pos < 0 or pos > 70:
-            pos = 70
-        if argspec:
-            argspec += "\n"
-        argspec += doc[:pos]
+        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)
     if not argspec:
         argspec = _default_callable_argspec
     return argspec
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
@@ -42,17 +42,15 @@
     # For a simple mismatch, change the expected output to the actual.
 
     def test_builtins(self):
-        # These test will break if
 
         # Python class that inherits builtin methods
         class List(list): "List() doc"
-        # Simulate builtin with no docstring for default argspec test
+        # Simulate builtin with no docstring for default tip test
         class SB:  __call__ = None
 
         def gtest(obj, out):
             self.assertEqual(signature(obj), out)
 
-        gtest(list, "list() -> new empty list")
         gtest(List, List.__doc__)
         gtest(list.__new__,
                'T.__new__(S, ...) -> a new object with type S, a subtype of T')
@@ -66,6 +64,21 @@
         gtest(types.MethodType, "method(function, instance)")
         gtest(SB(), default_tip)
 
+    def test_multiline_docstring(self):
+        # Test fewer lines than max.
+        self.assertEqual(signature(list),
+                "list() -> new empty list\n"
+                "list(iterable) -> new list initialized from iterable's items")
+
+        # Test max lines and line (currently) too long.
+        self.assertEqual(signature(bytes),
+"bytes(iterable_of_ints) -> bytes\n"
+"bytes(string, encoding[, errors]) -> bytes\n"
+"bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n"
+#bytes(int) -> bytes object of size given by the parameter initialized with null bytes
+"bytes(int) -> bytes object of size given by the parameter initialized with n...\n"
+"bytes() -> empty bytes object")
+
     def test_functions(self):
         def t1(): 'doc'
         t1.tip = "()"
@@ -100,7 +113,8 @@
         assert ct._first_param.sub('', uni) == '(a)'
 
     def test_no_docstring(self):
-        def nd(s): pass
+        def nd(s):
+            pass
         TC.nd = nd
         self.assertEqual(signature(nd), "(s)")
         self.assertEqual(signature(TC.nd), "(s)")

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


More information about the Python-checkins mailing list