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