##// END OF EJS Templates
Fix bug reported by Jeremy Jones where %pfile would fail on object...
Fernando Perez -
Show More
@@ -1,593 +1,610 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8
8
9 $Id: OInspect.py 2843 2007-10-15 21:22:32Z fperez $
9 $Id: OInspect.py 2843 2007-10-15 21:22:32Z fperez $
10 """
10 """
11
11
12 #*****************************************************************************
12 #*****************************************************************************
13 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
13 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #*****************************************************************************
17 #*****************************************************************************
18
18
19 from IPython import Release
19 from IPython import Release
20 __author__ = '%s <%s>' % Release.authors['Fernando']
20 __author__ = '%s <%s>' % Release.authors['Fernando']
21 __license__ = Release.license
21 __license__ = Release.license
22
22
23 __all__ = ['Inspector','InspectColors']
23 __all__ = ['Inspector','InspectColors']
24
24
25 # stdlib modules
25 # stdlib modules
26 import __builtin__
26 import __builtin__
27 import inspect
27 import inspect
28 import linecache
28 import linecache
29 import string
29 import string
30 import StringIO
30 import StringIO
31 import types
31 import types
32 import os
32 import os
33 import sys
33 import sys
34 # IPython's own
34 # IPython's own
35 from IPython import PyColorize
35 from IPython import PyColorize
36 from IPython.genutils import page,indent,Term,mkdict
36 from IPython.genutils import page,indent,Term,mkdict
37 from IPython.Itpl import itpl
37 from IPython.Itpl import itpl
38 from IPython.wildcard import list_namespace
38 from IPython.wildcard import list_namespace
39 from IPython.ColorANSI import *
39 from IPython.ColorANSI import *
40
40
41 #****************************************************************************
41 #****************************************************************************
42 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
42 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
43 # simply monkeypatch inspect with code copied from python 2.4.
43 # simply monkeypatch inspect with code copied from python 2.4.
44 if sys.version_info[:2] == (2,3):
44 if sys.version_info[:2] == (2,3):
45 from inspect import ismodule, getabsfile, modulesbyfile
45 from inspect import ismodule, getabsfile, modulesbyfile
46 def getmodule(object):
46 def getmodule(object):
47 """Return the module an object was defined in, or None if not found."""
47 """Return the module an object was defined in, or None if not found."""
48 if ismodule(object):
48 if ismodule(object):
49 return object
49 return object
50 if hasattr(object, '__module__'):
50 if hasattr(object, '__module__'):
51 return sys.modules.get(object.__module__)
51 return sys.modules.get(object.__module__)
52 try:
52 try:
53 file = getabsfile(object)
53 file = getabsfile(object)
54 except TypeError:
54 except TypeError:
55 return None
55 return None
56 if file in modulesbyfile:
56 if file in modulesbyfile:
57 return sys.modules.get(modulesbyfile[file])
57 return sys.modules.get(modulesbyfile[file])
58 for module in sys.modules.values():
58 for module in sys.modules.values():
59 if hasattr(module, '__file__'):
59 if hasattr(module, '__file__'):
60 modulesbyfile[
60 modulesbyfile[
61 os.path.realpath(
61 os.path.realpath(
62 getabsfile(module))] = module.__name__
62 getabsfile(module))] = module.__name__
63 if file in modulesbyfile:
63 if file in modulesbyfile:
64 return sys.modules.get(modulesbyfile[file])
64 return sys.modules.get(modulesbyfile[file])
65 main = sys.modules['__main__']
65 main = sys.modules['__main__']
66 if not hasattr(object, '__name__'):
66 if not hasattr(object, '__name__'):
67 return None
67 return None
68 if hasattr(main, object.__name__):
68 if hasattr(main, object.__name__):
69 mainobject = getattr(main, object.__name__)
69 mainobject = getattr(main, object.__name__)
70 if mainobject is object:
70 if mainobject is object:
71 return main
71 return main
72 builtin = sys.modules['__builtin__']
72 builtin = sys.modules['__builtin__']
73 if hasattr(builtin, object.__name__):
73 if hasattr(builtin, object.__name__):
74 builtinobject = getattr(builtin, object.__name__)
74 builtinobject = getattr(builtin, object.__name__)
75 if builtinobject is object:
75 if builtinobject is object:
76 return builtin
76 return builtin
77
77
78 inspect.getmodule = getmodule
78 inspect.getmodule = getmodule
79
79
80 #****************************************************************************
80 #****************************************************************************
81 # Builtin color schemes
81 # Builtin color schemes
82
82
83 Colors = TermColors # just a shorthand
83 Colors = TermColors # just a shorthand
84
84
85 # Build a few color schemes
85 # Build a few color schemes
86 NoColor = ColorScheme(
86 NoColor = ColorScheme(
87 'NoColor',{
87 'NoColor',{
88 'header' : Colors.NoColor,
88 'header' : Colors.NoColor,
89 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
89 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
90 } )
90 } )
91
91
92 LinuxColors = ColorScheme(
92 LinuxColors = ColorScheme(
93 'Linux',{
93 'Linux',{
94 'header' : Colors.LightRed,
94 'header' : Colors.LightRed,
95 'normal' : Colors.Normal # color off (usu. Colors.Normal)
95 'normal' : Colors.Normal # color off (usu. Colors.Normal)
96 } )
96 } )
97
97
98 LightBGColors = ColorScheme(
98 LightBGColors = ColorScheme(
99 'LightBG',{
99 'LightBG',{
100 'header' : Colors.Red,
100 'header' : Colors.Red,
101 'normal' : Colors.Normal # color off (usu. Colors.Normal)
101 'normal' : Colors.Normal # color off (usu. Colors.Normal)
102 } )
102 } )
103
103
104 # Build table of color schemes (needed by the parser)
104 # Build table of color schemes (needed by the parser)
105 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
105 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
106 'Linux')
106 'Linux')
107
107
108 #****************************************************************************
108 #****************************************************************************
109 # Auxiliary functions
109 # Auxiliary functions
110 def getdoc(obj):
110 def getdoc(obj):
111 """Stable wrapper around inspect.getdoc.
111 """Stable wrapper around inspect.getdoc.
112
112
113 This can't crash because of attribute problems.
113 This can't crash because of attribute problems.
114
114
115 It also attempts to call a getdoc() method on the given object. This
115 It also attempts to call a getdoc() method on the given object. This
116 allows objects which provide their docstrings via non-standard mechanisms
116 allows objects which provide their docstrings via non-standard mechanisms
117 (like Pyro proxies) to still be inspected by ipython's ? system."""
117 (like Pyro proxies) to still be inspected by ipython's ? system."""
118
118
119 ds = None # default return value
119 ds = None # default return value
120 try:
120 try:
121 ds = inspect.getdoc(obj)
121 ds = inspect.getdoc(obj)
122 except:
122 except:
123 # Harden against an inspect failure, which can occur with
123 # Harden against an inspect failure, which can occur with
124 # SWIG-wrapped extensions.
124 # SWIG-wrapped extensions.
125 pass
125 pass
126 # Allow objects to offer customized documentation via a getdoc method:
126 # Allow objects to offer customized documentation via a getdoc method:
127 try:
127 try:
128 ds2 = obj.getdoc()
128 ds2 = obj.getdoc()
129 except:
129 except:
130 pass
130 pass
131 else:
131 else:
132 # if we get extra info, we add it to the normal docstring.
132 # if we get extra info, we add it to the normal docstring.
133 if ds is None:
133 if ds is None:
134 ds = ds2
134 ds = ds2
135 else:
135 else:
136 ds = '%s\n%s' % (ds,ds2)
136 ds = '%s\n%s' % (ds,ds2)
137 return ds
137 return ds
138
138
139 def getsource(obj,is_binary=False):
139 def getsource(obj,is_binary=False):
140 """Wrapper around inspect.getsource.
140 """Wrapper around inspect.getsource.
141
141
142 This can be modified by other projects to provide customized source
142 This can be modified by other projects to provide customized source
143 extraction.
143 extraction.
144
144
145 Inputs:
145 Inputs:
146
146
147 - obj: an object whose source code we will attempt to extract.
147 - obj: an object whose source code we will attempt to extract.
148
148
149 Optional inputs:
149 Optional inputs:
150
150
151 - is_binary: whether the object is known to come from a binary source.
151 - is_binary: whether the object is known to come from a binary source.
152 This implementation will skip returning any output for binary objects, but
152 This implementation will skip returning any output for binary objects, but
153 custom extractors may know how to meaningfully process them."""
153 custom extractors may know how to meaningfully process them."""
154
154
155 if is_binary:
155 if is_binary:
156 return None
156 return None
157 else:
157 else:
158 return inspect.getsource(obj)
158 try:
159 src = inspect.getsource(obj)
160 except TypeError:
161 if hasattr(obj,'__class__'):
162 src = inspect.getsource(obj.__class__)
163 return src
159
164
160 #****************************************************************************
165 #****************************************************************************
161 # Class definitions
166 # Class definitions
162
167
163 class myStringIO(StringIO.StringIO):
168 class myStringIO(StringIO.StringIO):
164 """Adds a writeln method to normal StringIO."""
169 """Adds a writeln method to normal StringIO."""
165 def writeln(self,*arg,**kw):
170 def writeln(self,*arg,**kw):
166 """Does a write() and then a write('\n')"""
171 """Does a write() and then a write('\n')"""
167 self.write(*arg,**kw)
172 self.write(*arg,**kw)
168 self.write('\n')
173 self.write('\n')
169
174
170 class Inspector:
175 class Inspector:
171 def __init__(self,color_table,code_color_table,scheme,
176 def __init__(self,color_table,code_color_table,scheme,
172 str_detail_level=0):
177 str_detail_level=0):
173 self.color_table = color_table
178 self.color_table = color_table
174 self.parser = PyColorize.Parser(code_color_table,out='str')
179 self.parser = PyColorize.Parser(code_color_table,out='str')
175 self.format = self.parser.format
180 self.format = self.parser.format
176 self.str_detail_level = str_detail_level
181 self.str_detail_level = str_detail_level
177 self.set_active_scheme(scheme)
182 self.set_active_scheme(scheme)
178
183
179 def __getargspec(self,obj):
184 def __getargspec(self,obj):
180 """Get the names and default values of a function's arguments.
185 """Get the names and default values of a function's arguments.
181
186
182 A tuple of four things is returned: (args, varargs, varkw, defaults).
187 A tuple of four things is returned: (args, varargs, varkw, defaults).
183 'args' is a list of the argument names (it may contain nested lists).
188 'args' is a list of the argument names (it may contain nested lists).
184 'varargs' and 'varkw' are the names of the * and ** arguments or None.
189 'varargs' and 'varkw' are the names of the * and ** arguments or None.
185 'defaults' is an n-tuple of the default values of the last n arguments.
190 'defaults' is an n-tuple of the default values of the last n arguments.
186
191
187 Modified version of inspect.getargspec from the Python Standard
192 Modified version of inspect.getargspec from the Python Standard
188 Library."""
193 Library."""
189
194
190 if inspect.isfunction(obj):
195 if inspect.isfunction(obj):
191 func_obj = obj
196 func_obj = obj
192 elif inspect.ismethod(obj):
197 elif inspect.ismethod(obj):
193 func_obj = obj.im_func
198 func_obj = obj.im_func
194 else:
199 else:
195 raise TypeError, 'arg is not a Python function'
200 raise TypeError, 'arg is not a Python function'
196 args, varargs, varkw = inspect.getargs(func_obj.func_code)
201 args, varargs, varkw = inspect.getargs(func_obj.func_code)
197 return args, varargs, varkw, func_obj.func_defaults
202 return args, varargs, varkw, func_obj.func_defaults
198
203
199 def __getdef(self,obj,oname=''):
204 def __getdef(self,obj,oname=''):
200 """Return the definition header for any callable object.
205 """Return the definition header for any callable object.
201
206
202 If any exception is generated, None is returned instead and the
207 If any exception is generated, None is returned instead and the
203 exception is suppressed."""
208 exception is suppressed."""
204
209
205 try:
210 try:
206 return oname + inspect.formatargspec(*self.__getargspec(obj))
211 return oname + inspect.formatargspec(*self.__getargspec(obj))
207 except:
212 except:
208 return None
213 return None
209
214
210 def __head(self,h):
215 def __head(self,h):
211 """Return a header string with proper colors."""
216 """Return a header string with proper colors."""
212 return '%s%s%s' % (self.color_table.active_colors.header,h,
217 return '%s%s%s' % (self.color_table.active_colors.header,h,
213 self.color_table.active_colors.normal)
218 self.color_table.active_colors.normal)
214
219
215 def set_active_scheme(self,scheme):
220 def set_active_scheme(self,scheme):
216 self.color_table.set_active_scheme(scheme)
221 self.color_table.set_active_scheme(scheme)
217 self.parser.color_table.set_active_scheme(scheme)
222 self.parser.color_table.set_active_scheme(scheme)
218
223
219 def noinfo(self,msg,oname):
224 def noinfo(self,msg,oname):
220 """Generic message when no information is found."""
225 """Generic message when no information is found."""
221 print 'No %s found' % msg,
226 print 'No %s found' % msg,
222 if oname:
227 if oname:
223 print 'for %s' % oname
228 print 'for %s' % oname
224 else:
229 else:
225 print
230 print
226
231
227 def pdef(self,obj,oname=''):
232 def pdef(self,obj,oname=''):
228 """Print the definition header for any callable object.
233 """Print the definition header for any callable object.
229
234
230 If the object is a class, print the constructor information."""
235 If the object is a class, print the constructor information."""
231
236
232 if not callable(obj):
237 if not callable(obj):
233 print 'Object is not callable.'
238 print 'Object is not callable.'
234 return
239 return
235
240
236 header = ''
241 header = ''
237
242
238 if inspect.isclass(obj):
243 if inspect.isclass(obj):
239 header = self.__head('Class constructor information:\n')
244 header = self.__head('Class constructor information:\n')
240 obj = obj.__init__
245 obj = obj.__init__
241 elif type(obj) is types.InstanceType:
246 elif type(obj) is types.InstanceType:
242 obj = obj.__call__
247 obj = obj.__call__
243
248
244 output = self.__getdef(obj,oname)
249 output = self.__getdef(obj,oname)
245 if output is None:
250 if output is None:
246 self.noinfo('definition header',oname)
251 self.noinfo('definition header',oname)
247 else:
252 else:
248 print >>Term.cout, header,self.format(output),
253 print >>Term.cout, header,self.format(output),
249
254
250 def pdoc(self,obj,oname='',formatter = None):
255 def pdoc(self,obj,oname='',formatter = None):
251 """Print the docstring for any object.
256 """Print the docstring for any object.
252
257
253 Optional:
258 Optional:
254 -formatter: a function to run the docstring through for specially
259 -formatter: a function to run the docstring through for specially
255 formatted docstrings."""
260 formatted docstrings."""
256
261
257 head = self.__head # so that itpl can find it even if private
262 head = self.__head # so that itpl can find it even if private
258 ds = getdoc(obj)
263 ds = getdoc(obj)
259 if formatter:
264 if formatter:
260 ds = formatter(ds)
265 ds = formatter(ds)
261 if inspect.isclass(obj):
266 if inspect.isclass(obj):
262 init_ds = getdoc(obj.__init__)
267 init_ds = getdoc(obj.__init__)
263 output = itpl('$head("Class Docstring:")\n'
268 output = itpl('$head("Class Docstring:")\n'
264 '$indent(ds)\n'
269 '$indent(ds)\n'
265 '$head("Constructor Docstring"):\n'
270 '$head("Constructor Docstring"):\n'
266 '$indent(init_ds)')
271 '$indent(init_ds)')
267 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
272 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
268 and hasattr(obj,'__call__'):
273 and hasattr(obj,'__call__'):
269 call_ds = getdoc(obj.__call__)
274 call_ds = getdoc(obj.__call__)
270 if call_ds:
275 if call_ds:
271 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
276 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
272 '$head("Calling Docstring:")\n$indent(call_ds)')
277 '$head("Calling Docstring:")\n$indent(call_ds)')
273 else:
278 else:
274 output = ds
279 output = ds
275 else:
280 else:
276 output = ds
281 output = ds
277 if output is None:
282 if output is None:
278 self.noinfo('documentation',oname)
283 self.noinfo('documentation',oname)
279 return
284 return
280 page(output)
285 page(output)
281
286
282 def psource(self,obj,oname=''):
287 def psource(self,obj,oname=''):
283 """Print the source code for an object."""
288 """Print the source code for an object."""
284
289
285 # Flush the source cache because inspect can return out-of-date source
290 # Flush the source cache because inspect can return out-of-date source
286 linecache.checkcache()
291 linecache.checkcache()
287 try:
292 try:
288 src = getsource(obj)
293 src = getsource(obj)
289 except:
294 except:
290 self.noinfo('source',oname)
295 self.noinfo('source',oname)
291 else:
296 else:
292 page(self.format(src))
297 page(self.format(src))
293
298
294 def pfile(self,obj,oname=''):
299 def pfile(self,obj,oname=''):
295 """Show the whole file where an object was defined."""
300 """Show the whole file where an object was defined."""
301
296 try:
302 try:
297 sourcelines,lineno = inspect.getsourcelines(obj)
303 try:
304 lineno = inspect.getsourcelines(obj)[1]
305 except TypeError:
306 # For instances, try the class object like getsource() does
307 if hasattr(obj,'__class__'):
308 lineno = inspect.getsourcelines(obj.__class__)[1]
309 # Adjust the inspected object so getabsfile() below works
310 obj = obj.__class__
298 except:
311 except:
299 self.noinfo('file',oname)
312 self.noinfo('file',oname)
313 return
314
315 # We only reach this point if object was successfully queried
316
317 # run contents of file through pager starting at line
318 # where the object is defined
319 ofile = inspect.getabsfile(obj)
320
321 if (ofile.endswith('.so') or ofile.endswith('.dll')):
322 print 'File %r is binary, not printing.' % ofile
323 elif not os.path.isfile(ofile):
324 print 'File %r does not exist, not printing.' % ofile
300 else:
325 else:
301 # run contents of file through pager starting at line
326 # Print only text files, not extension binaries. Note that
302 # where the object is defined
327 # getsourcelines returns lineno with 1-offset and page() uses
303 ofile = inspect.getabsfile(obj)
328 # 0-offset, so we must adjust.
304
329 page(self.format(open(ofile).read()),lineno-1)
305 if (ofile.endswith('.so') or ofile.endswith('.dll')):
306 print 'File %r is binary, not printing.' % ofile
307 elif not os.path.isfile(ofile):
308 print 'File %r does not exist, not printing.' % ofile
309 else:
310 # Print only text files, not extension binaries.
311 page(self.format(open(ofile).read()),lineno)
312 #page(self.format(open(inspect.getabsfile(obj)).read()),lineno)
313
330
314 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
331 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
315 """Show detailed information about an object.
332 """Show detailed information about an object.
316
333
317 Optional arguments:
334 Optional arguments:
318
335
319 - oname: name of the variable pointing to the object.
336 - oname: name of the variable pointing to the object.
320
337
321 - formatter: special formatter for docstrings (see pdoc)
338 - formatter: special formatter for docstrings (see pdoc)
322
339
323 - info: a structure with some information fields which may have been
340 - info: a structure with some information fields which may have been
324 precomputed already.
341 precomputed already.
325
342
326 - detail_level: if set to 1, more information is given.
343 - detail_level: if set to 1, more information is given.
327 """
344 """
328
345
329 obj_type = type(obj)
346 obj_type = type(obj)
330
347
331 header = self.__head
348 header = self.__head
332 if info is None:
349 if info is None:
333 ismagic = 0
350 ismagic = 0
334 isalias = 0
351 isalias = 0
335 ospace = ''
352 ospace = ''
336 else:
353 else:
337 ismagic = info.ismagic
354 ismagic = info.ismagic
338 isalias = info.isalias
355 isalias = info.isalias
339 ospace = info.namespace
356 ospace = info.namespace
340 # Get docstring, special-casing aliases:
357 # Get docstring, special-casing aliases:
341 if isalias:
358 if isalias:
342 if not callable(obj):
359 if not callable(obj):
343 try:
360 try:
344 ds = "Alias to the system command:\n %s" % obj[1]
361 ds = "Alias to the system command:\n %s" % obj[1]
345 except:
362 except:
346 ds = "Alias: " + str(obj)
363 ds = "Alias: " + str(obj)
347 else:
364 else:
348 ds = "Alias to " + str(obj)
365 ds = "Alias to " + str(obj)
349 if obj.__doc__:
366 if obj.__doc__:
350 ds += "\nDocstring:\n" + obj.__doc__
367 ds += "\nDocstring:\n" + obj.__doc__
351 else:
368 else:
352 ds = getdoc(obj)
369 ds = getdoc(obj)
353 if ds is None:
370 if ds is None:
354 ds = '<no docstring>'
371 ds = '<no docstring>'
355 if formatter is not None:
372 if formatter is not None:
356 ds = formatter(ds)
373 ds = formatter(ds)
357
374
358 # store output in a list which gets joined with \n at the end.
375 # store output in a list which gets joined with \n at the end.
359 out = myStringIO()
376 out = myStringIO()
360
377
361 string_max = 200 # max size of strings to show (snipped if longer)
378 string_max = 200 # max size of strings to show (snipped if longer)
362 shalf = int((string_max -5)/2)
379 shalf = int((string_max -5)/2)
363
380
364 if ismagic:
381 if ismagic:
365 obj_type_name = 'Magic function'
382 obj_type_name = 'Magic function'
366 elif isalias:
383 elif isalias:
367 obj_type_name = 'System alias'
384 obj_type_name = 'System alias'
368 else:
385 else:
369 obj_type_name = obj_type.__name__
386 obj_type_name = obj_type.__name__
370 out.writeln(header('Type:\t\t')+obj_type_name)
387 out.writeln(header('Type:\t\t')+obj_type_name)
371
388
372 try:
389 try:
373 bclass = obj.__class__
390 bclass = obj.__class__
374 out.writeln(header('Base Class:\t')+str(bclass))
391 out.writeln(header('Base Class:\t')+str(bclass))
375 except: pass
392 except: pass
376
393
377 # String form, but snip if too long in ? form (full in ??)
394 # String form, but snip if too long in ? form (full in ??)
378 if detail_level >= self.str_detail_level:
395 if detail_level >= self.str_detail_level:
379 try:
396 try:
380 ostr = str(obj)
397 ostr = str(obj)
381 str_head = 'String Form:'
398 str_head = 'String Form:'
382 if not detail_level and len(ostr)>string_max:
399 if not detail_level and len(ostr)>string_max:
383 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
400 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
384 ostr = ("\n" + " " * len(str_head.expandtabs())).\
401 ostr = ("\n" + " " * len(str_head.expandtabs())).\
385 join(map(string.strip,ostr.split("\n")))
402 join(map(string.strip,ostr.split("\n")))
386 if ostr.find('\n') > -1:
403 if ostr.find('\n') > -1:
387 # Print multi-line strings starting at the next line.
404 # Print multi-line strings starting at the next line.
388 str_sep = '\n'
405 str_sep = '\n'
389 else:
406 else:
390 str_sep = '\t'
407 str_sep = '\t'
391 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
408 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
392 except:
409 except:
393 pass
410 pass
394
411
395 if ospace:
412 if ospace:
396 out.writeln(header('Namespace:\t')+ospace)
413 out.writeln(header('Namespace:\t')+ospace)
397
414
398 # Length (for strings and lists)
415 # Length (for strings and lists)
399 try:
416 try:
400 length = str(len(obj))
417 length = str(len(obj))
401 out.writeln(header('Length:\t\t')+length)
418 out.writeln(header('Length:\t\t')+length)
402 except: pass
419 except: pass
403
420
404 # Filename where object was defined
421 # Filename where object was defined
405 binary_file = False
422 binary_file = False
406 try:
423 try:
407 try:
424 try:
408 fname = inspect.getabsfile(obj)
425 fname = inspect.getabsfile(obj)
409 except TypeError:
426 except TypeError:
410 # For an instance, the file that matters is where its class was
427 # For an instance, the file that matters is where its class was
411 # declared.
428 # declared.
412 if hasattr(obj,'__class__'):
429 if hasattr(obj,'__class__'):
413 fname = inspect.getabsfile(obj.__class__)
430 fname = inspect.getabsfile(obj.__class__)
414 if fname.endswith('<string>'):
431 if fname.endswith('<string>'):
415 fname = 'Dynamically generated function. No source code available.'
432 fname = 'Dynamically generated function. No source code available.'
416 if (fname.endswith('.so') or fname.endswith('.dll')):
433 if (fname.endswith('.so') or fname.endswith('.dll')):
417 binary_file = True
434 binary_file = True
418 out.writeln(header('File:\t\t')+fname)
435 out.writeln(header('File:\t\t')+fname)
419 except:
436 except:
420 # if anything goes wrong, we don't want to show source, so it's as
437 # if anything goes wrong, we don't want to show source, so it's as
421 # if the file was binary
438 # if the file was binary
422 binary_file = True
439 binary_file = True
423
440
424 # reconstruct the function definition and print it:
441 # reconstruct the function definition and print it:
425 defln = self.__getdef(obj,oname)
442 defln = self.__getdef(obj,oname)
426 if defln:
443 if defln:
427 out.write(header('Definition:\t')+self.format(defln))
444 out.write(header('Definition:\t')+self.format(defln))
428
445
429 # Docstrings only in detail 0 mode, since source contains them (we
446 # Docstrings only in detail 0 mode, since source contains them (we
430 # avoid repetitions). If source fails, we add them back, see below.
447 # avoid repetitions). If source fails, we add them back, see below.
431 if ds and detail_level == 0:
448 if ds and detail_level == 0:
432 out.writeln(header('Docstring:\n') + indent(ds))
449 out.writeln(header('Docstring:\n') + indent(ds))
433
450
434 # Original source code for any callable
451 # Original source code for any callable
435 if detail_level:
452 if detail_level:
436 # Flush the source cache because inspect can return out-of-date
453 # Flush the source cache because inspect can return out-of-date
437 # source
454 # source
438 linecache.checkcache()
455 linecache.checkcache()
439 source_success = False
456 source_success = False
440 try:
457 try:
441 try:
458 try:
442 src = getsource(obj,binary_file)
459 src = getsource(obj,binary_file)
443 except TypeError:
460 except TypeError:
444 if hasattr(obj,'__class__'):
461 if hasattr(obj,'__class__'):
445 src = getsource(obj.__class__,binary_file)
462 src = getsource(obj.__class__,binary_file)
446 if src is not None:
463 if src is not None:
447 source = self.format(src)
464 source = self.format(src)
448 out.write(header('Source:\n')+source.rstrip())
465 out.write(header('Source:\n')+source.rstrip())
449 source_success = True
466 source_success = True
450 except Exception, msg:
467 except Exception, msg:
451 pass
468 pass
452
469
453 if ds and not source_success:
470 if ds and not source_success:
454 out.writeln(header('Docstring [source file open failed]:\n')
471 out.writeln(header('Docstring [source file open failed]:\n')
455 + indent(ds))
472 + indent(ds))
456
473
457 # Constructor docstring for classes
474 # Constructor docstring for classes
458 if inspect.isclass(obj):
475 if inspect.isclass(obj):
459 # reconstruct the function definition and print it:
476 # reconstruct the function definition and print it:
460 try:
477 try:
461 obj_init = obj.__init__
478 obj_init = obj.__init__
462 except AttributeError:
479 except AttributeError:
463 init_def = init_ds = None
480 init_def = init_ds = None
464 else:
481 else:
465 init_def = self.__getdef(obj_init,oname)
482 init_def = self.__getdef(obj_init,oname)
466 init_ds = getdoc(obj_init)
483 init_ds = getdoc(obj_init)
467 # Skip Python's auto-generated docstrings
484 # Skip Python's auto-generated docstrings
468 if init_ds and \
485 if init_ds and \
469 init_ds.startswith('x.__init__(...) initializes'):
486 init_ds.startswith('x.__init__(...) initializes'):
470 init_ds = None
487 init_ds = None
471
488
472 if init_def or init_ds:
489 if init_def or init_ds:
473 out.writeln(header('\nConstructor information:'))
490 out.writeln(header('\nConstructor information:'))
474 if init_def:
491 if init_def:
475 out.write(header('Definition:\t')+ self.format(init_def))
492 out.write(header('Definition:\t')+ self.format(init_def))
476 if init_ds:
493 if init_ds:
477 out.writeln(header('Docstring:\n') + indent(init_ds))
494 out.writeln(header('Docstring:\n') + indent(init_ds))
478 # and class docstring for instances:
495 # and class docstring for instances:
479 elif obj_type is types.InstanceType or \
496 elif obj_type is types.InstanceType or \
480 isinstance(obj,object):
497 isinstance(obj,object):
481
498
482 # First, check whether the instance docstring is identical to the
499 # First, check whether the instance docstring is identical to the
483 # class one, and print it separately if they don't coincide. In
500 # class one, and print it separately if they don't coincide. In
484 # most cases they will, but it's nice to print all the info for
501 # most cases they will, but it's nice to print all the info for
485 # objects which use instance-customized docstrings.
502 # objects which use instance-customized docstrings.
486 if ds:
503 if ds:
487 try:
504 try:
488 cls = getattr(obj,'__class__')
505 cls = getattr(obj,'__class__')
489 except:
506 except:
490 class_ds = None
507 class_ds = None
491 else:
508 else:
492 class_ds = getdoc(cls)
509 class_ds = getdoc(cls)
493 # Skip Python's auto-generated docstrings
510 # Skip Python's auto-generated docstrings
494 if class_ds and \
511 if class_ds and \
495 (class_ds.startswith('function(code, globals[,') or \
512 (class_ds.startswith('function(code, globals[,') or \
496 class_ds.startswith('instancemethod(function, instance,') or \
513 class_ds.startswith('instancemethod(function, instance,') or \
497 class_ds.startswith('module(name[,') ):
514 class_ds.startswith('module(name[,') ):
498 class_ds = None
515 class_ds = None
499 if class_ds and ds != class_ds:
516 if class_ds and ds != class_ds:
500 out.writeln(header('Class Docstring:\n') +
517 out.writeln(header('Class Docstring:\n') +
501 indent(class_ds))
518 indent(class_ds))
502
519
503 # Next, try to show constructor docstrings
520 # Next, try to show constructor docstrings
504 try:
521 try:
505 init_ds = getdoc(obj.__init__)
522 init_ds = getdoc(obj.__init__)
506 # Skip Python's auto-generated docstrings
523 # Skip Python's auto-generated docstrings
507 if init_ds and \
524 if init_ds and \
508 init_ds.startswith('x.__init__(...) initializes'):
525 init_ds.startswith('x.__init__(...) initializes'):
509 init_ds = None
526 init_ds = None
510 except AttributeError:
527 except AttributeError:
511 init_ds = None
528 init_ds = None
512 if init_ds:
529 if init_ds:
513 out.writeln(header('Constructor Docstring:\n') +
530 out.writeln(header('Constructor Docstring:\n') +
514 indent(init_ds))
531 indent(init_ds))
515
532
516 # Call form docstring for callable instances
533 # Call form docstring for callable instances
517 if hasattr(obj,'__call__'):
534 if hasattr(obj,'__call__'):
518 #out.writeln(header('Callable:\t')+'Yes')
535 #out.writeln(header('Callable:\t')+'Yes')
519 call_def = self.__getdef(obj.__call__,oname)
536 call_def = self.__getdef(obj.__call__,oname)
520 #if call_def is None:
537 #if call_def is None:
521 # out.writeln(header('Call def:\t')+
538 # out.writeln(header('Call def:\t')+
522 # 'Calling definition not available.')
539 # 'Calling definition not available.')
523 if call_def is not None:
540 if call_def is not None:
524 out.writeln(header('Call def:\t')+self.format(call_def))
541 out.writeln(header('Call def:\t')+self.format(call_def))
525 call_ds = getdoc(obj.__call__)
542 call_ds = getdoc(obj.__call__)
526 # Skip Python's auto-generated docstrings
543 # Skip Python's auto-generated docstrings
527 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
544 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
528 call_ds = None
545 call_ds = None
529 if call_ds:
546 if call_ds:
530 out.writeln(header('Call docstring:\n') + indent(call_ds))
547 out.writeln(header('Call docstring:\n') + indent(call_ds))
531
548
532 # Finally send to printer/pager
549 # Finally send to printer/pager
533 output = out.getvalue()
550 output = out.getvalue()
534 if output:
551 if output:
535 page(output)
552 page(output)
536 # end pinfo
553 # end pinfo
537
554
538 def psearch(self,pattern,ns_table,ns_search=[],
555 def psearch(self,pattern,ns_table,ns_search=[],
539 ignore_case=False,show_all=False):
556 ignore_case=False,show_all=False):
540 """Search namespaces with wildcards for objects.
557 """Search namespaces with wildcards for objects.
541
558
542 Arguments:
559 Arguments:
543
560
544 - pattern: string containing shell-like wildcards to use in namespace
561 - pattern: string containing shell-like wildcards to use in namespace
545 searches and optionally a type specification to narrow the search to
562 searches and optionally a type specification to narrow the search to
546 objects of that type.
563 objects of that type.
547
564
548 - ns_table: dict of name->namespaces for search.
565 - ns_table: dict of name->namespaces for search.
549
566
550 Optional arguments:
567 Optional arguments:
551
568
552 - ns_search: list of namespace names to include in search.
569 - ns_search: list of namespace names to include in search.
553
570
554 - ignore_case(False): make the search case-insensitive.
571 - ignore_case(False): make the search case-insensitive.
555
572
556 - show_all(False): show all names, including those starting with
573 - show_all(False): show all names, including those starting with
557 underscores.
574 underscores.
558 """
575 """
559 #print 'ps pattern:<%r>' % pattern # dbg
576 #print 'ps pattern:<%r>' % pattern # dbg
560
577
561 # defaults
578 # defaults
562 type_pattern = 'all'
579 type_pattern = 'all'
563 filter = ''
580 filter = ''
564
581
565 cmds = pattern.split()
582 cmds = pattern.split()
566 len_cmds = len(cmds)
583 len_cmds = len(cmds)
567 if len_cmds == 1:
584 if len_cmds == 1:
568 # Only filter pattern given
585 # Only filter pattern given
569 filter = cmds[0]
586 filter = cmds[0]
570 elif len_cmds == 2:
587 elif len_cmds == 2:
571 # Both filter and type specified
588 # Both filter and type specified
572 filter,type_pattern = cmds
589 filter,type_pattern = cmds
573 else:
590 else:
574 raise ValueError('invalid argument string for psearch: <%s>' %
591 raise ValueError('invalid argument string for psearch: <%s>' %
575 pattern)
592 pattern)
576
593
577 # filter search namespaces
594 # filter search namespaces
578 for name in ns_search:
595 for name in ns_search:
579 if name not in ns_table:
596 if name not in ns_table:
580 raise ValueError('invalid namespace <%s>. Valid names: %s' %
597 raise ValueError('invalid namespace <%s>. Valid names: %s' %
581 (name,ns_table.keys()))
598 (name,ns_table.keys()))
582
599
583 #print 'type_pattern:',type_pattern # dbg
600 #print 'type_pattern:',type_pattern # dbg
584 search_result = []
601 search_result = []
585 for ns_name in ns_search:
602 for ns_name in ns_search:
586 ns = ns_table[ns_name]
603 ns = ns_table[ns_name]
587 tmp_res = list(list_namespace(ns,type_pattern,filter,
604 tmp_res = list(list_namespace(ns,type_pattern,filter,
588 ignore_case=ignore_case,
605 ignore_case=ignore_case,
589 show_all=show_all))
606 show_all=show_all))
590 search_result.extend(tmp_res)
607 search_result.extend(tmp_res)
591 search_result.sort()
608 search_result.sort()
592
609
593 page('\n'.join(search_result))
610 page('\n'.join(search_result))
@@ -1,2043 +1,2046 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 General purpose utilities.
3 General purpose utilities.
4
4
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 these things are also convenient when working at the command line.
6 these things are also convenient when working at the command line.
7
7
8 $Id: genutils.py 2998 2008-01-31 10:06:04Z vivainio $"""
8 $Id: genutils.py 2998 2008-01-31 10:06:04Z vivainio $"""
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 from IPython import Release
17 from IPython import Release
18 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 __license__ = Release.license
19 __license__ = Release.license
20
20
21 #****************************************************************************
21 #****************************************************************************
22 # required modules from the Python standard library
22 # required modules from the Python standard library
23 import __main__
23 import __main__
24 import commands
24 import commands
25 try:
25 try:
26 import doctest
26 import doctest
27 except ImportError:
27 except ImportError:
28 pass
28 pass
29 import os
29 import os
30 import re
30 import re
31 import shlex
31 import shlex
32 import shutil
32 import shutil
33 import sys
33 import sys
34 import tempfile
34 import tempfile
35 import time
35 import time
36 import types
36 import types
37 import warnings
37 import warnings
38
38
39 # Curses and termios are Unix-only modules
39 # Curses and termios are Unix-only modules
40 try:
40 try:
41 import curses
41 import curses
42 # We need termios as well, so if its import happens to raise, we bail on
42 # We need termios as well, so if its import happens to raise, we bail on
43 # using curses altogether.
43 # using curses altogether.
44 import termios
44 import termios
45 except ImportError:
45 except ImportError:
46 USE_CURSES = False
46 USE_CURSES = False
47 else:
47 else:
48 # Curses on Solaris may not be complete, so we can't use it there
48 # Curses on Solaris may not be complete, so we can't use it there
49 USE_CURSES = hasattr(curses,'initscr')
49 USE_CURSES = hasattr(curses,'initscr')
50
50
51 # Other IPython utilities
51 # Other IPython utilities
52 import IPython
52 import IPython
53 from IPython.Itpl import Itpl,itpl,printpl
53 from IPython.Itpl import Itpl,itpl,printpl
54 from IPython import DPyGetOpt, platutils
54 from IPython import DPyGetOpt, platutils
55 from IPython.generics import result_display
55 from IPython.generics import result_display
56 import IPython.ipapi
56 import IPython.ipapi
57 from IPython.external.path import path
57 from IPython.external.path import path
58 if os.name == "nt":
58 if os.name == "nt":
59 from IPython.winconsole import get_console_size
59 from IPython.winconsole import get_console_size
60
60
61 try:
61 try:
62 set
62 set
63 except:
63 except:
64 from sets import Set as set
64 from sets import Set as set
65
65
66
66
67 #****************************************************************************
67 #****************************************************************************
68 # Exceptions
68 # Exceptions
69 class Error(Exception):
69 class Error(Exception):
70 """Base class for exceptions in this module."""
70 """Base class for exceptions in this module."""
71 pass
71 pass
72
72
73 #----------------------------------------------------------------------------
73 #----------------------------------------------------------------------------
74 class IOStream:
74 class IOStream:
75 def __init__(self,stream,fallback):
75 def __init__(self,stream,fallback):
76 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
76 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
77 stream = fallback
77 stream = fallback
78 self.stream = stream
78 self.stream = stream
79 self._swrite = stream.write
79 self._swrite = stream.write
80 self.flush = stream.flush
80 self.flush = stream.flush
81
81
82 def write(self,data):
82 def write(self,data):
83 try:
83 try:
84 self._swrite(data)
84 self._swrite(data)
85 except:
85 except:
86 try:
86 try:
87 # print handles some unicode issues which may trip a plain
87 # print handles some unicode issues which may trip a plain
88 # write() call. Attempt to emulate write() by using a
88 # write() call. Attempt to emulate write() by using a
89 # trailing comma
89 # trailing comma
90 print >> self.stream, data,
90 print >> self.stream, data,
91 except:
91 except:
92 # if we get here, something is seriously broken.
92 # if we get here, something is seriously broken.
93 print >> sys.stderr, \
93 print >> sys.stderr, \
94 'ERROR - failed to write data to stream:', self.stream
94 'ERROR - failed to write data to stream:', self.stream
95
95
96 def close(self):
96 def close(self):
97 pass
97 pass
98
98
99
99
100 class IOTerm:
100 class IOTerm:
101 """ Term holds the file or file-like objects for handling I/O operations.
101 """ Term holds the file or file-like objects for handling I/O operations.
102
102
103 These are normally just sys.stdin, sys.stdout and sys.stderr but for
103 These are normally just sys.stdin, sys.stdout and sys.stderr but for
104 Windows they can can replaced to allow editing the strings before they are
104 Windows they can can replaced to allow editing the strings before they are
105 displayed."""
105 displayed."""
106
106
107 # In the future, having IPython channel all its I/O operations through
107 # In the future, having IPython channel all its I/O operations through
108 # this class will make it easier to embed it into other environments which
108 # this class will make it easier to embed it into other environments which
109 # are not a normal terminal (such as a GUI-based shell)
109 # are not a normal terminal (such as a GUI-based shell)
110 def __init__(self,cin=None,cout=None,cerr=None):
110 def __init__(self,cin=None,cout=None,cerr=None):
111 self.cin = IOStream(cin,sys.stdin)
111 self.cin = IOStream(cin,sys.stdin)
112 self.cout = IOStream(cout,sys.stdout)
112 self.cout = IOStream(cout,sys.stdout)
113 self.cerr = IOStream(cerr,sys.stderr)
113 self.cerr = IOStream(cerr,sys.stderr)
114
114
115 # Global variable to be used for all I/O
115 # Global variable to be used for all I/O
116 Term = IOTerm()
116 Term = IOTerm()
117
117
118 import IPython.rlineimpl as readline
118 import IPython.rlineimpl as readline
119 # Remake Term to use the readline i/o facilities
119 # Remake Term to use the readline i/o facilities
120 if sys.platform == 'win32' and readline.have_readline:
120 if sys.platform == 'win32' and readline.have_readline:
121
121
122 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
122 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
123
123
124
124
125 #****************************************************************************
125 #****************************************************************************
126 # Generic warning/error printer, used by everything else
126 # Generic warning/error printer, used by everything else
127 def warn(msg,level=2,exit_val=1):
127 def warn(msg,level=2,exit_val=1):
128 """Standard warning printer. Gives formatting consistency.
128 """Standard warning printer. Gives formatting consistency.
129
129
130 Output is sent to Term.cerr (sys.stderr by default).
130 Output is sent to Term.cerr (sys.stderr by default).
131
131
132 Options:
132 Options:
133
133
134 -level(2): allows finer control:
134 -level(2): allows finer control:
135 0 -> Do nothing, dummy function.
135 0 -> Do nothing, dummy function.
136 1 -> Print message.
136 1 -> Print message.
137 2 -> Print 'WARNING:' + message. (Default level).
137 2 -> Print 'WARNING:' + message. (Default level).
138 3 -> Print 'ERROR:' + message.
138 3 -> Print 'ERROR:' + message.
139 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
139 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
140
140
141 -exit_val (1): exit value returned by sys.exit() for a level 4
141 -exit_val (1): exit value returned by sys.exit() for a level 4
142 warning. Ignored for all other levels."""
142 warning. Ignored for all other levels."""
143
143
144 if level>0:
144 if level>0:
145 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
145 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
146 print >> Term.cerr, '%s%s' % (header[level],msg)
146 print >> Term.cerr, '%s%s' % (header[level],msg)
147 if level == 4:
147 if level == 4:
148 print >> Term.cerr,'Exiting.\n'
148 print >> Term.cerr,'Exiting.\n'
149 sys.exit(exit_val)
149 sys.exit(exit_val)
150
150
151 def info(msg):
151 def info(msg):
152 """Equivalent to warn(msg,level=1)."""
152 """Equivalent to warn(msg,level=1)."""
153
153
154 warn(msg,level=1)
154 warn(msg,level=1)
155
155
156 def error(msg):
156 def error(msg):
157 """Equivalent to warn(msg,level=3)."""
157 """Equivalent to warn(msg,level=3)."""
158
158
159 warn(msg,level=3)
159 warn(msg,level=3)
160
160
161 def fatal(msg,exit_val=1):
161 def fatal(msg,exit_val=1):
162 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
162 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
163
163
164 warn(msg,exit_val=exit_val,level=4)
164 warn(msg,exit_val=exit_val,level=4)
165
165
166 #---------------------------------------------------------------------------
166 #---------------------------------------------------------------------------
167 # Debugging routines
167 # Debugging routines
168 #
168 #
169 def debugx(expr,pre_msg=''):
169 def debugx(expr,pre_msg=''):
170 """Print the value of an expression from the caller's frame.
170 """Print the value of an expression from the caller's frame.
171
171
172 Takes an expression, evaluates it in the caller's frame and prints both
172 Takes an expression, evaluates it in the caller's frame and prints both
173 the given expression and the resulting value (as well as a debug mark
173 the given expression and the resulting value (as well as a debug mark
174 indicating the name of the calling function. The input must be of a form
174 indicating the name of the calling function. The input must be of a form
175 suitable for eval().
175 suitable for eval().
176
176
177 An optional message can be passed, which will be prepended to the printed
177 An optional message can be passed, which will be prepended to the printed
178 expr->value pair."""
178 expr->value pair."""
179
179
180 cf = sys._getframe(1)
180 cf = sys._getframe(1)
181 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
181 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
182 eval(expr,cf.f_globals,cf.f_locals))
182 eval(expr,cf.f_globals,cf.f_locals))
183
183
184 # deactivate it by uncommenting the following line, which makes it a no-op
184 # deactivate it by uncommenting the following line, which makes it a no-op
185 #def debugx(expr,pre_msg=''): pass
185 #def debugx(expr,pre_msg=''): pass
186
186
187 #----------------------------------------------------------------------------
187 #----------------------------------------------------------------------------
188 StringTypes = types.StringTypes
188 StringTypes = types.StringTypes
189
189
190 # Basic timing functionality
190 # Basic timing functionality
191
191
192 # If possible (Unix), use the resource module instead of time.clock()
192 # If possible (Unix), use the resource module instead of time.clock()
193 try:
193 try:
194 import resource
194 import resource
195 def clocku():
195 def clocku():
196 """clocku() -> floating point number
196 """clocku() -> floating point number
197
197
198 Return the *USER* CPU time in seconds since the start of the process.
198 Return the *USER* CPU time in seconds since the start of the process.
199 This is done via a call to resource.getrusage, so it avoids the
199 This is done via a call to resource.getrusage, so it avoids the
200 wraparound problems in time.clock()."""
200 wraparound problems in time.clock()."""
201
201
202 return resource.getrusage(resource.RUSAGE_SELF)[0]
202 return resource.getrusage(resource.RUSAGE_SELF)[0]
203
203
204 def clocks():
204 def clocks():
205 """clocks() -> floating point number
205 """clocks() -> floating point number
206
206
207 Return the *SYSTEM* CPU time in seconds since the start of the process.
207 Return the *SYSTEM* CPU time in seconds since the start of the process.
208 This is done via a call to resource.getrusage, so it avoids the
208 This is done via a call to resource.getrusage, so it avoids the
209 wraparound problems in time.clock()."""
209 wraparound problems in time.clock()."""
210
210
211 return resource.getrusage(resource.RUSAGE_SELF)[1]
211 return resource.getrusage(resource.RUSAGE_SELF)[1]
212
212
213 def clock():
213 def clock():
214 """clock() -> floating point number
214 """clock() -> floating point number
215
215
216 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
216 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
217 the process. This is done via a call to resource.getrusage, so it
217 the process. This is done via a call to resource.getrusage, so it
218 avoids the wraparound problems in time.clock()."""
218 avoids the wraparound problems in time.clock()."""
219
219
220 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
220 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
221 return u+s
221 return u+s
222
222
223 def clock2():
223 def clock2():
224 """clock2() -> (t_user,t_system)
224 """clock2() -> (t_user,t_system)
225
225
226 Similar to clock(), but return a tuple of user/system times."""
226 Similar to clock(), but return a tuple of user/system times."""
227 return resource.getrusage(resource.RUSAGE_SELF)[:2]
227 return resource.getrusage(resource.RUSAGE_SELF)[:2]
228
228
229 except ImportError:
229 except ImportError:
230 # There is no distinction of user/system time under windows, so we just use
230 # There is no distinction of user/system time under windows, so we just use
231 # time.clock() for everything...
231 # time.clock() for everything...
232 clocku = clocks = clock = time.clock
232 clocku = clocks = clock = time.clock
233 def clock2():
233 def clock2():
234 """Under windows, system CPU time can't be measured.
234 """Under windows, system CPU time can't be measured.
235
235
236 This just returns clock() and zero."""
236 This just returns clock() and zero."""
237 return time.clock(),0.0
237 return time.clock(),0.0
238
238
239 def timings_out(reps,func,*args,**kw):
239 def timings_out(reps,func,*args,**kw):
240 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
240 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
241
241
242 Execute a function reps times, return a tuple with the elapsed total
242 Execute a function reps times, return a tuple with the elapsed total
243 CPU time in seconds, the time per call and the function's output.
243 CPU time in seconds, the time per call and the function's output.
244
244
245 Under Unix, the return value is the sum of user+system time consumed by
245 Under Unix, the return value is the sum of user+system time consumed by
246 the process, computed via the resource module. This prevents problems
246 the process, computed via the resource module. This prevents problems
247 related to the wraparound effect which the time.clock() function has.
247 related to the wraparound effect which the time.clock() function has.
248
248
249 Under Windows the return value is in wall clock seconds. See the
249 Under Windows the return value is in wall clock seconds. See the
250 documentation for the time module for more details."""
250 documentation for the time module for more details."""
251
251
252 reps = int(reps)
252 reps = int(reps)
253 assert reps >=1, 'reps must be >= 1'
253 assert reps >=1, 'reps must be >= 1'
254 if reps==1:
254 if reps==1:
255 start = clock()
255 start = clock()
256 out = func(*args,**kw)
256 out = func(*args,**kw)
257 tot_time = clock()-start
257 tot_time = clock()-start
258 else:
258 else:
259 rng = xrange(reps-1) # the last time is executed separately to store output
259 rng = xrange(reps-1) # the last time is executed separately to store output
260 start = clock()
260 start = clock()
261 for dummy in rng: func(*args,**kw)
261 for dummy in rng: func(*args,**kw)
262 out = func(*args,**kw) # one last time
262 out = func(*args,**kw) # one last time
263 tot_time = clock()-start
263 tot_time = clock()-start
264 av_time = tot_time / reps
264 av_time = tot_time / reps
265 return tot_time,av_time,out
265 return tot_time,av_time,out
266
266
267 def timings(reps,func,*args,**kw):
267 def timings(reps,func,*args,**kw):
268 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
268 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
269
269
270 Execute a function reps times, return a tuple with the elapsed total CPU
270 Execute a function reps times, return a tuple with the elapsed total CPU
271 time in seconds and the time per call. These are just the first two values
271 time in seconds and the time per call. These are just the first two values
272 in timings_out()."""
272 in timings_out()."""
273
273
274 return timings_out(reps,func,*args,**kw)[0:2]
274 return timings_out(reps,func,*args,**kw)[0:2]
275
275
276 def timing(func,*args,**kw):
276 def timing(func,*args,**kw):
277 """timing(func,*args,**kw) -> t_total
277 """timing(func,*args,**kw) -> t_total
278
278
279 Execute a function once, return the elapsed total CPU time in
279 Execute a function once, return the elapsed total CPU time in
280 seconds. This is just the first value in timings_out()."""
280 seconds. This is just the first value in timings_out()."""
281
281
282 return timings_out(1,func,*args,**kw)[0]
282 return timings_out(1,func,*args,**kw)[0]
283
283
284 #****************************************************************************
284 #****************************************************************************
285 # file and system
285 # file and system
286
286
287 def arg_split(s,posix=False):
287 def arg_split(s,posix=False):
288 """Split a command line's arguments in a shell-like manner.
288 """Split a command line's arguments in a shell-like manner.
289
289
290 This is a modified version of the standard library's shlex.split()
290 This is a modified version of the standard library's shlex.split()
291 function, but with a default of posix=False for splitting, so that quotes
291 function, but with a default of posix=False for splitting, so that quotes
292 in inputs are respected."""
292 in inputs are respected."""
293
293
294 # XXX - there may be unicode-related problems here!!! I'm not sure that
294 # XXX - there may be unicode-related problems here!!! I'm not sure that
295 # shlex is truly unicode-safe, so it might be necessary to do
295 # shlex is truly unicode-safe, so it might be necessary to do
296 #
296 #
297 # s = s.encode(sys.stdin.encoding)
297 # s = s.encode(sys.stdin.encoding)
298 #
298 #
299 # first, to ensure that shlex gets a normal string. Input from anyone who
299 # first, to ensure that shlex gets a normal string. Input from anyone who
300 # knows more about unicode and shlex than I would be good to have here...
300 # knows more about unicode and shlex than I would be good to have here...
301 lex = shlex.shlex(s, posix=posix)
301 lex = shlex.shlex(s, posix=posix)
302 lex.whitespace_split = True
302 lex.whitespace_split = True
303 return list(lex)
303 return list(lex)
304
304
305 def system(cmd,verbose=0,debug=0,header=''):
305 def system(cmd,verbose=0,debug=0,header=''):
306 """Execute a system command, return its exit status.
306 """Execute a system command, return its exit status.
307
307
308 Options:
308 Options:
309
309
310 - verbose (0): print the command to be executed.
310 - verbose (0): print the command to be executed.
311
311
312 - debug (0): only print, do not actually execute.
312 - debug (0): only print, do not actually execute.
313
313
314 - header (''): Header to print on screen prior to the executed command (it
314 - header (''): Header to print on screen prior to the executed command (it
315 is only prepended to the command, no newlines are added).
315 is only prepended to the command, no newlines are added).
316
316
317 Note: a stateful version of this function is available through the
317 Note: a stateful version of this function is available through the
318 SystemExec class."""
318 SystemExec class."""
319
319
320 stat = 0
320 stat = 0
321 if verbose or debug: print header+cmd
321 if verbose or debug: print header+cmd
322 sys.stdout.flush()
322 sys.stdout.flush()
323 if not debug: stat = os.system(cmd)
323 if not debug: stat = os.system(cmd)
324 return stat
324 return stat
325
325
326 def abbrev_cwd():
326 def abbrev_cwd():
327 """ Return abbreviated version of cwd, e.g. d:mydir """
327 """ Return abbreviated version of cwd, e.g. d:mydir """
328 cwd = os.getcwd().replace('\\','/')
328 cwd = os.getcwd().replace('\\','/')
329 drivepart = ''
329 drivepart = ''
330 tail = cwd
330 tail = cwd
331 if sys.platform == 'win32':
331 if sys.platform == 'win32':
332 if len(cwd) < 4:
332 if len(cwd) < 4:
333 return cwd
333 return cwd
334 drivepart,tail = os.path.splitdrive(cwd)
334 drivepart,tail = os.path.splitdrive(cwd)
335
335
336
336
337 parts = tail.split('/')
337 parts = tail.split('/')
338 if len(parts) > 2:
338 if len(parts) > 2:
339 tail = '/'.join(parts[-2:])
339 tail = '/'.join(parts[-2:])
340
340
341 return (drivepart + (
341 return (drivepart + (
342 cwd == '/' and '/' or tail))
342 cwd == '/' and '/' or tail))
343
343
344
344
345 # This function is used by ipython in a lot of places to make system calls.
345 # This function is used by ipython in a lot of places to make system calls.
346 # We need it to be slightly different under win32, due to the vagaries of
346 # We need it to be slightly different under win32, due to the vagaries of
347 # 'network shares'. A win32 override is below.
347 # 'network shares'. A win32 override is below.
348
348
349 def shell(cmd,verbose=0,debug=0,header=''):
349 def shell(cmd,verbose=0,debug=0,header=''):
350 """Execute a command in the system shell, always return None.
350 """Execute a command in the system shell, always return None.
351
351
352 Options:
352 Options:
353
353
354 - verbose (0): print the command to be executed.
354 - verbose (0): print the command to be executed.
355
355
356 - debug (0): only print, do not actually execute.
356 - debug (0): only print, do not actually execute.
357
357
358 - header (''): Header to print on screen prior to the executed command (it
358 - header (''): Header to print on screen prior to the executed command (it
359 is only prepended to the command, no newlines are added).
359 is only prepended to the command, no newlines are added).
360
360
361 Note: this is similar to genutils.system(), but it returns None so it can
361 Note: this is similar to genutils.system(), but it returns None so it can
362 be conveniently used in interactive loops without getting the return value
362 be conveniently used in interactive loops without getting the return value
363 (typically 0) printed many times."""
363 (typically 0) printed many times."""
364
364
365 stat = 0
365 stat = 0
366 if verbose or debug: print header+cmd
366 if verbose or debug: print header+cmd
367 # flush stdout so we don't mangle python's buffering
367 # flush stdout so we don't mangle python's buffering
368 sys.stdout.flush()
368 sys.stdout.flush()
369
369
370 if not debug:
370 if not debug:
371 platutils.set_term_title("IPy " + cmd)
371 platutils.set_term_title("IPy " + cmd)
372 os.system(cmd)
372 os.system(cmd)
373 platutils.set_term_title("IPy " + abbrev_cwd())
373 platutils.set_term_title("IPy " + abbrev_cwd())
374
374
375 # override shell() for win32 to deal with network shares
375 # override shell() for win32 to deal with network shares
376 if os.name in ('nt','dos'):
376 if os.name in ('nt','dos'):
377
377
378 shell_ori = shell
378 shell_ori = shell
379
379
380 def shell(cmd,verbose=0,debug=0,header=''):
380 def shell(cmd,verbose=0,debug=0,header=''):
381 if os.getcwd().startswith(r"\\"):
381 if os.getcwd().startswith(r"\\"):
382 path = os.getcwd()
382 path = os.getcwd()
383 # change to c drive (cannot be on UNC-share when issuing os.system,
383 # change to c drive (cannot be on UNC-share when issuing os.system,
384 # as cmd.exe cannot handle UNC addresses)
384 # as cmd.exe cannot handle UNC addresses)
385 os.chdir("c:")
385 os.chdir("c:")
386 # issue pushd to the UNC-share and then run the command
386 # issue pushd to the UNC-share and then run the command
387 try:
387 try:
388 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
388 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
389 finally:
389 finally:
390 os.chdir(path)
390 os.chdir(path)
391 else:
391 else:
392 shell_ori(cmd,verbose,debug,header)
392 shell_ori(cmd,verbose,debug,header)
393
393
394 shell.__doc__ = shell_ori.__doc__
394 shell.__doc__ = shell_ori.__doc__
395
395
396 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
396 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
397 """Dummy substitute for perl's backquotes.
397 """Dummy substitute for perl's backquotes.
398
398
399 Executes a command and returns the output.
399 Executes a command and returns the output.
400
400
401 Accepts the same arguments as system(), plus:
401 Accepts the same arguments as system(), plus:
402
402
403 - split(0): if true, the output is returned as a list split on newlines.
403 - split(0): if true, the output is returned as a list split on newlines.
404
404
405 Note: a stateful version of this function is available through the
405 Note: a stateful version of this function is available through the
406 SystemExec class.
406 SystemExec class.
407
407
408 This is pretty much deprecated and rarely used,
408 This is pretty much deprecated and rarely used,
409 genutils.getoutputerror may be what you need.
409 genutils.getoutputerror may be what you need.
410
410
411 """
411 """
412
412
413 if verbose or debug: print header+cmd
413 if verbose or debug: print header+cmd
414 if not debug:
414 if not debug:
415 output = os.popen(cmd).read()
415 output = os.popen(cmd).read()
416 # stipping last \n is here for backwards compat.
416 # stipping last \n is here for backwards compat.
417 if output.endswith('\n'):
417 if output.endswith('\n'):
418 output = output[:-1]
418 output = output[:-1]
419 if split:
419 if split:
420 return output.split('\n')
420 return output.split('\n')
421 else:
421 else:
422 return output
422 return output
423
423
424 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
424 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
425 """Return (standard output,standard error) of executing cmd in a shell.
425 """Return (standard output,standard error) of executing cmd in a shell.
426
426
427 Accepts the same arguments as system(), plus:
427 Accepts the same arguments as system(), plus:
428
428
429 - split(0): if true, each of stdout/err is returned as a list split on
429 - split(0): if true, each of stdout/err is returned as a list split on
430 newlines.
430 newlines.
431
431
432 Note: a stateful version of this function is available through the
432 Note: a stateful version of this function is available through the
433 SystemExec class."""
433 SystemExec class."""
434
434
435 if verbose or debug: print header+cmd
435 if verbose or debug: print header+cmd
436 if not cmd:
436 if not cmd:
437 if split:
437 if split:
438 return [],[]
438 return [],[]
439 else:
439 else:
440 return '',''
440 return '',''
441 if not debug:
441 if not debug:
442 pin,pout,perr = os.popen3(cmd)
442 pin,pout,perr = os.popen3(cmd)
443 tout = pout.read().rstrip()
443 tout = pout.read().rstrip()
444 terr = perr.read().rstrip()
444 terr = perr.read().rstrip()
445 pin.close()
445 pin.close()
446 pout.close()
446 pout.close()
447 perr.close()
447 perr.close()
448 if split:
448 if split:
449 return tout.split('\n'),terr.split('\n')
449 return tout.split('\n'),terr.split('\n')
450 else:
450 else:
451 return tout,terr
451 return tout,terr
452
452
453 # for compatibility with older naming conventions
453 # for compatibility with older naming conventions
454 xsys = system
454 xsys = system
455 bq = getoutput
455 bq = getoutput
456
456
457 class SystemExec:
457 class SystemExec:
458 """Access the system and getoutput functions through a stateful interface.
458 """Access the system and getoutput functions through a stateful interface.
459
459
460 Note: here we refer to the system and getoutput functions from this
460 Note: here we refer to the system and getoutput functions from this
461 library, not the ones from the standard python library.
461 library, not the ones from the standard python library.
462
462
463 This class offers the system and getoutput functions as methods, but the
463 This class offers the system and getoutput functions as methods, but the
464 verbose, debug and header parameters can be set for the instance (at
464 verbose, debug and header parameters can be set for the instance (at
465 creation time or later) so that they don't need to be specified on each
465 creation time or later) so that they don't need to be specified on each
466 call.
466 call.
467
467
468 For efficiency reasons, there's no way to override the parameters on a
468 For efficiency reasons, there's no way to override the parameters on a
469 per-call basis other than by setting instance attributes. If you need
469 per-call basis other than by setting instance attributes. If you need
470 local overrides, it's best to directly call system() or getoutput().
470 local overrides, it's best to directly call system() or getoutput().
471
471
472 The following names are provided as alternate options:
472 The following names are provided as alternate options:
473 - xsys: alias to system
473 - xsys: alias to system
474 - bq: alias to getoutput
474 - bq: alias to getoutput
475
475
476 An instance can then be created as:
476 An instance can then be created as:
477 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
477 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
478
478
479 And used as:
479 And used as:
480 >>> sysexec.xsys('pwd')
480 >>> sysexec.xsys('pwd')
481 >>> dirlist = sysexec.bq('ls -l')
481 >>> dirlist = sysexec.bq('ls -l')
482 """
482 """
483
483
484 def __init__(self,verbose=0,debug=0,header='',split=0):
484 def __init__(self,verbose=0,debug=0,header='',split=0):
485 """Specify the instance's values for verbose, debug and header."""
485 """Specify the instance's values for verbose, debug and header."""
486 setattr_list(self,'verbose debug header split')
486 setattr_list(self,'verbose debug header split')
487
487
488 def system(self,cmd):
488 def system(self,cmd):
489 """Stateful interface to system(), with the same keyword parameters."""
489 """Stateful interface to system(), with the same keyword parameters."""
490
490
491 system(cmd,self.verbose,self.debug,self.header)
491 system(cmd,self.verbose,self.debug,self.header)
492
492
493 def shell(self,cmd):
493 def shell(self,cmd):
494 """Stateful interface to shell(), with the same keyword parameters."""
494 """Stateful interface to shell(), with the same keyword parameters."""
495
495
496 shell(cmd,self.verbose,self.debug,self.header)
496 shell(cmd,self.verbose,self.debug,self.header)
497
497
498 xsys = system # alias
498 xsys = system # alias
499
499
500 def getoutput(self,cmd):
500 def getoutput(self,cmd):
501 """Stateful interface to getoutput()."""
501 """Stateful interface to getoutput()."""
502
502
503 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
503 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
504
504
505 def getoutputerror(self,cmd):
505 def getoutputerror(self,cmd):
506 """Stateful interface to getoutputerror()."""
506 """Stateful interface to getoutputerror()."""
507
507
508 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
508 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
509
509
510 bq = getoutput # alias
510 bq = getoutput # alias
511
511
512 #-----------------------------------------------------------------------------
512 #-----------------------------------------------------------------------------
513 def mutex_opts(dict,ex_op):
513 def mutex_opts(dict,ex_op):
514 """Check for presence of mutually exclusive keys in a dict.
514 """Check for presence of mutually exclusive keys in a dict.
515
515
516 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
516 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
517 for op1,op2 in ex_op:
517 for op1,op2 in ex_op:
518 if op1 in dict and op2 in dict:
518 if op1 in dict and op2 in dict:
519 raise ValueError,'\n*** ERROR in Arguments *** '\
519 raise ValueError,'\n*** ERROR in Arguments *** '\
520 'Options '+op1+' and '+op2+' are mutually exclusive.'
520 'Options '+op1+' and '+op2+' are mutually exclusive.'
521
521
522 #-----------------------------------------------------------------------------
522 #-----------------------------------------------------------------------------
523 def get_py_filename(name):
523 def get_py_filename(name):
524 """Return a valid python filename in the current directory.
524 """Return a valid python filename in the current directory.
525
525
526 If the given name is not a file, it adds '.py' and searches again.
526 If the given name is not a file, it adds '.py' and searches again.
527 Raises IOError with an informative message if the file isn't found."""
527 Raises IOError with an informative message if the file isn't found."""
528
528
529 name = os.path.expanduser(name)
529 name = os.path.expanduser(name)
530 if not os.path.isfile(name) and not name.endswith('.py'):
530 if not os.path.isfile(name) and not name.endswith('.py'):
531 name += '.py'
531 name += '.py'
532 if os.path.isfile(name):
532 if os.path.isfile(name):
533 return name
533 return name
534 else:
534 else:
535 raise IOError,'File `%s` not found.' % name
535 raise IOError,'File `%s` not found.' % name
536
536
537 #-----------------------------------------------------------------------------
537 #-----------------------------------------------------------------------------
538 def filefind(fname,alt_dirs = None):
538 def filefind(fname,alt_dirs = None):
539 """Return the given filename either in the current directory, if it
539 """Return the given filename either in the current directory, if it
540 exists, or in a specified list of directories.
540 exists, or in a specified list of directories.
541
541
542 ~ expansion is done on all file and directory names.
542 ~ expansion is done on all file and directory names.
543
543
544 Upon an unsuccessful search, raise an IOError exception."""
544 Upon an unsuccessful search, raise an IOError exception."""
545
545
546 if alt_dirs is None:
546 if alt_dirs is None:
547 try:
547 try:
548 alt_dirs = get_home_dir()
548 alt_dirs = get_home_dir()
549 except HomeDirError:
549 except HomeDirError:
550 alt_dirs = os.getcwd()
550 alt_dirs = os.getcwd()
551 search = [fname] + list_strings(alt_dirs)
551 search = [fname] + list_strings(alt_dirs)
552 search = map(os.path.expanduser,search)
552 search = map(os.path.expanduser,search)
553 #print 'search list for',fname,'list:',search # dbg
553 #print 'search list for',fname,'list:',search # dbg
554 fname = search[0]
554 fname = search[0]
555 if os.path.isfile(fname):
555 if os.path.isfile(fname):
556 return fname
556 return fname
557 for direc in search[1:]:
557 for direc in search[1:]:
558 testname = os.path.join(direc,fname)
558 testname = os.path.join(direc,fname)
559 #print 'testname',testname # dbg
559 #print 'testname',testname # dbg
560 if os.path.isfile(testname):
560 if os.path.isfile(testname):
561 return testname
561 return testname
562 raise IOError,'File' + `fname` + \
562 raise IOError,'File' + `fname` + \
563 ' not found in current or supplied directories:' + `alt_dirs`
563 ' not found in current or supplied directories:' + `alt_dirs`
564
564
565 #----------------------------------------------------------------------------
565 #----------------------------------------------------------------------------
566 def file_read(filename):
566 def file_read(filename):
567 """Read a file and close it. Returns the file source."""
567 """Read a file and close it. Returns the file source."""
568 fobj = open(filename,'r');
568 fobj = open(filename,'r');
569 source = fobj.read();
569 source = fobj.read();
570 fobj.close()
570 fobj.close()
571 return source
571 return source
572
572
573 def file_readlines(filename):
573 def file_readlines(filename):
574 """Read a file and close it. Returns the file source using readlines()."""
574 """Read a file and close it. Returns the file source using readlines()."""
575 fobj = open(filename,'r');
575 fobj = open(filename,'r');
576 lines = fobj.readlines();
576 lines = fobj.readlines();
577 fobj.close()
577 fobj.close()
578 return lines
578 return lines
579
579
580 #----------------------------------------------------------------------------
580 #----------------------------------------------------------------------------
581 def target_outdated(target,deps):
581 def target_outdated(target,deps):
582 """Determine whether a target is out of date.
582 """Determine whether a target is out of date.
583
583
584 target_outdated(target,deps) -> 1/0
584 target_outdated(target,deps) -> 1/0
585
585
586 deps: list of filenames which MUST exist.
586 deps: list of filenames which MUST exist.
587 target: single filename which may or may not exist.
587 target: single filename which may or may not exist.
588
588
589 If target doesn't exist or is older than any file listed in deps, return
589 If target doesn't exist or is older than any file listed in deps, return
590 true, otherwise return false.
590 true, otherwise return false.
591 """
591 """
592 try:
592 try:
593 target_time = os.path.getmtime(target)
593 target_time = os.path.getmtime(target)
594 except os.error:
594 except os.error:
595 return 1
595 return 1
596 for dep in deps:
596 for dep in deps:
597 dep_time = os.path.getmtime(dep)
597 dep_time = os.path.getmtime(dep)
598 if dep_time > target_time:
598 if dep_time > target_time:
599 #print "For target",target,"Dep failed:",dep # dbg
599 #print "For target",target,"Dep failed:",dep # dbg
600 #print "times (dep,tar):",dep_time,target_time # dbg
600 #print "times (dep,tar):",dep_time,target_time # dbg
601 return 1
601 return 1
602 return 0
602 return 0
603
603
604 #-----------------------------------------------------------------------------
604 #-----------------------------------------------------------------------------
605 def target_update(target,deps,cmd):
605 def target_update(target,deps,cmd):
606 """Update a target with a given command given a list of dependencies.
606 """Update a target with a given command given a list of dependencies.
607
607
608 target_update(target,deps,cmd) -> runs cmd if target is outdated.
608 target_update(target,deps,cmd) -> runs cmd if target is outdated.
609
609
610 This is just a wrapper around target_outdated() which calls the given
610 This is just a wrapper around target_outdated() which calls the given
611 command if target is outdated."""
611 command if target is outdated."""
612
612
613 if target_outdated(target,deps):
613 if target_outdated(target,deps):
614 xsys(cmd)
614 xsys(cmd)
615
615
616 #----------------------------------------------------------------------------
616 #----------------------------------------------------------------------------
617 def unquote_ends(istr):
617 def unquote_ends(istr):
618 """Remove a single pair of quotes from the endpoints of a string."""
618 """Remove a single pair of quotes from the endpoints of a string."""
619
619
620 if not istr:
620 if not istr:
621 return istr
621 return istr
622 if (istr[0]=="'" and istr[-1]=="'") or \
622 if (istr[0]=="'" and istr[-1]=="'") or \
623 (istr[0]=='"' and istr[-1]=='"'):
623 (istr[0]=='"' and istr[-1]=='"'):
624 return istr[1:-1]
624 return istr[1:-1]
625 else:
625 else:
626 return istr
626 return istr
627
627
628 #----------------------------------------------------------------------------
628 #----------------------------------------------------------------------------
629 def process_cmdline(argv,names=[],defaults={},usage=''):
629 def process_cmdline(argv,names=[],defaults={},usage=''):
630 """ Process command-line options and arguments.
630 """ Process command-line options and arguments.
631
631
632 Arguments:
632 Arguments:
633
633
634 - argv: list of arguments, typically sys.argv.
634 - argv: list of arguments, typically sys.argv.
635
635
636 - names: list of option names. See DPyGetOpt docs for details on options
636 - names: list of option names. See DPyGetOpt docs for details on options
637 syntax.
637 syntax.
638
638
639 - defaults: dict of default values.
639 - defaults: dict of default values.
640
640
641 - usage: optional usage notice to print if a wrong argument is passed.
641 - usage: optional usage notice to print if a wrong argument is passed.
642
642
643 Return a dict of options and a list of free arguments."""
643 Return a dict of options and a list of free arguments."""
644
644
645 getopt = DPyGetOpt.DPyGetOpt()
645 getopt = DPyGetOpt.DPyGetOpt()
646 getopt.setIgnoreCase(0)
646 getopt.setIgnoreCase(0)
647 getopt.parseConfiguration(names)
647 getopt.parseConfiguration(names)
648
648
649 try:
649 try:
650 getopt.processArguments(argv)
650 getopt.processArguments(argv)
651 except DPyGetOpt.ArgumentError, exc:
651 except DPyGetOpt.ArgumentError, exc:
652 print usage
652 print usage
653 warn('"%s"' % exc,level=4)
653 warn('"%s"' % exc,level=4)
654
654
655 defaults.update(getopt.optionValues)
655 defaults.update(getopt.optionValues)
656 args = getopt.freeValues
656 args = getopt.freeValues
657
657
658 return defaults,args
658 return defaults,args
659
659
660 #----------------------------------------------------------------------------
660 #----------------------------------------------------------------------------
661 def optstr2types(ostr):
661 def optstr2types(ostr):
662 """Convert a string of option names to a dict of type mappings.
662 """Convert a string of option names to a dict of type mappings.
663
663
664 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
664 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
665
665
666 This is used to get the types of all the options in a string formatted
666 This is used to get the types of all the options in a string formatted
667 with the conventions of DPyGetOpt. The 'type' None is used for options
667 with the conventions of DPyGetOpt. The 'type' None is used for options
668 which are strings (they need no further conversion). This function's main
668 which are strings (they need no further conversion). This function's main
669 use is to get a typemap for use with read_dict().
669 use is to get a typemap for use with read_dict().
670 """
670 """
671
671
672 typeconv = {None:'',int:'',float:''}
672 typeconv = {None:'',int:'',float:''}
673 typemap = {'s':None,'i':int,'f':float}
673 typemap = {'s':None,'i':int,'f':float}
674 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
674 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
675
675
676 for w in ostr.split():
676 for w in ostr.split():
677 oname,alias,otype = opt_re.match(w).groups()
677 oname,alias,otype = opt_re.match(w).groups()
678 if otype == '' or alias == '!': # simple switches are integers too
678 if otype == '' or alias == '!': # simple switches are integers too
679 otype = 'i'
679 otype = 'i'
680 typeconv[typemap[otype]] += oname + ' '
680 typeconv[typemap[otype]] += oname + ' '
681 return typeconv
681 return typeconv
682
682
683 #----------------------------------------------------------------------------
683 #----------------------------------------------------------------------------
684 def read_dict(filename,type_conv=None,**opt):
684 def read_dict(filename,type_conv=None,**opt):
685
685
686 """Read a dictionary of key=value pairs from an input file, optionally
686 """Read a dictionary of key=value pairs from an input file, optionally
687 performing conversions on the resulting values.
687 performing conversions on the resulting values.
688
688
689 read_dict(filename,type_conv,**opt) -> dict
689 read_dict(filename,type_conv,**opt) -> dict
690
690
691 Only one value per line is accepted, the format should be
691 Only one value per line is accepted, the format should be
692 # optional comments are ignored
692 # optional comments are ignored
693 key value\n
693 key value\n
694
694
695 Args:
695 Args:
696
696
697 - type_conv: A dictionary specifying which keys need to be converted to
697 - type_conv: A dictionary specifying which keys need to be converted to
698 which types. By default all keys are read as strings. This dictionary
698 which types. By default all keys are read as strings. This dictionary
699 should have as its keys valid conversion functions for strings
699 should have as its keys valid conversion functions for strings
700 (int,long,float,complex, or your own). The value for each key
700 (int,long,float,complex, or your own). The value for each key
701 (converter) should be a whitespace separated string containing the names
701 (converter) should be a whitespace separated string containing the names
702 of all the entries in the file to be converted using that function. For
702 of all the entries in the file to be converted using that function. For
703 keys to be left alone, use None as the conversion function (only needed
703 keys to be left alone, use None as the conversion function (only needed
704 with purge=1, see below).
704 with purge=1, see below).
705
705
706 - opt: dictionary with extra options as below (default in parens)
706 - opt: dictionary with extra options as below (default in parens)
707
707
708 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
708 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
709 of the dictionary to be returned. If purge is going to be used, the
709 of the dictionary to be returned. If purge is going to be used, the
710 set of keys to be left as strings also has to be explicitly specified
710 set of keys to be left as strings also has to be explicitly specified
711 using the (non-existent) conversion function None.
711 using the (non-existent) conversion function None.
712
712
713 fs(None): field separator. This is the key/value separator to be used
713 fs(None): field separator. This is the key/value separator to be used
714 when parsing the file. The None default means any whitespace [behavior
714 when parsing the file. The None default means any whitespace [behavior
715 of string.split()].
715 of string.split()].
716
716
717 strip(0): if 1, strip string values of leading/trailinig whitespace.
717 strip(0): if 1, strip string values of leading/trailinig whitespace.
718
718
719 warn(1): warning level if requested keys are not found in file.
719 warn(1): warning level if requested keys are not found in file.
720 - 0: silently ignore.
720 - 0: silently ignore.
721 - 1: inform but proceed.
721 - 1: inform but proceed.
722 - 2: raise KeyError exception.
722 - 2: raise KeyError exception.
723
723
724 no_empty(0): if 1, remove keys with whitespace strings as a value.
724 no_empty(0): if 1, remove keys with whitespace strings as a value.
725
725
726 unique([]): list of keys (or space separated string) which can't be
726 unique([]): list of keys (or space separated string) which can't be
727 repeated. If one such key is found in the file, each new instance
727 repeated. If one such key is found in the file, each new instance
728 overwrites the previous one. For keys not listed here, the behavior is
728 overwrites the previous one. For keys not listed here, the behavior is
729 to make a list of all appearances.
729 to make a list of all appearances.
730
730
731 Example:
731 Example:
732 If the input file test.ini has:
732 If the input file test.ini has:
733 i 3
733 i 3
734 x 4.5
734 x 4.5
735 y 5.5
735 y 5.5
736 s hi ho
736 s hi ho
737 Then:
737 Then:
738
738
739 >>> type_conv={int:'i',float:'x',None:'s'}
739 >>> type_conv={int:'i',float:'x',None:'s'}
740 >>> read_dict('test.ini')
740 >>> read_dict('test.ini')
741 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
741 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
742 >>> read_dict('test.ini',type_conv)
742 >>> read_dict('test.ini',type_conv)
743 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
743 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
744 >>> read_dict('test.ini',type_conv,purge=1)
744 >>> read_dict('test.ini',type_conv,purge=1)
745 {'i': 3, 's': 'hi ho', 'x': 4.5}
745 {'i': 3, 's': 'hi ho', 'x': 4.5}
746 """
746 """
747
747
748 # starting config
748 # starting config
749 opt.setdefault('purge',0)
749 opt.setdefault('purge',0)
750 opt.setdefault('fs',None) # field sep defaults to any whitespace
750 opt.setdefault('fs',None) # field sep defaults to any whitespace
751 opt.setdefault('strip',0)
751 opt.setdefault('strip',0)
752 opt.setdefault('warn',1)
752 opt.setdefault('warn',1)
753 opt.setdefault('no_empty',0)
753 opt.setdefault('no_empty',0)
754 opt.setdefault('unique','')
754 opt.setdefault('unique','')
755 if type(opt['unique']) in StringTypes:
755 if type(opt['unique']) in StringTypes:
756 unique_keys = qw(opt['unique'])
756 unique_keys = qw(opt['unique'])
757 elif type(opt['unique']) in (types.TupleType,types.ListType):
757 elif type(opt['unique']) in (types.TupleType,types.ListType):
758 unique_keys = opt['unique']
758 unique_keys = opt['unique']
759 else:
759 else:
760 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
760 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
761
761
762 dict = {}
762 dict = {}
763 # first read in table of values as strings
763 # first read in table of values as strings
764 file = open(filename,'r')
764 file = open(filename,'r')
765 for line in file.readlines():
765 for line in file.readlines():
766 line = line.strip()
766 line = line.strip()
767 if len(line) and line[0]=='#': continue
767 if len(line) and line[0]=='#': continue
768 if len(line)>0:
768 if len(line)>0:
769 lsplit = line.split(opt['fs'],1)
769 lsplit = line.split(opt['fs'],1)
770 try:
770 try:
771 key,val = lsplit
771 key,val = lsplit
772 except ValueError:
772 except ValueError:
773 key,val = lsplit[0],''
773 key,val = lsplit[0],''
774 key = key.strip()
774 key = key.strip()
775 if opt['strip']: val = val.strip()
775 if opt['strip']: val = val.strip()
776 if val == "''" or val == '""': val = ''
776 if val == "''" or val == '""': val = ''
777 if opt['no_empty'] and (val=='' or val.isspace()):
777 if opt['no_empty'] and (val=='' or val.isspace()):
778 continue
778 continue
779 # if a key is found more than once in the file, build a list
779 # if a key is found more than once in the file, build a list
780 # unless it's in the 'unique' list. In that case, last found in file
780 # unless it's in the 'unique' list. In that case, last found in file
781 # takes precedence. User beware.
781 # takes precedence. User beware.
782 try:
782 try:
783 if dict[key] and key in unique_keys:
783 if dict[key] and key in unique_keys:
784 dict[key] = val
784 dict[key] = val
785 elif type(dict[key]) is types.ListType:
785 elif type(dict[key]) is types.ListType:
786 dict[key].append(val)
786 dict[key].append(val)
787 else:
787 else:
788 dict[key] = [dict[key],val]
788 dict[key] = [dict[key],val]
789 except KeyError:
789 except KeyError:
790 dict[key] = val
790 dict[key] = val
791 # purge if requested
791 # purge if requested
792 if opt['purge']:
792 if opt['purge']:
793 accepted_keys = qwflat(type_conv.values())
793 accepted_keys = qwflat(type_conv.values())
794 for key in dict.keys():
794 for key in dict.keys():
795 if key in accepted_keys: continue
795 if key in accepted_keys: continue
796 del(dict[key])
796 del(dict[key])
797 # now convert if requested
797 # now convert if requested
798 if type_conv==None: return dict
798 if type_conv==None: return dict
799 conversions = type_conv.keys()
799 conversions = type_conv.keys()
800 try: conversions.remove(None)
800 try: conversions.remove(None)
801 except: pass
801 except: pass
802 for convert in conversions:
802 for convert in conversions:
803 for val in qw(type_conv[convert]):
803 for val in qw(type_conv[convert]):
804 try:
804 try:
805 dict[val] = convert(dict[val])
805 dict[val] = convert(dict[val])
806 except KeyError,e:
806 except KeyError,e:
807 if opt['warn'] == 0:
807 if opt['warn'] == 0:
808 pass
808 pass
809 elif opt['warn'] == 1:
809 elif opt['warn'] == 1:
810 print >>sys.stderr, 'Warning: key',val,\
810 print >>sys.stderr, 'Warning: key',val,\
811 'not found in file',filename
811 'not found in file',filename
812 elif opt['warn'] == 2:
812 elif opt['warn'] == 2:
813 raise KeyError,e
813 raise KeyError,e
814 else:
814 else:
815 raise ValueError,'Warning level must be 0,1 or 2'
815 raise ValueError,'Warning level must be 0,1 or 2'
816
816
817 return dict
817 return dict
818
818
819 #----------------------------------------------------------------------------
819 #----------------------------------------------------------------------------
820 def flag_calls(func):
820 def flag_calls(func):
821 """Wrap a function to detect and flag when it gets called.
821 """Wrap a function to detect and flag when it gets called.
822
822
823 This is a decorator which takes a function and wraps it in a function with
823 This is a decorator which takes a function and wraps it in a function with
824 a 'called' attribute. wrapper.called is initialized to False.
824 a 'called' attribute. wrapper.called is initialized to False.
825
825
826 The wrapper.called attribute is set to False right before each call to the
826 The wrapper.called attribute is set to False right before each call to the
827 wrapped function, so if the call fails it remains False. After the call
827 wrapped function, so if the call fails it remains False. After the call
828 completes, wrapper.called is set to True and the output is returned.
828 completes, wrapper.called is set to True and the output is returned.
829
829
830 Testing for truth in wrapper.called allows you to determine if a call to
830 Testing for truth in wrapper.called allows you to determine if a call to
831 func() was attempted and succeeded."""
831 func() was attempted and succeeded."""
832
832
833 def wrapper(*args,**kw):
833 def wrapper(*args,**kw):
834 wrapper.called = False
834 wrapper.called = False
835 out = func(*args,**kw)
835 out = func(*args,**kw)
836 wrapper.called = True
836 wrapper.called = True
837 return out
837 return out
838
838
839 wrapper.called = False
839 wrapper.called = False
840 wrapper.__doc__ = func.__doc__
840 wrapper.__doc__ = func.__doc__
841 return wrapper
841 return wrapper
842
842
843 #----------------------------------------------------------------------------
843 #----------------------------------------------------------------------------
844 def dhook_wrap(func,*a,**k):
844 def dhook_wrap(func,*a,**k):
845 """Wrap a function call in a sys.displayhook controller.
845 """Wrap a function call in a sys.displayhook controller.
846
846
847 Returns a wrapper around func which calls func, with all its arguments and
847 Returns a wrapper around func which calls func, with all its arguments and
848 keywords unmodified, using the default sys.displayhook. Since IPython
848 keywords unmodified, using the default sys.displayhook. Since IPython
849 modifies sys.displayhook, it breaks the behavior of certain systems that
849 modifies sys.displayhook, it breaks the behavior of certain systems that
850 rely on the default behavior, notably doctest.
850 rely on the default behavior, notably doctest.
851 """
851 """
852
852
853 def f(*a,**k):
853 def f(*a,**k):
854
854
855 dhook_s = sys.displayhook
855 dhook_s = sys.displayhook
856 sys.displayhook = sys.__displayhook__
856 sys.displayhook = sys.__displayhook__
857 try:
857 try:
858 out = func(*a,**k)
858 out = func(*a,**k)
859 finally:
859 finally:
860 sys.displayhook = dhook_s
860 sys.displayhook = dhook_s
861
861
862 return out
862 return out
863
863
864 f.__doc__ = func.__doc__
864 f.__doc__ = func.__doc__
865 return f
865 return f
866
866
867 #----------------------------------------------------------------------------
867 #----------------------------------------------------------------------------
868 def doctest_reload():
868 def doctest_reload():
869 """Properly reload doctest to reuse it interactively.
869 """Properly reload doctest to reuse it interactively.
870
870
871 This routine:
871 This routine:
872
872
873 - reloads doctest
873 - reloads doctest
874
874
875 - resets its global 'master' attribute to None, so that multiple uses of
875 - resets its global 'master' attribute to None, so that multiple uses of
876 the module interactively don't produce cumulative reports.
876 the module interactively don't produce cumulative reports.
877
877
878 - Monkeypatches its core test runner method to protect it from IPython's
878 - Monkeypatches its core test runner method to protect it from IPython's
879 modified displayhook. Doctest expects the default displayhook behavior
879 modified displayhook. Doctest expects the default displayhook behavior
880 deep down, so our modification breaks it completely. For this reason, a
880 deep down, so our modification breaks it completely. For this reason, a
881 hard monkeypatch seems like a reasonable solution rather than asking
881 hard monkeypatch seems like a reasonable solution rather than asking
882 users to manually use a different doctest runner when under IPython."""
882 users to manually use a different doctest runner when under IPython."""
883
883
884 import doctest
884 import doctest
885 reload(doctest)
885 reload(doctest)
886 doctest.master=None
886 doctest.master=None
887
887
888 try:
888 try:
889 doctest.DocTestRunner
889 doctest.DocTestRunner
890 except AttributeError:
890 except AttributeError:
891 # This is only for python 2.3 compatibility, remove once we move to
891 # This is only for python 2.3 compatibility, remove once we move to
892 # 2.4 only.
892 # 2.4 only.
893 pass
893 pass
894 else:
894 else:
895 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
895 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
896
896
897 #----------------------------------------------------------------------------
897 #----------------------------------------------------------------------------
898 class HomeDirError(Error):
898 class HomeDirError(Error):
899 pass
899 pass
900
900
901 def get_home_dir():
901 def get_home_dir():
902 """Return the closest possible equivalent to a 'home' directory.
902 """Return the closest possible equivalent to a 'home' directory.
903
903
904 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
904 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
905
905
906 Currently only Posix and NT are implemented, a HomeDirError exception is
906 Currently only Posix and NT are implemented, a HomeDirError exception is
907 raised for all other OSes. """
907 raised for all other OSes. """
908
908
909 isdir = os.path.isdir
909 isdir = os.path.isdir
910 env = os.environ
910 env = os.environ
911
911
912 # first, check py2exe distribution root directory for _ipython.
912 # first, check py2exe distribution root directory for _ipython.
913 # This overrides all. Normally does not exist.
913 # This overrides all. Normally does not exist.
914
914
915 if '\\library.zip\\' in IPython.__file__.lower():
915 if '\\library.zip\\' in IPython.__file__.lower():
916 root, rest = IPython.__file__.lower().split('library.zip')
916 root, rest = IPython.__file__.lower().split('library.zip')
917 if isdir(root + '_ipython'):
917 if isdir(root + '_ipython'):
918 os.environ["IPYKITROOT"] = root.rstrip('\\')
918 os.environ["IPYKITROOT"] = root.rstrip('\\')
919 return root
919 return root
920
920
921 try:
921 try:
922 homedir = env['HOME']
922 homedir = env['HOME']
923 if not isdir(homedir):
923 if not isdir(homedir):
924 # in case a user stuck some string which does NOT resolve to a
924 # in case a user stuck some string which does NOT resolve to a
925 # valid path, it's as good as if we hadn't foud it
925 # valid path, it's as good as if we hadn't foud it
926 raise KeyError
926 raise KeyError
927 return homedir
927 return homedir
928 except KeyError:
928 except KeyError:
929 if os.name == 'posix':
929 if os.name == 'posix':
930 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
930 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
931 elif os.name == 'nt':
931 elif os.name == 'nt':
932 # For some strange reason, win9x returns 'nt' for os.name.
932 # For some strange reason, win9x returns 'nt' for os.name.
933 try:
933 try:
934 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
934 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
935 if not isdir(homedir):
935 if not isdir(homedir):
936 homedir = os.path.join(env['USERPROFILE'])
936 homedir = os.path.join(env['USERPROFILE'])
937 if not isdir(homedir):
937 if not isdir(homedir):
938 raise HomeDirError
938 raise HomeDirError
939 return homedir
939 return homedir
940 except:
940 except:
941 try:
941 try:
942 # Use the registry to get the 'My Documents' folder.
942 # Use the registry to get the 'My Documents' folder.
943 import _winreg as wreg
943 import _winreg as wreg
944 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
944 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
945 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
945 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
946 homedir = wreg.QueryValueEx(key,'Personal')[0]
946 homedir = wreg.QueryValueEx(key,'Personal')[0]
947 key.Close()
947 key.Close()
948 if not isdir(homedir):
948 if not isdir(homedir):
949 e = ('Invalid "Personal" folder registry key '
949 e = ('Invalid "Personal" folder registry key '
950 'typically "My Documents".\n'
950 'typically "My Documents".\n'
951 'Value: %s\n'
951 'Value: %s\n'
952 'This is not a valid directory on your system.' %
952 'This is not a valid directory on your system.' %
953 homedir)
953 homedir)
954 raise HomeDirError(e)
954 raise HomeDirError(e)
955 return homedir
955 return homedir
956 except HomeDirError:
956 except HomeDirError:
957 raise
957 raise
958 except:
958 except:
959 return 'C:\\'
959 return 'C:\\'
960 elif os.name == 'dos':
960 elif os.name == 'dos':
961 # Desperate, may do absurd things in classic MacOS. May work under DOS.
961 # Desperate, may do absurd things in classic MacOS. May work under DOS.
962 return 'C:\\'
962 return 'C:\\'
963 else:
963 else:
964 raise HomeDirError,'support for your operating system not implemented.'
964 raise HomeDirError,'support for your operating system not implemented.'
965
965
966 #****************************************************************************
966 #****************************************************************************
967 # strings and text
967 # strings and text
968
968
969 class LSString(str):
969 class LSString(str):
970 """String derivative with a special access attributes.
970 """String derivative with a special access attributes.
971
971
972 These are normal strings, but with the special attributes:
972 These are normal strings, but with the special attributes:
973
973
974 .l (or .list) : value as list (split on newlines).
974 .l (or .list) : value as list (split on newlines).
975 .n (or .nlstr): original value (the string itself).
975 .n (or .nlstr): original value (the string itself).
976 .s (or .spstr): value as whitespace-separated string.
976 .s (or .spstr): value as whitespace-separated string.
977 .p (or .paths): list of path objects
977 .p (or .paths): list of path objects
978
978
979 Any values which require transformations are computed only once and
979 Any values which require transformations are computed only once and
980 cached.
980 cached.
981
981
982 Such strings are very useful to efficiently interact with the shell, which
982 Such strings are very useful to efficiently interact with the shell, which
983 typically only understands whitespace-separated options for commands."""
983 typically only understands whitespace-separated options for commands."""
984
984
985 def get_list(self):
985 def get_list(self):
986 try:
986 try:
987 return self.__list
987 return self.__list
988 except AttributeError:
988 except AttributeError:
989 self.__list = self.split('\n')
989 self.__list = self.split('\n')
990 return self.__list
990 return self.__list
991
991
992 l = list = property(get_list)
992 l = list = property(get_list)
993
993
994 def get_spstr(self):
994 def get_spstr(self):
995 try:
995 try:
996 return self.__spstr
996 return self.__spstr
997 except AttributeError:
997 except AttributeError:
998 self.__spstr = self.replace('\n',' ')
998 self.__spstr = self.replace('\n',' ')
999 return self.__spstr
999 return self.__spstr
1000
1000
1001 s = spstr = property(get_spstr)
1001 s = spstr = property(get_spstr)
1002
1002
1003 def get_nlstr(self):
1003 def get_nlstr(self):
1004 return self
1004 return self
1005
1005
1006 n = nlstr = property(get_nlstr)
1006 n = nlstr = property(get_nlstr)
1007
1007
1008 def get_paths(self):
1008 def get_paths(self):
1009 try:
1009 try:
1010 return self.__paths
1010 return self.__paths
1011 except AttributeError:
1011 except AttributeError:
1012 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1012 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1013 return self.__paths
1013 return self.__paths
1014
1014
1015 p = paths = property(get_paths)
1015 p = paths = property(get_paths)
1016
1016
1017 def print_lsstring(arg):
1017 def print_lsstring(arg):
1018 """ Prettier (non-repr-like) and more informative printer for LSString """
1018 """ Prettier (non-repr-like) and more informative printer for LSString """
1019 print "LSString (.p, .n, .l, .s available). Value:"
1019 print "LSString (.p, .n, .l, .s available). Value:"
1020 print arg
1020 print arg
1021
1021
1022 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1022 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1023
1023
1024 #----------------------------------------------------------------------------
1024 #----------------------------------------------------------------------------
1025 class SList(list):
1025 class SList(list):
1026 """List derivative with a special access attributes.
1026 """List derivative with a special access attributes.
1027
1027
1028 These are normal lists, but with the special attributes:
1028 These are normal lists, but with the special attributes:
1029
1029
1030 .l (or .list) : value as list (the list itself).
1030 .l (or .list) : value as list (the list itself).
1031 .n (or .nlstr): value as a string, joined on newlines.
1031 .n (or .nlstr): value as a string, joined on newlines.
1032 .s (or .spstr): value as a string, joined on spaces.
1032 .s (or .spstr): value as a string, joined on spaces.
1033 .p (or .paths): list of path objects
1033 .p (or .paths): list of path objects
1034
1034
1035 Any values which require transformations are computed only once and
1035 Any values which require transformations are computed only once and
1036 cached."""
1036 cached."""
1037
1037
1038 def get_list(self):
1038 def get_list(self):
1039 return self
1039 return self
1040
1040
1041 l = list = property(get_list)
1041 l = list = property(get_list)
1042
1042
1043 def get_spstr(self):
1043 def get_spstr(self):
1044 try:
1044 try:
1045 return self.__spstr
1045 return self.__spstr
1046 except AttributeError:
1046 except AttributeError:
1047 self.__spstr = ' '.join(self)
1047 self.__spstr = ' '.join(self)
1048 return self.__spstr
1048 return self.__spstr
1049
1049
1050 s = spstr = property(get_spstr)
1050 s = spstr = property(get_spstr)
1051
1051
1052 def get_nlstr(self):
1052 def get_nlstr(self):
1053 try:
1053 try:
1054 return self.__nlstr
1054 return self.__nlstr
1055 except AttributeError:
1055 except AttributeError:
1056 self.__nlstr = '\n'.join(self)
1056 self.__nlstr = '\n'.join(self)
1057 return self.__nlstr
1057 return self.__nlstr
1058
1058
1059 n = nlstr = property(get_nlstr)
1059 n = nlstr = property(get_nlstr)
1060
1060
1061 def get_paths(self):
1061 def get_paths(self):
1062 try:
1062 try:
1063 return self.__paths
1063 return self.__paths
1064 except AttributeError:
1064 except AttributeError:
1065 self.__paths = [path(p) for p in self if os.path.exists(p)]
1065 self.__paths = [path(p) for p in self if os.path.exists(p)]
1066 return self.__paths
1066 return self.__paths
1067
1067
1068 p = paths = property(get_paths)
1068 p = paths = property(get_paths)
1069
1069
1070 def grep(self, pattern, prune = False, field = None):
1070 def grep(self, pattern, prune = False, field = None):
1071 """ Return all strings matching 'pattern' (a regex or callable)
1071 """ Return all strings matching 'pattern' (a regex or callable)
1072
1072
1073 This is case-insensitive. If prune is true, return all items
1073 This is case-insensitive. If prune is true, return all items
1074 NOT matching the pattern.
1074 NOT matching the pattern.
1075
1075
1076 If field is specified, the match must occur in the specified
1076 If field is specified, the match must occur in the specified
1077 whitespace-separated field.
1077 whitespace-separated field.
1078
1078
1079 Examples::
1079 Examples::
1080
1080
1081 a.grep( lambda x: x.startswith('C') )
1081 a.grep( lambda x: x.startswith('C') )
1082 a.grep('Cha.*log', prune=1)
1082 a.grep('Cha.*log', prune=1)
1083 a.grep('chm', field=-1)
1083 a.grep('chm', field=-1)
1084 """
1084 """
1085
1085
1086 def match_target(s):
1086 def match_target(s):
1087 if field is None:
1087 if field is None:
1088 return s
1088 return s
1089 parts = s.split()
1089 parts = s.split()
1090 try:
1090 try:
1091 tgt = parts[field]
1091 tgt = parts[field]
1092 return tgt
1092 return tgt
1093 except IndexError:
1093 except IndexError:
1094 return ""
1094 return ""
1095
1095
1096 if isinstance(pattern, basestring):
1096 if isinstance(pattern, basestring):
1097 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1097 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1098 else:
1098 else:
1099 pred = pattern
1099 pred = pattern
1100 if not prune:
1100 if not prune:
1101 return SList([el for el in self if pred(match_target(el))])
1101 return SList([el for el in self if pred(match_target(el))])
1102 else:
1102 else:
1103 return SList([el for el in self if not pred(match_target(el))])
1103 return SList([el for el in self if not pred(match_target(el))])
1104 def fields(self, *fields):
1104 def fields(self, *fields):
1105 """ Collect whitespace-separated fields from string list
1105 """ Collect whitespace-separated fields from string list
1106
1106
1107 Allows quick awk-like usage of string lists.
1107 Allows quick awk-like usage of string lists.
1108
1108
1109 Example data (in var a, created by 'a = !ls -l')::
1109 Example data (in var a, created by 'a = !ls -l')::
1110 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1110 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1111 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1111 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1112
1112
1113 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1113 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1114 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1114 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1115 (note the joining by space).
1115 (note the joining by space).
1116 a.fields(-1) is ['ChangeLog', 'IPython']
1116 a.fields(-1) is ['ChangeLog', 'IPython']
1117
1117
1118 IndexErrors are ignored.
1118 IndexErrors are ignored.
1119
1119
1120 Without args, fields() just split()'s the strings.
1120 Without args, fields() just split()'s the strings.
1121 """
1121 """
1122 if len(fields) == 0:
1122 if len(fields) == 0:
1123 return [el.split() for el in self]
1123 return [el.split() for el in self]
1124
1124
1125 res = SList()
1125 res = SList()
1126 for el in [f.split() for f in self]:
1126 for el in [f.split() for f in self]:
1127 lineparts = []
1127 lineparts = []
1128
1128
1129 for fd in fields:
1129 for fd in fields:
1130 try:
1130 try:
1131 lineparts.append(el[fd])
1131 lineparts.append(el[fd])
1132 except IndexError:
1132 except IndexError:
1133 pass
1133 pass
1134 if lineparts:
1134 if lineparts:
1135 res.append(" ".join(lineparts))
1135 res.append(" ".join(lineparts))
1136
1136
1137 return res
1137 return res
1138
1138
1139
1139
1140
1140
1141
1141
1142
1142
1143 def print_slist(arg):
1143 def print_slist(arg):
1144 """ Prettier (non-repr-like) and more informative printer for SList """
1144 """ Prettier (non-repr-like) and more informative printer for SList """
1145 print "SList (.p, .n, .l, .s, .grep(), .fields() available). Value:"
1145 print "SList (.p, .n, .l, .s, .grep(), .fields() available). Value:"
1146 nlprint(arg)
1146 nlprint(arg)
1147
1147
1148 print_slist = result_display.when_type(SList)(print_slist)
1148 print_slist = result_display.when_type(SList)(print_slist)
1149
1149
1150
1150
1151
1151
1152 #----------------------------------------------------------------------------
1152 #----------------------------------------------------------------------------
1153 def esc_quotes(strng):
1153 def esc_quotes(strng):
1154 """Return the input string with single and double quotes escaped out"""
1154 """Return the input string with single and double quotes escaped out"""
1155
1155
1156 return strng.replace('"','\\"').replace("'","\\'")
1156 return strng.replace('"','\\"').replace("'","\\'")
1157
1157
1158 #----------------------------------------------------------------------------
1158 #----------------------------------------------------------------------------
1159 def make_quoted_expr(s):
1159 def make_quoted_expr(s):
1160 """Return string s in appropriate quotes, using raw string if possible.
1160 """Return string s in appropriate quotes, using raw string if possible.
1161
1161
1162 Effectively this turns string: cd \ao\ao\
1162 Effectively this turns string: cd \ao\ao\
1163 to: r"cd \ao\ao\_"[:-1]
1163 to: r"cd \ao\ao\_"[:-1]
1164
1164
1165 Note the use of raw string and padding at the end to allow trailing backslash.
1165 Note the use of raw string and padding at the end to allow trailing backslash.
1166
1166
1167 """
1167 """
1168
1168
1169 tail = ''
1169 tail = ''
1170 tailpadding = ''
1170 tailpadding = ''
1171 raw = ''
1171 raw = ''
1172 if "\\" in s:
1172 if "\\" in s:
1173 raw = 'r'
1173 raw = 'r'
1174 if s.endswith('\\'):
1174 if s.endswith('\\'):
1175 tail = '[:-1]'
1175 tail = '[:-1]'
1176 tailpadding = '_'
1176 tailpadding = '_'
1177 if '"' not in s:
1177 if '"' not in s:
1178 quote = '"'
1178 quote = '"'
1179 elif "'" not in s:
1179 elif "'" not in s:
1180 quote = "'"
1180 quote = "'"
1181 elif '"""' not in s and not s.endswith('"'):
1181 elif '"""' not in s and not s.endswith('"'):
1182 quote = '"""'
1182 quote = '"""'
1183 elif "'''" not in s and not s.endswith("'"):
1183 elif "'''" not in s and not s.endswith("'"):
1184 quote = "'''"
1184 quote = "'''"
1185 else:
1185 else:
1186 # give up, backslash-escaped string will do
1186 # give up, backslash-escaped string will do
1187 return '"%s"' % esc_quotes(s)
1187 return '"%s"' % esc_quotes(s)
1188 res = raw + quote + s + tailpadding + quote + tail
1188 res = raw + quote + s + tailpadding + quote + tail
1189 return res
1189 return res
1190
1190
1191
1191
1192 #----------------------------------------------------------------------------
1192 #----------------------------------------------------------------------------
1193 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1193 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1194 """Take multiple lines of input.
1194 """Take multiple lines of input.
1195
1195
1196 A list with each line of input as a separate element is returned when a
1196 A list with each line of input as a separate element is returned when a
1197 termination string is entered (defaults to a single '.'). Input can also
1197 termination string is entered (defaults to a single '.'). Input can also
1198 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1198 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1199
1199
1200 Lines of input which end in \\ are joined into single entries (and a
1200 Lines of input which end in \\ are joined into single entries (and a
1201 secondary continuation prompt is issued as long as the user terminates
1201 secondary continuation prompt is issued as long as the user terminates
1202 lines with \\). This allows entering very long strings which are still
1202 lines with \\). This allows entering very long strings which are still
1203 meant to be treated as single entities.
1203 meant to be treated as single entities.
1204 """
1204 """
1205
1205
1206 try:
1206 try:
1207 if header:
1207 if header:
1208 header += '\n'
1208 header += '\n'
1209 lines = [raw_input(header + ps1)]
1209 lines = [raw_input(header + ps1)]
1210 except EOFError:
1210 except EOFError:
1211 return []
1211 return []
1212 terminate = [terminate_str]
1212 terminate = [terminate_str]
1213 try:
1213 try:
1214 while lines[-1:] != terminate:
1214 while lines[-1:] != terminate:
1215 new_line = raw_input(ps1)
1215 new_line = raw_input(ps1)
1216 while new_line.endswith('\\'):
1216 while new_line.endswith('\\'):
1217 new_line = new_line[:-1] + raw_input(ps2)
1217 new_line = new_line[:-1] + raw_input(ps2)
1218 lines.append(new_line)
1218 lines.append(new_line)
1219
1219
1220 return lines[:-1] # don't return the termination command
1220 return lines[:-1] # don't return the termination command
1221 except EOFError:
1221 except EOFError:
1222 print
1222 print
1223 return lines
1223 return lines
1224
1224
1225 #----------------------------------------------------------------------------
1225 #----------------------------------------------------------------------------
1226 def raw_input_ext(prompt='', ps2='... '):
1226 def raw_input_ext(prompt='', ps2='... '):
1227 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1227 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1228
1228
1229 line = raw_input(prompt)
1229 line = raw_input(prompt)
1230 while line.endswith('\\'):
1230 while line.endswith('\\'):
1231 line = line[:-1] + raw_input(ps2)
1231 line = line[:-1] + raw_input(ps2)
1232 return line
1232 return line
1233
1233
1234 #----------------------------------------------------------------------------
1234 #----------------------------------------------------------------------------
1235 def ask_yes_no(prompt,default=None):
1235 def ask_yes_no(prompt,default=None):
1236 """Asks a question and returns a boolean (y/n) answer.
1236 """Asks a question and returns a boolean (y/n) answer.
1237
1237
1238 If default is given (one of 'y','n'), it is used if the user input is
1238 If default is given (one of 'y','n'), it is used if the user input is
1239 empty. Otherwise the question is repeated until an answer is given.
1239 empty. Otherwise the question is repeated until an answer is given.
1240
1240
1241 An EOF is treated as the default answer. If there is no default, an
1241 An EOF is treated as the default answer. If there is no default, an
1242 exception is raised to prevent infinite loops.
1242 exception is raised to prevent infinite loops.
1243
1243
1244 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1244 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1245
1245
1246 answers = {'y':True,'n':False,'yes':True,'no':False}
1246 answers = {'y':True,'n':False,'yes':True,'no':False}
1247 ans = None
1247 ans = None
1248 while ans not in answers.keys():
1248 while ans not in answers.keys():
1249 try:
1249 try:
1250 ans = raw_input(prompt+' ').lower()
1250 ans = raw_input(prompt+' ').lower()
1251 if not ans: # response was an empty string
1251 if not ans: # response was an empty string
1252 ans = default
1252 ans = default
1253 except KeyboardInterrupt:
1253 except KeyboardInterrupt:
1254 pass
1254 pass
1255 except EOFError:
1255 except EOFError:
1256 if default in answers.keys():
1256 if default in answers.keys():
1257 ans = default
1257 ans = default
1258 print
1258 print
1259 else:
1259 else:
1260 raise
1260 raise
1261
1261
1262 return answers[ans]
1262 return answers[ans]
1263
1263
1264 #----------------------------------------------------------------------------
1264 #----------------------------------------------------------------------------
1265 def marquee(txt='',width=78,mark='*'):
1265 def marquee(txt='',width=78,mark='*'):
1266 """Return the input string centered in a 'marquee'."""
1266 """Return the input string centered in a 'marquee'."""
1267 if not txt:
1267 if not txt:
1268 return (mark*width)[:width]
1268 return (mark*width)[:width]
1269 nmark = (width-len(txt)-2)/len(mark)/2
1269 nmark = (width-len(txt)-2)/len(mark)/2
1270 if nmark < 0: nmark =0
1270 if nmark < 0: nmark =0
1271 marks = mark*nmark
1271 marks = mark*nmark
1272 return '%s %s %s' % (marks,txt,marks)
1272 return '%s %s %s' % (marks,txt,marks)
1273
1273
1274 #----------------------------------------------------------------------------
1274 #----------------------------------------------------------------------------
1275 class EvalDict:
1275 class EvalDict:
1276 """
1276 """
1277 Emulate a dict which evaluates its contents in the caller's frame.
1277 Emulate a dict which evaluates its contents in the caller's frame.
1278
1278
1279 Usage:
1279 Usage:
1280 >>>number = 19
1280 >>>number = 19
1281 >>>text = "python"
1281 >>>text = "python"
1282 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1282 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1283 """
1283 """
1284
1284
1285 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1285 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1286 # modified (shorter) version of:
1286 # modified (shorter) version of:
1287 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1287 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1288 # Skip Montanaro (skip@pobox.com).
1288 # Skip Montanaro (skip@pobox.com).
1289
1289
1290 def __getitem__(self, name):
1290 def __getitem__(self, name):
1291 frame = sys._getframe(1)
1291 frame = sys._getframe(1)
1292 return eval(name, frame.f_globals, frame.f_locals)
1292 return eval(name, frame.f_globals, frame.f_locals)
1293
1293
1294 EvalString = EvalDict # for backwards compatibility
1294 EvalString = EvalDict # for backwards compatibility
1295 #----------------------------------------------------------------------------
1295 #----------------------------------------------------------------------------
1296 def qw(words,flat=0,sep=None,maxsplit=-1):
1296 def qw(words,flat=0,sep=None,maxsplit=-1):
1297 """Similar to Perl's qw() operator, but with some more options.
1297 """Similar to Perl's qw() operator, but with some more options.
1298
1298
1299 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1299 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1300
1300
1301 words can also be a list itself, and with flat=1, the output will be
1301 words can also be a list itself, and with flat=1, the output will be
1302 recursively flattened. Examples:
1302 recursively flattened. Examples:
1303
1303
1304 >>> qw('1 2')
1304 >>> qw('1 2')
1305 ['1', '2']
1305 ['1', '2']
1306 >>> qw(['a b','1 2',['m n','p q']])
1306 >>> qw(['a b','1 2',['m n','p q']])
1307 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1307 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1308 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1308 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1309 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1309 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1310
1310
1311 if type(words) in StringTypes:
1311 if type(words) in StringTypes:
1312 return [word.strip() for word in words.split(sep,maxsplit)
1312 return [word.strip() for word in words.split(sep,maxsplit)
1313 if word and not word.isspace() ]
1313 if word and not word.isspace() ]
1314 if flat:
1314 if flat:
1315 return flatten(map(qw,words,[1]*len(words)))
1315 return flatten(map(qw,words,[1]*len(words)))
1316 return map(qw,words)
1316 return map(qw,words)
1317
1317
1318 #----------------------------------------------------------------------------
1318 #----------------------------------------------------------------------------
1319 def qwflat(words,sep=None,maxsplit=-1):
1319 def qwflat(words,sep=None,maxsplit=-1):
1320 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1320 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1321 return qw(words,1,sep,maxsplit)
1321 return qw(words,1,sep,maxsplit)
1322
1322
1323 #----------------------------------------------------------------------------
1323 #----------------------------------------------------------------------------
1324 def qw_lol(indata):
1324 def qw_lol(indata):
1325 """qw_lol('a b') -> [['a','b']],
1325 """qw_lol('a b') -> [['a','b']],
1326 otherwise it's just a call to qw().
1326 otherwise it's just a call to qw().
1327
1327
1328 We need this to make sure the modules_some keys *always* end up as a
1328 We need this to make sure the modules_some keys *always* end up as a
1329 list of lists."""
1329 list of lists."""
1330
1330
1331 if type(indata) in StringTypes:
1331 if type(indata) in StringTypes:
1332 return [qw(indata)]
1332 return [qw(indata)]
1333 else:
1333 else:
1334 return qw(indata)
1334 return qw(indata)
1335
1335
1336 #-----------------------------------------------------------------------------
1336 #-----------------------------------------------------------------------------
1337 def list_strings(arg):
1337 def list_strings(arg):
1338 """Always return a list of strings, given a string or list of strings
1338 """Always return a list of strings, given a string or list of strings
1339 as input."""
1339 as input."""
1340
1340
1341 if type(arg) in StringTypes: return [arg]
1341 if type(arg) in StringTypes: return [arg]
1342 else: return arg
1342 else: return arg
1343
1343
1344 #----------------------------------------------------------------------------
1344 #----------------------------------------------------------------------------
1345 def grep(pat,list,case=1):
1345 def grep(pat,list,case=1):
1346 """Simple minded grep-like function.
1346 """Simple minded grep-like function.
1347 grep(pat,list) returns occurrences of pat in list, None on failure.
1347 grep(pat,list) returns occurrences of pat in list, None on failure.
1348
1348
1349 It only does simple string matching, with no support for regexps. Use the
1349 It only does simple string matching, with no support for regexps. Use the
1350 option case=0 for case-insensitive matching."""
1350 option case=0 for case-insensitive matching."""
1351
1351
1352 # This is pretty crude. At least it should implement copying only references
1352 # This is pretty crude. At least it should implement copying only references
1353 # to the original data in case it's big. Now it copies the data for output.
1353 # to the original data in case it's big. Now it copies the data for output.
1354 out=[]
1354 out=[]
1355 if case:
1355 if case:
1356 for term in list:
1356 for term in list:
1357 if term.find(pat)>-1: out.append(term)
1357 if term.find(pat)>-1: out.append(term)
1358 else:
1358 else:
1359 lpat=pat.lower()
1359 lpat=pat.lower()
1360 for term in list:
1360 for term in list:
1361 if term.lower().find(lpat)>-1: out.append(term)
1361 if term.lower().find(lpat)>-1: out.append(term)
1362
1362
1363 if len(out): return out
1363 if len(out): return out
1364 else: return None
1364 else: return None
1365
1365
1366 #----------------------------------------------------------------------------
1366 #----------------------------------------------------------------------------
1367 def dgrep(pat,*opts):
1367 def dgrep(pat,*opts):
1368 """Return grep() on dir()+dir(__builtins__).
1368 """Return grep() on dir()+dir(__builtins__).
1369
1369
1370 A very common use of grep() when working interactively."""
1370 A very common use of grep() when working interactively."""
1371
1371
1372 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1372 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1373
1373
1374 #----------------------------------------------------------------------------
1374 #----------------------------------------------------------------------------
1375 def idgrep(pat):
1375 def idgrep(pat):
1376 """Case-insensitive dgrep()"""
1376 """Case-insensitive dgrep()"""
1377
1377
1378 return dgrep(pat,0)
1378 return dgrep(pat,0)
1379
1379
1380 #----------------------------------------------------------------------------
1380 #----------------------------------------------------------------------------
1381 def igrep(pat,list):
1381 def igrep(pat,list):
1382 """Synonym for case-insensitive grep."""
1382 """Synonym for case-insensitive grep."""
1383
1383
1384 return grep(pat,list,case=0)
1384 return grep(pat,list,case=0)
1385
1385
1386 #----------------------------------------------------------------------------
1386 #----------------------------------------------------------------------------
1387 def indent(str,nspaces=4,ntabs=0):
1387 def indent(str,nspaces=4,ntabs=0):
1388 """Indent a string a given number of spaces or tabstops.
1388 """Indent a string a given number of spaces or tabstops.
1389
1389
1390 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1390 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1391 """
1391 """
1392 if str is None:
1392 if str is None:
1393 return
1393 return
1394 ind = '\t'*ntabs+' '*nspaces
1394 ind = '\t'*ntabs+' '*nspaces
1395 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1395 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1396 if outstr.endswith(os.linesep+ind):
1396 if outstr.endswith(os.linesep+ind):
1397 return outstr[:-len(ind)]
1397 return outstr[:-len(ind)]
1398 else:
1398 else:
1399 return outstr
1399 return outstr
1400
1400
1401 #-----------------------------------------------------------------------------
1401 #-----------------------------------------------------------------------------
1402 def native_line_ends(filename,backup=1):
1402 def native_line_ends(filename,backup=1):
1403 """Convert (in-place) a file to line-ends native to the current OS.
1403 """Convert (in-place) a file to line-ends native to the current OS.
1404
1404
1405 If the optional backup argument is given as false, no backup of the
1405 If the optional backup argument is given as false, no backup of the
1406 original file is left. """
1406 original file is left. """
1407
1407
1408 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1408 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1409
1409
1410 bak_filename = filename + backup_suffixes[os.name]
1410 bak_filename = filename + backup_suffixes[os.name]
1411
1411
1412 original = open(filename).read()
1412 original = open(filename).read()
1413 shutil.copy2(filename,bak_filename)
1413 shutil.copy2(filename,bak_filename)
1414 try:
1414 try:
1415 new = open(filename,'wb')
1415 new = open(filename,'wb')
1416 new.write(os.linesep.join(original.splitlines()))
1416 new.write(os.linesep.join(original.splitlines()))
1417 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1417 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1418 new.close()
1418 new.close()
1419 except:
1419 except:
1420 os.rename(bak_filename,filename)
1420 os.rename(bak_filename,filename)
1421 if not backup:
1421 if not backup:
1422 try:
1422 try:
1423 os.remove(bak_filename)
1423 os.remove(bak_filename)
1424 except:
1424 except:
1425 pass
1425 pass
1426
1426
1427 #----------------------------------------------------------------------------
1427 #----------------------------------------------------------------------------
1428 def get_pager_cmd(pager_cmd = None):
1428 def get_pager_cmd(pager_cmd = None):
1429 """Return a pager command.
1429 """Return a pager command.
1430
1430
1431 Makes some attempts at finding an OS-correct one."""
1431 Makes some attempts at finding an OS-correct one."""
1432
1432
1433 if os.name == 'posix':
1433 if os.name == 'posix':
1434 default_pager_cmd = 'less -r' # -r for color control sequences
1434 default_pager_cmd = 'less -r' # -r for color control sequences
1435 elif os.name in ['nt','dos']:
1435 elif os.name in ['nt','dos']:
1436 default_pager_cmd = 'type'
1436 default_pager_cmd = 'type'
1437
1437
1438 if pager_cmd is None:
1438 if pager_cmd is None:
1439 try:
1439 try:
1440 pager_cmd = os.environ['PAGER']
1440 pager_cmd = os.environ['PAGER']
1441 except:
1441 except:
1442 pager_cmd = default_pager_cmd
1442 pager_cmd = default_pager_cmd
1443 return pager_cmd
1443 return pager_cmd
1444
1444
1445 #-----------------------------------------------------------------------------
1445 #-----------------------------------------------------------------------------
1446 def get_pager_start(pager,start):
1446 def get_pager_start(pager,start):
1447 """Return the string for paging files with an offset.
1447 """Return the string for paging files with an offset.
1448
1448
1449 This is the '+N' argument which less and more (under Unix) accept.
1449 This is the '+N' argument which less and more (under Unix) accept.
1450 """
1450 """
1451
1451
1452 if pager in ['less','more']:
1452 if pager in ['less','more']:
1453 if start:
1453 if start:
1454 start_string = '+' + str(start)
1454 start_string = '+' + str(start)
1455 else:
1455 else:
1456 start_string = ''
1456 start_string = ''
1457 else:
1457 else:
1458 start_string = ''
1458 start_string = ''
1459 return start_string
1459 return start_string
1460
1460
1461 #----------------------------------------------------------------------------
1461 #----------------------------------------------------------------------------
1462 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1462 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1463 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1463 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1464 import msvcrt
1464 import msvcrt
1465 def page_more():
1465 def page_more():
1466 """ Smart pausing between pages
1466 """ Smart pausing between pages
1467
1467
1468 @return: True if need print more lines, False if quit
1468 @return: True if need print more lines, False if quit
1469 """
1469 """
1470 Term.cout.write('---Return to continue, q to quit--- ')
1470 Term.cout.write('---Return to continue, q to quit--- ')
1471 ans = msvcrt.getch()
1471 ans = msvcrt.getch()
1472 if ans in ("q", "Q"):
1472 if ans in ("q", "Q"):
1473 result = False
1473 result = False
1474 else:
1474 else:
1475 result = True
1475 result = True
1476 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1476 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1477 return result
1477 return result
1478 else:
1478 else:
1479 def page_more():
1479 def page_more():
1480 ans = raw_input('---Return to continue, q to quit--- ')
1480 ans = raw_input('---Return to continue, q to quit--- ')
1481 if ans.lower().startswith('q'):
1481 if ans.lower().startswith('q'):
1482 return False
1482 return False
1483 else:
1483 else:
1484 return True
1484 return True
1485
1485
1486 esc_re = re.compile(r"(\x1b[^m]+m)")
1486 esc_re = re.compile(r"(\x1b[^m]+m)")
1487
1487
1488 def page_dumb(strng,start=0,screen_lines=25):
1488 def page_dumb(strng,start=0,screen_lines=25):
1489 """Very dumb 'pager' in Python, for when nothing else works.
1489 """Very dumb 'pager' in Python, for when nothing else works.
1490
1490
1491 Only moves forward, same interface as page(), except for pager_cmd and
1491 Only moves forward, same interface as page(), except for pager_cmd and
1492 mode."""
1492 mode."""
1493
1493
1494 out_ln = strng.splitlines()[start:]
1494 out_ln = strng.splitlines()[start:]
1495 screens = chop(out_ln,screen_lines-1)
1495 screens = chop(out_ln,screen_lines-1)
1496 if len(screens) == 1:
1496 if len(screens) == 1:
1497 print >>Term.cout, os.linesep.join(screens[0])
1497 print >>Term.cout, os.linesep.join(screens[0])
1498 else:
1498 else:
1499 last_escape = ""
1499 last_escape = ""
1500 for scr in screens[0:-1]:
1500 for scr in screens[0:-1]:
1501 hunk = os.linesep.join(scr)
1501 hunk = os.linesep.join(scr)
1502 print >>Term.cout, last_escape + hunk
1502 print >>Term.cout, last_escape + hunk
1503 if not page_more():
1503 if not page_more():
1504 return
1504 return
1505 esc_list = esc_re.findall(hunk)
1505 esc_list = esc_re.findall(hunk)
1506 if len(esc_list) > 0:
1506 if len(esc_list) > 0:
1507 last_escape = esc_list[-1]
1507 last_escape = esc_list[-1]
1508 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1508 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1509
1509
1510 #----------------------------------------------------------------------------
1510 #----------------------------------------------------------------------------
1511 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1511 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1512 """Print a string, piping through a pager after a certain length.
1512 """Print a string, piping through a pager after a certain length.
1513
1513
1514 The screen_lines parameter specifies the number of *usable* lines of your
1514 The screen_lines parameter specifies the number of *usable* lines of your
1515 terminal screen (total lines minus lines you need to reserve to show other
1515 terminal screen (total lines minus lines you need to reserve to show other
1516 information).
1516 information).
1517
1517
1518 If you set screen_lines to a number <=0, page() will try to auto-determine
1518 If you set screen_lines to a number <=0, page() will try to auto-determine
1519 your screen size and will only use up to (screen_size+screen_lines) for
1519 your screen size and will only use up to (screen_size+screen_lines) for
1520 printing, paging after that. That is, if you want auto-detection but need
1520 printing, paging after that. That is, if you want auto-detection but need
1521 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1521 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1522 auto-detection without any lines reserved simply use screen_lines = 0.
1522 auto-detection without any lines reserved simply use screen_lines = 0.
1523
1523
1524 If a string won't fit in the allowed lines, it is sent through the
1524 If a string won't fit in the allowed lines, it is sent through the
1525 specified pager command. If none given, look for PAGER in the environment,
1525 specified pager command. If none given, look for PAGER in the environment,
1526 and ultimately default to less.
1526 and ultimately default to less.
1527
1527
1528 If no system pager works, the string is sent through a 'dumb pager'
1528 If no system pager works, the string is sent through a 'dumb pager'
1529 written in python, very simplistic.
1529 written in python, very simplistic.
1530 """
1530 """
1531
1531
1532 # Some routines may auto-compute start offsets incorrectly and pass a
1533 # negative value. Offset to 0 for robustness.
1534 start = max(0,start)
1532
1535
1533 # first, try the hook
1536 # first, try the hook
1534 ip = IPython.ipapi.get()
1537 ip = IPython.ipapi.get()
1535 if ip:
1538 if ip:
1536 try:
1539 try:
1537 ip.IP.hooks.show_in_pager(strng)
1540 ip.IP.hooks.show_in_pager(strng)
1538 return
1541 return
1539 except IPython.ipapi.TryNext:
1542 except IPython.ipapi.TryNext:
1540 pass
1543 pass
1541
1544
1542 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1545 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1543 TERM = os.environ.get('TERM','dumb')
1546 TERM = os.environ.get('TERM','dumb')
1544 if TERM in ['dumb','emacs'] and os.name != 'nt':
1547 if TERM in ['dumb','emacs'] and os.name != 'nt':
1545 print strng
1548 print strng
1546 return
1549 return
1547 # chop off the topmost part of the string we don't want to see
1550 # chop off the topmost part of the string we don't want to see
1548 str_lines = strng.split(os.linesep)[start:]
1551 str_lines = strng.split(os.linesep)[start:]
1549 str_toprint = os.linesep.join(str_lines)
1552 str_toprint = os.linesep.join(str_lines)
1550 num_newlines = len(str_lines)
1553 num_newlines = len(str_lines)
1551 len_str = len(str_toprint)
1554 len_str = len(str_toprint)
1552
1555
1553 # Dumb heuristics to guesstimate number of on-screen lines the string
1556 # Dumb heuristics to guesstimate number of on-screen lines the string
1554 # takes. Very basic, but good enough for docstrings in reasonable
1557 # takes. Very basic, but good enough for docstrings in reasonable
1555 # terminals. If someone later feels like refining it, it's not hard.
1558 # terminals. If someone later feels like refining it, it's not hard.
1556 numlines = max(num_newlines,int(len_str/80)+1)
1559 numlines = max(num_newlines,int(len_str/80)+1)
1557
1560
1558 if os.name == "nt":
1561 if os.name == "nt":
1559 screen_lines_def = get_console_size(defaulty=25)[1]
1562 screen_lines_def = get_console_size(defaulty=25)[1]
1560 else:
1563 else:
1561 screen_lines_def = 25 # default value if we can't auto-determine
1564 screen_lines_def = 25 # default value if we can't auto-determine
1562
1565
1563 # auto-determine screen size
1566 # auto-determine screen size
1564 if screen_lines <= 0:
1567 if screen_lines <= 0:
1565 if TERM=='xterm':
1568 if TERM=='xterm':
1566 use_curses = USE_CURSES
1569 use_curses = USE_CURSES
1567 else:
1570 else:
1568 # curses causes problems on many terminals other than xterm.
1571 # curses causes problems on many terminals other than xterm.
1569 use_curses = False
1572 use_curses = False
1570 if use_curses:
1573 if use_curses:
1571 # There is a bug in curses, where *sometimes* it fails to properly
1574 # There is a bug in curses, where *sometimes* it fails to properly
1572 # initialize, and then after the endwin() call is made, the
1575 # initialize, and then after the endwin() call is made, the
1573 # terminal is left in an unusable state. Rather than trying to
1576 # terminal is left in an unusable state. Rather than trying to
1574 # check everytime for this (by requesting and comparing termios
1577 # check everytime for this (by requesting and comparing termios
1575 # flags each time), we just save the initial terminal state and
1578 # flags each time), we just save the initial terminal state and
1576 # unconditionally reset it every time. It's cheaper than making
1579 # unconditionally reset it every time. It's cheaper than making
1577 # the checks.
1580 # the checks.
1578 term_flags = termios.tcgetattr(sys.stdout)
1581 term_flags = termios.tcgetattr(sys.stdout)
1579 scr = curses.initscr()
1582 scr = curses.initscr()
1580 screen_lines_real,screen_cols = scr.getmaxyx()
1583 screen_lines_real,screen_cols = scr.getmaxyx()
1581 curses.endwin()
1584 curses.endwin()
1582 # Restore terminal state in case endwin() didn't.
1585 # Restore terminal state in case endwin() didn't.
1583 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1586 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1584 # Now we have what we needed: the screen size in rows/columns
1587 # Now we have what we needed: the screen size in rows/columns
1585 screen_lines += screen_lines_real
1588 screen_lines += screen_lines_real
1586 #print '***Screen size:',screen_lines_real,'lines x',\
1589 #print '***Screen size:',screen_lines_real,'lines x',\
1587 #screen_cols,'columns.' # dbg
1590 #screen_cols,'columns.' # dbg
1588 else:
1591 else:
1589 screen_lines += screen_lines_def
1592 screen_lines += screen_lines_def
1590
1593
1591 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1594 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1592 if numlines <= screen_lines :
1595 if numlines <= screen_lines :
1593 #print '*** normal print' # dbg
1596 #print '*** normal print' # dbg
1594 print >>Term.cout, str_toprint
1597 print >>Term.cout, str_toprint
1595 else:
1598 else:
1596 # Try to open pager and default to internal one if that fails.
1599 # Try to open pager and default to internal one if that fails.
1597 # All failure modes are tagged as 'retval=1', to match the return
1600 # All failure modes are tagged as 'retval=1', to match the return
1598 # value of a failed system command. If any intermediate attempt
1601 # value of a failed system command. If any intermediate attempt
1599 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1602 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1600 pager_cmd = get_pager_cmd(pager_cmd)
1603 pager_cmd = get_pager_cmd(pager_cmd)
1601 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1604 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1602 if os.name == 'nt':
1605 if os.name == 'nt':
1603 if pager_cmd.startswith('type'):
1606 if pager_cmd.startswith('type'):
1604 # The default WinXP 'type' command is failing on complex strings.
1607 # The default WinXP 'type' command is failing on complex strings.
1605 retval = 1
1608 retval = 1
1606 else:
1609 else:
1607 tmpname = tempfile.mktemp('.txt')
1610 tmpname = tempfile.mktemp('.txt')
1608 tmpfile = file(tmpname,'wt')
1611 tmpfile = file(tmpname,'wt')
1609 tmpfile.write(strng)
1612 tmpfile.write(strng)
1610 tmpfile.close()
1613 tmpfile.close()
1611 cmd = "%s < %s" % (pager_cmd,tmpname)
1614 cmd = "%s < %s" % (pager_cmd,tmpname)
1612 if os.system(cmd):
1615 if os.system(cmd):
1613 retval = 1
1616 retval = 1
1614 else:
1617 else:
1615 retval = None
1618 retval = None
1616 os.remove(tmpname)
1619 os.remove(tmpname)
1617 else:
1620 else:
1618 try:
1621 try:
1619 retval = None
1622 retval = None
1620 # if I use popen4, things hang. No idea why.
1623 # if I use popen4, things hang. No idea why.
1621 #pager,shell_out = os.popen4(pager_cmd)
1624 #pager,shell_out = os.popen4(pager_cmd)
1622 pager = os.popen(pager_cmd,'w')
1625 pager = os.popen(pager_cmd,'w')
1623 pager.write(strng)
1626 pager.write(strng)
1624 pager.close()
1627 pager.close()
1625 retval = pager.close() # success returns None
1628 retval = pager.close() # success returns None
1626 except IOError,msg: # broken pipe when user quits
1629 except IOError,msg: # broken pipe when user quits
1627 if msg.args == (32,'Broken pipe'):
1630 if msg.args == (32,'Broken pipe'):
1628 retval = None
1631 retval = None
1629 else:
1632 else:
1630 retval = 1
1633 retval = 1
1631 except OSError:
1634 except OSError:
1632 # Other strange problems, sometimes seen in Win2k/cygwin
1635 # Other strange problems, sometimes seen in Win2k/cygwin
1633 retval = 1
1636 retval = 1
1634 if retval is not None:
1637 if retval is not None:
1635 page_dumb(strng,screen_lines=screen_lines)
1638 page_dumb(strng,screen_lines=screen_lines)
1636
1639
1637 #----------------------------------------------------------------------------
1640 #----------------------------------------------------------------------------
1638 def page_file(fname,start = 0, pager_cmd = None):
1641 def page_file(fname,start = 0, pager_cmd = None):
1639 """Page a file, using an optional pager command and starting line.
1642 """Page a file, using an optional pager command and starting line.
1640 """
1643 """
1641
1644
1642 pager_cmd = get_pager_cmd(pager_cmd)
1645 pager_cmd = get_pager_cmd(pager_cmd)
1643 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1646 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1644
1647
1645 try:
1648 try:
1646 if os.environ['TERM'] in ['emacs','dumb']:
1649 if os.environ['TERM'] in ['emacs','dumb']:
1647 raise EnvironmentError
1650 raise EnvironmentError
1648 xsys(pager_cmd + ' ' + fname)
1651 xsys(pager_cmd + ' ' + fname)
1649 except:
1652 except:
1650 try:
1653 try:
1651 if start > 0:
1654 if start > 0:
1652 start -= 1
1655 start -= 1
1653 page(open(fname).read(),start)
1656 page(open(fname).read(),start)
1654 except:
1657 except:
1655 print 'Unable to show file',`fname`
1658 print 'Unable to show file',`fname`
1656
1659
1657
1660
1658 #----------------------------------------------------------------------------
1661 #----------------------------------------------------------------------------
1659 def snip_print(str,width = 75,print_full = 0,header = ''):
1662 def snip_print(str,width = 75,print_full = 0,header = ''):
1660 """Print a string snipping the midsection to fit in width.
1663 """Print a string snipping the midsection to fit in width.
1661
1664
1662 print_full: mode control:
1665 print_full: mode control:
1663 - 0: only snip long strings
1666 - 0: only snip long strings
1664 - 1: send to page() directly.
1667 - 1: send to page() directly.
1665 - 2: snip long strings and ask for full length viewing with page()
1668 - 2: snip long strings and ask for full length viewing with page()
1666 Return 1 if snipping was necessary, 0 otherwise."""
1669 Return 1 if snipping was necessary, 0 otherwise."""
1667
1670
1668 if print_full == 1:
1671 if print_full == 1:
1669 page(header+str)
1672 page(header+str)
1670 return 0
1673 return 0
1671
1674
1672 print header,
1675 print header,
1673 if len(str) < width:
1676 if len(str) < width:
1674 print str
1677 print str
1675 snip = 0
1678 snip = 0
1676 else:
1679 else:
1677 whalf = int((width -5)/2)
1680 whalf = int((width -5)/2)
1678 print str[:whalf] + ' <...> ' + str[-whalf:]
1681 print str[:whalf] + ' <...> ' + str[-whalf:]
1679 snip = 1
1682 snip = 1
1680 if snip and print_full == 2:
1683 if snip and print_full == 2:
1681 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1684 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1682 page(str)
1685 page(str)
1683 return snip
1686 return snip
1684
1687
1685 #****************************************************************************
1688 #****************************************************************************
1686 # lists, dicts and structures
1689 # lists, dicts and structures
1687
1690
1688 def belong(candidates,checklist):
1691 def belong(candidates,checklist):
1689 """Check whether a list of items appear in a given list of options.
1692 """Check whether a list of items appear in a given list of options.
1690
1693
1691 Returns a list of 1 and 0, one for each candidate given."""
1694 Returns a list of 1 and 0, one for each candidate given."""
1692
1695
1693 return [x in checklist for x in candidates]
1696 return [x in checklist for x in candidates]
1694
1697
1695 #----------------------------------------------------------------------------
1698 #----------------------------------------------------------------------------
1696 def uniq_stable(elems):
1699 def uniq_stable(elems):
1697 """uniq_stable(elems) -> list
1700 """uniq_stable(elems) -> list
1698
1701
1699 Return from an iterable, a list of all the unique elements in the input,
1702 Return from an iterable, a list of all the unique elements in the input,
1700 but maintaining the order in which they first appear.
1703 but maintaining the order in which they first appear.
1701
1704
1702 A naive solution to this problem which just makes a dictionary with the
1705 A naive solution to this problem which just makes a dictionary with the
1703 elements as keys fails to respect the stability condition, since
1706 elements as keys fails to respect the stability condition, since
1704 dictionaries are unsorted by nature.
1707 dictionaries are unsorted by nature.
1705
1708
1706 Note: All elements in the input must be valid dictionary keys for this
1709 Note: All elements in the input must be valid dictionary keys for this
1707 routine to work, as it internally uses a dictionary for efficiency
1710 routine to work, as it internally uses a dictionary for efficiency
1708 reasons."""
1711 reasons."""
1709
1712
1710 unique = []
1713 unique = []
1711 unique_dict = {}
1714 unique_dict = {}
1712 for nn in elems:
1715 for nn in elems:
1713 if nn not in unique_dict:
1716 if nn not in unique_dict:
1714 unique.append(nn)
1717 unique.append(nn)
1715 unique_dict[nn] = None
1718 unique_dict[nn] = None
1716 return unique
1719 return unique
1717
1720
1718 #----------------------------------------------------------------------------
1721 #----------------------------------------------------------------------------
1719 class NLprinter:
1722 class NLprinter:
1720 """Print an arbitrarily nested list, indicating index numbers.
1723 """Print an arbitrarily nested list, indicating index numbers.
1721
1724
1722 An instance of this class called nlprint is available and callable as a
1725 An instance of this class called nlprint is available and callable as a
1723 function.
1726 function.
1724
1727
1725 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1728 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1726 and using 'sep' to separate the index from the value. """
1729 and using 'sep' to separate the index from the value. """
1727
1730
1728 def __init__(self):
1731 def __init__(self):
1729 self.depth = 0
1732 self.depth = 0
1730
1733
1731 def __call__(self,lst,pos='',**kw):
1734 def __call__(self,lst,pos='',**kw):
1732 """Prints the nested list numbering levels."""
1735 """Prints the nested list numbering levels."""
1733 kw.setdefault('indent',' ')
1736 kw.setdefault('indent',' ')
1734 kw.setdefault('sep',': ')
1737 kw.setdefault('sep',': ')
1735 kw.setdefault('start',0)
1738 kw.setdefault('start',0)
1736 kw.setdefault('stop',len(lst))
1739 kw.setdefault('stop',len(lst))
1737 # we need to remove start and stop from kw so they don't propagate
1740 # we need to remove start and stop from kw so they don't propagate
1738 # into a recursive call for a nested list.
1741 # into a recursive call for a nested list.
1739 start = kw['start']; del kw['start']
1742 start = kw['start']; del kw['start']
1740 stop = kw['stop']; del kw['stop']
1743 stop = kw['stop']; del kw['stop']
1741 if self.depth == 0 and 'header' in kw.keys():
1744 if self.depth == 0 and 'header' in kw.keys():
1742 print kw['header']
1745 print kw['header']
1743
1746
1744 for idx in range(start,stop):
1747 for idx in range(start,stop):
1745 elem = lst[idx]
1748 elem = lst[idx]
1746 if type(elem)==type([]):
1749 if type(elem)==type([]):
1747 self.depth += 1
1750 self.depth += 1
1748 self.__call__(elem,itpl('$pos$idx,'),**kw)
1751 self.__call__(elem,itpl('$pos$idx,'),**kw)
1749 self.depth -= 1
1752 self.depth -= 1
1750 else:
1753 else:
1751 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1754 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1752
1755
1753 nlprint = NLprinter()
1756 nlprint = NLprinter()
1754 #----------------------------------------------------------------------------
1757 #----------------------------------------------------------------------------
1755 def all_belong(candidates,checklist):
1758 def all_belong(candidates,checklist):
1756 """Check whether a list of items ALL appear in a given list of options.
1759 """Check whether a list of items ALL appear in a given list of options.
1757
1760
1758 Returns a single 1 or 0 value."""
1761 Returns a single 1 or 0 value."""
1759
1762
1760 return 1-(0 in [x in checklist for x in candidates])
1763 return 1-(0 in [x in checklist for x in candidates])
1761
1764
1762 #----------------------------------------------------------------------------
1765 #----------------------------------------------------------------------------
1763 def sort_compare(lst1,lst2,inplace = 1):
1766 def sort_compare(lst1,lst2,inplace = 1):
1764 """Sort and compare two lists.
1767 """Sort and compare two lists.
1765
1768
1766 By default it does it in place, thus modifying the lists. Use inplace = 0
1769 By default it does it in place, thus modifying the lists. Use inplace = 0
1767 to avoid that (at the cost of temporary copy creation)."""
1770 to avoid that (at the cost of temporary copy creation)."""
1768 if not inplace:
1771 if not inplace:
1769 lst1 = lst1[:]
1772 lst1 = lst1[:]
1770 lst2 = lst2[:]
1773 lst2 = lst2[:]
1771 lst1.sort(); lst2.sort()
1774 lst1.sort(); lst2.sort()
1772 return lst1 == lst2
1775 return lst1 == lst2
1773
1776
1774 #----------------------------------------------------------------------------
1777 #----------------------------------------------------------------------------
1775 def mkdict(**kwargs):
1778 def mkdict(**kwargs):
1776 """Return a dict from a keyword list.
1779 """Return a dict from a keyword list.
1777
1780
1778 It's just syntactic sugar for making ditcionary creation more convenient:
1781 It's just syntactic sugar for making ditcionary creation more convenient:
1779 # the standard way
1782 # the standard way
1780 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1783 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1781 # a cleaner way
1784 # a cleaner way
1782 >>>data = dict(red=1, green=2, blue=3)
1785 >>>data = dict(red=1, green=2, blue=3)
1783
1786
1784 If you need more than this, look at the Struct() class."""
1787 If you need more than this, look at the Struct() class."""
1785
1788
1786 return kwargs
1789 return kwargs
1787
1790
1788 #----------------------------------------------------------------------------
1791 #----------------------------------------------------------------------------
1789 def list2dict(lst):
1792 def list2dict(lst):
1790 """Takes a list of (key,value) pairs and turns it into a dict."""
1793 """Takes a list of (key,value) pairs and turns it into a dict."""
1791
1794
1792 dic = {}
1795 dic = {}
1793 for k,v in lst: dic[k] = v
1796 for k,v in lst: dic[k] = v
1794 return dic
1797 return dic
1795
1798
1796 #----------------------------------------------------------------------------
1799 #----------------------------------------------------------------------------
1797 def list2dict2(lst,default=''):
1800 def list2dict2(lst,default=''):
1798 """Takes a list and turns it into a dict.
1801 """Takes a list and turns it into a dict.
1799 Much slower than list2dict, but more versatile. This version can take
1802 Much slower than list2dict, but more versatile. This version can take
1800 lists with sublists of arbitrary length (including sclars)."""
1803 lists with sublists of arbitrary length (including sclars)."""
1801
1804
1802 dic = {}
1805 dic = {}
1803 for elem in lst:
1806 for elem in lst:
1804 if type(elem) in (types.ListType,types.TupleType):
1807 if type(elem) in (types.ListType,types.TupleType):
1805 size = len(elem)
1808 size = len(elem)
1806 if size == 0:
1809 if size == 0:
1807 pass
1810 pass
1808 elif size == 1:
1811 elif size == 1:
1809 dic[elem] = default
1812 dic[elem] = default
1810 else:
1813 else:
1811 k,v = elem[0], elem[1:]
1814 k,v = elem[0], elem[1:]
1812 if len(v) == 1: v = v[0]
1815 if len(v) == 1: v = v[0]
1813 dic[k] = v
1816 dic[k] = v
1814 else:
1817 else:
1815 dic[elem] = default
1818 dic[elem] = default
1816 return dic
1819 return dic
1817
1820
1818 #----------------------------------------------------------------------------
1821 #----------------------------------------------------------------------------
1819 def flatten(seq):
1822 def flatten(seq):
1820 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1823 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1821
1824
1822 return [x for subseq in seq for x in subseq]
1825 return [x for subseq in seq for x in subseq]
1823
1826
1824 #----------------------------------------------------------------------------
1827 #----------------------------------------------------------------------------
1825 def get_slice(seq,start=0,stop=None,step=1):
1828 def get_slice(seq,start=0,stop=None,step=1):
1826 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1829 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1827 if stop == None:
1830 if stop == None:
1828 stop = len(seq)
1831 stop = len(seq)
1829 item = lambda i: seq[i]
1832 item = lambda i: seq[i]
1830 return map(item,xrange(start,stop,step))
1833 return map(item,xrange(start,stop,step))
1831
1834
1832 #----------------------------------------------------------------------------
1835 #----------------------------------------------------------------------------
1833 def chop(seq,size):
1836 def chop(seq,size):
1834 """Chop a sequence into chunks of the given size."""
1837 """Chop a sequence into chunks of the given size."""
1835 chunk = lambda i: seq[i:i+size]
1838 chunk = lambda i: seq[i:i+size]
1836 return map(chunk,xrange(0,len(seq),size))
1839 return map(chunk,xrange(0,len(seq),size))
1837
1840
1838 #----------------------------------------------------------------------------
1841 #----------------------------------------------------------------------------
1839 # with is a keyword as of python 2.5, so this function is renamed to withobj
1842 # with is a keyword as of python 2.5, so this function is renamed to withobj
1840 # from its old 'with' name.
1843 # from its old 'with' name.
1841 def with_obj(object, **args):
1844 def with_obj(object, **args):
1842 """Set multiple attributes for an object, similar to Pascal's with.
1845 """Set multiple attributes for an object, similar to Pascal's with.
1843
1846
1844 Example:
1847 Example:
1845 with_obj(jim,
1848 with_obj(jim,
1846 born = 1960,
1849 born = 1960,
1847 haircolour = 'Brown',
1850 haircolour = 'Brown',
1848 eyecolour = 'Green')
1851 eyecolour = 'Green')
1849
1852
1850 Credit: Greg Ewing, in
1853 Credit: Greg Ewing, in
1851 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1854 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1852
1855
1853 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1856 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1854 has become a keyword for Python 2.5, so we had to rename it."""
1857 has become a keyword for Python 2.5, so we had to rename it."""
1855
1858
1856 object.__dict__.update(args)
1859 object.__dict__.update(args)
1857
1860
1858 #----------------------------------------------------------------------------
1861 #----------------------------------------------------------------------------
1859 def setattr_list(obj,alist,nspace = None):
1862 def setattr_list(obj,alist,nspace = None):
1860 """Set a list of attributes for an object taken from a namespace.
1863 """Set a list of attributes for an object taken from a namespace.
1861
1864
1862 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1865 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1863 alist with their values taken from nspace, which must be a dict (something
1866 alist with their values taken from nspace, which must be a dict (something
1864 like locals() will often do) If nspace isn't given, locals() of the
1867 like locals() will often do) If nspace isn't given, locals() of the
1865 *caller* is used, so in most cases you can omit it.
1868 *caller* is used, so in most cases you can omit it.
1866
1869
1867 Note that alist can be given as a string, which will be automatically
1870 Note that alist can be given as a string, which will be automatically
1868 split into a list on whitespace. If given as a list, it must be a list of
1871 split into a list on whitespace. If given as a list, it must be a list of
1869 *strings* (the variable names themselves), not of variables."""
1872 *strings* (the variable names themselves), not of variables."""
1870
1873
1871 # this grabs the local variables from the *previous* call frame -- that is
1874 # this grabs the local variables from the *previous* call frame -- that is
1872 # the locals from the function that called setattr_list().
1875 # the locals from the function that called setattr_list().
1873 # - snipped from weave.inline()
1876 # - snipped from weave.inline()
1874 if nspace is None:
1877 if nspace is None:
1875 call_frame = sys._getframe().f_back
1878 call_frame = sys._getframe().f_back
1876 nspace = call_frame.f_locals
1879 nspace = call_frame.f_locals
1877
1880
1878 if type(alist) in StringTypes:
1881 if type(alist) in StringTypes:
1879 alist = alist.split()
1882 alist = alist.split()
1880 for attr in alist:
1883 for attr in alist:
1881 val = eval(attr,nspace)
1884 val = eval(attr,nspace)
1882 setattr(obj,attr,val)
1885 setattr(obj,attr,val)
1883
1886
1884 #----------------------------------------------------------------------------
1887 #----------------------------------------------------------------------------
1885 def getattr_list(obj,alist,*args):
1888 def getattr_list(obj,alist,*args):
1886 """getattr_list(obj,alist[, default]) -> attribute list.
1889 """getattr_list(obj,alist[, default]) -> attribute list.
1887
1890
1888 Get a list of named attributes for an object. When a default argument is
1891 Get a list of named attributes for an object. When a default argument is
1889 given, it is returned when the attribute doesn't exist; without it, an
1892 given, it is returned when the attribute doesn't exist; without it, an
1890 exception is raised in that case.
1893 exception is raised in that case.
1891
1894
1892 Note that alist can be given as a string, which will be automatically
1895 Note that alist can be given as a string, which will be automatically
1893 split into a list on whitespace. If given as a list, it must be a list of
1896 split into a list on whitespace. If given as a list, it must be a list of
1894 *strings* (the variable names themselves), not of variables."""
1897 *strings* (the variable names themselves), not of variables."""
1895
1898
1896 if type(alist) in StringTypes:
1899 if type(alist) in StringTypes:
1897 alist = alist.split()
1900 alist = alist.split()
1898 if args:
1901 if args:
1899 if len(args)==1:
1902 if len(args)==1:
1900 default = args[0]
1903 default = args[0]
1901 return map(lambda attr: getattr(obj,attr,default),alist)
1904 return map(lambda attr: getattr(obj,attr,default),alist)
1902 else:
1905 else:
1903 raise ValueError,'getattr_list() takes only one optional argument'
1906 raise ValueError,'getattr_list() takes only one optional argument'
1904 else:
1907 else:
1905 return map(lambda attr: getattr(obj,attr),alist)
1908 return map(lambda attr: getattr(obj,attr),alist)
1906
1909
1907 #----------------------------------------------------------------------------
1910 #----------------------------------------------------------------------------
1908 def map_method(method,object_list,*argseq,**kw):
1911 def map_method(method,object_list,*argseq,**kw):
1909 """map_method(method,object_list,*args,**kw) -> list
1912 """map_method(method,object_list,*args,**kw) -> list
1910
1913
1911 Return a list of the results of applying the methods to the items of the
1914 Return a list of the results of applying the methods to the items of the
1912 argument sequence(s). If more than one sequence is given, the method is
1915 argument sequence(s). If more than one sequence is given, the method is
1913 called with an argument list consisting of the corresponding item of each
1916 called with an argument list consisting of the corresponding item of each
1914 sequence. All sequences must be of the same length.
1917 sequence. All sequences must be of the same length.
1915
1918
1916 Keyword arguments are passed verbatim to all objects called.
1919 Keyword arguments are passed verbatim to all objects called.
1917
1920
1918 This is Python code, so it's not nearly as fast as the builtin map()."""
1921 This is Python code, so it's not nearly as fast as the builtin map()."""
1919
1922
1920 out_list = []
1923 out_list = []
1921 idx = 0
1924 idx = 0
1922 for object in object_list:
1925 for object in object_list:
1923 try:
1926 try:
1924 handler = getattr(object, method)
1927 handler = getattr(object, method)
1925 except AttributeError:
1928 except AttributeError:
1926 out_list.append(None)
1929 out_list.append(None)
1927 else:
1930 else:
1928 if argseq:
1931 if argseq:
1929 args = map(lambda lst:lst[idx],argseq)
1932 args = map(lambda lst:lst[idx],argseq)
1930 #print 'ob',object,'hand',handler,'ar',args # dbg
1933 #print 'ob',object,'hand',handler,'ar',args # dbg
1931 out_list.append(handler(args,**kw))
1934 out_list.append(handler(args,**kw))
1932 else:
1935 else:
1933 out_list.append(handler(**kw))
1936 out_list.append(handler(**kw))
1934 idx += 1
1937 idx += 1
1935 return out_list
1938 return out_list
1936
1939
1937 #----------------------------------------------------------------------------
1940 #----------------------------------------------------------------------------
1938 def get_class_members(cls):
1941 def get_class_members(cls):
1939 ret = dir(cls)
1942 ret = dir(cls)
1940 if hasattr(cls,'__bases__'):
1943 if hasattr(cls,'__bases__'):
1941 for base in cls.__bases__:
1944 for base in cls.__bases__:
1942 ret.extend(get_class_members(base))
1945 ret.extend(get_class_members(base))
1943 return ret
1946 return ret
1944
1947
1945 #----------------------------------------------------------------------------
1948 #----------------------------------------------------------------------------
1946 def dir2(obj):
1949 def dir2(obj):
1947 """dir2(obj) -> list of strings
1950 """dir2(obj) -> list of strings
1948
1951
1949 Extended version of the Python builtin dir(), which does a few extra
1952 Extended version of the Python builtin dir(), which does a few extra
1950 checks, and supports common objects with unusual internals that confuse
1953 checks, and supports common objects with unusual internals that confuse
1951 dir(), such as Traits and PyCrust.
1954 dir(), such as Traits and PyCrust.
1952
1955
1953 This version is guaranteed to return only a list of true strings, whereas
1956 This version is guaranteed to return only a list of true strings, whereas
1954 dir() returns anything that objects inject into themselves, even if they
1957 dir() returns anything that objects inject into themselves, even if they
1955 are later not really valid for attribute access (many extension libraries
1958 are later not really valid for attribute access (many extension libraries
1956 have such bugs).
1959 have such bugs).
1957 """
1960 """
1958
1961
1959 # Start building the attribute list via dir(), and then complete it
1962 # Start building the attribute list via dir(), and then complete it
1960 # with a few extra special-purpose calls.
1963 # with a few extra special-purpose calls.
1961 words = dir(obj)
1964 words = dir(obj)
1962
1965
1963 if hasattr(obj,'__class__'):
1966 if hasattr(obj,'__class__'):
1964 words.append('__class__')
1967 words.append('__class__')
1965 words.extend(get_class_members(obj.__class__))
1968 words.extend(get_class_members(obj.__class__))
1966 #if '__base__' in words: 1/0
1969 #if '__base__' in words: 1/0
1967
1970
1968 # Some libraries (such as traits) may introduce duplicates, we want to
1971 # Some libraries (such as traits) may introduce duplicates, we want to
1969 # track and clean this up if it happens
1972 # track and clean this up if it happens
1970 may_have_dupes = False
1973 may_have_dupes = False
1971
1974
1972 # this is the 'dir' function for objects with Enthought's traits
1975 # this is the 'dir' function for objects with Enthought's traits
1973 if hasattr(obj, 'trait_names'):
1976 if hasattr(obj, 'trait_names'):
1974 try:
1977 try:
1975 words.extend(obj.trait_names())
1978 words.extend(obj.trait_names())
1976 may_have_dupes = True
1979 may_have_dupes = True
1977 except TypeError:
1980 except TypeError:
1978 # This will happen if `obj` is a class and not an instance.
1981 # This will happen if `obj` is a class and not an instance.
1979 pass
1982 pass
1980
1983
1981 # Support for PyCrust-style _getAttributeNames magic method.
1984 # Support for PyCrust-style _getAttributeNames magic method.
1982 if hasattr(obj, '_getAttributeNames'):
1985 if hasattr(obj, '_getAttributeNames'):
1983 try:
1986 try:
1984 words.extend(obj._getAttributeNames())
1987 words.extend(obj._getAttributeNames())
1985 may_have_dupes = True
1988 may_have_dupes = True
1986 except TypeError:
1989 except TypeError:
1987 # `obj` is a class and not an instance. Ignore
1990 # `obj` is a class and not an instance. Ignore
1988 # this error.
1991 # this error.
1989 pass
1992 pass
1990
1993
1991 if may_have_dupes:
1994 if may_have_dupes:
1992 # eliminate possible duplicates, as some traits may also
1995 # eliminate possible duplicates, as some traits may also
1993 # appear as normal attributes in the dir() call.
1996 # appear as normal attributes in the dir() call.
1994 words = list(set(words))
1997 words = list(set(words))
1995 words.sort()
1998 words.sort()
1996
1999
1997 # filter out non-string attributes which may be stuffed by dir() calls
2000 # filter out non-string attributes which may be stuffed by dir() calls
1998 # and poor coding in third-party modules
2001 # and poor coding in third-party modules
1999 return [w for w in words if isinstance(w, basestring)]
2002 return [w for w in words if isinstance(w, basestring)]
2000
2003
2001 #----------------------------------------------------------------------------
2004 #----------------------------------------------------------------------------
2002 def import_fail_info(mod_name,fns=None):
2005 def import_fail_info(mod_name,fns=None):
2003 """Inform load failure for a module."""
2006 """Inform load failure for a module."""
2004
2007
2005 if fns == None:
2008 if fns == None:
2006 warn("Loading of %s failed.\n" % (mod_name,))
2009 warn("Loading of %s failed.\n" % (mod_name,))
2007 else:
2010 else:
2008 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2011 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2009
2012
2010 #----------------------------------------------------------------------------
2013 #----------------------------------------------------------------------------
2011 # Proposed popitem() extension, written as a method
2014 # Proposed popitem() extension, written as a method
2012
2015
2013
2016
2014 class NotGiven: pass
2017 class NotGiven: pass
2015
2018
2016 def popkey(dct,key,default=NotGiven):
2019 def popkey(dct,key,default=NotGiven):
2017 """Return dct[key] and delete dct[key].
2020 """Return dct[key] and delete dct[key].
2018
2021
2019 If default is given, return it if dct[key] doesn't exist, otherwise raise
2022 If default is given, return it if dct[key] doesn't exist, otherwise raise
2020 KeyError. """
2023 KeyError. """
2021
2024
2022 try:
2025 try:
2023 val = dct[key]
2026 val = dct[key]
2024 except KeyError:
2027 except KeyError:
2025 if default is NotGiven:
2028 if default is NotGiven:
2026 raise
2029 raise
2027 else:
2030 else:
2028 return default
2031 return default
2029 else:
2032 else:
2030 del dct[key]
2033 del dct[key]
2031 return val
2034 return val
2032
2035
2033 def wrap_deprecated(func, suggest = '<nothing>'):
2036 def wrap_deprecated(func, suggest = '<nothing>'):
2034 def newFunc(*args, **kwargs):
2037 def newFunc(*args, **kwargs):
2035 warnings.warn("Call to deprecated function %s, use %s instead" %
2038 warnings.warn("Call to deprecated function %s, use %s instead" %
2036 ( func.__name__, suggest),
2039 ( func.__name__, suggest),
2037 category=DeprecationWarning,
2040 category=DeprecationWarning,
2038 stacklevel = 2)
2041 stacklevel = 2)
2039 return func(*args, **kwargs)
2042 return func(*args, **kwargs)
2040 return newFunc
2043 return newFunc
2041
2044
2042 #*************************** end of file <genutils.py> **********************
2045 #*************************** end of file <genutils.py> **********************
2043
2046
General Comments 0
You need to be logged in to leave comments. Login now