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