##// END OF EJS Templates
add object_inspect_text...
MinRK -
Show More

The requested changes are too big and content was truncated. Show full diff

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