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