diff -r b26db63bb931 Lib/idlelib/CallTips.py --- a/Lib/idlelib/CallTips.py Thu Jan 23 00:36:46 2014 -0500 +++ b/Lib/idlelib/CallTips.py Fri Jan 24 02:03:21 2014 -0500 @@ -5,16 +5,16 @@ which disappear when you type a closing parenthesis. """ +import __main__ +import inspect import re import sys +import textwrap import types -import inspect from idlelib import CallTipWindow from idlelib.HyperParser import HyperParser -import __main__ - class CallTips: menudefs = [ @@ -117,8 +117,9 @@ return None # The following are used in get_argspec and some in tests -_MAX_COLS = 79 +_MAX_COLS = 85 _MAX_LINES = 5 # enough for bytes +_INDENT = ' ' # for wrapped signatures _first_param = re.compile('(?<=\()\w*\,?\s*') _default_callable_argspec = "See source or doc" @@ -145,17 +146,21 @@ fob = ob if isinstance(fob, (types.FunctionType, types.MethodType)): argspec = inspect.formatargspec(*inspect.getfullargspec(fob)) + #argspec = str(inspect.signature(fob)) if (isinstance(ob, (type, types.MethodType)) or isinstance(ob_call, types.MethodType)): argspec = _first_param.sub("", argspec) + lines = (textwrap.wrap(argspec, _MAX_COLS, subsequent_indent=_INDENT) + if len(argspec) > _MAX_COLS else [argspec] if argspec else []) + if isinstance(ob_call, types.MethodType): doc = ob_call.__doc__ else: doc = getattr(ob, "__doc__", "") if doc: - lines = [argspec] if argspec else [] - for line in doc.split('\n', 5)[:_MAX_LINES]: +# lines = [argspec] if argspec else [] + for line in doc.split('\n', _MAX_LINES)[:_MAX_LINES]: line = line.strip() if not line: break diff -r b26db63bb931 Lib/idlelib/idle_test/test_calltips.py --- a/Lib/idlelib/idle_test/test_calltips.py Thu Jan 23 00:36:46 2014 -0500 +++ b/Lib/idlelib/idle_test/test_calltips.py Fri Jan 24 02:03:21 2014 -0500 @@ -1,5 +1,6 @@ import unittest import idlelib.CallTips as ct +import textwrap import types default_tip = ct._default_callable_argspec @@ -64,20 +65,39 @@ gtest(types.MethodType, "method(function, instance)") gtest(SB(), default_tip) + def test_signature_wrap(self): + self.assertEqual(signature(textwrap.TextWrapper), '''\ +(width=70, initial_indent='', subsequent_indent='', expand_tabs=True, + replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, + drop_whitespace=True, break_on_hyphens=True, tabsize=8)''') + +## drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None, +## placeholder=' [...]') +# is the correct ending but *, ... not handled in 3.3. + + def test_docline_truncation(self): + def f(): pass + f.__doc__ = 'a'*300 + self.assertEqual(signature(f), '()\n' + 'a' * (ct._MAX_COLS-3) + '...') + 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") + # Test max lines + self.assertEqual(signature(bytes), '''\ +bytes(iterable_of_ints) -> bytes +bytes(string, encoding[, errors]) -> bytes +bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer +bytes(int) -> bytes object of size given by the parameter initialized with null bytes +bytes() -> empty bytes object''') + + # Test more than max lines + def f(): pass + f.__doc__ = 'a\n' * 15 + self.assertEqual(signature(f), '()' + '\na' * ct._MAX_LINES) def test_functions(self): def t1(): 'doc'