##// END OF EJS Templates
remove Python2 specific code
Srinivas Reddy Thatiparthy -
Show More
@@ -1,987 +1,980 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 __all__ = ['Inspector','InspectColors']
13 __all__ = ['Inspector','InspectColors']
14
14
15 # stdlib modules
15 # stdlib modules
16 import inspect
16 import inspect
17 from inspect import signature
17 from inspect import signature
18 import linecache
18 import linecache
19 import warnings
19 import warnings
20 import os
20 import os
21 from textwrap import dedent
21 from textwrap import dedent
22 import types
22 import types
23 import io as stdlib_io
23 import io as stdlib_io
24 from itertools import zip_longest
24 from itertools import zip_longest
25
25
26 # IPython's own
26 # IPython's own
27 from IPython.core import page
27 from IPython.core import page
28 from IPython.lib.pretty import pretty
28 from IPython.lib.pretty import pretty
29 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.testing.skipdoctest import skip_doctest
30 from IPython.utils import PyColorize
30 from IPython.utils import PyColorize
31 from IPython.utils import openpy
31 from IPython.utils import openpy
32 from IPython.utils import py3compat
32 from IPython.utils import py3compat
33 from IPython.utils.dir2 import safe_hasattr
33 from IPython.utils.dir2 import safe_hasattr
34 from IPython.utils.path import compress_user
34 from IPython.utils.path import compress_user
35 from IPython.utils.text import indent
35 from IPython.utils.text import indent
36 from IPython.utils.wildcard import list_namespace
36 from IPython.utils.wildcard import list_namespace
37 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
37 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
38 from IPython.utils.py3compat import cast_unicode
38 from IPython.utils.py3compat import cast_unicode
39 from IPython.utils.colorable import Colorable
39 from IPython.utils.colorable import Colorable
40 from IPython.utils.decorators import undoc
40 from IPython.utils.decorators import undoc
41
41
42 from pygments import highlight
42 from pygments import highlight
43 from pygments.lexers import PythonLexer
43 from pygments.lexers import PythonLexer
44 from pygments.formatters import HtmlFormatter
44 from pygments.formatters import HtmlFormatter
45
45
46 def pylight(code):
46 def pylight(code):
47 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
47 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
48
48
49 # builtin docstrings to ignore
49 # builtin docstrings to ignore
50 _func_call_docstring = types.FunctionType.__call__.__doc__
50 _func_call_docstring = types.FunctionType.__call__.__doc__
51 _object_init_docstring = object.__init__.__doc__
51 _object_init_docstring = object.__init__.__doc__
52 _builtin_type_docstrings = {
52 _builtin_type_docstrings = {
53 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
53 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
54 types.FunctionType, property)
54 types.FunctionType, property)
55 }
55 }
56
56
57 _builtin_func_type = type(all)
57 _builtin_func_type = type(all)
58 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
58 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
59 #****************************************************************************
59 #****************************************************************************
60 # Builtin color schemes
60 # Builtin color schemes
61
61
62 Colors = TermColors # just a shorthand
62 Colors = TermColors # just a shorthand
63
63
64 InspectColors = PyColorize.ANSICodeColors
64 InspectColors = PyColorize.ANSICodeColors
65
65
66 #****************************************************************************
66 #****************************************************************************
67 # Auxiliary functions and objects
67 # Auxiliary functions and objects
68
68
69 # See the messaging spec for the definition of all these fields. This list
69 # See the messaging spec for the definition of all these fields. This list
70 # effectively defines the order of display
70 # effectively defines the order of display
71 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
71 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
72 'length', 'file', 'definition', 'docstring', 'source',
72 'length', 'file', 'definition', 'docstring', 'source',
73 'init_definition', 'class_docstring', 'init_docstring',
73 'init_definition', 'class_docstring', 'init_docstring',
74 'call_def', 'call_docstring',
74 'call_def', 'call_docstring',
75 # These won't be printed but will be used to determine how to
75 # These won't be printed but will be used to determine how to
76 # format the object
76 # format the object
77 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
77 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
78 ]
78 ]
79
79
80
80
81 def object_info(**kw):
81 def object_info(**kw):
82 """Make an object info dict with all fields present."""
82 """Make an object info dict with all fields present."""
83 infodict = dict(zip_longest(info_fields, [None]))
83 infodict = dict(zip_longest(info_fields, [None]))
84 infodict.update(kw)
84 infodict.update(kw)
85 return infodict
85 return infodict
86
86
87
87
88 def get_encoding(obj):
88 def get_encoding(obj):
89 """Get encoding for python source file defining obj
89 """Get encoding for python source file defining obj
90
90
91 Returns None if obj is not defined in a sourcefile.
91 Returns None if obj is not defined in a sourcefile.
92 """
92 """
93 ofile = find_file(obj)
93 ofile = find_file(obj)
94 # run contents of file through pager starting at line where the object
94 # run contents of file through pager starting at line where the object
95 # is defined, as long as the file isn't binary and is actually on the
95 # is defined, as long as the file isn't binary and is actually on the
96 # filesystem.
96 # filesystem.
97 if ofile is None:
97 if ofile is None:
98 return None
98 return None
99 elif ofile.endswith(('.so', '.dll', '.pyd')):
99 elif ofile.endswith(('.so', '.dll', '.pyd')):
100 return None
100 return None
101 elif not os.path.isfile(ofile):
101 elif not os.path.isfile(ofile):
102 return None
102 return None
103 else:
103 else:
104 # Print only text files, not extension binaries. Note that
104 # Print only text files, not extension binaries. Note that
105 # getsourcelines returns lineno with 1-offset and page() uses
105 # getsourcelines returns lineno with 1-offset and page() uses
106 # 0-offset, so we must adjust.
106 # 0-offset, so we must adjust.
107 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
107 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
108 encoding, lines = openpy.detect_encoding(buffer.readline)
108 encoding, lines = openpy.detect_encoding(buffer.readline)
109 return encoding
109 return encoding
110
110
111 def getdoc(obj):
111 def getdoc(obj):
112 """Stable wrapper around inspect.getdoc.
112 """Stable wrapper around inspect.getdoc.
113
113
114 This can't crash because of attribute problems.
114 This can't crash because of attribute problems.
115
115
116 It also attempts to call a getdoc() method on the given object. This
116 It also attempts to call a getdoc() method on the given object. This
117 allows objects which provide their docstrings via non-standard mechanisms
117 allows objects which provide their docstrings via non-standard mechanisms
118 (like Pyro proxies) to still be inspected by ipython's ? system.
118 (like Pyro proxies) to still be inspected by ipython's ? system.
119 """
119 """
120 # Allow objects to offer customized documentation via a getdoc method:
120 # Allow objects to offer customized documentation via a getdoc method:
121 try:
121 try:
122 ds = obj.getdoc()
122 ds = obj.getdoc()
123 except Exception:
123 except Exception:
124 pass
124 pass
125 else:
125 else:
126 # if we get extra info, we add it to the normal docstring.
126 # if we get extra info, we add it to the normal docstring.
127 if isinstance(ds, str):
127 if isinstance(ds, str):
128 return inspect.cleandoc(ds)
128 return inspect.cleandoc(ds)
129 try:
129 try:
130 docstr = inspect.getdoc(obj)
130 docstr = inspect.getdoc(obj)
131 encoding = get_encoding(obj)
131 encoding = get_encoding(obj)
132 return py3compat.cast_unicode(docstr, encoding=encoding)
132 return py3compat.cast_unicode(docstr, encoding=encoding)
133 except Exception:
133 except Exception:
134 # Harden against an inspect failure, which can occur with
134 # Harden against an inspect failure, which can occur with
135 # extensions modules.
135 # extensions modules.
136 raise
136 raise
137 return None
137 return None
138
138
139
139
140 def getsource(obj, oname=''):
140 def getsource(obj, oname=''):
141 """Wrapper around inspect.getsource.
141 """Wrapper around inspect.getsource.
142
142
143 This can be modified by other projects to provide customized source
143 This can be modified by other projects to provide customized source
144 extraction.
144 extraction.
145
145
146 Parameters
146 Parameters
147 ----------
147 ----------
148 obj : object
148 obj : object
149 an object whose source code we will attempt to extract
149 an object whose source code we will attempt to extract
150 oname : str
150 oname : str
151 (optional) a name under which the object is known
151 (optional) a name under which the object is known
152
152
153 Returns
153 Returns
154 -------
154 -------
155 src : unicode or None
155 src : unicode or None
156
156
157 """
157 """
158
158
159 if isinstance(obj, property):
159 if isinstance(obj, property):
160 sources = []
160 sources = []
161 for attrname in ['fget', 'fset', 'fdel']:
161 for attrname in ['fget', 'fset', 'fdel']:
162 fn = getattr(obj, attrname)
162 fn = getattr(obj, attrname)
163 if fn is not None:
163 if fn is not None:
164 encoding = get_encoding(fn)
164 encoding = get_encoding(fn)
165 oname_prefix = ('%s.' % oname) if oname else ''
165 oname_prefix = ('%s.' % oname) if oname else ''
166 sources.append(cast_unicode(
166 sources.append(cast_unicode(
167 ''.join(('# ', oname_prefix, attrname)),
167 ''.join(('# ', oname_prefix, attrname)),
168 encoding=encoding))
168 encoding=encoding))
169 if inspect.isfunction(fn):
169 if inspect.isfunction(fn):
170 sources.append(dedent(getsource(fn)))
170 sources.append(dedent(getsource(fn)))
171 else:
171 else:
172 # Default str/repr only prints function name,
172 # Default str/repr only prints function name,
173 # pretty.pretty prints module name too.
173 # pretty.pretty prints module name too.
174 sources.append(cast_unicode(
174 sources.append(cast_unicode(
175 '%s%s = %s\n' % (
175 '%s%s = %s\n' % (
176 oname_prefix, attrname, pretty(fn)),
176 oname_prefix, attrname, pretty(fn)),
177 encoding=encoding))
177 encoding=encoding))
178 if sources:
178 if sources:
179 return '\n'.join(sources)
179 return '\n'.join(sources)
180 else:
180 else:
181 return None
181 return None
182
182
183 else:
183 else:
184 # Get source for non-property objects.
184 # Get source for non-property objects.
185
185
186 obj = _get_wrapped(obj)
186 obj = _get_wrapped(obj)
187
187
188 try:
188 try:
189 src = inspect.getsource(obj)
189 src = inspect.getsource(obj)
190 except TypeError:
190 except TypeError:
191 # The object itself provided no meaningful source, try looking for
191 # The object itself provided no meaningful source, try looking for
192 # its class definition instead.
192 # its class definition instead.
193 if hasattr(obj, '__class__'):
193 if hasattr(obj, '__class__'):
194 try:
194 try:
195 src = inspect.getsource(obj.__class__)
195 src = inspect.getsource(obj.__class__)
196 except TypeError:
196 except TypeError:
197 return None
197 return None
198
198
199 encoding = get_encoding(obj)
199 encoding = get_encoding(obj)
200 return cast_unicode(src, encoding=encoding)
200 return cast_unicode(src, encoding=encoding)
201
201
202
202
203 def is_simple_callable(obj):
203 def is_simple_callable(obj):
204 """True if obj is a function ()"""
204 """True if obj is a function ()"""
205 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
205 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
206 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
206 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
207
207
208
208
209 def getargspec(obj):
209 def getargspec(obj):
210 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
210 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
211 :func:inspect.getargspec` on Python 2.
211 :func:inspect.getargspec` on Python 2.
212
212
213 In addition to functions and methods, this can also handle objects with a
213 In addition to functions and methods, this can also handle objects with a
214 ``__call__`` attribute.
214 ``__call__`` attribute.
215 """
215 """
216 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
216 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
217 obj = obj.__call__
217 obj = obj.__call__
218
218
219 return inspect.getfullargspec(obj)
219 return inspect.getfullargspec(obj)
220
220
221
221
222 def format_argspec(argspec):
222 def format_argspec(argspec):
223 """Format argspect, convenience wrapper around inspect's.
223 """Format argspect, convenience wrapper around inspect's.
224
224
225 This takes a dict instead of ordered arguments and calls
225 This takes a dict instead of ordered arguments and calls
226 inspect.format_argspec with the arguments in the necessary order.
226 inspect.format_argspec with the arguments in the necessary order.
227 """
227 """
228 return inspect.formatargspec(argspec['args'], argspec['varargs'],
228 return inspect.formatargspec(argspec['args'], argspec['varargs'],
229 argspec['varkw'], argspec['defaults'])
229 argspec['varkw'], argspec['defaults'])
230
230
231 @undoc
231 @undoc
232 def call_tip(oinfo, format_call=True):
232 def call_tip(oinfo, format_call=True):
233 """DEPRECATED. Extract call tip data from an oinfo dict.
233 """DEPRECATED. Extract call tip data from an oinfo dict.
234 """
234 """
235 warnings.warn('`call_tip` function is deprecated as of IPython 6.0'
235 warnings.warn('`call_tip` function is deprecated as of IPython 6.0'
236 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
236 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
237 # Get call definition
237 # Get call definition
238 argspec = oinfo.get('argspec')
238 argspec = oinfo.get('argspec')
239 if argspec is None:
239 if argspec is None:
240 call_line = None
240 call_line = None
241 else:
241 else:
242 # Callable objects will have 'self' as their first argument, prune
242 # Callable objects will have 'self' as their first argument, prune
243 # it out if it's there for clarity (since users do *not* pass an
243 # it out if it's there for clarity (since users do *not* pass an
244 # extra first argument explicitly).
244 # extra first argument explicitly).
245 try:
245 try:
246 has_self = argspec['args'][0] == 'self'
246 has_self = argspec['args'][0] == 'self'
247 except (KeyError, IndexError):
247 except (KeyError, IndexError):
248 pass
248 pass
249 else:
249 else:
250 if has_self:
250 if has_self:
251 argspec['args'] = argspec['args'][1:]
251 argspec['args'] = argspec['args'][1:]
252
252
253 call_line = oinfo['name']+format_argspec(argspec)
253 call_line = oinfo['name']+format_argspec(argspec)
254
254
255 # Now get docstring.
255 # Now get docstring.
256 # The priority is: call docstring, constructor docstring, main one.
256 # The priority is: call docstring, constructor docstring, main one.
257 doc = oinfo.get('call_docstring')
257 doc = oinfo.get('call_docstring')
258 if doc is None:
258 if doc is None:
259 doc = oinfo.get('init_docstring')
259 doc = oinfo.get('init_docstring')
260 if doc is None:
260 if doc is None:
261 doc = oinfo.get('docstring','')
261 doc = oinfo.get('docstring','')
262
262
263 return call_line, doc
263 return call_line, doc
264
264
265
265
266 def _get_wrapped(obj):
266 def _get_wrapped(obj):
267 """Get the original object if wrapped in one or more @decorators
267 """Get the original object if wrapped in one or more @decorators
268
268
269 Some objects automatically construct similar objects on any unrecognised
269 Some objects automatically construct similar objects on any unrecognised
270 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
270 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
271 this will arbitrarily cut off after 100 levels of obj.__wrapped__
271 this will arbitrarily cut off after 100 levels of obj.__wrapped__
272 attribute access. --TK, Jan 2016
272 attribute access. --TK, Jan 2016
273 """
273 """
274 orig_obj = obj
274 orig_obj = obj
275 i = 0
275 i = 0
276 while safe_hasattr(obj, '__wrapped__'):
276 while safe_hasattr(obj, '__wrapped__'):
277 obj = obj.__wrapped__
277 obj = obj.__wrapped__
278 i += 1
278 i += 1
279 if i > 100:
279 if i > 100:
280 # __wrapped__ is probably a lie, so return the thing we started with
280 # __wrapped__ is probably a lie, so return the thing we started with
281 return orig_obj
281 return orig_obj
282 return obj
282 return obj
283
283
284 def find_file(obj):
284 def find_file(obj):
285 """Find the absolute path to the file where an object was defined.
285 """Find the absolute path to the file where an object was defined.
286
286
287 This is essentially a robust wrapper around `inspect.getabsfile`.
287 This is essentially a robust wrapper around `inspect.getabsfile`.
288
288
289 Returns None if no file can be found.
289 Returns None if no file can be found.
290
290
291 Parameters
291 Parameters
292 ----------
292 ----------
293 obj : any Python object
293 obj : any Python object
294
294
295 Returns
295 Returns
296 -------
296 -------
297 fname : str
297 fname : str
298 The absolute path to the file where the object was defined.
298 The absolute path to the file where the object was defined.
299 """
299 """
300 obj = _get_wrapped(obj)
300 obj = _get_wrapped(obj)
301
301
302 fname = None
302 fname = None
303 try:
303 try:
304 fname = inspect.getabsfile(obj)
304 fname = inspect.getabsfile(obj)
305 except TypeError:
305 except TypeError:
306 # For an instance, the file that matters is where its class was
306 # For an instance, the file that matters is where its class was
307 # declared.
307 # declared.
308 if hasattr(obj, '__class__'):
308 if hasattr(obj, '__class__'):
309 try:
309 try:
310 fname = inspect.getabsfile(obj.__class__)
310 fname = inspect.getabsfile(obj.__class__)
311 except TypeError:
311 except TypeError:
312 # Can happen for builtins
312 # Can happen for builtins
313 pass
313 pass
314 except:
314 except:
315 pass
315 pass
316 return cast_unicode(fname)
316 return cast_unicode(fname)
317
317
318
318
319 def find_source_lines(obj):
319 def find_source_lines(obj):
320 """Find the line number in a file where an object was defined.
320 """Find the line number in a file where an object was defined.
321
321
322 This is essentially a robust wrapper around `inspect.getsourcelines`.
322 This is essentially a robust wrapper around `inspect.getsourcelines`.
323
323
324 Returns None if no file can be found.
324 Returns None if no file can be found.
325
325
326 Parameters
326 Parameters
327 ----------
327 ----------
328 obj : any Python object
328 obj : any Python object
329
329
330 Returns
330 Returns
331 -------
331 -------
332 lineno : int
332 lineno : int
333 The line number where the object definition starts.
333 The line number where the object definition starts.
334 """
334 """
335 obj = _get_wrapped(obj)
335 obj = _get_wrapped(obj)
336
336
337 try:
337 try:
338 try:
338 try:
339 lineno = inspect.getsourcelines(obj)[1]
339 lineno = inspect.getsourcelines(obj)[1]
340 except TypeError:
340 except TypeError:
341 # For instances, try the class object like getsource() does
341 # For instances, try the class object like getsource() does
342 if hasattr(obj, '__class__'):
342 if hasattr(obj, '__class__'):
343 lineno = inspect.getsourcelines(obj.__class__)[1]
343 lineno = inspect.getsourcelines(obj.__class__)[1]
344 else:
344 else:
345 lineno = None
345 lineno = None
346 except:
346 except:
347 return None
347 return None
348
348
349 return lineno
349 return lineno
350
350
351 class Inspector(Colorable):
351 class Inspector(Colorable):
352
352
353 def __init__(self, color_table=InspectColors,
353 def __init__(self, color_table=InspectColors,
354 code_color_table=PyColorize.ANSICodeColors,
354 code_color_table=PyColorize.ANSICodeColors,
355 scheme='NoColor',
355 scheme='NoColor',
356 str_detail_level=0,
356 str_detail_level=0,
357 parent=None, config=None):
357 parent=None, config=None):
358 super(Inspector, self).__init__(parent=parent, config=config)
358 super(Inspector, self).__init__(parent=parent, config=config)
359 self.color_table = color_table
359 self.color_table = color_table
360 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
360 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
361 self.format = self.parser.format
361 self.format = self.parser.format
362 self.str_detail_level = str_detail_level
362 self.str_detail_level = str_detail_level
363 self.set_active_scheme(scheme)
363 self.set_active_scheme(scheme)
364
364
365 def _getdef(self,obj,oname=''):
365 def _getdef(self,obj,oname=''):
366 """Return the call signature for any callable object.
366 """Return the call signature for any callable object.
367
367
368 If any exception is generated, None is returned instead and the
368 If any exception is generated, None is returned instead and the
369 exception is suppressed."""
369 exception is suppressed."""
370 try:
370 try:
371 hdef = oname + str(signature(obj))
371 hdef = oname + str(signature(obj))
372 return cast_unicode(hdef)
372 return cast_unicode(hdef)
373 except:
373 except:
374 return None
374 return None
375
375
376 def __head(self,h):
376 def __head(self,h):
377 """Return a header string with proper colors."""
377 """Return a header string with proper colors."""
378 return '%s%s%s' % (self.color_table.active_colors.header,h,
378 return '%s%s%s' % (self.color_table.active_colors.header,h,
379 self.color_table.active_colors.normal)
379 self.color_table.active_colors.normal)
380
380
381 def set_active_scheme(self, scheme):
381 def set_active_scheme(self, scheme):
382 self.color_table.set_active_scheme(scheme)
382 self.color_table.set_active_scheme(scheme)
383 self.parser.color_table.set_active_scheme(scheme)
383 self.parser.color_table.set_active_scheme(scheme)
384
384
385 def noinfo(self, msg, oname):
385 def noinfo(self, msg, oname):
386 """Generic message when no information is found."""
386 """Generic message when no information is found."""
387 print('No %s found' % msg, end=' ')
387 print('No %s found' % msg, end=' ')
388 if oname:
388 if oname:
389 print('for %s' % oname)
389 print('for %s' % oname)
390 else:
390 else:
391 print()
391 print()
392
392
393 def pdef(self, obj, oname=''):
393 def pdef(self, obj, oname=''):
394 """Print the call signature for any callable object.
394 """Print the call signature for any callable object.
395
395
396 If the object is a class, print the constructor information."""
396 If the object is a class, print the constructor information."""
397
397
398 if not callable(obj):
398 if not callable(obj):
399 print('Object is not callable.')
399 print('Object is not callable.')
400 return
400 return
401
401
402 header = ''
402 header = ''
403
403
404 if inspect.isclass(obj):
404 if inspect.isclass(obj):
405 header = self.__head('Class constructor information:\n')
405 header = self.__head('Class constructor information:\n')
406 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
406
407 obj = obj.__call__
408
407
409 output = self._getdef(obj,oname)
408 output = self._getdef(obj,oname)
410 if output is None:
409 if output is None:
411 self.noinfo('definition header',oname)
410 self.noinfo('definition header',oname)
412 else:
411 else:
413 print(header,self.format(output), end=' ')
412 print(header,self.format(output), end=' ')
414
413
415 # In Python 3, all classes are new-style, so they all have __init__.
414 # In Python 3, all classes are new-style, so they all have __init__.
416 @skip_doctest
415 @skip_doctest
417 def pdoc(self, obj, oname='', formatter=None):
416 def pdoc(self, obj, oname='', formatter=None):
418 """Print the docstring for any object.
417 """Print the docstring for any object.
419
418
420 Optional:
419 Optional:
421 -formatter: a function to run the docstring through for specially
420 -formatter: a function to run the docstring through for specially
422 formatted docstrings.
421 formatted docstrings.
423
422
424 Examples
423 Examples
425 --------
424 --------
426
425
427 In [1]: class NoInit:
426 In [1]: class NoInit:
428 ...: pass
427 ...: pass
429
428
430 In [2]: class NoDoc:
429 In [2]: class NoDoc:
431 ...: def __init__(self):
430 ...: def __init__(self):
432 ...: pass
431 ...: pass
433
432
434 In [3]: %pdoc NoDoc
433 In [3]: %pdoc NoDoc
435 No documentation found for NoDoc
434 No documentation found for NoDoc
436
435
437 In [4]: %pdoc NoInit
436 In [4]: %pdoc NoInit
438 No documentation found for NoInit
437 No documentation found for NoInit
439
438
440 In [5]: obj = NoInit()
439 In [5]: obj = NoInit()
441
440
442 In [6]: %pdoc obj
441 In [6]: %pdoc obj
443 No documentation found for obj
442 No documentation found for obj
444
443
445 In [5]: obj2 = NoDoc()
444 In [5]: obj2 = NoDoc()
446
445
447 In [6]: %pdoc obj2
446 In [6]: %pdoc obj2
448 No documentation found for obj2
447 No documentation found for obj2
449 """
448 """
450
449
451 head = self.__head # For convenience
450 head = self.__head # For convenience
452 lines = []
451 lines = []
453 ds = getdoc(obj)
452 ds = getdoc(obj)
454 if formatter:
453 if formatter:
455 ds = formatter(ds).get('plain/text', ds)
454 ds = formatter(ds).get('plain/text', ds)
456 if ds:
455 if ds:
457 lines.append(head("Class docstring:"))
456 lines.append(head("Class docstring:"))
458 lines.append(indent(ds))
457 lines.append(indent(ds))
459 if inspect.isclass(obj) and hasattr(obj, '__init__'):
458 if inspect.isclass(obj) and hasattr(obj, '__init__'):
460 init_ds = getdoc(obj.__init__)
459 init_ds = getdoc(obj.__init__)
461 if init_ds is not None:
460 if init_ds is not None:
462 lines.append(head("Init docstring:"))
461 lines.append(head("Init docstring:"))
463 lines.append(indent(init_ds))
462 lines.append(indent(init_ds))
464 elif hasattr(obj,'__call__'):
463 elif hasattr(obj,'__call__'):
465 call_ds = getdoc(obj.__call__)
464 call_ds = getdoc(obj.__call__)
466 if call_ds:
465 if call_ds:
467 lines.append(head("Call docstring:"))
466 lines.append(head("Call docstring:"))
468 lines.append(indent(call_ds))
467 lines.append(indent(call_ds))
469
468
470 if not lines:
469 if not lines:
471 self.noinfo('documentation',oname)
470 self.noinfo('documentation',oname)
472 else:
471 else:
473 page.page('\n'.join(lines))
472 page.page('\n'.join(lines))
474
473
475 def psource(self, obj, oname=''):
474 def psource(self, obj, oname=''):
476 """Print the source code for an object."""
475 """Print the source code for an object."""
477
476
478 # Flush the source cache because inspect can return out-of-date source
477 # Flush the source cache because inspect can return out-of-date source
479 linecache.checkcache()
478 linecache.checkcache()
480 try:
479 try:
481 src = getsource(obj, oname=oname)
480 src = getsource(obj, oname=oname)
482 except Exception:
481 except Exception:
483 src = None
482 src = None
484
483
485 if src is None:
484 if src is None:
486 self.noinfo('source', oname)
485 self.noinfo('source', oname)
487 else:
486 else:
488 page.page(self.format(src))
487 page.page(self.format(src))
489
488
490 def pfile(self, obj, oname=''):
489 def pfile(self, obj, oname=''):
491 """Show the whole file where an object was defined."""
490 """Show the whole file where an object was defined."""
492
491
493 lineno = find_source_lines(obj)
492 lineno = find_source_lines(obj)
494 if lineno is None:
493 if lineno is None:
495 self.noinfo('file', oname)
494 self.noinfo('file', oname)
496 return
495 return
497
496
498 ofile = find_file(obj)
497 ofile = find_file(obj)
499 # run contents of file through pager starting at line where the object
498 # run contents of file through pager starting at line where the object
500 # is defined, as long as the file isn't binary and is actually on the
499 # is defined, as long as the file isn't binary and is actually on the
501 # filesystem.
500 # filesystem.
502 if ofile.endswith(('.so', '.dll', '.pyd')):
501 if ofile.endswith(('.so', '.dll', '.pyd')):
503 print('File %r is binary, not printing.' % ofile)
502 print('File %r is binary, not printing.' % ofile)
504 elif not os.path.isfile(ofile):
503 elif not os.path.isfile(ofile):
505 print('File %r does not exist, not printing.' % ofile)
504 print('File %r does not exist, not printing.' % ofile)
506 else:
505 else:
507 # Print only text files, not extension binaries. Note that
506 # Print only text files, not extension binaries. Note that
508 # getsourcelines returns lineno with 1-offset and page() uses
507 # getsourcelines returns lineno with 1-offset and page() uses
509 # 0-offset, so we must adjust.
508 # 0-offset, so we must adjust.
510 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
509 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
511
510
512 def _format_fields(self, fields, title_width=0):
511 def _format_fields(self, fields, title_width=0):
513 """Formats a list of fields for display.
512 """Formats a list of fields for display.
514
513
515 Parameters
514 Parameters
516 ----------
515 ----------
517 fields : list
516 fields : list
518 A list of 2-tuples: (field_title, field_content)
517 A list of 2-tuples: (field_title, field_content)
519 title_width : int
518 title_width : int
520 How many characters to pad titles to. Default to longest title.
519 How many characters to pad titles to. Default to longest title.
521 """
520 """
522 out = []
521 out = []
523 header = self.__head
522 header = self.__head
524 if title_width == 0:
523 if title_width == 0:
525 title_width = max(len(title) + 2 for title, _ in fields)
524 title_width = max(len(title) + 2 for title, _ in fields)
526 for title, content in fields:
525 for title, content in fields:
527 if len(content.splitlines()) > 1:
526 if len(content.splitlines()) > 1:
528 title = header(title + ':') + '\n'
527 title = header(title + ':') + '\n'
529 else:
528 else:
530 title = header((title + ':').ljust(title_width))
529 title = header((title + ':').ljust(title_width))
531 out.append(cast_unicode(title) + cast_unicode(content))
530 out.append(cast_unicode(title) + cast_unicode(content))
532 return "\n".join(out)
531 return "\n".join(out)
533
532
534 def _mime_format(self, text, formatter=None):
533 def _mime_format(self, text, formatter=None):
535 """Return a mime bundle representation of the input text.
534 """Return a mime bundle representation of the input text.
536
535
537 - if `formatter` is None, the returned mime bundle has
536 - if `formatter` is None, the returned mime bundle has
538 a `text/plain` field, with the input text.
537 a `text/plain` field, with the input text.
539 a `text/html` field with a `<pre>` tag containing the input text.
538 a `text/html` field with a `<pre>` tag containing the input text.
540
539
541 - if `formatter` is not None, it must be a callable transforming the
540 - if `formatter` is not None, it must be a callable transforming the
542 input text into a mime bundle. Default values for `text/plain` and
541 input text into a mime bundle. Default values for `text/plain` and
543 `text/html` representations are the ones described above.
542 `text/html` representations are the ones described above.
544
543
545 Note:
544 Note:
546
545
547 Formatters returning strings are supported but this behavior is deprecated.
546 Formatters returning strings are supported but this behavior is deprecated.
548
547
549 """
548 """
550 text = cast_unicode(text)
549 text = cast_unicode(text)
551 defaults = {
550 defaults = {
552 'text/plain': text,
551 'text/plain': text,
553 'text/html': '<pre>' + text + '</pre>'
552 'text/html': '<pre>' + text + '</pre>'
554 }
553 }
555
554
556 if formatter is None:
555 if formatter is None:
557 return defaults
556 return defaults
558 else:
557 else:
559 formatted = formatter(text)
558 formatted = formatter(text)
560
559
561 if not isinstance(formatted, dict):
560 if not isinstance(formatted, dict):
562 # Handle the deprecated behavior of a formatter returning
561 # Handle the deprecated behavior of a formatter returning
563 # a string instead of a mime bundle.
562 # a string instead of a mime bundle.
564 return {
563 return {
565 'text/plain': formatted,
564 'text/plain': formatted,
566 'text/html': '<pre>' + formatted + '</pre>'
565 'text/html': '<pre>' + formatted + '</pre>'
567 }
566 }
568
567
569 else:
568 else:
570 return dict(defaults, **formatted)
569 return dict(defaults, **formatted)
571
570
572
571
573 def format_mime(self, bundle):
572 def format_mime(self, bundle):
574
573
575 text_plain = bundle['text/plain']
574 text_plain = bundle['text/plain']
576
575
577 text = ''
576 text = ''
578 heads, bodies = list(zip(*text_plain))
577 heads, bodies = list(zip(*text_plain))
579 _len = max(len(h) for h in heads)
578 _len = max(len(h) for h in heads)
580
579
581 for head, body in zip(heads, bodies):
580 for head, body in zip(heads, bodies):
582 body = body.strip('\n')
581 body = body.strip('\n')
583 delim = '\n' if '\n' in body else ' '
582 delim = '\n' if '\n' in body else ' '
584 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
583 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
585
584
586 bundle['text/plain'] = text
585 bundle['text/plain'] = text
587 return bundle
586 return bundle
588
587
589 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
588 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
590 """Retrieve an info dict and format it."""
589 """Retrieve an info dict and format it."""
591
590
592 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
591 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
593
592
594 _mime = {
593 _mime = {
595 'text/plain': [],
594 'text/plain': [],
596 'text/html': '',
595 'text/html': '',
597 }
596 }
598
597
599 def append_field(bundle, title, key, formatter=None):
598 def append_field(bundle, title, key, formatter=None):
600 field = info[key]
599 field = info[key]
601 if field is not None:
600 if field is not None:
602 formatted_field = self._mime_format(field, formatter)
601 formatted_field = self._mime_format(field, formatter)
603 bundle['text/plain'].append((title, formatted_field['text/plain']))
602 bundle['text/plain'].append((title, formatted_field['text/plain']))
604 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
603 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
605
604
606 def code_formatter(text):
605 def code_formatter(text):
607 return {
606 return {
608 'text/plain': self.format(text),
607 'text/plain': self.format(text),
609 'text/html': pylight(text)
608 'text/html': pylight(text)
610 }
609 }
611
610
612 if info['isalias']:
611 if info['isalias']:
613 append_field(_mime, 'Repr', 'string_form')
612 append_field(_mime, 'Repr', 'string_form')
614
613
615 elif info['ismagic']:
614 elif info['ismagic']:
616 if detail_level > 0:
615 if detail_level > 0:
617 append_field(_mime, 'Source', 'source', code_formatter)
616 append_field(_mime, 'Source', 'source', code_formatter)
618 else:
617 else:
619 append_field(_mime, 'Docstring', 'docstring', formatter)
618 append_field(_mime, 'Docstring', 'docstring', formatter)
620 append_field(_mime, 'File', 'file')
619 append_field(_mime, 'File', 'file')
621
620
622 elif info['isclass'] or is_simple_callable(obj):
621 elif info['isclass'] or is_simple_callable(obj):
623 # Functions, methods, classes
622 # Functions, methods, classes
624 append_field(_mime, 'Signature', 'definition', code_formatter)
623 append_field(_mime, 'Signature', 'definition', code_formatter)
625 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
624 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
626 if detail_level > 0 and info['source']:
625 if detail_level > 0 and info['source']:
627 append_field(_mime, 'Source', 'source', code_formatter)
626 append_field(_mime, 'Source', 'source', code_formatter)
628 else:
627 else:
629 append_field(_mime, 'Docstring', 'docstring', formatter)
628 append_field(_mime, 'Docstring', 'docstring', formatter)
630 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
629 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
631
630
632 append_field(_mime, 'File', 'file')
631 append_field(_mime, 'File', 'file')
633 append_field(_mime, 'Type', 'type_name')
632 append_field(_mime, 'Type', 'type_name')
634
633
635 else:
634 else:
636 # General Python objects
635 # General Python objects
637 append_field(_mime, 'Signature', 'definition', code_formatter)
636 append_field(_mime, 'Signature', 'definition', code_formatter)
638 append_field(_mime, 'Call signature', 'call_def', code_formatter)
637 append_field(_mime, 'Call signature', 'call_def', code_formatter)
639
640 append_field(_mime, 'Type', 'type_name')
638 append_field(_mime, 'Type', 'type_name')
641
642 # Base class for old-style instances
643 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
644 append_field(_mime, 'Base Class', 'base_class')
645
646 append_field(_mime, 'String form', 'string_form')
639 append_field(_mime, 'String form', 'string_form')
647
640
648 # Namespace
641 # Namespace
649 if info['namespace'] != 'Interactive':
642 if info['namespace'] != 'Interactive':
650 append_field(_mime, 'Namespace', 'namespace')
643 append_field(_mime, 'Namespace', 'namespace')
651
644
652 append_field(_mime, 'Length', 'length')
645 append_field(_mime, 'Length', 'length')
653 append_field(_mime, 'File', 'file')
646 append_field(_mime, 'File', 'file')
654
647
655 # Source or docstring, depending on detail level and whether
648 # Source or docstring, depending on detail level and whether
656 # source found.
649 # source found.
657 if detail_level > 0:
650 if detail_level > 0:
658 append_field(_mime, 'Source', 'source', code_formatter)
651 append_field(_mime, 'Source', 'source', code_formatter)
659 else:
652 else:
660 append_field(_mime, 'Docstring', 'docstring', formatter)
653 append_field(_mime, 'Docstring', 'docstring', formatter)
661
654
662 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
655 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
663 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
656 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
664 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
657 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
665
658
666
659
667 return self.format_mime(_mime)
660 return self.format_mime(_mime)
668
661
669 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
662 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
670 """Show detailed information about an object.
663 """Show detailed information about an object.
671
664
672 Optional arguments:
665 Optional arguments:
673
666
674 - oname: name of the variable pointing to the object.
667 - oname: name of the variable pointing to the object.
675
668
676 - formatter: callable (optional)
669 - formatter: callable (optional)
677 A special formatter for docstrings.
670 A special formatter for docstrings.
678
671
679 The formatter is a callable that takes a string as an input
672 The formatter is a callable that takes a string as an input
680 and returns either a formatted string or a mime type bundle
673 and returns either a formatted string or a mime type bundle
681 in the form of a dictionnary.
674 in the form of a dictionnary.
682
675
683 Although the support of custom formatter returning a string
676 Although the support of custom formatter returning a string
684 instead of a mime type bundle is deprecated.
677 instead of a mime type bundle is deprecated.
685
678
686 - info: a structure with some information fields which may have been
679 - info: a structure with some information fields which may have been
687 precomputed already.
680 precomputed already.
688
681
689 - detail_level: if set to 1, more information is given.
682 - detail_level: if set to 1, more information is given.
690 """
683 """
691 info = self._get_info(obj, oname, formatter, info, detail_level)
684 info = self._get_info(obj, oname, formatter, info, detail_level)
692 if not enable_html_pager:
685 if not enable_html_pager:
693 del info['text/html']
686 del info['text/html']
694 page.page(info)
687 page.page(info)
695
688
696 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
689 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
697 """DEPRECATED. Compute a dict with detailed information about an object.
690 """DEPRECATED. Compute a dict with detailed information about an object.
698 """
691 """
699 if formatter is not None:
692 if formatter is not None:
700 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
693 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
701 'is deprecated as of IPython 5.0 and will have no effects.',
694 'is deprecated as of IPython 5.0 and will have no effects.',
702 DeprecationWarning, stacklevel=2)
695 DeprecationWarning, stacklevel=2)
703 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
696 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
704
697
705 def _info(self, obj, oname='', info=None, detail_level=0):
698 def _info(self, obj, oname='', info=None, detail_level=0):
706 """Compute a dict with detailed information about an object.
699 """Compute a dict with detailed information about an object.
707
700
708 Optional arguments:
701 Optional arguments:
709
702
710 - oname: name of the variable pointing to the object.
703 - oname: name of the variable pointing to the object.
711
704
712 - info: a structure with some information fields which may have been
705 - info: a structure with some information fields which may have been
713 precomputed already.
706 precomputed already.
714
707
715 - detail_level: if set to 1, more information is given.
708 - detail_level: if set to 1, more information is given.
716 """
709 """
717
710
718 obj_type = type(obj)
711 obj_type = type(obj)
719
712
720 if info is None:
713 if info is None:
721 ismagic = 0
714 ismagic = 0
722 isalias = 0
715 isalias = 0
723 ospace = ''
716 ospace = ''
724 else:
717 else:
725 ismagic = info.ismagic
718 ismagic = info.ismagic
726 isalias = info.isalias
719 isalias = info.isalias
727 ospace = info.namespace
720 ospace = info.namespace
728
721
729 # Get docstring, special-casing aliases:
722 # Get docstring, special-casing aliases:
730 if isalias:
723 if isalias:
731 if not callable(obj):
724 if not callable(obj):
732 try:
725 try:
733 ds = "Alias to the system command:\n %s" % obj[1]
726 ds = "Alias to the system command:\n %s" % obj[1]
734 except:
727 except:
735 ds = "Alias: " + str(obj)
728 ds = "Alias: " + str(obj)
736 else:
729 else:
737 ds = "Alias to " + str(obj)
730 ds = "Alias to " + str(obj)
738 if obj.__doc__:
731 if obj.__doc__:
739 ds += "\nDocstring:\n" + obj.__doc__
732 ds += "\nDocstring:\n" + obj.__doc__
740 else:
733 else:
741 ds = getdoc(obj)
734 ds = getdoc(obj)
742 if ds is None:
735 if ds is None:
743 ds = '<no docstring>'
736 ds = '<no docstring>'
744
737
745 # store output in a dict, we initialize it here and fill it as we go
738 # store output in a dict, we initialize it here and fill it as we go
746 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
739 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
747
740
748 string_max = 200 # max size of strings to show (snipped if longer)
741 string_max = 200 # max size of strings to show (snipped if longer)
749 shalf = int((string_max - 5) / 2)
742 shalf = int((string_max - 5) / 2)
750
743
751 if ismagic:
744 if ismagic:
752 obj_type_name = 'Magic function'
745 obj_type_name = 'Magic function'
753 elif isalias:
746 elif isalias:
754 obj_type_name = 'System alias'
747 obj_type_name = 'System alias'
755 else:
748 else:
756 obj_type_name = obj_type.__name__
749 obj_type_name = obj_type.__name__
757 out['type_name'] = obj_type_name
750 out['type_name'] = obj_type_name
758
751
759 try:
752 try:
760 bclass = obj.__class__
753 bclass = obj.__class__
761 out['base_class'] = str(bclass)
754 out['base_class'] = str(bclass)
762 except: pass
755 except: pass
763
756
764 # String form, but snip if too long in ? form (full in ??)
757 # String form, but snip if too long in ? form (full in ??)
765 if detail_level >= self.str_detail_level:
758 if detail_level >= self.str_detail_level:
766 try:
759 try:
767 ostr = str(obj)
760 ostr = str(obj)
768 str_head = 'string_form'
761 str_head = 'string_form'
769 if not detail_level and len(ostr)>string_max:
762 if not detail_level and len(ostr)>string_max:
770 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
763 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
771 ostr = ("\n" + " " * len(str_head.expandtabs())).\
764 ostr = ("\n" + " " * len(str_head.expandtabs())).\
772 join(q.strip() for q in ostr.split("\n"))
765 join(q.strip() for q in ostr.split("\n"))
773 out[str_head] = ostr
766 out[str_head] = ostr
774 except:
767 except:
775 pass
768 pass
776
769
777 if ospace:
770 if ospace:
778 out['namespace'] = ospace
771 out['namespace'] = ospace
779
772
780 # Length (for strings and lists)
773 # Length (for strings and lists)
781 try:
774 try:
782 out['length'] = str(len(obj))
775 out['length'] = str(len(obj))
783 except: pass
776 except: pass
784
777
785 # Filename where object was defined
778 # Filename where object was defined
786 binary_file = False
779 binary_file = False
787 fname = find_file(obj)
780 fname = find_file(obj)
788 if fname is None:
781 if fname is None:
789 # if anything goes wrong, we don't want to show source, so it's as
782 # if anything goes wrong, we don't want to show source, so it's as
790 # if the file was binary
783 # if the file was binary
791 binary_file = True
784 binary_file = True
792 else:
785 else:
793 if fname.endswith(('.so', '.dll', '.pyd')):
786 if fname.endswith(('.so', '.dll', '.pyd')):
794 binary_file = True
787 binary_file = True
795 elif fname.endswith('<string>'):
788 elif fname.endswith('<string>'):
796 fname = 'Dynamically generated function. No source code available.'
789 fname = 'Dynamically generated function. No source code available.'
797 out['file'] = compress_user(fname)
790 out['file'] = compress_user(fname)
798
791
799 # Original source code for a callable, class or property.
792 # Original source code for a callable, class or property.
800 if detail_level:
793 if detail_level:
801 # Flush the source cache because inspect can return out-of-date
794 # Flush the source cache because inspect can return out-of-date
802 # source
795 # source
803 linecache.checkcache()
796 linecache.checkcache()
804 try:
797 try:
805 if isinstance(obj, property) or not binary_file:
798 if isinstance(obj, property) or not binary_file:
806 src = getsource(obj, oname)
799 src = getsource(obj, oname)
807 if src is not None:
800 if src is not None:
808 src = src.rstrip()
801 src = src.rstrip()
809 out['source'] = src
802 out['source'] = src
810
803
811 except Exception:
804 except Exception:
812 pass
805 pass
813
806
814 # Add docstring only if no source is to be shown (avoid repetitions).
807 # Add docstring only if no source is to be shown (avoid repetitions).
815 if ds and out.get('source', None) is None:
808 if ds and out.get('source', None) is None:
816 out['docstring'] = ds
809 out['docstring'] = ds
817
810
818 # Constructor docstring for classes
811 # Constructor docstring for classes
819 if inspect.isclass(obj):
812 if inspect.isclass(obj):
820 out['isclass'] = True
813 out['isclass'] = True
821
814
822 # get the init signature:
815 # get the init signature:
823 try:
816 try:
824 init_def = self._getdef(obj, oname)
817 init_def = self._getdef(obj, oname)
825 except AttributeError:
818 except AttributeError:
826 init_def = None
819 init_def = None
827
820
828 # get the __init__ docstring
821 # get the __init__ docstring
829 try:
822 try:
830 obj_init = obj.__init__
823 obj_init = obj.__init__
831 except AttributeError:
824 except AttributeError:
832 init_ds = None
825 init_ds = None
833 else:
826 else:
834 if init_def is None:
827 if init_def is None:
835 # Get signature from init if top-level sig failed.
828 # Get signature from init if top-level sig failed.
836 # Can happen for built-in types (list, etc.).
829 # Can happen for built-in types (list, etc.).
837 try:
830 try:
838 init_def = self._getdef(obj_init, oname)
831 init_def = self._getdef(obj_init, oname)
839 except AttributeError:
832 except AttributeError:
840 pass
833 pass
841 init_ds = getdoc(obj_init)
834 init_ds = getdoc(obj_init)
842 # Skip Python's auto-generated docstrings
835 # Skip Python's auto-generated docstrings
843 if init_ds == _object_init_docstring:
836 if init_ds == _object_init_docstring:
844 init_ds = None
837 init_ds = None
845
838
846 if init_def:
839 if init_def:
847 out['init_definition'] = init_def
840 out['init_definition'] = init_def
848
841
849 if init_ds:
842 if init_ds:
850 out['init_docstring'] = init_ds
843 out['init_docstring'] = init_ds
851
844
852 # and class docstring for instances:
845 # and class docstring for instances:
853 else:
846 else:
854 # reconstruct the function definition and print it:
847 # reconstruct the function definition and print it:
855 defln = self._getdef(obj, oname)
848 defln = self._getdef(obj, oname)
856 if defln:
849 if defln:
857 out['definition'] = defln
850 out['definition'] = defln
858
851
859 # First, check whether the instance docstring is identical to the
852 # First, check whether the instance docstring is identical to the
860 # class one, and print it separately if they don't coincide. In
853 # class one, and print it separately if they don't coincide. In
861 # most cases they will, but it's nice to print all the info for
854 # most cases they will, but it's nice to print all the info for
862 # objects which use instance-customized docstrings.
855 # objects which use instance-customized docstrings.
863 if ds:
856 if ds:
864 try:
857 try:
865 cls = getattr(obj,'__class__')
858 cls = getattr(obj,'__class__')
866 except:
859 except:
867 class_ds = None
860 class_ds = None
868 else:
861 else:
869 class_ds = getdoc(cls)
862 class_ds = getdoc(cls)
870 # Skip Python's auto-generated docstrings
863 # Skip Python's auto-generated docstrings
871 if class_ds in _builtin_type_docstrings:
864 if class_ds in _builtin_type_docstrings:
872 class_ds = None
865 class_ds = None
873 if class_ds and ds != class_ds:
866 if class_ds and ds != class_ds:
874 out['class_docstring'] = class_ds
867 out['class_docstring'] = class_ds
875
868
876 # Next, try to show constructor docstrings
869 # Next, try to show constructor docstrings
877 try:
870 try:
878 init_ds = getdoc(obj.__init__)
871 init_ds = getdoc(obj.__init__)
879 # Skip Python's auto-generated docstrings
872 # Skip Python's auto-generated docstrings
880 if init_ds == _object_init_docstring:
873 if init_ds == _object_init_docstring:
881 init_ds = None
874 init_ds = None
882 except AttributeError:
875 except AttributeError:
883 init_ds = None
876 init_ds = None
884 if init_ds:
877 if init_ds:
885 out['init_docstring'] = init_ds
878 out['init_docstring'] = init_ds
886
879
887 # Call form docstring for callable instances
880 # Call form docstring for callable instances
888 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
881 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
889 call_def = self._getdef(obj.__call__, oname)
882 call_def = self._getdef(obj.__call__, oname)
890 if call_def and (call_def != out.get('definition')):
883 if call_def and (call_def != out.get('definition')):
891 # it may never be the case that call def and definition differ,
884 # it may never be the case that call def and definition differ,
892 # but don't include the same signature twice
885 # but don't include the same signature twice
893 out['call_def'] = call_def
886 out['call_def'] = call_def
894 call_ds = getdoc(obj.__call__)
887 call_ds = getdoc(obj.__call__)
895 # Skip Python's auto-generated docstrings
888 # Skip Python's auto-generated docstrings
896 if call_ds == _func_call_docstring:
889 if call_ds == _func_call_docstring:
897 call_ds = None
890 call_ds = None
898 if call_ds:
891 if call_ds:
899 out['call_docstring'] = call_ds
892 out['call_docstring'] = call_ds
900
893
901 # Compute the object's argspec as a callable. The key is to decide
894 # Compute the object's argspec as a callable. The key is to decide
902 # whether to pull it from the object itself, from its __init__ or
895 # whether to pull it from the object itself, from its __init__ or
903 # from its __call__ method.
896 # from its __call__ method.
904
897
905 if inspect.isclass(obj):
898 if inspect.isclass(obj):
906 # Old-style classes need not have an __init__
899 # Old-style classes need not have an __init__
907 callable_obj = getattr(obj, "__init__", None)
900 callable_obj = getattr(obj, "__init__", None)
908 elif callable(obj):
901 elif callable(obj):
909 callable_obj = obj
902 callable_obj = obj
910 else:
903 else:
911 callable_obj = None
904 callable_obj = None
912
905
913 if callable_obj is not None:
906 if callable_obj is not None:
914 try:
907 try:
915 argspec = getargspec(callable_obj)
908 argspec = getargspec(callable_obj)
916 except (TypeError, AttributeError):
909 except (TypeError, AttributeError):
917 # For extensions/builtins we can't retrieve the argspec
910 # For extensions/builtins we can't retrieve the argspec
918 pass
911 pass
919 else:
912 else:
920 # named tuples' _asdict() method returns an OrderedDict, but we
913 # named tuples' _asdict() method returns an OrderedDict, but we
921 # we want a normal
914 # we want a normal
922 out['argspec'] = argspec_dict = dict(argspec._asdict())
915 out['argspec'] = argspec_dict = dict(argspec._asdict())
923 # We called this varkw before argspec became a named tuple.
916 # We called this varkw before argspec became a named tuple.
924 # With getfullargspec it's also called varkw.
917 # With getfullargspec it's also called varkw.
925 if 'varkw' not in argspec_dict:
918 if 'varkw' not in argspec_dict:
926 argspec_dict['varkw'] = argspec_dict.pop('keywords')
919 argspec_dict['varkw'] = argspec_dict.pop('keywords')
927
920
928 return object_info(**out)
921 return object_info(**out)
929
922
930 def psearch(self,pattern,ns_table,ns_search=[],
923 def psearch(self,pattern,ns_table,ns_search=[],
931 ignore_case=False,show_all=False):
924 ignore_case=False,show_all=False):
932 """Search namespaces with wildcards for objects.
925 """Search namespaces with wildcards for objects.
933
926
934 Arguments:
927 Arguments:
935
928
936 - pattern: string containing shell-like wildcards to use in namespace
929 - pattern: string containing shell-like wildcards to use in namespace
937 searches and optionally a type specification to narrow the search to
930 searches and optionally a type specification to narrow the search to
938 objects of that type.
931 objects of that type.
939
932
940 - ns_table: dict of name->namespaces for search.
933 - ns_table: dict of name->namespaces for search.
941
934
942 Optional arguments:
935 Optional arguments:
943
936
944 - ns_search: list of namespace names to include in search.
937 - ns_search: list of namespace names to include in search.
945
938
946 - ignore_case(False): make the search case-insensitive.
939 - ignore_case(False): make the search case-insensitive.
947
940
948 - show_all(False): show all names, including those starting with
941 - show_all(False): show all names, including those starting with
949 underscores.
942 underscores.
950 """
943 """
951 #print 'ps pattern:<%r>' % pattern # dbg
944 #print 'ps pattern:<%r>' % pattern # dbg
952
945
953 # defaults
946 # defaults
954 type_pattern = 'all'
947 type_pattern = 'all'
955 filter = ''
948 filter = ''
956
949
957 cmds = pattern.split()
950 cmds = pattern.split()
958 len_cmds = len(cmds)
951 len_cmds = len(cmds)
959 if len_cmds == 1:
952 if len_cmds == 1:
960 # Only filter pattern given
953 # Only filter pattern given
961 filter = cmds[0]
954 filter = cmds[0]
962 elif len_cmds == 2:
955 elif len_cmds == 2:
963 # Both filter and type specified
956 # Both filter and type specified
964 filter,type_pattern = cmds
957 filter,type_pattern = cmds
965 else:
958 else:
966 raise ValueError('invalid argument string for psearch: <%s>' %
959 raise ValueError('invalid argument string for psearch: <%s>' %
967 pattern)
960 pattern)
968
961
969 # filter search namespaces
962 # filter search namespaces
970 for name in ns_search:
963 for name in ns_search:
971 if name not in ns_table:
964 if name not in ns_table:
972 raise ValueError('invalid namespace <%s>. Valid names: %s' %
965 raise ValueError('invalid namespace <%s>. Valid names: %s' %
973 (name,ns_table.keys()))
966 (name,ns_table.keys()))
974
967
975 #print 'type_pattern:',type_pattern # dbg
968 #print 'type_pattern:',type_pattern # dbg
976 search_result, namespaces_seen = set(), set()
969 search_result, namespaces_seen = set(), set()
977 for ns_name in ns_search:
970 for ns_name in ns_search:
978 ns = ns_table[ns_name]
971 ns = ns_table[ns_name]
979 # Normally, locals and globals are the same, so we just check one.
972 # Normally, locals and globals are the same, so we just check one.
980 if id(ns) in namespaces_seen:
973 if id(ns) in namespaces_seen:
981 continue
974 continue
982 namespaces_seen.add(id(ns))
975 namespaces_seen.add(id(ns))
983 tmp_res = list_namespace(ns, type_pattern, filter,
976 tmp_res = list_namespace(ns, type_pattern, filter,
984 ignore_case=ignore_case, show_all=show_all)
977 ignore_case=ignore_case, show_all=show_all)
985 search_result.update(tmp_res)
978 search_result.update(tmp_res)
986
979
987 page.page('\n'.join(sorted(search_result)))
980 page.page('\n'.join(sorted(search_result)))
General Comments 0
You need to be logged in to leave comments. Login now