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