##// END OF EJS Templates
revert fakemodule and oinspect mods, they broke unittest. monkeypatch is back
vivainio -
Show More

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

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