##// END OF EJS Templates
Cleaning of Oinspect....
Matthias Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

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