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