##// END OF EJS Templates
- Implement a traits-aware tab-completer. See ipy_traits_completer in...
fperez -
Show More

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

@@ -0,0 +1,173 b''
1 """Traits-aware tab completion.
2
3 This module provides a custom tab-completer that intelligently hides the names
4 that the enthought.traits library (http://code.enthought.com/traits)
5 automatically adds to all objects that inherit from its base HasTraits class.
6
7
8 Activation
9 ==========
10
11 To use this, put in your ~/.ipython/ipy_user_conf.py file:
12
13 from ipy_traits_completer import activate
14 activate([complete_threshold])
15
16 The optional complete_threshold argument is the minimal length of text you need
17 to type for tab-completion to list names that are automatically generated by
18 traits. The default value is 3. Note that at runtime, you can change this
19 value simply by doing:
20
21 import ipy_traits_completer
22 ipy_traits_completer.COMPLETE_THRESHOLD = 4
23
24
25 Usage
26 =====
27
28 The system works as follows. If t is an empty object that HasTraits, then
29 (assuming the threshold is at the default value of 3):
30
31 In [7]: t.ed<TAB>
32
33 doesn't show anything at all, but:
34
35 In [7]: t.edi<TAB>
36 t.edit_traits t.editable_traits
37
38 shows these two names that come from traits. This allows you to complete on
39 the traits-specific names by typing at least 3 letters from them (or whatever
40 you set your threshold to), but to otherwise not see them in normal completion.
41
42
43 Notes
44 =====
45
46 - This requires Python 2.4 to work (I use sets). I don't think anyone is
47 using traits with 2.3 anyway, so that's OK.
48 """
49
50 #############################################################################
51 # External imports
52 from enthought.traits import api as T
53
54 # IPython imports
55 from IPython.ipapi import TryNext, get as ipget
56 from IPython.genutils import dir2
57
58 #############################################################################
59 # Module constants
60
61 # The completion threshold
62 # This is currently implemented as a module global, since this sytem isn't
63 # likely to be modified at runtime by multiple instances. If needed in the
64 # future, we can always make it local to the completer as a function attribute.
65 COMPLETE_THRESHOLD = 3
66
67 # Set of names that Traits automatically adds to ANY traits-inheriting object.
68 # These are the names we'll filter out.
69 TRAIT_NAMES = set( dir2(T.HasTraits()) ) - set( dir2(object()) )
70
71 #############################################################################
72 # Code begins
73
74 def trait_completer(self,event):
75 """A custom IPython tab-completer that is traits-aware.
76
77 It tries to hide the internal traits attributes, and reveal them only when
78 it can reasonably guess that the user really is after one of them.
79 """
80
81 #print '\nevent is:',event # dbg
82 symbol_parts = event.symbol.split('.')
83 base = '.'.join(symbol_parts[:-1])
84 #print 'base:',base # dbg
85
86 oinfo = self._ofind(base)
87 if not oinfo['found']:
88 raise TryNext
89
90 obj = oinfo['obj']
91 # OK, we got the object. See if it's traits, else punt
92 if not isinstance(obj,T.HasTraits):
93 raise TryNext
94
95 # it's a traits object, don't show the tr* attributes unless the completion
96 # begins with 'tr'
97 attrs = dir2(obj)
98 # Now, filter out the attributes that start with the user's request
99 attr_start = symbol_parts[-1]
100 if attr_start:
101 attrs = [a for a in attrs if a.startswith(attr_start)]
102
103 #print '\nastart:<%r>' % attr_start # dbg
104
105 if len(attr_start)<COMPLETE_THRESHOLD:
106 attrs = list(set(attrs) - TRAIT_NAMES)
107
108 # The base of the completion, so we can form the final results list
109 bdot = base+'.'
110
111 tcomp = [bdot+a for a in attrs]
112 #print 'tcomp:',tcomp
113 return tcomp
114
115 def activate(complete_threshold = COMPLETE_THRESHOLD):
116 """Activate the Traits completer.
117
118 :Keywords:
119 complete_threshold : int
120 The minimum number of letters that a user must type in order to
121 activate completion of traits-private names."""
122
123 if not (isinstance(complete_threshold,int) and
124 complete_threshold>0):
125 e='complete_threshold must be a positive integer, not %r' % \
126 complete_threshold
127 raise ValueError(e)
128
129 # Set the module global
130 global COMPLETE_THRESHOLD
131 COMPLETE_THRESHOLD = complete_threshold
132
133 # Activate the traits aware completer
134 ip = ipget()
135 ip.set_hook('complete_command', trait_completer, re_key = '.*')
136
137
138 #############################################################################
139 if __name__ == '__main__':
140 # Testing/debugging
141
142 # A sorted list of the names we'll filter out
143 TNL = list(TRAIT_NAMES)
144 TNL.sort()
145
146 # Make a few objects for testing
147 class TClean(T.HasTraits): pass
148 class Bunch(object): pass
149 # A clean traits object
150 t = TClean()
151 # A nested object containing t
152 f = Bunch()
153 f.t = t
154 # And a naked new-style object
155 o = object()
156
157 ip = ipget().IP
158
159 # A few simplistic tests
160
161 # Reset the threshold to the default, in case the test is running inside an
162 # instance of ipython that changed it
163 import ipy_traits_completer
164 ipy_traits_completer.COMPLETE_THRESHOLD = 3
165
166 assert ip.complete('t.ed') ==[]
167
168 # For some bizarre reason, these fail on the first time I run them, but not
169 # afterwards. Traits does some really weird stuff at object instantiation
170 # time...
171 ta = ip.complete('t.edi')
172 assert ta == ['t.edit_traits', 't.editable_traits']
173 print 'Tests OK'
@@ -1,565 +1,568 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 2558 2007-07-25 19:54:28Z fperez $
9 $Id: OInspect.py 2568 2007-07-29 21:38:44Z 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 470 # Skip Python's auto-generated docstrings
471 if class_ds.startswith('function(code, globals[, name[,') or \
472 class_ds.startswith('instancemethod(function, instance,'):
471 if class_ds and \
472 (class_ds.startswith('function(code, globals[,') or \
473 class_ds.startswith('instancemethod(function, instance,')):
473 474 class_ds = None
474 475 if class_ds and ds != class_ds:
475 476 out.writeln(header('Class Docstring:\n') +
476 477 indent(class_ds))
477 478
478 479 # Next, try to show constructor docstrings
479 480 try:
480 481 init_ds = getdoc(obj.__init__)
481 482 # Skip Python's auto-generated docstrings
482 483 if init_ds.startswith('x.__init__(...) initializes x'):
483 484 init_ds = None
484 485 except AttributeError:
485 486 init_ds = None
486 487 if init_ds:
487 488 out.writeln(header('Constructor Docstring:\n') +
488 489 indent(init_ds))
489 490
490 491 # Call form docstring for callable instances
491 492 if hasattr(obj,'__call__'):
492 493 #out.writeln(header('Callable:\t')+'Yes')
493 494 call_def = self.__getdef(obj.__call__,oname)
494 495 #if call_def is None:
495 496 # out.writeln(header('Call def:\t')+
496 497 # 'Calling definition not available.')
497 498 if call_def is not None:
498 499 out.writeln(header('Call def:\t')+self.format(call_def))
499 500 call_ds = getdoc(obj.__call__)
500 501 # Skip Python's auto-generated docstrings
501 502 if call_ds.startswith('x.__call__(...) <==> x(...)'):
502 503 call_ds = None
503 504 if call_ds:
504 505 out.writeln(header('Call docstring:\n') + indent(call_ds))
505 506
506 507 # Finally send to printer/pager
507 508 output = out.getvalue()
508 509 if output:
509 510 page(output)
510 511 # end pinfo
511 512
512 513 def psearch(self,pattern,ns_table,ns_search=[],
513 514 ignore_case=False,show_all=False):
514 515 """Search namespaces with wildcards for objects.
515 516
516 517 Arguments:
517 518
518 519 - pattern: string containing shell-like wildcards to use in namespace
519 520 searches and optionally a type specification to narrow the search to
520 521 objects of that type.
521 522
522 523 - ns_table: dict of name->namespaces for search.
523 524
524 525 Optional arguments:
525 526
526 527 - ns_search: list of namespace names to include in search.
527 528
528 529 - ignore_case(False): make the search case-insensitive.
529 530
530 531 - show_all(False): show all names, including those starting with
531 532 underscores.
532 533 """
534 #print 'ps pattern:<%r>' % pattern # dbg
535
533 536 # defaults
534 537 type_pattern = 'all'
535 538 filter = ''
536 539
537 540 cmds = pattern.split()
538 541 len_cmds = len(cmds)
539 542 if len_cmds == 1:
540 543 # Only filter pattern given
541 544 filter = cmds[0]
542 545 elif len_cmds == 2:
543 546 # Both filter and type specified
544 547 filter,type_pattern = cmds
545 548 else:
546 549 raise ValueError('invalid argument string for psearch: <%s>' %
547 550 pattern)
548 551
549 552 # filter search namespaces
550 553 for name in ns_search:
551 554 if name not in ns_table:
552 555 raise ValueError('invalid namespace <%s>. Valid names: %s' %
553 556 (name,ns_table.keys()))
554 557
555 558 #print 'type_pattern:',type_pattern # dbg
556 559 search_result = []
557 560 for ns_name in ns_search:
558 561 ns = ns_table[ns_name]
559 562 tmp_res = list(list_namespace(ns,type_pattern,filter,
560 563 ignore_case=ignore_case,
561 564 show_all=show_all))
562 565 search_result.extend(tmp_res)
563 566 search_result.sort()
564 567
565 568 page('\n'.join(search_result))
@@ -1,674 +1,627 b''
1 1 """Word completion for IPython.
2 2
3 3 This module is a fork of the rlcompleter module in the Python standard
4 4 library. The original enhancements made to rlcompleter have been sent
5 5 upstream and were accepted as of Python 2.3, but we need a lot more
6 6 functionality specific to IPython, so this module will continue to live as an
7 7 IPython-specific utility.
8 8
9 9 ---------------------------------------------------------------------------
10 10 Original rlcompleter documentation:
11 11
12 12 This requires the latest extension to the readline module (the
13 13 completes keywords, built-ins and globals in __main__; when completing
14 14 NAME.NAME..., it evaluates (!) the expression up to the last dot and
15 15 completes its attributes.
16 16
17 17 It's very cool to do "import string" type "string.", hit the
18 18 completion key (twice), and see the list of names defined by the
19 19 string module!
20 20
21 21 Tip: to use the tab key as the completion key, call
22 22
23 23 readline.parse_and_bind("tab: complete")
24 24
25 25 Notes:
26 26
27 27 - Exceptions raised by the completer function are *ignored* (and
28 28 generally cause the completion to fail). This is a feature -- since
29 29 readline sets the tty device in raw (or cbreak) mode, printing a
30 30 traceback wouldn't work well without some complicated hoopla to save,
31 31 reset and restore the tty state.
32 32
33 33 - The evaluation of the NAME.NAME... form may cause arbitrary
34 34 application defined code to be executed if an object with a
35 35 __getattr__ hook is found. Since it is the responsibility of the
36 36 application (or the user) to enable this feature, I consider this an
37 37 acceptable risk. More complicated expressions (e.g. function calls or
38 38 indexing operations) are *not* evaluated.
39 39
40 40 - GNU readline is also used by the built-in functions input() and
41 41 raw_input(), and thus these also benefit/suffer from the completer
42 42 features. Clearly an interactive application can benefit by
43 43 specifying its own completer function and using raw_input() for all
44 44 its input.
45 45
46 46 - When the original stdin is not a tty device, GNU readline is never
47 47 used, and this module (and the readline module) are silently inactive.
48 48
49 49 """
50 50
51 51 #*****************************************************************************
52 52 #
53 53 # Since this file is essentially a minimally modified copy of the rlcompleter
54 54 # module which is part of the standard Python distribution, I assume that the
55 55 # proper procedure is to maintain its copyright as belonging to the Python
56 56 # Software Foundation (in addition to my own, for all new code).
57 57 #
58 58 # Copyright (C) 2001 Python Software Foundation, www.python.org
59 59 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
60 60 #
61 61 # Distributed under the terms of the BSD License. The full license is in
62 62 # the file COPYING, distributed as part of this software.
63 63 #
64 64 #*****************************************************************************
65 65
66 66 import __builtin__
67 67 import __main__
68 68 import glob
69 69 import keyword
70 70 import os
71 71 import re
72 72 import shlex
73 73 import sys
74 74 import IPython.rlineimpl as readline
75 75 import itertools
76 76 from IPython.ipstruct import Struct
77 77 from IPython import ipapi
78 78
79 79 import types
80 80
81 81 # Python 2.4 offers sets as a builtin
82 82 try:
83 83 set([1,2])
84 84 except NameError:
85 85 from sets import Set as set
86 86
87 from IPython.genutils import debugx
87 from IPython.genutils import debugx, dir2
88 88
89 89 __all__ = ['Completer','IPCompleter']
90 90
91 def get_class_members(cls):
92 ret = dir(cls)
93 if hasattr(cls,'__bases__'):
94 for base in cls.__bases__:
95 ret.extend(get_class_members(base))
96 return ret
97
98 91 class Completer:
99 92 def __init__(self,namespace=None,global_namespace=None):
100 93 """Create a new completer for the command line.
101 94
102 95 Completer([namespace,global_namespace]) -> completer instance.
103 96
104 97 If unspecified, the default namespace where completions are performed
105 98 is __main__ (technically, __main__.__dict__). Namespaces should be
106 99 given as dictionaries.
107 100
108 101 An optional second namespace can be given. This allows the completer
109 102 to handle cases where both the local and global scopes need to be
110 103 distinguished.
111 104
112 105 Completer instances should be used as the completion mechanism of
113 106 readline via the set_completer() call:
114 107
115 108 readline.set_completer(Completer(my_namespace).complete)
116 109 """
117 110
118 111 # some minimal strict typechecks. For some core data structures, I
119 112 # want actual basic python types, not just anything that looks like
120 113 # one. This is especially true for namespaces.
121 114 for ns in (namespace,global_namespace):
122 115 if ns is not None and type(ns) != types.DictType:
123 116 raise TypeError,'namespace must be a dictionary'
124 117
125 118 # Don't bind to namespace quite yet, but flag whether the user wants a
126 119 # specific namespace or to use __main__.__dict__. This will allow us
127 120 # to bind to __main__.__dict__ at completion time, not now.
128 121 if namespace is None:
129 122 self.use_main_ns = 1
130 123 else:
131 124 self.use_main_ns = 0
132 125 self.namespace = namespace
133 126
134 127 # The global namespace, if given, can be bound directly
135 128 if global_namespace is None:
136 129 self.global_namespace = {}
137 130 else:
138 131 self.global_namespace = global_namespace
139 132
140 133 def complete(self, text, state):
141 134 """Return the next possible completion for 'text'.
142 135
143 136 This is called successively with state == 0, 1, 2, ... until it
144 137 returns None. The completion should begin with 'text'.
145 138
146 139 """
147 140 if self.use_main_ns:
148 141 self.namespace = __main__.__dict__
149 142
150 143 if state == 0:
151 144 if "." in text:
152 145 self.matches = self.attr_matches(text)
153 146 else:
154 147 self.matches = self.global_matches(text)
155 148 try:
156 149 return self.matches[state]
157 150 except IndexError:
158 151 return None
159 152
160 153 def global_matches(self, text):
161 154 """Compute matches when text is a simple name.
162 155
163 156 Return a list of all keywords, built-in functions and names currently
164 157 defined in self.namespace or self.global_namespace that match.
165 158
166 159 """
167 160 matches = []
168 161 match_append = matches.append
169 162 n = len(text)
170 163 for lst in [keyword.kwlist,
171 164 __builtin__.__dict__.keys(),
172 165 self.namespace.keys(),
173 166 self.global_namespace.keys()]:
174 167 for word in lst:
175 168 if word[:n] == text and word != "__builtins__":
176 169 match_append(word)
177 170 return matches
178 171
179 172 def attr_matches(self, text):
180 173 """Compute matches when text contains a dot.
181 174
182 175 Assuming the text is of the form NAME.NAME....[NAME], and is
183 176 evaluatable in self.namespace or self.global_namespace, it will be
184 177 evaluated and its attributes (as revealed by dir()) are used as
185 178 possible completions. (For class instances, class members are are
186 179 also considered.)
187 180
188 181 WARNING: this can still invoke arbitrary C code, if an object
189 182 with a __getattr__ hook is evaluated.
190 183
191 184 """
192 185 import re
193 186
194 187 # Another option, seems to work great. Catches things like ''.<tab>
195 188 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
196 189
197 190 if not m:
198 191 return []
199 192
200 193 expr, attr = m.group(1, 3)
201 194 try:
202 object = eval(expr, self.namespace)
195 obj = eval(expr, self.namespace)
203 196 except:
204 197 try:
205 object = eval(expr, self.global_namespace)
198 obj = eval(expr, self.global_namespace)
206 199 except:
207 200 return []
208
209
210 # Start building the attribute list via dir(), and then complete it
211 # with a few extra special-purpose calls.
212 words = dir(object)
213
214 if hasattr(object,'__class__'):
215 words.append('__class__')
216 words.extend(get_class_members(object.__class__))
217
218 # Some libraries (such as traits) may introduce duplicates, we want to
219 # track and clean this up if it happens
220 may_have_dupes = False
221
222 # this is the 'dir' function for objects with Enthought's traits
223 if hasattr(object, 'trait_names'):
224 try:
225 words.extend(object.trait_names())
226 may_have_dupes = True
227 except TypeError:
228 # This will happen if `object` is a class and not an instance.
229 pass
230
231 # Support for PyCrust-style _getAttributeNames magic method.
232 if hasattr(object, '_getAttributeNames'):
233 try:
234 words.extend(object._getAttributeNames())
235 may_have_dupes = True
236 except TypeError:
237 # `object` is a class and not an instance. Ignore
238 # this error.
239 pass
240 201
241 if may_have_dupes:
242 # eliminate possible duplicates, as some traits may also
243 # appear as normal attributes in the dir() call.
244 words = list(set(words))
245 words.sort()
202 words = dir2(obj)
246 203
247 # filter out non-string attributes which may be stuffed by dir() calls
248 # and poor coding in third-party modules
249 words = [w for w in words
250 if isinstance(w, basestring) and w != "__builtins__"]
251 204 # Build match list to return
252 205 n = len(attr)
253 206 return ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
254 207
255 208 class IPCompleter(Completer):
256 209 """Extension of the completer class with IPython-specific features"""
257 210
258 211 def __init__(self,shell,namespace=None,global_namespace=None,
259 212 omit__names=0,alias_table=None):
260 213 """IPCompleter() -> completer
261 214
262 215 Return a completer object suitable for use by the readline library
263 216 via readline.set_completer().
264 217
265 218 Inputs:
266 219
267 220 - shell: a pointer to the ipython shell itself. This is needed
268 221 because this completer knows about magic functions, and those can
269 222 only be accessed via the ipython instance.
270 223
271 224 - namespace: an optional dict where completions are performed.
272 225
273 226 - global_namespace: secondary optional dict for completions, to
274 227 handle cases (such as IPython embedded inside functions) where
275 228 both Python scopes are visible.
276 229
277 230 - The optional omit__names parameter sets the completer to omit the
278 231 'magic' names (__magicname__) for python objects unless the text
279 232 to be completed explicitly starts with one or more underscores.
280 233
281 234 - If alias_table is supplied, it should be a dictionary of aliases
282 235 to complete. """
283 236
284 237 Completer.__init__(self,namespace,global_namespace)
285 238 self.magic_prefix = shell.name+'.magic_'
286 239 self.magic_escape = shell.ESC_MAGIC
287 240 self.readline = readline
288 241 delims = self.readline.get_completer_delims()
289 242 delims = delims.replace(self.magic_escape,'')
290 243 self.readline.set_completer_delims(delims)
291 244 self.get_line_buffer = self.readline.get_line_buffer
292 245 self.omit__names = omit__names
293 246 self.merge_completions = shell.rc.readline_merge_completions
294 247
295 248 if alias_table is None:
296 249 alias_table = {}
297 250 self.alias_table = alias_table
298 251 # Regexp to split filenames with spaces in them
299 252 self.space_name_re = re.compile(r'([^\\] )')
300 253 # Hold a local ref. to glob.glob for speed
301 254 self.glob = glob.glob
302 255
303 256 # Determine if we are running on 'dumb' terminals, like (X)Emacs
304 257 # buffers, to avoid completion problems.
305 258 term = os.environ.get('TERM','xterm')
306 259 self.dumb_terminal = term in ['dumb','emacs']
307 260
308 261 # Special handling of backslashes needed in win32 platforms
309 262 if sys.platform == "win32":
310 263 self.clean_glob = self._clean_glob_win32
311 264 else:
312 265 self.clean_glob = self._clean_glob
313 266 self.matchers = [self.python_matches,
314 267 self.file_matches,
315 268 self.alias_matches,
316 269 self.python_func_kw_matches]
317 270
318 271 # Code contributed by Alex Schmolck, for ipython/emacs integration
319 272 def all_completions(self, text):
320 273 """Return all possible completions for the benefit of emacs."""
321 274
322 275 completions = []
323 276 comp_append = completions.append
324 277 try:
325 278 for i in xrange(sys.maxint):
326 279 res = self.complete(text, i)
327 280
328 281 if not res: break
329 282
330 283 comp_append(res)
331 284 #XXX workaround for ``notDefined.<tab>``
332 285 except NameError:
333 286 pass
334 287 return completions
335 288 # /end Alex Schmolck code.
336 289
337 290 def _clean_glob(self,text):
338 291 return self.glob("%s*" % text)
339 292
340 293 def _clean_glob_win32(self,text):
341 294 return [f.replace("\\","/")
342 295 for f in self.glob("%s*" % text)]
343 296
344 297 def file_matches(self, text):
345 298 """Match filenames, expanding ~USER type strings.
346 299
347 300 Most of the seemingly convoluted logic in this completer is an
348 301 attempt to handle filenames with spaces in them. And yet it's not
349 302 quite perfect, because Python's readline doesn't expose all of the
350 303 GNU readline details needed for this to be done correctly.
351 304
352 305 For a filename with a space in it, the printed completions will be
353 306 only the parts after what's already been typed (instead of the
354 307 full completions, as is normally done). I don't think with the
355 308 current (as of Python 2.3) Python readline it's possible to do
356 309 better."""
357 310
358 311 #print 'Completer->file_matches: <%s>' % text # dbg
359 312
360 313 # chars that require escaping with backslash - i.e. chars
361 314 # that readline treats incorrectly as delimiters, but we
362 315 # don't want to treat as delimiters in filename matching
363 316 # when escaped with backslash
364 317
365 318 protectables = ' ()[]{}'
366 319
367 320 if text.startswith('!'):
368 321 text = text[1:]
369 322 text_prefix = '!'
370 323 else:
371 324 text_prefix = ''
372 325
373 326 def protect_filename(s):
374 327 return "".join([(ch in protectables and '\\' + ch or ch)
375 328 for ch in s])
376 329
377 330 def single_dir_expand(matches):
378 331 "Recursively expand match lists containing a single dir."
379 332
380 333 if len(matches) == 1 and os.path.isdir(matches[0]):
381 334 # Takes care of links to directories also. Use '/'
382 335 # explicitly, even under Windows, so that name completions
383 336 # don't end up escaped.
384 337 d = matches[0]
385 338 if d[-1] in ['/','\\']:
386 339 d = d[:-1]
387 340
388 341 subdirs = os.listdir(d)
389 342 if subdirs:
390 343 matches = [ (d + '/' + p) for p in subdirs]
391 344 return single_dir_expand(matches)
392 345 else:
393 346 return matches
394 347 else:
395 348 return matches
396 349
397 350 lbuf = self.lbuf
398 351 open_quotes = 0 # track strings with open quotes
399 352 try:
400 353 lsplit = shlex.split(lbuf)[-1]
401 354 except ValueError:
402 355 # typically an unmatched ", or backslash without escaped char.
403 356 if lbuf.count('"')==1:
404 357 open_quotes = 1
405 358 lsplit = lbuf.split('"')[-1]
406 359 elif lbuf.count("'")==1:
407 360 open_quotes = 1
408 361 lsplit = lbuf.split("'")[-1]
409 362 else:
410 363 return []
411 364 except IndexError:
412 365 # tab pressed on empty line
413 366 lsplit = ""
414 367
415 368 if lsplit != protect_filename(lsplit):
416 369 # if protectables are found, do matching on the whole escaped
417 370 # name
418 371 has_protectables = 1
419 372 text0,text = text,lsplit
420 373 else:
421 374 has_protectables = 0
422 375 text = os.path.expanduser(text)
423 376
424 377 if text == "":
425 378 return [text_prefix + protect_filename(f) for f in self.glob("*")]
426 379
427 380 m0 = self.clean_glob(text.replace('\\',''))
428 381 if has_protectables:
429 382 # If we had protectables, we need to revert our changes to the
430 383 # beginning of filename so that we don't double-write the part
431 384 # of the filename we have so far
432 385 len_lsplit = len(lsplit)
433 386 matches = [text_prefix + text0 +
434 387 protect_filename(f[len_lsplit:]) for f in m0]
435 388 else:
436 389 if open_quotes:
437 390 # if we have a string with an open quote, we don't need to
438 391 # protect the names at all (and we _shouldn't_, as it
439 392 # would cause bugs when the filesystem call is made).
440 393 matches = m0
441 394 else:
442 395 matches = [text_prefix +
443 396 protect_filename(f) for f in m0]
444 397
445 398 #print 'mm',matches # dbg
446 399 return single_dir_expand(matches)
447 400
448 401 def alias_matches(self, text):
449 402 """Match internal system aliases"""
450 403 #print 'Completer->alias_matches:',text,'lb',self.lbuf # dbg
451 404
452 405 # if we are not in the first 'item', alias matching
453 406 # doesn't make sense
454 407 if ' ' in self.lbuf.lstrip():
455 408 return []
456 409 text = os.path.expanduser(text)
457 410 aliases = self.alias_table.keys()
458 411 if text == "":
459 412 return aliases
460 413 else:
461 414 return [alias for alias in aliases if alias.startswith(text)]
462 415
463 416 def python_matches(self,text):
464 417 """Match attributes or global python names"""
465 418
466 419 #print 'Completer->python_matches, txt=<%s>' % text # dbg
467 420 if "." in text:
468 421 try:
469 422 matches = self.attr_matches(text)
470 423 if text.endswith('.') and self.omit__names:
471 424 if self.omit__names == 1:
472 425 # true if txt is _not_ a __ name, false otherwise:
473 426 no__name = (lambda txt:
474 427 re.match(r'.*\.__.*?__',txt) is None)
475 428 else:
476 429 # true if txt is _not_ a _ name, false otherwise:
477 430 no__name = (lambda txt:
478 431 re.match(r'.*\._.*?',txt) is None)
479 432 matches = filter(no__name, matches)
480 433 except NameError:
481 434 # catches <undefined attributes>.<tab>
482 435 matches = []
483 436 else:
484 437 matches = self.global_matches(text)
485 438 # this is so completion finds magics when automagic is on:
486 439 if (matches == [] and
487 440 not text.startswith(os.sep) and
488 441 not ' ' in self.lbuf):
489 442 matches = self.attr_matches(self.magic_prefix+text)
490 443 return matches
491 444
492 445 def _default_arguments(self, obj):
493 446 """Return the list of default arguments of obj if it is callable,
494 447 or empty list otherwise."""
495 448
496 449 if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
497 450 # for classes, check for __init__,__new__
498 451 if inspect.isclass(obj):
499 452 obj = (getattr(obj,'__init__',None) or
500 453 getattr(obj,'__new__',None))
501 454 # for all others, check if they are __call__able
502 455 elif hasattr(obj, '__call__'):
503 456 obj = obj.__call__
504 457 # XXX: is there a way to handle the builtins ?
505 458 try:
506 459 args,_,_1,defaults = inspect.getargspec(obj)
507 460 if defaults:
508 461 return args[-len(defaults):]
509 462 except TypeError: pass
510 463 return []
511 464
512 465 def python_func_kw_matches(self,text):
513 466 """Match named parameters (kwargs) of the last open function"""
514 467
515 468 if "." in text: # a parameter cannot be dotted
516 469 return []
517 470 try: regexp = self.__funcParamsRegex
518 471 except AttributeError:
519 472 regexp = self.__funcParamsRegex = re.compile(r'''
520 473 '.*?' | # single quoted strings or
521 474 ".*?" | # double quoted strings or
522 475 \w+ | # identifier
523 476 \S # other characters
524 477 ''', re.VERBOSE | re.DOTALL)
525 478 # 1. find the nearest identifier that comes before an unclosed
526 479 # parenthesis e.g. for "foo (1+bar(x), pa", the candidate is "foo"
527 480 tokens = regexp.findall(self.get_line_buffer())
528 481 tokens.reverse()
529 482 iterTokens = iter(tokens); openPar = 0
530 483 for token in iterTokens:
531 484 if token == ')':
532 485 openPar -= 1
533 486 elif token == '(':
534 487 openPar += 1
535 488 if openPar > 0:
536 489 # found the last unclosed parenthesis
537 490 break
538 491 else:
539 492 return []
540 493 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
541 494 ids = []
542 495 isId = re.compile(r'\w+$').match
543 496 while True:
544 497 try:
545 498 ids.append(iterTokens.next())
546 499 if not isId(ids[-1]):
547 500 ids.pop(); break
548 501 if not iterTokens.next() == '.':
549 502 break
550 503 except StopIteration:
551 504 break
552 505 # lookup the candidate callable matches either using global_matches
553 506 # or attr_matches for dotted names
554 507 if len(ids) == 1:
555 508 callableMatches = self.global_matches(ids[0])
556 509 else:
557 510 callableMatches = self.attr_matches('.'.join(ids[::-1]))
558 511 argMatches = []
559 512 for callableMatch in callableMatches:
560 513 try: namedArgs = self._default_arguments(eval(callableMatch,
561 514 self.namespace))
562 515 except: continue
563 516 for namedArg in namedArgs:
564 517 if namedArg.startswith(text):
565 518 argMatches.append("%s=" %namedArg)
566 519 return argMatches
567 520
568 521 def dispatch_custom_completer(self,text):
569 # print "Custom! '%s' %s" % (text, self.custom_completers) # dbg
522 #print "Custom! '%s' %s" % (text, self.custom_completers) # dbg
570 523 line = self.full_lbuf
571 524 if not line.strip():
572 525 return None
573 526
574 527 event = Struct()
575 528 event.line = line
576 529 event.symbol = text
577 530 cmd = line.split(None,1)[0]
578 531 event.command = cmd
579 532 #print "\ncustom:{%s]\n" % event # dbg
580 533
581 534 # for foo etc, try also to find completer for %foo
582 535 if not cmd.startswith(self.magic_escape):
583 536 try_magic = self.custom_completers.s_matches(
584 537 self.magic_escape + cmd)
585 538 else:
586 539 try_magic = []
587 540
588 541
589 542 for c in itertools.chain(
590 543 self.custom_completers.s_matches(cmd),
591 544 try_magic,
592 545 self.custom_completers.flat_matches(self.lbuf)):
593 # print "try",c # dbg
546 #print "try",c # dbg
594 547 try:
595 548 res = c(event)
596 549 return [r for r in res if r.lower().startswith(text.lower())]
597 550 except ipapi.TryNext:
598 551 pass
599 552
600 553 return None
601 554
602 555
603 556 def complete(self, text, state,line_buffer=None):
604 557 """Return the next possible completion for 'text'.
605 558
606 559 This is called successively with state == 0, 1, 2, ... until it
607 560 returns None. The completion should begin with 'text'.
608 561
609 562 :Keywords:
610 563 - line_buffer: string
611 564 If not given, the completer attempts to obtain the current line buffer
612 565 via readline. This keyword allows clients which are requesting for
613 566 text completions in non-readline contexts to inform the completer of
614 567 the entire text.
615 568 """
616 569
617 570 #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg
618 571
619 572 # if there is only a tab on a line with only whitespace, instead
620 573 # of the mostly useless 'do you want to see all million
621 574 # completions' message, just do the right thing and give the user
622 575 # his tab! Incidentally, this enables pasting of tabbed text from
623 576 # an editor (as long as autoindent is off).
624 577
625 578 # don't apply this on 'dumb' terminals, such as emacs buffers, so we
626 579 # don't interfere with their own tab-completion mechanism.
627 580 if line_buffer is None:
628 581 self.full_lbuf = self.get_line_buffer()
629 582 else:
630 583 self.full_lbuf = line_buffer
631 584
632 585 if not (self.dumb_terminal or self.full_lbuf.strip()):
633 586 self.readline.insert_text('\t')
634 587 return None
635 588
636 589 magic_escape = self.magic_escape
637 590 magic_prefix = self.magic_prefix
638 591
639 592 self.lbuf = self.full_lbuf[:self.readline.get_endidx()]
640 593
641 594 try:
642 595 if text.startswith(magic_escape):
643 596 text = text.replace(magic_escape,magic_prefix)
644 597 elif text.startswith('~'):
645 598 text = os.path.expanduser(text)
646 599 if state == 0:
647 600 custom_res = self.dispatch_custom_completer(text)
648 601 if custom_res is not None:
649 602 # did custom completers produce something?
650 603 self.matches = custom_res
651 604 else:
652 605 # Extend the list of completions with the results of each
653 606 # matcher, so we return results to the user from all
654 607 # namespaces.
655 608 if self.merge_completions:
656 609 self.matches = []
657 610 for matcher in self.matchers:
658 611 self.matches.extend(matcher(text))
659 612 else:
660 613 for matcher in self.matchers:
661 614 self.matches = matcher(text)
662 615 if self.matches:
663 616 break
664 617
665 618 try:
666 619 return self.matches[state].replace(magic_prefix,magic_escape)
667 620 except IndexError:
668 621 return None
669 622 except:
670 623 #from IPython.ultraTB import AutoFormattedTB; # dbg
671 624 #tb=AutoFormattedTB('Verbose');tb() #dbg
672 625
673 626 # If completion fails, don't annoy the user.
674 627 return None
@@ -1,1786 +1,1850 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 General purpose utilities.
4 4
5 5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 6 these things are also convenient when working at the command line.
7 7
8 $Id: genutils.py 2439 2007-06-14 18:41:48Z vivainio $"""
8 $Id: genutils.py 2568 2007-07-29 21:38:44Z fperez $"""
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001-2006 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 17 from IPython import Release
18 18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 19 __license__ = Release.license
20 20
21 21 #****************************************************************************
22 22 # required modules from the Python standard library
23 23 import __main__
24 24 import commands
25 25 import os
26 26 import re
27 27 import shlex
28 28 import shutil
29 29 import sys
30 30 import tempfile
31 31 import time
32 32 import types
33 33 import warnings
34 34
35 35 # Other IPython utilities
36 36 import IPython
37 37 from IPython.Itpl import Itpl,itpl,printpl
38 38 from IPython import DPyGetOpt, platutils
39 39 from IPython.generics import result_display
40 40 from path import path
41 41 if os.name == "nt":
42 42 from IPython.winconsole import get_console_size
43 43
44 44 #****************************************************************************
45 45 # Exceptions
46 46 class Error(Exception):
47 47 """Base class for exceptions in this module."""
48 48 pass
49 49
50 50 #----------------------------------------------------------------------------
51 51 class IOStream:
52 52 def __init__(self,stream,fallback):
53 53 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
54 54 stream = fallback
55 55 self.stream = stream
56 56 self._swrite = stream.write
57 57 self.flush = stream.flush
58 58
59 59 def write(self,data):
60 60 try:
61 61 self._swrite(data)
62 62 except:
63 63 try:
64 64 # print handles some unicode issues which may trip a plain
65 65 # write() call. Attempt to emulate write() by using a
66 66 # trailing comma
67 67 print >> self.stream, data,
68 68 except:
69 69 # if we get here, something is seriously broken.
70 70 print >> sys.stderr, \
71 71 'ERROR - failed to write data to stream:', self.stream
72 72
73 73 def close(self):
74 74 pass
75 75
76 76
77 77 class IOTerm:
78 78 """ Term holds the file or file-like objects for handling I/O operations.
79 79
80 80 These are normally just sys.stdin, sys.stdout and sys.stderr but for
81 81 Windows they can can replaced to allow editing the strings before they are
82 82 displayed."""
83 83
84 84 # In the future, having IPython channel all its I/O operations through
85 85 # this class will make it easier to embed it into other environments which
86 86 # are not a normal terminal (such as a GUI-based shell)
87 87 def __init__(self,cin=None,cout=None,cerr=None):
88 88 self.cin = IOStream(cin,sys.stdin)
89 89 self.cout = IOStream(cout,sys.stdout)
90 90 self.cerr = IOStream(cerr,sys.stderr)
91 91
92 92 # Global variable to be used for all I/O
93 93 Term = IOTerm()
94 94
95 95 import IPython.rlineimpl as readline
96 96 # Remake Term to use the readline i/o facilities
97 97 if sys.platform == 'win32' and readline.have_readline:
98 98
99 99 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
100 100
101 101
102 102 #****************************************************************************
103 103 # Generic warning/error printer, used by everything else
104 104 def warn(msg,level=2,exit_val=1):
105 105 """Standard warning printer. Gives formatting consistency.
106 106
107 107 Output is sent to Term.cerr (sys.stderr by default).
108 108
109 109 Options:
110 110
111 111 -level(2): allows finer control:
112 112 0 -> Do nothing, dummy function.
113 113 1 -> Print message.
114 114 2 -> Print 'WARNING:' + message. (Default level).
115 115 3 -> Print 'ERROR:' + message.
116 116 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
117 117
118 118 -exit_val (1): exit value returned by sys.exit() for a level 4
119 119 warning. Ignored for all other levels."""
120 120
121 121 if level>0:
122 122 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
123 123 print >> Term.cerr, '%s%s' % (header[level],msg)
124 124 if level == 4:
125 125 print >> Term.cerr,'Exiting.\n'
126 126 sys.exit(exit_val)
127 127
128 128 def info(msg):
129 129 """Equivalent to warn(msg,level=1)."""
130 130
131 131 warn(msg,level=1)
132 132
133 133 def error(msg):
134 134 """Equivalent to warn(msg,level=3)."""
135 135
136 136 warn(msg,level=3)
137 137
138 138 def fatal(msg,exit_val=1):
139 139 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
140 140
141 141 warn(msg,exit_val=exit_val,level=4)
142 142
143 143 #---------------------------------------------------------------------------
144 144 # Debugging routines
145 145 #
146 146 def debugx(expr,pre_msg=''):
147 147 """Print the value of an expression from the caller's frame.
148 148
149 149 Takes an expression, evaluates it in the caller's frame and prints both
150 150 the given expression and the resulting value (as well as a debug mark
151 151 indicating the name of the calling function. The input must be of a form
152 152 suitable for eval().
153 153
154 154 An optional message can be passed, which will be prepended to the printed
155 155 expr->value pair."""
156 156
157 157 cf = sys._getframe(1)
158 158 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
159 159 eval(expr,cf.f_globals,cf.f_locals))
160 160
161 161 # deactivate it by uncommenting the following line, which makes it a no-op
162 162 #def debugx(expr,pre_msg=''): pass
163 163
164 164 #----------------------------------------------------------------------------
165 165 StringTypes = types.StringTypes
166 166
167 167 # Basic timing functionality
168 168
169 169 # If possible (Unix), use the resource module instead of time.clock()
170 170 try:
171 171 import resource
172 172 def clocku():
173 173 """clocku() -> floating point number
174 174
175 175 Return the *USER* CPU time in seconds since the start of the process.
176 176 This is done via a call to resource.getrusage, so it avoids the
177 177 wraparound problems in time.clock()."""
178 178
179 179 return resource.getrusage(resource.RUSAGE_SELF)[0]
180 180
181 181 def clocks():
182 182 """clocks() -> floating point number
183 183
184 184 Return the *SYSTEM* CPU time in seconds since the start of the process.
185 185 This is done via a call to resource.getrusage, so it avoids the
186 186 wraparound problems in time.clock()."""
187 187
188 188 return resource.getrusage(resource.RUSAGE_SELF)[1]
189 189
190 190 def clock():
191 191 """clock() -> floating point number
192 192
193 193 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
194 194 the process. This is done via a call to resource.getrusage, so it
195 195 avoids the wraparound problems in time.clock()."""
196 196
197 197 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
198 198 return u+s
199 199
200 200 def clock2():
201 201 """clock2() -> (t_user,t_system)
202 202
203 203 Similar to clock(), but return a tuple of user/system times."""
204 204 return resource.getrusage(resource.RUSAGE_SELF)[:2]
205 205
206 206 except ImportError:
207 207 # There is no distinction of user/system time under windows, so we just use
208 208 # time.clock() for everything...
209 209 clocku = clocks = clock = time.clock
210 210 def clock2():
211 211 """Under windows, system CPU time can't be measured.
212 212
213 213 This just returns clock() and zero."""
214 214 return time.clock(),0.0
215 215
216 216 def timings_out(reps,func,*args,**kw):
217 217 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
218 218
219 219 Execute a function reps times, return a tuple with the elapsed total
220 220 CPU time in seconds, the time per call and the function's output.
221 221
222 222 Under Unix, the return value is the sum of user+system time consumed by
223 223 the process, computed via the resource module. This prevents problems
224 224 related to the wraparound effect which the time.clock() function has.
225 225
226 226 Under Windows the return value is in wall clock seconds. See the
227 227 documentation for the time module for more details."""
228 228
229 229 reps = int(reps)
230 230 assert reps >=1, 'reps must be >= 1'
231 231 if reps==1:
232 232 start = clock()
233 233 out = func(*args,**kw)
234 234 tot_time = clock()-start
235 235 else:
236 236 rng = xrange(reps-1) # the last time is executed separately to store output
237 237 start = clock()
238 238 for dummy in rng: func(*args,**kw)
239 239 out = func(*args,**kw) # one last time
240 240 tot_time = clock()-start
241 241 av_time = tot_time / reps
242 242 return tot_time,av_time,out
243 243
244 244 def timings(reps,func,*args,**kw):
245 245 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
246 246
247 247 Execute a function reps times, return a tuple with the elapsed total CPU
248 248 time in seconds and the time per call. These are just the first two values
249 249 in timings_out()."""
250 250
251 251 return timings_out(reps,func,*args,**kw)[0:2]
252 252
253 253 def timing(func,*args,**kw):
254 254 """timing(func,*args,**kw) -> t_total
255 255
256 256 Execute a function once, return the elapsed total CPU time in
257 257 seconds. This is just the first value in timings_out()."""
258 258
259 259 return timings_out(1,func,*args,**kw)[0]
260 260
261 261 #****************************************************************************
262 262 # file and system
263 263
264 264 def arg_split(s,posix=False):
265 265 """Split a command line's arguments in a shell-like manner.
266 266
267 267 This is a modified version of the standard library's shlex.split()
268 268 function, but with a default of posix=False for splitting, so that quotes
269 269 in inputs are respected."""
270 270
271 271 # XXX - there may be unicode-related problems here!!! I'm not sure that
272 272 # shlex is truly unicode-safe, so it might be necessary to do
273 273 #
274 274 # s = s.encode(sys.stdin.encoding)
275 275 #
276 276 # first, to ensure that shlex gets a normal string. Input from anyone who
277 277 # knows more about unicode and shlex than I would be good to have here...
278 278 lex = shlex.shlex(s, posix=posix)
279 279 lex.whitespace_split = True
280 280 return list(lex)
281 281
282 282 def system(cmd,verbose=0,debug=0,header=''):
283 283 """Execute a system command, return its exit status.
284 284
285 285 Options:
286 286
287 287 - verbose (0): print the command to be executed.
288 288
289 289 - debug (0): only print, do not actually execute.
290 290
291 291 - header (''): Header to print on screen prior to the executed command (it
292 292 is only prepended to the command, no newlines are added).
293 293
294 294 Note: a stateful version of this function is available through the
295 295 SystemExec class."""
296 296
297 297 stat = 0
298 298 if verbose or debug: print header+cmd
299 299 sys.stdout.flush()
300 300 if not debug: stat = os.system(cmd)
301 301 return stat
302 302
303 303 # This function is used by ipython in a lot of places to make system calls.
304 304 # We need it to be slightly different under win32, due to the vagaries of
305 305 # 'network shares'. A win32 override is below.
306 306
307 307 def shell(cmd,verbose=0,debug=0,header=''):
308 308 """Execute a command in the system shell, always return None.
309 309
310 310 Options:
311 311
312 312 - verbose (0): print the command to be executed.
313 313
314 314 - debug (0): only print, do not actually execute.
315 315
316 316 - header (''): Header to print on screen prior to the executed command (it
317 317 is only prepended to the command, no newlines are added).
318 318
319 319 Note: this is similar to genutils.system(), but it returns None so it can
320 320 be conveniently used in interactive loops without getting the return value
321 321 (typically 0) printed many times."""
322 322
323 323 stat = 0
324 324 if verbose or debug: print header+cmd
325 325 # flush stdout so we don't mangle python's buffering
326 326 sys.stdout.flush()
327 327
328 328 if not debug:
329 329 platutils.set_term_title("IPy:" + cmd)
330 330 os.system(cmd)
331 331 platutils.set_term_title("IPy:" + os.path.basename(os.getcwd()))
332 332
333 333 # override shell() for win32 to deal with network shares
334 334 if os.name in ('nt','dos'):
335 335
336 336 shell_ori = shell
337 337
338 338 def shell(cmd,verbose=0,debug=0,header=''):
339 339 if os.getcwd().startswith(r"\\"):
340 340 path = os.getcwd()
341 341 # change to c drive (cannot be on UNC-share when issuing os.system,
342 342 # as cmd.exe cannot handle UNC addresses)
343 343 os.chdir("c:")
344 344 # issue pushd to the UNC-share and then run the command
345 345 try:
346 346 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
347 347 finally:
348 348 os.chdir(path)
349 349 else:
350 350 shell_ori(cmd,verbose,debug,header)
351 351
352 352 shell.__doc__ = shell_ori.__doc__
353 353
354 354 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
355 355 """Dummy substitute for perl's backquotes.
356 356
357 357 Executes a command and returns the output.
358 358
359 359 Accepts the same arguments as system(), plus:
360 360
361 361 - split(0): if true, the output is returned as a list split on newlines.
362 362
363 363 Note: a stateful version of this function is available through the
364 364 SystemExec class.
365 365
366 366 This is pretty much deprecated and rarely used,
367 367 genutils.getoutputerror may be what you need.
368 368
369 369 """
370 370
371 371 if verbose or debug: print header+cmd
372 372 if not debug:
373 373 output = os.popen(cmd).read()
374 374 # stipping last \n is here for backwards compat.
375 375 if output.endswith('\n'):
376 376 output = output[:-1]
377 377 if split:
378 378 return output.split('\n')
379 379 else:
380 380 return output
381 381
382 382 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
383 383 """Return (standard output,standard error) of executing cmd in a shell.
384 384
385 385 Accepts the same arguments as system(), plus:
386 386
387 387 - split(0): if true, each of stdout/err is returned as a list split on
388 388 newlines.
389 389
390 390 Note: a stateful version of this function is available through the
391 391 SystemExec class."""
392 392
393 393 if verbose or debug: print header+cmd
394 394 if not cmd:
395 395 if split:
396 396 return [],[]
397 397 else:
398 398 return '',''
399 399 if not debug:
400 400 pin,pout,perr = os.popen3(cmd)
401 401 tout = pout.read().rstrip()
402 402 terr = perr.read().rstrip()
403 403 pin.close()
404 404 pout.close()
405 405 perr.close()
406 406 if split:
407 407 return tout.split('\n'),terr.split('\n')
408 408 else:
409 409 return tout,terr
410 410
411 411 # for compatibility with older naming conventions
412 412 xsys = system
413 413 bq = getoutput
414 414
415 415 class SystemExec:
416 416 """Access the system and getoutput functions through a stateful interface.
417 417
418 418 Note: here we refer to the system and getoutput functions from this
419 419 library, not the ones from the standard python library.
420 420
421 421 This class offers the system and getoutput functions as methods, but the
422 422 verbose, debug and header parameters can be set for the instance (at
423 423 creation time or later) so that they don't need to be specified on each
424 424 call.
425 425
426 426 For efficiency reasons, there's no way to override the parameters on a
427 427 per-call basis other than by setting instance attributes. If you need
428 428 local overrides, it's best to directly call system() or getoutput().
429 429
430 430 The following names are provided as alternate options:
431 431 - xsys: alias to system
432 432 - bq: alias to getoutput
433 433
434 434 An instance can then be created as:
435 435 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
436 436
437 437 And used as:
438 438 >>> sysexec.xsys('pwd')
439 439 >>> dirlist = sysexec.bq('ls -l')
440 440 """
441 441
442 442 def __init__(self,verbose=0,debug=0,header='',split=0):
443 443 """Specify the instance's values for verbose, debug and header."""
444 444 setattr_list(self,'verbose debug header split')
445 445
446 446 def system(self,cmd):
447 447 """Stateful interface to system(), with the same keyword parameters."""
448 448
449 449 system(cmd,self.verbose,self.debug,self.header)
450 450
451 451 def shell(self,cmd):
452 452 """Stateful interface to shell(), with the same keyword parameters."""
453 453
454 454 shell(cmd,self.verbose,self.debug,self.header)
455 455
456 456 xsys = system # alias
457 457
458 458 def getoutput(self,cmd):
459 459 """Stateful interface to getoutput()."""
460 460
461 461 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
462 462
463 463 def getoutputerror(self,cmd):
464 464 """Stateful interface to getoutputerror()."""
465 465
466 466 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
467 467
468 468 bq = getoutput # alias
469 469
470 470 #-----------------------------------------------------------------------------
471 471 def mutex_opts(dict,ex_op):
472 472 """Check for presence of mutually exclusive keys in a dict.
473 473
474 474 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
475 475 for op1,op2 in ex_op:
476 476 if op1 in dict and op2 in dict:
477 477 raise ValueError,'\n*** ERROR in Arguments *** '\
478 478 'Options '+op1+' and '+op2+' are mutually exclusive.'
479 479
480 480 #-----------------------------------------------------------------------------
481 481 def get_py_filename(name):
482 482 """Return a valid python filename in the current directory.
483 483
484 484 If the given name is not a file, it adds '.py' and searches again.
485 485 Raises IOError with an informative message if the file isn't found."""
486 486
487 487 name = os.path.expanduser(name)
488 488 if not os.path.isfile(name) and not name.endswith('.py'):
489 489 name += '.py'
490 490 if os.path.isfile(name):
491 491 return name
492 492 else:
493 493 raise IOError,'File `%s` not found.' % name
494 494
495 495 #-----------------------------------------------------------------------------
496 496 def filefind(fname,alt_dirs = None):
497 497 """Return the given filename either in the current directory, if it
498 498 exists, or in a specified list of directories.
499 499
500 500 ~ expansion is done on all file and directory names.
501 501
502 502 Upon an unsuccessful search, raise an IOError exception."""
503 503
504 504 if alt_dirs is None:
505 505 try:
506 506 alt_dirs = get_home_dir()
507 507 except HomeDirError:
508 508 alt_dirs = os.getcwd()
509 509 search = [fname] + list_strings(alt_dirs)
510 510 search = map(os.path.expanduser,search)
511 511 #print 'search list for',fname,'list:',search # dbg
512 512 fname = search[0]
513 513 if os.path.isfile(fname):
514 514 return fname
515 515 for direc in search[1:]:
516 516 testname = os.path.join(direc,fname)
517 517 #print 'testname',testname # dbg
518 518 if os.path.isfile(testname):
519 519 return testname
520 520 raise IOError,'File' + `fname` + \
521 521 ' not found in current or supplied directories:' + `alt_dirs`
522 522
523 523 #----------------------------------------------------------------------------
524 524 def file_read(filename):
525 525 """Read a file and close it. Returns the file source."""
526 526 fobj = open(filename,'r');
527 527 source = fobj.read();
528 528 fobj.close()
529 529 return source
530 530
531 531 def file_readlines(filename):
532 532 """Read a file and close it. Returns the file source using readlines()."""
533 533 fobj = open(filename,'r');
534 534 lines = fobj.readlines();
535 535 fobj.close()
536 536 return lines
537 537
538 538 #----------------------------------------------------------------------------
539 539 def target_outdated(target,deps):
540 540 """Determine whether a target is out of date.
541 541
542 542 target_outdated(target,deps) -> 1/0
543 543
544 544 deps: list of filenames which MUST exist.
545 545 target: single filename which may or may not exist.
546 546
547 547 If target doesn't exist or is older than any file listed in deps, return
548 548 true, otherwise return false.
549 549 """
550 550 try:
551 551 target_time = os.path.getmtime(target)
552 552 except os.error:
553 553 return 1
554 554 for dep in deps:
555 555 dep_time = os.path.getmtime(dep)
556 556 if dep_time > target_time:
557 557 #print "For target",target,"Dep failed:",dep # dbg
558 558 #print "times (dep,tar):",dep_time,target_time # dbg
559 559 return 1
560 560 return 0
561 561
562 562 #-----------------------------------------------------------------------------
563 563 def target_update(target,deps,cmd):
564 564 """Update a target with a given command given a list of dependencies.
565 565
566 566 target_update(target,deps,cmd) -> runs cmd if target is outdated.
567 567
568 568 This is just a wrapper around target_outdated() which calls the given
569 569 command if target is outdated."""
570 570
571 571 if target_outdated(target,deps):
572 572 xsys(cmd)
573 573
574 574 #----------------------------------------------------------------------------
575 575 def unquote_ends(istr):
576 576 """Remove a single pair of quotes from the endpoints of a string."""
577 577
578 578 if not istr:
579 579 return istr
580 580 if (istr[0]=="'" and istr[-1]=="'") or \
581 581 (istr[0]=='"' and istr[-1]=='"'):
582 582 return istr[1:-1]
583 583 else:
584 584 return istr
585 585
586 586 #----------------------------------------------------------------------------
587 587 def process_cmdline(argv,names=[],defaults={},usage=''):
588 588 """ Process command-line options and arguments.
589 589
590 590 Arguments:
591 591
592 592 - argv: list of arguments, typically sys.argv.
593 593
594 594 - names: list of option names. See DPyGetOpt docs for details on options
595 595 syntax.
596 596
597 597 - defaults: dict of default values.
598 598
599 599 - usage: optional usage notice to print if a wrong argument is passed.
600 600
601 601 Return a dict of options and a list of free arguments."""
602 602
603 603 getopt = DPyGetOpt.DPyGetOpt()
604 604 getopt.setIgnoreCase(0)
605 605 getopt.parseConfiguration(names)
606 606
607 607 try:
608 608 getopt.processArguments(argv)
609 609 except:
610 610 print usage
611 611 warn(`sys.exc_value`,level=4)
612 612
613 613 defaults.update(getopt.optionValues)
614 614 args = getopt.freeValues
615 615
616 616 return defaults,args
617 617
618 618 #----------------------------------------------------------------------------
619 619 def optstr2types(ostr):
620 620 """Convert a string of option names to a dict of type mappings.
621 621
622 622 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
623 623
624 624 This is used to get the types of all the options in a string formatted
625 625 with the conventions of DPyGetOpt. The 'type' None is used for options
626 626 which are strings (they need no further conversion). This function's main
627 627 use is to get a typemap for use with read_dict().
628 628 """
629 629
630 630 typeconv = {None:'',int:'',float:''}
631 631 typemap = {'s':None,'i':int,'f':float}
632 632 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
633 633
634 634 for w in ostr.split():
635 635 oname,alias,otype = opt_re.match(w).groups()
636 636 if otype == '' or alias == '!': # simple switches are integers too
637 637 otype = 'i'
638 638 typeconv[typemap[otype]] += oname + ' '
639 639 return typeconv
640 640
641 641 #----------------------------------------------------------------------------
642 642 def read_dict(filename,type_conv=None,**opt):
643 643
644 644 """Read a dictionary of key=value pairs from an input file, optionally
645 645 performing conversions on the resulting values.
646 646
647 647 read_dict(filename,type_conv,**opt) -> dict
648 648
649 649 Only one value per line is accepted, the format should be
650 650 # optional comments are ignored
651 651 key value\n
652 652
653 653 Args:
654 654
655 655 - type_conv: A dictionary specifying which keys need to be converted to
656 656 which types. By default all keys are read as strings. This dictionary
657 657 should have as its keys valid conversion functions for strings
658 658 (int,long,float,complex, or your own). The value for each key
659 659 (converter) should be a whitespace separated string containing the names
660 660 of all the entries in the file to be converted using that function. For
661 661 keys to be left alone, use None as the conversion function (only needed
662 662 with purge=1, see below).
663 663
664 664 - opt: dictionary with extra options as below (default in parens)
665 665
666 666 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
667 667 of the dictionary to be returned. If purge is going to be used, the
668 668 set of keys to be left as strings also has to be explicitly specified
669 669 using the (non-existent) conversion function None.
670 670
671 671 fs(None): field separator. This is the key/value separator to be used
672 672 when parsing the file. The None default means any whitespace [behavior
673 673 of string.split()].
674 674
675 675 strip(0): if 1, strip string values of leading/trailinig whitespace.
676 676
677 677 warn(1): warning level if requested keys are not found in file.
678 678 - 0: silently ignore.
679 679 - 1: inform but proceed.
680 680 - 2: raise KeyError exception.
681 681
682 682 no_empty(0): if 1, remove keys with whitespace strings as a value.
683 683
684 684 unique([]): list of keys (or space separated string) which can't be
685 685 repeated. If one such key is found in the file, each new instance
686 686 overwrites the previous one. For keys not listed here, the behavior is
687 687 to make a list of all appearances.
688 688
689 689 Example:
690 690 If the input file test.ini has:
691 691 i 3
692 692 x 4.5
693 693 y 5.5
694 694 s hi ho
695 695 Then:
696 696
697 697 >>> type_conv={int:'i',float:'x',None:'s'}
698 698 >>> read_dict('test.ini')
699 699 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
700 700 >>> read_dict('test.ini',type_conv)
701 701 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
702 702 >>> read_dict('test.ini',type_conv,purge=1)
703 703 {'i': 3, 's': 'hi ho', 'x': 4.5}
704 704 """
705 705
706 706 # starting config
707 707 opt.setdefault('purge',0)
708 708 opt.setdefault('fs',None) # field sep defaults to any whitespace
709 709 opt.setdefault('strip',0)
710 710 opt.setdefault('warn',1)
711 711 opt.setdefault('no_empty',0)
712 712 opt.setdefault('unique','')
713 713 if type(opt['unique']) in StringTypes:
714 714 unique_keys = qw(opt['unique'])
715 715 elif type(opt['unique']) in (types.TupleType,types.ListType):
716 716 unique_keys = opt['unique']
717 717 else:
718 718 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
719 719
720 720 dict = {}
721 721 # first read in table of values as strings
722 722 file = open(filename,'r')
723 723 for line in file.readlines():
724 724 line = line.strip()
725 725 if len(line) and line[0]=='#': continue
726 726 if len(line)>0:
727 727 lsplit = line.split(opt['fs'],1)
728 728 try:
729 729 key,val = lsplit
730 730 except ValueError:
731 731 key,val = lsplit[0],''
732 732 key = key.strip()
733 733 if opt['strip']: val = val.strip()
734 734 if val == "''" or val == '""': val = ''
735 735 if opt['no_empty'] and (val=='' or val.isspace()):
736 736 continue
737 737 # if a key is found more than once in the file, build a list
738 738 # unless it's in the 'unique' list. In that case, last found in file
739 739 # takes precedence. User beware.
740 740 try:
741 741 if dict[key] and key in unique_keys:
742 742 dict[key] = val
743 743 elif type(dict[key]) is types.ListType:
744 744 dict[key].append(val)
745 745 else:
746 746 dict[key] = [dict[key],val]
747 747 except KeyError:
748 748 dict[key] = val
749 749 # purge if requested
750 750 if opt['purge']:
751 751 accepted_keys = qwflat(type_conv.values())
752 752 for key in dict.keys():
753 753 if key in accepted_keys: continue
754 754 del(dict[key])
755 755 # now convert if requested
756 756 if type_conv==None: return dict
757 757 conversions = type_conv.keys()
758 758 try: conversions.remove(None)
759 759 except: pass
760 760 for convert in conversions:
761 761 for val in qw(type_conv[convert]):
762 762 try:
763 763 dict[val] = convert(dict[val])
764 764 except KeyError,e:
765 765 if opt['warn'] == 0:
766 766 pass
767 767 elif opt['warn'] == 1:
768 768 print >>sys.stderr, 'Warning: key',val,\
769 769 'not found in file',filename
770 770 elif opt['warn'] == 2:
771 771 raise KeyError,e
772 772 else:
773 773 raise ValueError,'Warning level must be 0,1 or 2'
774 774
775 775 return dict
776 776
777 777 #----------------------------------------------------------------------------
778 778 def flag_calls(func):
779 779 """Wrap a function to detect and flag when it gets called.
780 780
781 781 This is a decorator which takes a function and wraps it in a function with
782 782 a 'called' attribute. wrapper.called is initialized to False.
783 783
784 784 The wrapper.called attribute is set to False right before each call to the
785 785 wrapped function, so if the call fails it remains False. After the call
786 786 completes, wrapper.called is set to True and the output is returned.
787 787
788 788 Testing for truth in wrapper.called allows you to determine if a call to
789 789 func() was attempted and succeeded."""
790 790
791 791 def wrapper(*args,**kw):
792 792 wrapper.called = False
793 793 out = func(*args,**kw)
794 794 wrapper.called = True
795 795 return out
796 796
797 797 wrapper.called = False
798 798 wrapper.__doc__ = func.__doc__
799 799 return wrapper
800 800
801 801 #----------------------------------------------------------------------------
802 802 class HomeDirError(Error):
803 803 pass
804 804
805 805 def get_home_dir():
806 806 """Return the closest possible equivalent to a 'home' directory.
807 807
808 808 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
809 809
810 810 Currently only Posix and NT are implemented, a HomeDirError exception is
811 811 raised for all other OSes. """
812 812
813 813 isdir = os.path.isdir
814 814 env = os.environ
815 815
816 816 # first, check py2exe distribution root directory for _ipython.
817 817 # This overrides all. Normally does not exist.
818 818
819 819 if '\\library.zip\\' in IPython.__file__.lower():
820 820 root, rest = IPython.__file__.lower().split('library.zip')
821 821 if isdir(root + '_ipython'):
822 822 os.environ["IPYKITROOT"] = root.rstrip('\\')
823 823 return root
824 824
825 825 try:
826 826 homedir = env['HOME']
827 827 if not isdir(homedir):
828 828 # in case a user stuck some string which does NOT resolve to a
829 829 # valid path, it's as good as if we hadn't foud it
830 830 raise KeyError
831 831 return homedir
832 832 except KeyError:
833 833 if os.name == 'posix':
834 834 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
835 835 elif os.name == 'nt':
836 836 # For some strange reason, win9x returns 'nt' for os.name.
837 837 try:
838 838 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
839 839 if not isdir(homedir):
840 840 homedir = os.path.join(env['USERPROFILE'])
841 841 if not isdir(homedir):
842 842 raise HomeDirError
843 843 return homedir
844 844 except:
845 845 try:
846 846 # Use the registry to get the 'My Documents' folder.
847 847 import _winreg as wreg
848 848 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
849 849 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
850 850 homedir = wreg.QueryValueEx(key,'Personal')[0]
851 851 key.Close()
852 852 if not isdir(homedir):
853 853 e = ('Invalid "Personal" folder registry key '
854 854 'typically "My Documents".\n'
855 855 'Value: %s\n'
856 856 'This is not a valid directory on your system.' %
857 857 homedir)
858 858 raise HomeDirError(e)
859 859 return homedir
860 860 except HomeDirError:
861 861 raise
862 862 except:
863 863 return 'C:\\'
864 864 elif os.name == 'dos':
865 865 # Desperate, may do absurd things in classic MacOS. May work under DOS.
866 866 return 'C:\\'
867 867 else:
868 868 raise HomeDirError,'support for your operating system not implemented.'
869 869
870 870 #****************************************************************************
871 871 # strings and text
872 872
873 873 class LSString(str):
874 874 """String derivative with a special access attributes.
875 875
876 876 These are normal strings, but with the special attributes:
877 877
878 878 .l (or .list) : value as list (split on newlines).
879 879 .n (or .nlstr): original value (the string itself).
880 880 .s (or .spstr): value as whitespace-separated string.
881 881 .p (or .paths): list of path objects
882 882
883 883 Any values which require transformations are computed only once and
884 884 cached.
885 885
886 886 Such strings are very useful to efficiently interact with the shell, which
887 887 typically only understands whitespace-separated options for commands."""
888 888
889 889 def get_list(self):
890 890 try:
891 891 return self.__list
892 892 except AttributeError:
893 893 self.__list = self.split('\n')
894 894 return self.__list
895 895
896 896 l = list = property(get_list)
897 897
898 898 def get_spstr(self):
899 899 try:
900 900 return self.__spstr
901 901 except AttributeError:
902 902 self.__spstr = self.replace('\n',' ')
903 903 return self.__spstr
904 904
905 905 s = spstr = property(get_spstr)
906 906
907 907 def get_nlstr(self):
908 908 return self
909 909
910 910 n = nlstr = property(get_nlstr)
911 911
912 912 def get_paths(self):
913 913 try:
914 914 return self.__paths
915 915 except AttributeError:
916 916 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
917 917 return self.__paths
918 918
919 919 p = paths = property(get_paths)
920 920
921 921 def print_lsstring(arg):
922 922 """ Prettier (non-repr-like) and more informative printer for LSString """
923 923 print "LSString (.p, .n, .l, .s available). Value:"
924 924 print arg
925 925
926 926 print_lsstring = result_display.when_type(LSString)(print_lsstring)
927 927
928 928 #----------------------------------------------------------------------------
929 929 class SList(list):
930 930 """List derivative with a special access attributes.
931 931
932 932 These are normal lists, but with the special attributes:
933 933
934 934 .l (or .list) : value as list (the list itself).
935 935 .n (or .nlstr): value as a string, joined on newlines.
936 936 .s (or .spstr): value as a string, joined on spaces.
937 937 .p (or .paths): list of path objects
938 938
939 939 Any values which require transformations are computed only once and
940 940 cached."""
941 941
942 942 def get_list(self):
943 943 return self
944 944
945 945 l = list = property(get_list)
946 946
947 947 def get_spstr(self):
948 948 try:
949 949 return self.__spstr
950 950 except AttributeError:
951 951 self.__spstr = ' '.join(self)
952 952 return self.__spstr
953 953
954 954 s = spstr = property(get_spstr)
955 955
956 956 def get_nlstr(self):
957 957 try:
958 958 return self.__nlstr
959 959 except AttributeError:
960 960 self.__nlstr = '\n'.join(self)
961 961 return self.__nlstr
962 962
963 963 n = nlstr = property(get_nlstr)
964 964
965 965 def get_paths(self):
966 966 try:
967 967 return self.__paths
968 968 except AttributeError:
969 969 self.__paths = [path(p) for p in self if os.path.exists(p)]
970 970 return self.__paths
971 971
972 972 p = paths = property(get_paths)
973 973
974 974 #----------------------------------------------------------------------------
975 975 def esc_quotes(strng):
976 976 """Return the input string with single and double quotes escaped out"""
977 977
978 978 return strng.replace('"','\\"').replace("'","\\'")
979 979
980 980 #----------------------------------------------------------------------------
981 981 def make_quoted_expr(s):
982 982 """Return string s in appropriate quotes, using raw string if possible.
983 983
984 984 Effectively this turns string: cd \ao\ao\
985 985 to: r"cd \ao\ao\_"[:-1]
986 986
987 987 Note the use of raw string and padding at the end to allow trailing backslash.
988 988
989 989 """
990 990
991 991 tail = ''
992 992 tailpadding = ''
993 993 raw = ''
994 994 if "\\" in s:
995 995 raw = 'r'
996 996 if s.endswith('\\'):
997 997 tail = '[:-1]'
998 998 tailpadding = '_'
999 999 if '"' not in s:
1000 1000 quote = '"'
1001 1001 elif "'" not in s:
1002 1002 quote = "'"
1003 1003 elif '"""' not in s and not s.endswith('"'):
1004 1004 quote = '"""'
1005 1005 elif "'''" not in s and not s.endswith("'"):
1006 1006 quote = "'''"
1007 1007 else:
1008 1008 # give up, backslash-escaped string will do
1009 1009 return '"%s"' % esc_quotes(s)
1010 1010 res = itpl("$raw$quote$s$tailpadding$quote$tail")
1011 1011 return res
1012 1012
1013 1013
1014 1014 #----------------------------------------------------------------------------
1015 1015 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1016 1016 """Take multiple lines of input.
1017 1017
1018 1018 A list with each line of input as a separate element is returned when a
1019 1019 termination string is entered (defaults to a single '.'). Input can also
1020 1020 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1021 1021
1022 1022 Lines of input which end in \\ are joined into single entries (and a
1023 1023 secondary continuation prompt is issued as long as the user terminates
1024 1024 lines with \\). This allows entering very long strings which are still
1025 1025 meant to be treated as single entities.
1026 1026 """
1027 1027
1028 1028 try:
1029 1029 if header:
1030 1030 header += '\n'
1031 1031 lines = [raw_input(header + ps1)]
1032 1032 except EOFError:
1033 1033 return []
1034 1034 terminate = [terminate_str]
1035 1035 try:
1036 1036 while lines[-1:] != terminate:
1037 1037 new_line = raw_input(ps1)
1038 1038 while new_line.endswith('\\'):
1039 1039 new_line = new_line[:-1] + raw_input(ps2)
1040 1040 lines.append(new_line)
1041 1041
1042 1042 return lines[:-1] # don't return the termination command
1043 1043 except EOFError:
1044 1044 print
1045 1045 return lines
1046 1046
1047 1047 #----------------------------------------------------------------------------
1048 1048 def raw_input_ext(prompt='', ps2='... '):
1049 1049 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1050 1050
1051 1051 line = raw_input(prompt)
1052 1052 while line.endswith('\\'):
1053 1053 line = line[:-1] + raw_input(ps2)
1054 1054 return line
1055 1055
1056 1056 #----------------------------------------------------------------------------
1057 1057 def ask_yes_no(prompt,default=None):
1058 1058 """Asks a question and returns an integer 1/0 (y/n) answer.
1059 1059
1060 1060 If default is given (one of 'y','n'), it is used if the user input is
1061 1061 empty. Otherwise the question is repeated until an answer is given.
1062 1062
1063 1063 An EOF is treated as the default answer. If there is no default, an
1064 1064 exception is raised to prevent infinite loops.
1065 1065
1066 1066 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1067 1067
1068 1068 answers = {'y':True,'n':False,'yes':True,'no':False}
1069 1069 ans = None
1070 1070 while ans not in answers.keys():
1071 1071 try:
1072 1072 ans = raw_input(prompt+' ').lower()
1073 1073 if not ans: # response was an empty string
1074 1074 ans = default
1075 1075 except KeyboardInterrupt:
1076 1076 pass
1077 1077 except EOFError:
1078 1078 if default in answers.keys():
1079 1079 ans = default
1080 1080 print
1081 1081 else:
1082 1082 raise
1083 1083
1084 1084 return answers[ans]
1085 1085
1086 1086 #----------------------------------------------------------------------------
1087 1087 def marquee(txt='',width=78,mark='*'):
1088 1088 """Return the input string centered in a 'marquee'."""
1089 1089 if not txt:
1090 1090 return (mark*width)[:width]
1091 1091 nmark = (width-len(txt)-2)/len(mark)/2
1092 1092 if nmark < 0: nmark =0
1093 1093 marks = mark*nmark
1094 1094 return '%s %s %s' % (marks,txt,marks)
1095 1095
1096 1096 #----------------------------------------------------------------------------
1097 1097 class EvalDict:
1098 1098 """
1099 1099 Emulate a dict which evaluates its contents in the caller's frame.
1100 1100
1101 1101 Usage:
1102 1102 >>>number = 19
1103 1103 >>>text = "python"
1104 1104 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1105 1105 """
1106 1106
1107 1107 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1108 1108 # modified (shorter) version of:
1109 1109 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1110 1110 # Skip Montanaro (skip@pobox.com).
1111 1111
1112 1112 def __getitem__(self, name):
1113 1113 frame = sys._getframe(1)
1114 1114 return eval(name, frame.f_globals, frame.f_locals)
1115 1115
1116 1116 EvalString = EvalDict # for backwards compatibility
1117 1117 #----------------------------------------------------------------------------
1118 1118 def qw(words,flat=0,sep=None,maxsplit=-1):
1119 1119 """Similar to Perl's qw() operator, but with some more options.
1120 1120
1121 1121 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1122 1122
1123 1123 words can also be a list itself, and with flat=1, the output will be
1124 1124 recursively flattened. Examples:
1125 1125
1126 1126 >>> qw('1 2')
1127 1127 ['1', '2']
1128 1128 >>> qw(['a b','1 2',['m n','p q']])
1129 1129 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1130 1130 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1131 1131 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1132 1132
1133 1133 if type(words) in StringTypes:
1134 1134 return [word.strip() for word in words.split(sep,maxsplit)
1135 1135 if word and not word.isspace() ]
1136 1136 if flat:
1137 1137 return flatten(map(qw,words,[1]*len(words)))
1138 1138 return map(qw,words)
1139 1139
1140 1140 #----------------------------------------------------------------------------
1141 1141 def qwflat(words,sep=None,maxsplit=-1):
1142 1142 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1143 1143 return qw(words,1,sep,maxsplit)
1144 1144
1145 1145 #----------------------------------------------------------------------------
1146 1146 def qw_lol(indata):
1147 1147 """qw_lol('a b') -> [['a','b']],
1148 1148 otherwise it's just a call to qw().
1149 1149
1150 1150 We need this to make sure the modules_some keys *always* end up as a
1151 1151 list of lists."""
1152 1152
1153 1153 if type(indata) in StringTypes:
1154 1154 return [qw(indata)]
1155 1155 else:
1156 1156 return qw(indata)
1157 1157
1158 1158 #-----------------------------------------------------------------------------
1159 1159 def list_strings(arg):
1160 1160 """Always return a list of strings, given a string or list of strings
1161 1161 as input."""
1162 1162
1163 1163 if type(arg) in StringTypes: return [arg]
1164 1164 else: return arg
1165 1165
1166 1166 #----------------------------------------------------------------------------
1167 1167 def grep(pat,list,case=1):
1168 1168 """Simple minded grep-like function.
1169 1169 grep(pat,list) returns occurrences of pat in list, None on failure.
1170 1170
1171 1171 It only does simple string matching, with no support for regexps. Use the
1172 1172 option case=0 for case-insensitive matching."""
1173 1173
1174 1174 # This is pretty crude. At least it should implement copying only references
1175 1175 # to the original data in case it's big. Now it copies the data for output.
1176 1176 out=[]
1177 1177 if case:
1178 1178 for term in list:
1179 1179 if term.find(pat)>-1: out.append(term)
1180 1180 else:
1181 1181 lpat=pat.lower()
1182 1182 for term in list:
1183 1183 if term.lower().find(lpat)>-1: out.append(term)
1184 1184
1185 1185 if len(out): return out
1186 1186 else: return None
1187 1187
1188 1188 #----------------------------------------------------------------------------
1189 1189 def dgrep(pat,*opts):
1190 1190 """Return grep() on dir()+dir(__builtins__).
1191 1191
1192 1192 A very common use of grep() when working interactively."""
1193 1193
1194 1194 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1195 1195
1196 1196 #----------------------------------------------------------------------------
1197 1197 def idgrep(pat):
1198 1198 """Case-insensitive dgrep()"""
1199 1199
1200 1200 return dgrep(pat,0)
1201 1201
1202 1202 #----------------------------------------------------------------------------
1203 1203 def igrep(pat,list):
1204 1204 """Synonym for case-insensitive grep."""
1205 1205
1206 1206 return grep(pat,list,case=0)
1207 1207
1208 1208 #----------------------------------------------------------------------------
1209 1209 def indent(str,nspaces=4,ntabs=0):
1210 1210 """Indent a string a given number of spaces or tabstops.
1211 1211
1212 1212 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1213 1213 """
1214 1214 if str is None:
1215 1215 return
1216 1216 ind = '\t'*ntabs+' '*nspaces
1217 1217 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1218 1218 if outstr.endswith(os.linesep+ind):
1219 1219 return outstr[:-len(ind)]
1220 1220 else:
1221 1221 return outstr
1222 1222
1223 1223 #-----------------------------------------------------------------------------
1224 1224 def native_line_ends(filename,backup=1):
1225 1225 """Convert (in-place) a file to line-ends native to the current OS.
1226 1226
1227 1227 If the optional backup argument is given as false, no backup of the
1228 1228 original file is left. """
1229 1229
1230 1230 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1231 1231
1232 1232 bak_filename = filename + backup_suffixes[os.name]
1233 1233
1234 1234 original = open(filename).read()
1235 1235 shutil.copy2(filename,bak_filename)
1236 1236 try:
1237 1237 new = open(filename,'wb')
1238 1238 new.write(os.linesep.join(original.splitlines()))
1239 1239 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1240 1240 new.close()
1241 1241 except:
1242 1242 os.rename(bak_filename,filename)
1243 1243 if not backup:
1244 1244 try:
1245 1245 os.remove(bak_filename)
1246 1246 except:
1247 1247 pass
1248 1248
1249 1249 #----------------------------------------------------------------------------
1250 1250 def get_pager_cmd(pager_cmd = None):
1251 1251 """Return a pager command.
1252 1252
1253 1253 Makes some attempts at finding an OS-correct one."""
1254 1254
1255 1255 if os.name == 'posix':
1256 1256 default_pager_cmd = 'less -r' # -r for color control sequences
1257 1257 elif os.name in ['nt','dos']:
1258 1258 default_pager_cmd = 'type'
1259 1259
1260 1260 if pager_cmd is None:
1261 1261 try:
1262 1262 pager_cmd = os.environ['PAGER']
1263 1263 except:
1264 1264 pager_cmd = default_pager_cmd
1265 1265 return pager_cmd
1266 1266
1267 1267 #-----------------------------------------------------------------------------
1268 1268 def get_pager_start(pager,start):
1269 1269 """Return the string for paging files with an offset.
1270 1270
1271 1271 This is the '+N' argument which less and more (under Unix) accept.
1272 1272 """
1273 1273
1274 1274 if pager in ['less','more']:
1275 1275 if start:
1276 1276 start_string = '+' + str(start)
1277 1277 else:
1278 1278 start_string = ''
1279 1279 else:
1280 1280 start_string = ''
1281 1281 return start_string
1282 1282
1283 1283 #----------------------------------------------------------------------------
1284 1284 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1285 1285 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1286 1286 import msvcrt
1287 1287 def page_more():
1288 1288 """ Smart pausing between pages
1289 1289
1290 1290 @return: True if need print more lines, False if quit
1291 1291 """
1292 1292 Term.cout.write('---Return to continue, q to quit--- ')
1293 1293 ans = msvcrt.getch()
1294 1294 if ans in ("q", "Q"):
1295 1295 result = False
1296 1296 else:
1297 1297 result = True
1298 1298 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1299 1299 return result
1300 1300 else:
1301 1301 def page_more():
1302 1302 ans = raw_input('---Return to continue, q to quit--- ')
1303 1303 if ans.lower().startswith('q'):
1304 1304 return False
1305 1305 else:
1306 1306 return True
1307 1307
1308 1308 esc_re = re.compile(r"(\x1b[^m]+m)")
1309 1309
1310 1310 def page_dumb(strng,start=0,screen_lines=25):
1311 1311 """Very dumb 'pager' in Python, for when nothing else works.
1312 1312
1313 1313 Only moves forward, same interface as page(), except for pager_cmd and
1314 1314 mode."""
1315 1315
1316 1316 out_ln = strng.splitlines()[start:]
1317 1317 screens = chop(out_ln,screen_lines-1)
1318 1318 if len(screens) == 1:
1319 1319 print >>Term.cout, os.linesep.join(screens[0])
1320 1320 else:
1321 1321 last_escape = ""
1322 1322 for scr in screens[0:-1]:
1323 1323 hunk = os.linesep.join(scr)
1324 1324 print >>Term.cout, last_escape + hunk
1325 1325 if not page_more():
1326 1326 return
1327 1327 esc_list = esc_re.findall(hunk)
1328 1328 if len(esc_list) > 0:
1329 1329 last_escape = esc_list[-1]
1330 1330 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1331 1331
1332 1332 #----------------------------------------------------------------------------
1333 1333 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1334 1334 """Print a string, piping through a pager after a certain length.
1335 1335
1336 1336 The screen_lines parameter specifies the number of *usable* lines of your
1337 1337 terminal screen (total lines minus lines you need to reserve to show other
1338 1338 information).
1339 1339
1340 1340 If you set screen_lines to a number <=0, page() will try to auto-determine
1341 1341 your screen size and will only use up to (screen_size+screen_lines) for
1342 1342 printing, paging after that. That is, if you want auto-detection but need
1343 1343 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1344 1344 auto-detection without any lines reserved simply use screen_lines = 0.
1345 1345
1346 1346 If a string won't fit in the allowed lines, it is sent through the
1347 1347 specified pager command. If none given, look for PAGER in the environment,
1348 1348 and ultimately default to less.
1349 1349
1350 1350 If no system pager works, the string is sent through a 'dumb pager'
1351 1351 written in python, very simplistic.
1352 1352 """
1353 1353
1354 1354 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1355 1355 TERM = os.environ.get('TERM','dumb')
1356 1356 if TERM in ['dumb','emacs'] and os.name != 'nt':
1357 1357 print strng
1358 1358 return
1359 1359 # chop off the topmost part of the string we don't want to see
1360 1360 str_lines = strng.split(os.linesep)[start:]
1361 1361 str_toprint = os.linesep.join(str_lines)
1362 1362 num_newlines = len(str_lines)
1363 1363 len_str = len(str_toprint)
1364 1364
1365 1365 # Dumb heuristics to guesstimate number of on-screen lines the string
1366 1366 # takes. Very basic, but good enough for docstrings in reasonable
1367 1367 # terminals. If someone later feels like refining it, it's not hard.
1368 1368 numlines = max(num_newlines,int(len_str/80)+1)
1369 1369
1370 1370 if os.name == "nt":
1371 1371 screen_lines_def = get_console_size(defaulty=25)[1]
1372 1372 else:
1373 1373 screen_lines_def = 25 # default value if we can't auto-determine
1374 1374
1375 1375 # auto-determine screen size
1376 1376 if screen_lines <= 0:
1377 1377 if TERM=='xterm':
1378 1378 try:
1379 1379 import curses
1380 1380 if hasattr(curses,'initscr'):
1381 1381 use_curses = 1
1382 1382 else:
1383 1383 use_curses = 0
1384 1384 except ImportError:
1385 1385 use_curses = 0
1386 1386 else:
1387 1387 # curses causes problems on many terminals other than xterm.
1388 1388 use_curses = 0
1389 1389 if use_curses:
1390 1390 scr = curses.initscr()
1391 1391 screen_lines_real,screen_cols = scr.getmaxyx()
1392 1392 curses.endwin()
1393 1393 screen_lines += screen_lines_real
1394 1394 #print '***Screen size:',screen_lines_real,'lines x',\
1395 1395 #screen_cols,'columns.' # dbg
1396 1396 else:
1397 1397 screen_lines += screen_lines_def
1398 1398
1399 1399 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1400 1400 if numlines <= screen_lines :
1401 1401 #print '*** normal print' # dbg
1402 1402 print >>Term.cout, str_toprint
1403 1403 else:
1404 1404 # Try to open pager and default to internal one if that fails.
1405 1405 # All failure modes are tagged as 'retval=1', to match the return
1406 1406 # value of a failed system command. If any intermediate attempt
1407 1407 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1408 1408 pager_cmd = get_pager_cmd(pager_cmd)
1409 1409 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1410 1410 if os.name == 'nt':
1411 1411 if pager_cmd.startswith('type'):
1412 1412 # The default WinXP 'type' command is failing on complex strings.
1413 1413 retval = 1
1414 1414 else:
1415 1415 tmpname = tempfile.mktemp('.txt')
1416 1416 tmpfile = file(tmpname,'wt')
1417 1417 tmpfile.write(strng)
1418 1418 tmpfile.close()
1419 1419 cmd = "%s < %s" % (pager_cmd,tmpname)
1420 1420 if os.system(cmd):
1421 1421 retval = 1
1422 1422 else:
1423 1423 retval = None
1424 1424 os.remove(tmpname)
1425 1425 else:
1426 1426 try:
1427 1427 retval = None
1428 1428 # if I use popen4, things hang. No idea why.
1429 1429 #pager,shell_out = os.popen4(pager_cmd)
1430 1430 pager = os.popen(pager_cmd,'w')
1431 1431 pager.write(strng)
1432 1432 pager.close()
1433 1433 retval = pager.close() # success returns None
1434 1434 except IOError,msg: # broken pipe when user quits
1435 1435 if msg.args == (32,'Broken pipe'):
1436 1436 retval = None
1437 1437 else:
1438 1438 retval = 1
1439 1439 except OSError:
1440 1440 # Other strange problems, sometimes seen in Win2k/cygwin
1441 1441 retval = 1
1442 1442 if retval is not None:
1443 1443 page_dumb(strng,screen_lines=screen_lines)
1444 1444
1445 1445 #----------------------------------------------------------------------------
1446 1446 def page_file(fname,start = 0, pager_cmd = None):
1447 1447 """Page a file, using an optional pager command and starting line.
1448 1448 """
1449 1449
1450 1450 pager_cmd = get_pager_cmd(pager_cmd)
1451 1451 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1452 1452
1453 1453 try:
1454 1454 if os.environ['TERM'] in ['emacs','dumb']:
1455 1455 raise EnvironmentError
1456 1456 xsys(pager_cmd + ' ' + fname)
1457 1457 except:
1458 1458 try:
1459 1459 if start > 0:
1460 1460 start -= 1
1461 1461 page(open(fname).read(),start)
1462 1462 except:
1463 1463 print 'Unable to show file',`fname`
1464 1464
1465 1465 #----------------------------------------------------------------------------
1466 1466 def snip_print(str,width = 75,print_full = 0,header = ''):
1467 1467 """Print a string snipping the midsection to fit in width.
1468 1468
1469 1469 print_full: mode control:
1470 1470 - 0: only snip long strings
1471 1471 - 1: send to page() directly.
1472 1472 - 2: snip long strings and ask for full length viewing with page()
1473 1473 Return 1 if snipping was necessary, 0 otherwise."""
1474 1474
1475 1475 if print_full == 1:
1476 1476 page(header+str)
1477 1477 return 0
1478 1478
1479 1479 print header,
1480 1480 if len(str) < width:
1481 1481 print str
1482 1482 snip = 0
1483 1483 else:
1484 1484 whalf = int((width -5)/2)
1485 1485 print str[:whalf] + ' <...> ' + str[-whalf:]
1486 1486 snip = 1
1487 1487 if snip and print_full == 2:
1488 1488 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1489 1489 page(str)
1490 1490 return snip
1491 1491
1492 1492 #****************************************************************************
1493 1493 # lists, dicts and structures
1494 1494
1495 1495 def belong(candidates,checklist):
1496 1496 """Check whether a list of items appear in a given list of options.
1497 1497
1498 1498 Returns a list of 1 and 0, one for each candidate given."""
1499 1499
1500 1500 return [x in checklist for x in candidates]
1501 1501
1502 1502 #----------------------------------------------------------------------------
1503 1503 def uniq_stable(elems):
1504 1504 """uniq_stable(elems) -> list
1505 1505
1506 1506 Return from an iterable, a list of all the unique elements in the input,
1507 1507 but maintaining the order in which they first appear.
1508 1508
1509 1509 A naive solution to this problem which just makes a dictionary with the
1510 1510 elements as keys fails to respect the stability condition, since
1511 1511 dictionaries are unsorted by nature.
1512 1512
1513 1513 Note: All elements in the input must be valid dictionary keys for this
1514 1514 routine to work, as it internally uses a dictionary for efficiency
1515 1515 reasons."""
1516 1516
1517 1517 unique = []
1518 1518 unique_dict = {}
1519 1519 for nn in elems:
1520 1520 if nn not in unique_dict:
1521 1521 unique.append(nn)
1522 1522 unique_dict[nn] = None
1523 1523 return unique
1524 1524
1525 1525 #----------------------------------------------------------------------------
1526 1526 class NLprinter:
1527 1527 """Print an arbitrarily nested list, indicating index numbers.
1528 1528
1529 1529 An instance of this class called nlprint is available and callable as a
1530 1530 function.
1531 1531
1532 1532 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1533 1533 and using 'sep' to separate the index from the value. """
1534 1534
1535 1535 def __init__(self):
1536 1536 self.depth = 0
1537 1537
1538 1538 def __call__(self,lst,pos='',**kw):
1539 1539 """Prints the nested list numbering levels."""
1540 1540 kw.setdefault('indent',' ')
1541 1541 kw.setdefault('sep',': ')
1542 1542 kw.setdefault('start',0)
1543 1543 kw.setdefault('stop',len(lst))
1544 1544 # we need to remove start and stop from kw so they don't propagate
1545 1545 # into a recursive call for a nested list.
1546 1546 start = kw['start']; del kw['start']
1547 1547 stop = kw['stop']; del kw['stop']
1548 1548 if self.depth == 0 and 'header' in kw.keys():
1549 1549 print kw['header']
1550 1550
1551 1551 for idx in range(start,stop):
1552 1552 elem = lst[idx]
1553 1553 if type(elem)==type([]):
1554 1554 self.depth += 1
1555 1555 self.__call__(elem,itpl('$pos$idx,'),**kw)
1556 1556 self.depth -= 1
1557 1557 else:
1558 1558 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1559 1559
1560 1560 nlprint = NLprinter()
1561 1561 #----------------------------------------------------------------------------
1562 1562 def all_belong(candidates,checklist):
1563 1563 """Check whether a list of items ALL appear in a given list of options.
1564 1564
1565 1565 Returns a single 1 or 0 value."""
1566 1566
1567 1567 return 1-(0 in [x in checklist for x in candidates])
1568 1568
1569 1569 #----------------------------------------------------------------------------
1570 1570 def sort_compare(lst1,lst2,inplace = 1):
1571 1571 """Sort and compare two lists.
1572 1572
1573 1573 By default it does it in place, thus modifying the lists. Use inplace = 0
1574 1574 to avoid that (at the cost of temporary copy creation)."""
1575 1575 if not inplace:
1576 1576 lst1 = lst1[:]
1577 1577 lst2 = lst2[:]
1578 1578 lst1.sort(); lst2.sort()
1579 1579 return lst1 == lst2
1580 1580
1581 1581 #----------------------------------------------------------------------------
1582 1582 def mkdict(**kwargs):
1583 1583 """Return a dict from a keyword list.
1584 1584
1585 1585 It's just syntactic sugar for making ditcionary creation more convenient:
1586 1586 # the standard way
1587 1587 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1588 1588 # a cleaner way
1589 1589 >>>data = dict(red=1, green=2, blue=3)
1590 1590
1591 1591 If you need more than this, look at the Struct() class."""
1592 1592
1593 1593 return kwargs
1594 1594
1595 1595 #----------------------------------------------------------------------------
1596 1596 def list2dict(lst):
1597 1597 """Takes a list of (key,value) pairs and turns it into a dict."""
1598 1598
1599 1599 dic = {}
1600 1600 for k,v in lst: dic[k] = v
1601 1601 return dic
1602 1602
1603 1603 #----------------------------------------------------------------------------
1604 1604 def list2dict2(lst,default=''):
1605 1605 """Takes a list and turns it into a dict.
1606 1606 Much slower than list2dict, but more versatile. This version can take
1607 1607 lists with sublists of arbitrary length (including sclars)."""
1608 1608
1609 1609 dic = {}
1610 1610 for elem in lst:
1611 1611 if type(elem) in (types.ListType,types.TupleType):
1612 1612 size = len(elem)
1613 1613 if size == 0:
1614 1614 pass
1615 1615 elif size == 1:
1616 1616 dic[elem] = default
1617 1617 else:
1618 1618 k,v = elem[0], elem[1:]
1619 1619 if len(v) == 1: v = v[0]
1620 1620 dic[k] = v
1621 1621 else:
1622 1622 dic[elem] = default
1623 1623 return dic
1624 1624
1625 1625 #----------------------------------------------------------------------------
1626 1626 def flatten(seq):
1627 1627 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1628 1628
1629 1629 return [x for subseq in seq for x in subseq]
1630 1630
1631 1631 #----------------------------------------------------------------------------
1632 1632 def get_slice(seq,start=0,stop=None,step=1):
1633 1633 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1634 1634 if stop == None:
1635 1635 stop = len(seq)
1636 1636 item = lambda i: seq[i]
1637 1637 return map(item,xrange(start,stop,step))
1638 1638
1639 1639 #----------------------------------------------------------------------------
1640 1640 def chop(seq,size):
1641 1641 """Chop a sequence into chunks of the given size."""
1642 1642 chunk = lambda i: seq[i:i+size]
1643 1643 return map(chunk,xrange(0,len(seq),size))
1644 1644
1645 1645 #----------------------------------------------------------------------------
1646 1646 # with is a keyword as of python 2.5, so this function is renamed to withobj
1647 1647 # from its old 'with' name.
1648 1648 def with_obj(object, **args):
1649 1649 """Set multiple attributes for an object, similar to Pascal's with.
1650 1650
1651 1651 Example:
1652 1652 with_obj(jim,
1653 1653 born = 1960,
1654 1654 haircolour = 'Brown',
1655 1655 eyecolour = 'Green')
1656 1656
1657 1657 Credit: Greg Ewing, in
1658 1658 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1659 1659
1660 1660 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1661 1661 has become a keyword for Python 2.5, so we had to rename it."""
1662 1662
1663 1663 object.__dict__.update(args)
1664 1664
1665 1665 #----------------------------------------------------------------------------
1666 1666 def setattr_list(obj,alist,nspace = None):
1667 1667 """Set a list of attributes for an object taken from a namespace.
1668 1668
1669 1669 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1670 1670 alist with their values taken from nspace, which must be a dict (something
1671 1671 like locals() will often do) If nspace isn't given, locals() of the
1672 1672 *caller* is used, so in most cases you can omit it.
1673 1673
1674 1674 Note that alist can be given as a string, which will be automatically
1675 1675 split into a list on whitespace. If given as a list, it must be a list of
1676 1676 *strings* (the variable names themselves), not of variables."""
1677 1677
1678 1678 # this grabs the local variables from the *previous* call frame -- that is
1679 1679 # the locals from the function that called setattr_list().
1680 1680 # - snipped from weave.inline()
1681 1681 if nspace is None:
1682 1682 call_frame = sys._getframe().f_back
1683 1683 nspace = call_frame.f_locals
1684 1684
1685 1685 if type(alist) in StringTypes:
1686 1686 alist = alist.split()
1687 1687 for attr in alist:
1688 1688 val = eval(attr,nspace)
1689 1689 setattr(obj,attr,val)
1690 1690
1691 1691 #----------------------------------------------------------------------------
1692 1692 def getattr_list(obj,alist,*args):
1693 1693 """getattr_list(obj,alist[, default]) -> attribute list.
1694 1694
1695 1695 Get a list of named attributes for an object. When a default argument is
1696 1696 given, it is returned when the attribute doesn't exist; without it, an
1697 1697 exception is raised in that case.
1698 1698
1699 1699 Note that alist can be given as a string, which will be automatically
1700 1700 split into a list on whitespace. If given as a list, it must be a list of
1701 1701 *strings* (the variable names themselves), not of variables."""
1702 1702
1703 1703 if type(alist) in StringTypes:
1704 1704 alist = alist.split()
1705 1705 if args:
1706 1706 if len(args)==1:
1707 1707 default = args[0]
1708 1708 return map(lambda attr: getattr(obj,attr,default),alist)
1709 1709 else:
1710 1710 raise ValueError,'getattr_list() takes only one optional argument'
1711 1711 else:
1712 1712 return map(lambda attr: getattr(obj,attr),alist)
1713 1713
1714 1714 #----------------------------------------------------------------------------
1715 1715 def map_method(method,object_list,*argseq,**kw):
1716 1716 """map_method(method,object_list,*args,**kw) -> list
1717 1717
1718 1718 Return a list of the results of applying the methods to the items of the
1719 1719 argument sequence(s). If more than one sequence is given, the method is
1720 1720 called with an argument list consisting of the corresponding item of each
1721 1721 sequence. All sequences must be of the same length.
1722 1722
1723 1723 Keyword arguments are passed verbatim to all objects called.
1724 1724
1725 1725 This is Python code, so it's not nearly as fast as the builtin map()."""
1726 1726
1727 1727 out_list = []
1728 1728 idx = 0
1729 1729 for object in object_list:
1730 1730 try:
1731 1731 handler = getattr(object, method)
1732 1732 except AttributeError:
1733 1733 out_list.append(None)
1734 1734 else:
1735 1735 if argseq:
1736 1736 args = map(lambda lst:lst[idx],argseq)
1737 1737 #print 'ob',object,'hand',handler,'ar',args # dbg
1738 1738 out_list.append(handler(args,**kw))
1739 1739 else:
1740 1740 out_list.append(handler(**kw))
1741 1741 idx += 1
1742 1742 return out_list
1743 1743
1744 1744 #----------------------------------------------------------------------------
1745 def get_class_members(cls):
1746 ret = dir(cls)
1747 if hasattr(cls,'__bases__'):
1748 for base in cls.__bases__:
1749 ret.extend(get_class_members(base))
1750 return ret
1751
1752 #----------------------------------------------------------------------------
1753 def dir2(obj):
1754 """dir2(obj) -> list of strings
1755
1756 Extended version of the Python builtin dir(), which does a few extra
1757 checks, and supports common objects with unusual internals that confuse
1758 dir(), such as Traits and PyCrust.
1759
1760 This version is guaranteed to return only a list of true strings, whereas
1761 dir() returns anything that objects inject into themselves, even if they
1762 are later not really valid for attribute access (many extension libraries
1763 have such bugs).
1764 """
1765
1766 # Start building the attribute list via dir(), and then complete it
1767 # with a few extra special-purpose calls.
1768 words = dir(obj)
1769
1770 if hasattr(obj,'__class__'):
1771 words.append('__class__')
1772 words.extend(get_class_members(obj.__class__))
1773 #if '__base__' in words: 1/0
1774
1775 # Some libraries (such as traits) may introduce duplicates, we want to
1776 # track and clean this up if it happens
1777 may_have_dupes = False
1778
1779 # this is the 'dir' function for objects with Enthought's traits
1780 if hasattr(obj, 'trait_names'):
1781 try:
1782 words.extend(obj.trait_names())
1783 may_have_dupes = True
1784 except TypeError:
1785 # This will happen if `obj` is a class and not an instance.
1786 pass
1787
1788 # Support for PyCrust-style _getAttributeNames magic method.
1789 if hasattr(obj, '_getAttributeNames'):
1790 try:
1791 words.extend(obj._getAttributeNames())
1792 may_have_dupes = True
1793 except TypeError:
1794 # `obj` is a class and not an instance. Ignore
1795 # this error.
1796 pass
1797
1798 if may_have_dupes:
1799 # eliminate possible duplicates, as some traits may also
1800 # appear as normal attributes in the dir() call.
1801 words = list(set(words))
1802 words.sort()
1803
1804 # filter out non-string attributes which may be stuffed by dir() calls
1805 # and poor coding in third-party modules
1806 return [w for w in words if isinstance(w, basestring)]
1807
1808 #----------------------------------------------------------------------------
1745 1809 def import_fail_info(mod_name,fns=None):
1746 1810 """Inform load failure for a module."""
1747 1811
1748 1812 if fns == None:
1749 1813 warn("Loading of %s failed.\n" % (mod_name,))
1750 1814 else:
1751 1815 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1752 1816
1753 1817 #----------------------------------------------------------------------------
1754 1818 # Proposed popitem() extension, written as a method
1755 1819
1756 1820
1757 1821 class NotGiven: pass
1758 1822
1759 1823 def popkey(dct,key,default=NotGiven):
1760 1824 """Return dct[key] and delete dct[key].
1761 1825
1762 1826 If default is given, return it if dct[key] doesn't exist, otherwise raise
1763 1827 KeyError. """
1764 1828
1765 1829 try:
1766 1830 val = dct[key]
1767 1831 except KeyError:
1768 1832 if default is NotGiven:
1769 1833 raise
1770 1834 else:
1771 1835 return default
1772 1836 else:
1773 1837 del dct[key]
1774 1838 return val
1775 1839
1776 1840 def wrap_deprecated(func, suggest = '<nothing>'):
1777 1841 def newFunc(*args, **kwargs):
1778 1842 warnings.warn("Call to deprecated function %s, use %s instead" %
1779 1843 ( func.__name__, suggest),
1780 1844 category=DeprecationWarning,
1781 1845 stacklevel = 2)
1782 1846 return func(*args, **kwargs)
1783 1847 return newFunc
1784 1848
1785 1849 #*************************** end of file <genutils.py> **********************
1786 1850
@@ -1,138 +1,151 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Support for wildcard pattern matching in object inspection.
3 3
4 4 $Id: OInspect.py 608 2005-07-06 17:52:32Z fperez $
5 5 """
6 6
7 7 #*****************************************************************************
8 8 # Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu>
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #*****************************************************************************
13 13
14 14 from IPython import Release
15 15 __author__ = "Jörgen Stenarson <jorgen.stenarson@bostream.nu>"
16 16 __license__ = Release.license
17 17
18 18 import __builtin__
19 19 import exceptions
20 20 import pdb
21 21 import pprint
22 22 import re
23 23 import types
24 24
25 from IPython.genutils import dir2
26
25 27 def create_typestr2type_dicts(dont_include_in_type2type2str=["lambda"]):
26 28 """Return dictionaries mapping lower case typename to type objects, from
27 29 the types package, and vice versa."""
28 30 typenamelist=[]
29 31 for tname in dir(types):
30 32 if tname[-4:]=="Type":
31 33 typenamelist.append(tname)
32 34 typestr2type={}
33 35 type2typestr={}
34 36 for tname in typenamelist:
35 37 name=tname[:-4].lower()
36 38 obj=getattr(types,tname)
37 39 typestr2type[name]=getattr(types,tname)
38 40 if name in dont_include_in_type2type2str:
39 41 type2typestr[obj]=name
40 42 return typestr2type,type2typestr
41 43
42 44 typestr2type,type2typestr=create_typestr2type_dicts()
43 45
44 46 def is_type(obj,typestr_or_type):
45 47 """is_type(obj,typestr_or_type) verifies if obj is of a certain type or
46 48 group of types takes strings as parameters of the for 'tuple'<->TupleType
47 49 'all' matches all types. TODO: Should be extended for choosing more than
48 50 one type
49 51 """
50 52 if typestr_or_type=="all":
51 53 return True
52 54 if type(typestr_or_type)==types.TypeType:
53 55 test_type=typestr_or_type
54 56 else:
55 57 test_type=typestr2type.get(typestr_or_type,False)
56 58 if test_type:
57 59 return isinstance(obj,test_type)
58 60 else:
59 61 return False
60 62
61 63 def show_hidden(str,show_all=False):
62 64 """Return true for strings starting with single _ if show_all is true."""
63 65 return show_all or str.startswith("__") or not str.startswith("_")
64 66
65
66 67 class NameSpace(object):
67 68 """NameSpace holds the dictionary for a namespace and implements filtering
68 69 on name and types"""
69 70 def __init__(self,obj,name_pattern="*",type_pattern="all",ignore_case=True,
70 71 show_all=True):
71 72 self.show_all = show_all #Hide names beginning with single _
72 73 self.object = obj
73 74 self.name_pattern = name_pattern
74 75 self.type_pattern = type_pattern
75 76 self.ignore_case = ignore_case
76 77
77 78 # We should only match EXACT dicts here, so DON'T use isinstance()
78 79 if type(obj) == types.DictType:
79 80 self._ns = obj
80 81 else:
81 self._ns = dict([(key,getattr(obj,key)) for key in dir(obj)
82 if isinstance(key, basestring)])
82 kv = []
83 for key in dir2(obj):
84 if isinstance(key, basestring):
85 # This seemingly unnecessary try/except is actually needed
86 # because there is code out there with metaclasses that
87 # create 'write only' attributes, where a getattr() call
88 # will fail even if the attribute appears listed in the
89 # object's dictionary. Properties can actually do the same
90 # thing. In particular, Traits use this pattern
91 try:
92 kv.append((key,getattr(obj,key)))
93 except AttributeError:
94 pass
95 self._ns = dict(kv)
83 96
84 97 def get_ns(self):
85 98 """Return name space dictionary with objects matching type and name patterns."""
86 99 return self.filter(self.name_pattern,self.type_pattern)
87 100 ns=property(get_ns)
88 101
89 102 def get_ns_names(self):
90 103 """Return list of object names in namespace that match the patterns."""
91 104 return self.ns.keys()
92 105 ns_names=property(get_ns_names,doc="List of objects in name space that "
93 106 "match the type and name patterns.")
94 107
95 108 def filter(self,name_pattern,type_pattern):
96 109 """Return dictionary of filtered namespace."""
97 110 def glob_filter(lista,name_pattern,hidehidden,ignore_case):
98 111 """Return list of elements in lista that match pattern."""
99 112 pattern=name_pattern.replace("*",".*").replace("?",".")
100 113 if ignore_case:
101 114 reg=re.compile(pattern+"$",re.I)
102 115 else:
103 116 reg=re.compile(pattern+"$")
104 117 result=[x for x in lista if reg.match(x) and show_hidden(x,hidehidden)]
105 118 return result
106 119 ns=self._ns
107 120 #Filter namespace by the name_pattern
108 121 all=[(x,ns[x]) for x in glob_filter(ns.keys(),name_pattern,
109 122 self.show_all,self.ignore_case)]
110 123 #Filter namespace by type_pattern
111 124 all=[(key,obj) for key,obj in all if is_type(obj,type_pattern)]
112 125 all=dict(all)
113 126 return all
114 127
115 128 #TODO: Implement dictionary like access to filtered name space?
116 129
117 130 def list_namespace(namespace,type_pattern,filter,ignore_case=False,show_all=False):
118 131 """Return dictionary of all objects in namespace that matches type_pattern
119 132 and filter."""
120 133 pattern_list=filter.split(".")
121 134 if len(pattern_list)==1:
122 135 ns=NameSpace(namespace,name_pattern=pattern_list[0],type_pattern=type_pattern,
123 136 ignore_case=ignore_case,show_all=show_all)
124 137 return ns.ns
125 138 else:
126 139 # This is where we can change if all objects should be searched or
127 140 # only modules. Just change the type_pattern to module to search only
128 141 # modules
129 142 ns=NameSpace(namespace,name_pattern=pattern_list[0],type_pattern="all",
130 143 ignore_case=ignore_case,show_all=show_all)
131 144 res={}
132 145 nsdict=ns.ns
133 146 for name,obj in nsdict.iteritems():
134 147 ns=list_namespace(obj,type_pattern,".".join(pattern_list[1:]),
135 148 ignore_case=ignore_case,show_all=show_all)
136 149 for inner_name,inner_obj in ns.iteritems():
137 150 res["%s.%s"%(name,inner_name)]=inner_obj
138 151 return res
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