##// END OF EJS Templates
- Small fixes and updates to 'foo?'.
fperez -
Show More

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

@@ -1,555 +1,565 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 $Id: OInspect.py 2480 2007-07-06 19:33:43Z fperez $
9 $Id: OInspect.py 2558 2007-07-25 19:54:28Z fperez $
10 10 """
11 11
12 12 #*****************************************************************************
13 13 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #*****************************************************************************
18 18
19 19 from IPython import Release
20 20 __author__ = '%s <%s>' % Release.authors['Fernando']
21 21 __license__ = Release.license
22 22
23 23 __all__ = ['Inspector','InspectColors']
24 24
25 25 # stdlib modules
26 26 import __builtin__
27 27 import inspect
28 28 import linecache
29 29 import string
30 30 import StringIO
31 31 import types
32 32 import os
33 33 import sys
34 34 # IPython's own
35 35 from IPython import PyColorize
36 36 from IPython.genutils import page,indent,Term,mkdict
37 37 from IPython.Itpl import itpl
38 38 from IPython.wildcard import list_namespace
39 39 from IPython.ColorANSI import *
40 40
41 41 #****************************************************************************
42 42 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
43 43 # simply monkeypatch inspect with code copied from python 2.4.
44 44 if sys.version_info[:2] == (2,3):
45 45 from inspect import ismodule, getabsfile, modulesbyfile
46 46 def getmodule(object):
47 47 """Return the module an object was defined in, or None if not found."""
48 48 if ismodule(object):
49 49 return object
50 50 if hasattr(object, '__module__'):
51 51 return sys.modules.get(object.__module__)
52 52 try:
53 53 file = getabsfile(object)
54 54 except TypeError:
55 55 return None
56 56 if file in modulesbyfile:
57 57 return sys.modules.get(modulesbyfile[file])
58 58 for module in sys.modules.values():
59 59 if hasattr(module, '__file__'):
60 60 modulesbyfile[
61 61 os.path.realpath(
62 62 getabsfile(module))] = module.__name__
63 63 if file in modulesbyfile:
64 64 return sys.modules.get(modulesbyfile[file])
65 65 main = sys.modules['__main__']
66 66 if not hasattr(object, '__name__'):
67 67 return None
68 68 if hasattr(main, object.__name__):
69 69 mainobject = getattr(main, object.__name__)
70 70 if mainobject is object:
71 71 return main
72 72 builtin = sys.modules['__builtin__']
73 73 if hasattr(builtin, object.__name__):
74 74 builtinobject = getattr(builtin, object.__name__)
75 75 if builtinobject is object:
76 76 return builtin
77 77
78 78 inspect.getmodule = getmodule
79 79
80 80 #****************************************************************************
81 81 # Builtin color schemes
82 82
83 83 Colors = TermColors # just a shorthand
84 84
85 85 # Build a few color schemes
86 86 NoColor = ColorScheme(
87 87 'NoColor',{
88 88 'header' : Colors.NoColor,
89 89 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
90 90 } )
91 91
92 92 LinuxColors = ColorScheme(
93 93 'Linux',{
94 94 'header' : Colors.LightRed,
95 95 'normal' : Colors.Normal # color off (usu. Colors.Normal)
96 96 } )
97 97
98 98 LightBGColors = ColorScheme(
99 99 'LightBG',{
100 100 'header' : Colors.Red,
101 101 'normal' : Colors.Normal # color off (usu. Colors.Normal)
102 102 } )
103 103
104 104 # Build table of color schemes (needed by the parser)
105 105 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
106 106 'Linux')
107 107
108 108 #****************************************************************************
109 109 # Auxiliary functions
110 110 def getdoc(obj):
111 111 """Stable wrapper around inspect.getdoc.
112 112
113 113 This can't crash because of attribute problems.
114 114
115 115 It also attempts to call a getdoc() method on the given object. This
116 116 allows objects which provide their docstrings via non-standard mechanisms
117 117 (like Pyro proxies) to still be inspected by ipython's ? system."""
118 118
119 119 ds = None # default return value
120 120 try:
121 121 ds = inspect.getdoc(obj)
122 122 except:
123 123 # Harden against an inspect failure, which can occur with
124 124 # SWIG-wrapped extensions.
125 125 pass
126 126 # Allow objects to offer customized documentation via a getdoc method:
127 127 try:
128 128 ds2 = obj.getdoc()
129 129 except:
130 130 pass
131 131 else:
132 132 # if we get extra info, we add it to the normal docstring.
133 133 if ds is None:
134 134 ds = ds2
135 135 else:
136 136 ds = '%s\n%s' % (ds,ds2)
137 137 return ds
138 138
139 139 def getsource(obj,is_binary=False):
140 140 """Wrapper around inspect.getsource.
141 141
142 142 This can be modified by other projects to provide customized source
143 143 extraction.
144 144
145 145 Inputs:
146 146
147 147 - obj: an object whose source code we will attempt to extract.
148 148
149 149 Optional inputs:
150 150
151 151 - is_binary: whether the object is known to come from a binary source.
152 152 This implementation will skip returning any output for binary objects, but
153 153 custom extractors may know how to meaningfully process them."""
154 154
155 155 if is_binary:
156 156 return None
157 157 else:
158 158 return inspect.getsource(obj)
159 159
160 160 #****************************************************************************
161 161 # Class definitions
162 162
163 163 class myStringIO(StringIO.StringIO):
164 164 """Adds a writeln method to normal StringIO."""
165 165 def writeln(self,*arg,**kw):
166 166 """Does a write() and then a write('\n')"""
167 167 self.write(*arg,**kw)
168 168 self.write('\n')
169 169
170 170 class Inspector:
171 171 def __init__(self,color_table,code_color_table,scheme,
172 172 str_detail_level=0):
173 173 self.color_table = color_table
174 174 self.parser = PyColorize.Parser(code_color_table,out='str')
175 175 self.format = self.parser.format
176 176 self.str_detail_level = str_detail_level
177 177 self.set_active_scheme(scheme)
178 178
179 179 def __getargspec(self,obj):
180 180 """Get the names and default values of a function's arguments.
181 181
182 182 A tuple of four things is returned: (args, varargs, varkw, defaults).
183 183 'args' is a list of the argument names (it may contain nested lists).
184 184 'varargs' and 'varkw' are the names of the * and ** arguments or None.
185 185 'defaults' is an n-tuple of the default values of the last n arguments.
186 186
187 187 Modified version of inspect.getargspec from the Python Standard
188 188 Library."""
189 189
190 190 if inspect.isfunction(obj):
191 191 func_obj = obj
192 192 elif inspect.ismethod(obj):
193 193 func_obj = obj.im_func
194 194 else:
195 195 raise TypeError, 'arg is not a Python function'
196 196 args, varargs, varkw = inspect.getargs(func_obj.func_code)
197 197 return args, varargs, varkw, func_obj.func_defaults
198 198
199 199 def __getdef(self,obj,oname=''):
200 200 """Return the definition header for any callable object.
201 201
202 202 If any exception is generated, None is returned instead and the
203 203 exception is suppressed."""
204 204
205 205 try:
206 206 return oname + inspect.formatargspec(*self.__getargspec(obj))
207 207 except:
208 208 return None
209 209
210 210 def __head(self,h):
211 211 """Return a header string with proper colors."""
212 212 return '%s%s%s' % (self.color_table.active_colors.header,h,
213 213 self.color_table.active_colors.normal)
214 214
215 215 def set_active_scheme(self,scheme):
216 216 self.color_table.set_active_scheme(scheme)
217 217 self.parser.color_table.set_active_scheme(scheme)
218 218
219 219 def noinfo(self,msg,oname):
220 220 """Generic message when no information is found."""
221 221 print 'No %s found' % msg,
222 222 if oname:
223 223 print 'for %s' % oname
224 224 else:
225 225 print
226 226
227 227 def pdef(self,obj,oname=''):
228 228 """Print the definition header for any callable object.
229 229
230 230 If the object is a class, print the constructor information."""
231 231
232 232 if not callable(obj):
233 233 print 'Object is not callable.'
234 234 return
235 235
236 236 header = ''
237 237
238 238 if inspect.isclass(obj):
239 239 header = self.__head('Class constructor information:\n')
240 240 obj = obj.__init__
241 241 elif type(obj) is types.InstanceType or \
242 242 isinstance(obj,object):
243 243 obj = obj.__call__
244 244
245 245 output = self.__getdef(obj,oname)
246 246 if output is None:
247 247 self.noinfo('definition header',oname)
248 248 else:
249 249 print >>Term.cout, header,self.format(output),
250 250
251 251 def pdoc(self,obj,oname='',formatter = None):
252 252 """Print the docstring for any object.
253 253
254 254 Optional:
255 255 -formatter: a function to run the docstring through for specially
256 256 formatted docstrings."""
257 257
258 258 head = self.__head # so that itpl can find it even if private
259 259 ds = getdoc(obj)
260 260 if formatter:
261 261 ds = formatter(ds)
262 262 if inspect.isclass(obj):
263 263 init_ds = getdoc(obj.__init__)
264 264 output = itpl('$head("Class Docstring:")\n'
265 265 '$indent(ds)\n'
266 266 '$head("Constructor Docstring"):\n'
267 267 '$indent(init_ds)')
268 268 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
269 269 and hasattr(obj,'__call__'):
270 270 call_ds = getdoc(obj.__call__)
271 271 if call_ds:
272 272 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
273 273 '$head("Calling Docstring:")\n$indent(call_ds)')
274 274 else:
275 275 output = ds
276 276 else:
277 277 output = ds
278 278 if output is None:
279 279 self.noinfo('documentation',oname)
280 280 return
281 281 page(output)
282 282
283 283 def psource(self,obj,oname=''):
284 284 """Print the source code for an object."""
285 285
286 286 # Flush the source cache because inspect can return out-of-date source
287 287 linecache.checkcache()
288 288 try:
289 289 src = getsource(obj)
290 290 except:
291 291 self.noinfo('source',oname)
292 292 else:
293 293 page(self.format(src))
294 294
295 295 def pfile(self,obj,oname=''):
296 296 """Show the whole file where an object was defined."""
297 297 try:
298 298 sourcelines,lineno = inspect.getsourcelines(obj)
299 299 except:
300 300 self.noinfo('file',oname)
301 301 else:
302 302 # run contents of file through pager starting at line
303 303 # where the object is defined
304 304 ofile = inspect.getabsfile(obj)
305 305
306 306 if (ofile.endswith('.so') or ofile.endswith('.dll')):
307 307 print 'File %r is binary, not printing.' % ofile
308 308 elif not os.path.isfile(ofile):
309 309 print 'File %r does not exist, not printing.' % ofile
310 310 else:
311 311 # Print only text files, not extension binaries.
312 312 page(self.format(open(ofile).read()),lineno)
313 313 #page(self.format(open(inspect.getabsfile(obj)).read()),lineno)
314 314
315 315 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
316 316 """Show detailed information about an object.
317 317
318 318 Optional arguments:
319 319
320 320 - oname: name of the variable pointing to the object.
321 321
322 322 - formatter: special formatter for docstrings (see pdoc)
323 323
324 324 - info: a structure with some information fields which may have been
325 325 precomputed already.
326 326
327 327 - detail_level: if set to 1, more information is given.
328 328 """
329 329
330 330 obj_type = type(obj)
331 331
332 332 header = self.__head
333 333 if info is None:
334 334 ismagic = 0
335 335 isalias = 0
336 336 ospace = ''
337 337 else:
338 338 ismagic = info.ismagic
339 339 isalias = info.isalias
340 340 ospace = info.namespace
341 341 # Get docstring, special-casing aliases:
342 342 if isalias:
343 343 if not callable(obj):
344 344 ds = "Alias to the system command:\n %s" % obj[1]
345 345 else:
346 346 ds = "Alias to " + str(obj)
347 347 else:
348 348 ds = getdoc(obj)
349 349 if ds is None:
350 350 ds = '<no docstring>'
351 351 if formatter is not None:
352 352 ds = formatter(ds)
353 353
354 354 # store output in a list which gets joined with \n at the end.
355 355 out = myStringIO()
356 356
357 357 string_max = 200 # max size of strings to show (snipped if longer)
358 358 shalf = int((string_max -5)/2)
359 359
360 360 if ismagic:
361 361 obj_type_name = 'Magic function'
362 362 elif isalias:
363 363 obj_type_name = 'System alias'
364 364 else:
365 365 obj_type_name = obj_type.__name__
366 366 out.writeln(header('Type:\t\t')+obj_type_name)
367 367
368 368 try:
369 369 bclass = obj.__class__
370 370 out.writeln(header('Base Class:\t')+str(bclass))
371 371 except: pass
372 372
373 373 # String form, but snip if too long in ? form (full in ??)
374 374 if detail_level >= self.str_detail_level:
375 375 try:
376 376 ostr = str(obj)
377 377 str_head = 'String Form:'
378 378 if not detail_level and len(ostr)>string_max:
379 379 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
380 380 ostr = ("\n" + " " * len(str_head.expandtabs())).\
381 381 join(map(string.strip,ostr.split("\n")))
382 382 if ostr.find('\n') > -1:
383 383 # Print multi-line strings starting at the next line.
384 384 str_sep = '\n'
385 385 else:
386 386 str_sep = '\t'
387 387 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
388 388 except:
389 389 pass
390 390
391 391 if ospace:
392 392 out.writeln(header('Namespace:\t')+ospace)
393 393
394 394 # Length (for strings and lists)
395 395 try:
396 396 length = str(len(obj))
397 397 out.writeln(header('Length:\t\t')+length)
398 398 except: pass
399 399
400 400 # Filename where object was defined
401 401 binary_file = False
402 402 try:
403 403 fname = inspect.getabsfile(obj)
404 404 if fname.endswith('<string>'):
405 405 fname = 'Dynamically generated function. No source code available.'
406 406 if (fname.endswith('.so') or fname.endswith('.dll') or
407 407 not os.path.isfile(fname)):
408 408 binary_file = True
409 409 out.writeln(header('File:\t\t')+fname)
410 410 except:
411 411 # if anything goes wrong, we don't want to show source, so it's as
412 412 # if the file was binary
413 413 binary_file = True
414 414
415 415 # reconstruct the function definition and print it:
416 416 defln = self.__getdef(obj,oname)
417 417 if defln:
418 418 out.write(header('Definition:\t')+self.format(defln))
419 419
420 420 # Docstrings only in detail 0 mode, since source contains them (we
421 421 # avoid repetitions). If source fails, we add them back, see below.
422 422 if ds and detail_level == 0:
423 423 out.writeln(header('Docstring:\n') + indent(ds))
424 424
425 425
426 426 # Original source code for any callable
427 427 if detail_level:
428 428 # Flush the source cache because inspect can return out-of-date source
429 429 linecache.checkcache()
430 430 source_success = False
431 431 try:
432 432 source = self.format(getsource(obj,binary_file))
433 433 if source:
434 434 out.write(header('Source:\n')+source.rstrip())
435 435 source_success = True
436 436 except Exception, msg:
437 437 pass
438 438
439 439 if ds and not source_success:
440 440 out.writeln(header('Docstring [source file open failed]:\n')
441 441 + indent(ds))
442 442
443 443 # Constructor docstring for classes
444 444 if inspect.isclass(obj):
445 445 # reconstruct the function definition and print it:
446 446 try:
447 447 obj_init = obj.__init__
448 448 except AttributeError:
449 449 init_def = init_ds = None
450 450 else:
451 451 init_def = self.__getdef(obj_init,oname)
452 452 init_ds = getdoc(obj_init)
453 453
454 454 if init_def or init_ds:
455 455 out.writeln(header('\nConstructor information:'))
456 456 if init_def:
457 457 out.write(header('Definition:\t')+ self.format(init_def))
458 458 if init_ds:
459 459 out.writeln(header('Docstring:\n') + indent(init_ds))
460 460 # and class docstring for instances:
461 461 elif obj_type is types.InstanceType or \
462 462 isinstance(obj,object):
463 463
464 464 # First, check whether the instance docstring is identical to the
465 465 # class one, and print it separately if they don't coincide. In
466 466 # most cases they will, but it's nice to print all the info for
467 467 # objects which use instance-customized docstrings.
468 468 if ds:
469 469 class_ds = getdoc(obj.__class__)
470 # Skip Python's auto-generated docstrings
471 if class_ds.startswith('function(code, globals[, name[,') or \
472 class_ds.startswith('instancemethod(function, instance,'):
473 class_ds = None
470 474 if class_ds and ds != class_ds:
471 475 out.writeln(header('Class Docstring:\n') +
472 476 indent(class_ds))
473 477
474 478 # Next, try to show constructor docstrings
475 479 try:
476 480 init_ds = getdoc(obj.__init__)
481 # Skip Python's auto-generated docstrings
482 if init_ds.startswith('x.__init__(...) initializes x'):
483 init_ds = None
477 484 except AttributeError:
478 485 init_ds = None
479 486 if init_ds:
480 487 out.writeln(header('Constructor Docstring:\n') +
481 488 indent(init_ds))
482 489
483 490 # Call form docstring for callable instances
484 491 if hasattr(obj,'__call__'):
485 out.writeln(header('Callable:\t')+'Yes')
492 #out.writeln(header('Callable:\t')+'Yes')
486 493 call_def = self.__getdef(obj.__call__,oname)
487 if call_def is None:
488 out.write(header('Call def:\t')+
489 'Calling definition not available.')
490 else:
491 out.write(header('Call def:\t')+self.format(call_def))
494 #if call_def is None:
495 # out.writeln(header('Call def:\t')+
496 # 'Calling definition not available.')
497 if call_def is not None:
498 out.writeln(header('Call def:\t')+self.format(call_def))
492 499 call_ds = getdoc(obj.__call__)
500 # Skip Python's auto-generated docstrings
501 if call_ds.startswith('x.__call__(...) <==> x(...)'):
502 call_ds = None
493 503 if call_ds:
494 504 out.writeln(header('Call docstring:\n') + indent(call_ds))
495 505
496 506 # Finally send to printer/pager
497 507 output = out.getvalue()
498 508 if output:
499 509 page(output)
500 510 # end pinfo
501 511
502 512 def psearch(self,pattern,ns_table,ns_search=[],
503 513 ignore_case=False,show_all=False):
504 514 """Search namespaces with wildcards for objects.
505 515
506 516 Arguments:
507 517
508 518 - pattern: string containing shell-like wildcards to use in namespace
509 519 searches and optionally a type specification to narrow the search to
510 520 objects of that type.
511 521
512 522 - ns_table: dict of name->namespaces for search.
513 523
514 524 Optional arguments:
515 525
516 526 - ns_search: list of namespace names to include in search.
517 527
518 528 - ignore_case(False): make the search case-insensitive.
519 529
520 530 - show_all(False): show all names, including those starting with
521 531 underscores.
522 532 """
523 533 # defaults
524 534 type_pattern = 'all'
525 535 filter = ''
526 536
527 537 cmds = pattern.split()
528 538 len_cmds = len(cmds)
529 539 if len_cmds == 1:
530 540 # Only filter pattern given
531 541 filter = cmds[0]
532 542 elif len_cmds == 2:
533 543 # Both filter and type specified
534 544 filter,type_pattern = cmds
535 545 else:
536 546 raise ValueError('invalid argument string for psearch: <%s>' %
537 547 pattern)
538 548
539 549 # filter search namespaces
540 550 for name in ns_search:
541 551 if name not in ns_table:
542 552 raise ValueError('invalid namespace <%s>. Valid names: %s' %
543 553 (name,ns_table.keys()))
544 554
545 555 #print 'type_pattern:',type_pattern # dbg
546 556 search_result = []
547 557 for ns_name in ns_search:
548 558 ns = ns_table[ns_name]
549 559 tmp_res = list(list_namespace(ns,type_pattern,filter,
550 560 ignore_case=ignore_case,
551 561 show_all=show_all))
552 562 search_result.extend(tmp_res)
553 563 search_result.sort()
554 564
555 565 page('\n'.join(search_result))
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now