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