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