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