##// END OF EJS Templates
Fix the display of functions with keyword-only arguments on Python 3.
Thomas Kluyver -
Show More
@@ -39,8 +39,8 b' from IPython.utils import py3compat'
39 from IPython.utils.dir2 import safe_hasattr
39 from IPython.utils.dir2 import safe_hasattr
40 from IPython.utils.text import indent
40 from IPython.utils.text import indent
41 from IPython.utils.wildcard import list_namespace
41 from IPython.utils.wildcard import list_namespace
42 from IPython.utils.coloransi import *
42 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
43 from IPython.utils.py3compat import cast_unicode, string_types
43 from IPython.utils.py3compat import cast_unicode, string_types, PY3
44
44
45 # builtin docstrings to ignore
45 # builtin docstrings to ignore
46 _func_call_docstring = types.FunctionType.__call__.__doc__
46 _func_call_docstring = types.FunctionType.__call__.__doc__
@@ -181,26 +181,17 b' def getsource(obj,is_binary=False):'
181 return cast_unicode(src, encoding=encoding)
181 return cast_unicode(src, encoding=encoding)
182
182
183 def getargspec(obj):
183 def getargspec(obj):
184 """Get the names and default values of a function's arguments.
184 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
185
185 :func:inspect.getargspec` on Python 2.
186 A tuple of four things is returned: (args, varargs, varkw, defaults).
186
187 'args' is a list of the argument names (it may contain nested lists).
187 In addition to functions and methods, this can also handle objects with a
188 'varargs' and 'varkw' are the names of the * and ** arguments or None.
188 ``__call__`` attribute.
189 'defaults' is an n-tuple of the default values of the last n arguments.
189 """
190
190 if not (inspect.isfunction(obj) or inspect.ismethod(obj)) \
191 Modified version of inspect.getargspec from the Python Standard
191 and safe_hasattr(obj, '__call__'):
192 Library."""
192 obj = obj.__call__
193
193
194 if inspect.isfunction(obj):
194 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
195 func_obj = obj
196 elif inspect.ismethod(obj):
197 func_obj = obj.__func__
198 elif hasattr(obj, '__call__'):
199 func_obj = obj.__call__
200 else:
201 raise TypeError('arg is not a Python function')
202 args, varargs, varkw = inspect.getargs(func_obj.__code__)
203 return args, varargs, varkw, func_obj.__defaults__
204
195
205
196
206 def format_argspec(argspec):
197 def format_argspec(argspec):
@@ -354,7 +345,6 b' class Inspector:'
354
345
355 If any exception is generated, None is returned instead and the
346 If any exception is generated, None is returned instead and the
356 exception is suppressed."""
347 exception is suppressed."""
357
358 try:
348 try:
359 hdef = oname + inspect.formatargspec(*getargspec(obj))
349 hdef = oname + inspect.formatargspec(*getargspec(obj))
360 return cast_unicode(hdef)
350 return cast_unicode(hdef)
@@ -613,7 +603,6 b' class Inspector:'
613
603
614 obj_type = type(obj)
604 obj_type = type(obj)
615
605
616 header = self.__head
617 if info is None:
606 if info is None:
618 ismagic = 0
607 ismagic = 0
619 isalias = 0
608 isalias = 0
@@ -803,13 +792,18 b' class Inspector:'
803
792
804 if callable_obj:
793 if callable_obj:
805 try:
794 try:
806 args, varargs, varkw, defaults = getargspec(callable_obj)
795 argspec = getargspec(callable_obj)
807 except (TypeError, AttributeError):
796 except (TypeError, AttributeError):
808 # For extensions/builtins we can't retrieve the argspec
797 # For extensions/builtins we can't retrieve the argspec
809 pass
798 pass
810 else:
799 else:
811 out['argspec'] = dict(args=args, varargs=varargs,
800 # named tuples' _asdict() method returns an OrderedDict, but we
812 varkw=varkw, defaults=defaults)
801 # we want a normal
802 out['argspec'] = argspec_dict = dict(argspec._asdict())
803 # We called this varkw before argspec became a named tuple.
804 # With getfullargspec it's also called varkw.
805 if 'varkw' not in argspec_dict:
806 argspec_dict['varkw'] = argspec_dict.pop('keywords')
813
807
814 return object_info(**out)
808 return object_info(**out)
815
809
@@ -27,6 +27,7 b' from IPython.core.magic import (Magics, magics_class, line_magic,'
27 register_line_magic, register_cell_magic,
27 register_line_magic, register_cell_magic,
28 register_line_cell_magic)
28 register_line_cell_magic)
29 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
30 from IPython.testing.decorators import skipif
30 from IPython.utils import py3compat
31 from IPython.utils import py3compat
31
32
32
33
@@ -45,7 +46,7 b' ip = get_ipython()'
45 # defined, if any code is inserted above, the following line will need to be
46 # defined, if any code is inserted above, the following line will need to be
46 # updated. Do NOT insert any whitespace between the next line and the function
47 # updated. Do NOT insert any whitespace between the next line and the function
47 # definition below.
48 # definition below.
48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
49 THIS_LINE_NUMBER = 49 # Put here the actual number of this line
49 def test_find_source_lines():
50 def test_find_source_lines():
50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 THIS_LINE_NUMBER+1)
52 THIS_LINE_NUMBER+1)
@@ -270,6 +271,14 b' def test_info_awkward():'
270 # Just test that this doesn't throw an error.
271 # Just test that this doesn't throw an error.
271 i = inspector.info(Awkward())
272 i = inspector.info(Awkward())
272
273
274 if py3compat.PY3:
275 exec("def f_kwarg(pos, *, kwonly): pass")
276
277 @skipif(not py3compat.PY3)
278 def test_definition_kwonlyargs():
279 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
280 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
281
273 def test_getdoc():
282 def test_getdoc():
274 class A(object):
283 class A(object):
275 """standard docstring"""
284 """standard docstring"""
General Comments 0
You need to be logged in to leave comments. Login now