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

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

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