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