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