##// END OF EJS Templates
Fixing two bugs in the handling of paths and profiles....
Brian Granger -
Show More
@@ -1,330 +1,336 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """A simple configuration system.
3 """A simple configuration system.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2009 The IPython Development Team
11 # Copyright (C) 2008-2009 The IPython Development Team
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 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import __builtin__
21 import __builtin__
22 import os
22 import os
23 import sys
23 import sys
24
24
25 from IPython.external import argparse
25 from IPython.external import argparse
26 from IPython.utils.genutils import filefind
26 from IPython.utils.genutils import filefind
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Exceptions
29 # Exceptions
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32
32
33 class ConfigError(Exception):
33 class ConfigError(Exception):
34 pass
34 pass
35
35
36
36
37 class ConfigLoaderError(ConfigError):
37 class ConfigLoaderError(ConfigError):
38 pass
38 pass
39
39
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Config class for holding config information
42 # Config class for holding config information
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45
45
46 class Config(dict):
46 class Config(dict):
47 """An attribute based dict that can do smart merges."""
47 """An attribute based dict that can do smart merges."""
48
48
49 def __init__(self, *args, **kwds):
49 def __init__(self, *args, **kwds):
50 dict.__init__(self, *args, **kwds)
50 dict.__init__(self, *args, **kwds)
51 # This sets self.__dict__ = self, but it has to be done this way
51 # This sets self.__dict__ = self, but it has to be done this way
52 # because we are also overriding __setattr__.
52 # because we are also overriding __setattr__.
53 dict.__setattr__(self, '__dict__', self)
53 dict.__setattr__(self, '__dict__', self)
54
54
55 def _merge(self, other):
55 def _merge(self, other):
56 to_update = {}
56 to_update = {}
57 for k, v in other.items():
57 for k, v in other.items():
58 if not self.has_key(k):
58 if not self.has_key(k):
59 to_update[k] = v
59 to_update[k] = v
60 else: # I have this key
60 else: # I have this key
61 if isinstance(v, Config):
61 if isinstance(v, Config):
62 # Recursively merge common sub Configs
62 # Recursively merge common sub Configs
63 self[k]._merge(v)
63 self[k]._merge(v)
64 else:
64 else:
65 # Plain updates for non-Configs
65 # Plain updates for non-Configs
66 to_update[k] = v
66 to_update[k] = v
67
67
68 self.update(to_update)
68 self.update(to_update)
69
69
70 def _is_section_key(self, key):
70 def _is_section_key(self, key):
71 if key[0].upper()==key[0] and not key.startswith('_'):
71 if key[0].upper()==key[0] and not key.startswith('_'):
72 return True
72 return True
73 else:
73 else:
74 return False
74 return False
75
75
76 def has_key(self, key):
76 def has_key(self, key):
77 if self._is_section_key(key):
77 if self._is_section_key(key):
78 return True
78 return True
79 else:
79 else:
80 return dict.has_key(self, key)
80 return dict.has_key(self, key)
81
81
82 def _has_section(self, key):
82 def _has_section(self, key):
83 if self._is_section_key(key):
83 if self._is_section_key(key):
84 if dict.has_key(self, key):
84 if dict.has_key(self, key):
85 return True
85 return True
86 return False
86 return False
87
87
88 def copy(self):
88 def copy(self):
89 return type(self)(dict.copy(self))
89 return type(self)(dict.copy(self))
90
90
91 def __copy__(self):
91 def __copy__(self):
92 return self.copy()
92 return self.copy()
93
93
94 def __deepcopy__(self, memo):
94 def __deepcopy__(self, memo):
95 import copy
95 import copy
96 return type(self)(copy.deepcopy(self.items()))
96 return type(self)(copy.deepcopy(self.items()))
97
97
98 def __getitem__(self, key):
98 def __getitem__(self, key):
99 # Because we use this for an exec namespace, we need to delegate
99 # Because we use this for an exec namespace, we need to delegate
100 # the lookup of names in __builtin__ to itself. This means
100 # the lookup of names in __builtin__ to itself. This means
101 # that you can't have section or attribute names that are
101 # that you can't have section or attribute names that are
102 # builtins.
102 # builtins.
103 try:
103 try:
104 return getattr(__builtin__, key)
104 return getattr(__builtin__, key)
105 except AttributeError:
105 except AttributeError:
106 pass
106 pass
107 if self._is_section_key(key):
107 if self._is_section_key(key):
108 try:
108 try:
109 return dict.__getitem__(self, key)
109 return dict.__getitem__(self, key)
110 except KeyError:
110 except KeyError:
111 c = Config()
111 c = Config()
112 dict.__setitem__(self, key, c)
112 dict.__setitem__(self, key, c)
113 return c
113 return c
114 else:
114 else:
115 return dict.__getitem__(self, key)
115 return dict.__getitem__(self, key)
116
116
117 def __setitem__(self, key, value):
117 def __setitem__(self, key, value):
118 # Don't allow names in __builtin__ to be modified.
118 # Don't allow names in __builtin__ to be modified.
119 if hasattr(__builtin__, key):
119 if hasattr(__builtin__, key):
120 raise ConfigError('Config variable names cannot have the same name '
120 raise ConfigError('Config variable names cannot have the same name '
121 'as a Python builtin: %s' % key)
121 'as a Python builtin: %s' % key)
122 if self._is_section_key(key):
122 if self._is_section_key(key):
123 if not isinstance(value, Config):
123 if not isinstance(value, Config):
124 raise ValueError('values whose keys begin with an uppercase '
124 raise ValueError('values whose keys begin with an uppercase '
125 'char must be Config instances: %r, %r' % (key, value))
125 'char must be Config instances: %r, %r' % (key, value))
126 else:
126 else:
127 dict.__setitem__(self, key, value)
127 dict.__setitem__(self, key, value)
128
128
129 def __getattr__(self, key):
129 def __getattr__(self, key):
130 try:
130 try:
131 return self.__getitem__(key)
131 return self.__getitem__(key)
132 except KeyError, e:
132 except KeyError, e:
133 raise AttributeError(e)
133 raise AttributeError(e)
134
134
135 def __setattr__(self, key, value):
135 def __setattr__(self, key, value):
136 try:
136 try:
137 self.__setitem__(key, value)
137 self.__setitem__(key, value)
138 except KeyError, e:
138 except KeyError, e:
139 raise AttributeError(e)
139 raise AttributeError(e)
140
140
141 def __delattr__(self, key):
141 def __delattr__(self, key):
142 try:
142 try:
143 dict.__delitem__(self, key)
143 dict.__delitem__(self, key)
144 except KeyError, e:
144 except KeyError, e:
145 raise AttributeError(e)
145 raise AttributeError(e)
146
146
147
147
148 #-----------------------------------------------------------------------------
148 #-----------------------------------------------------------------------------
149 # Config loading classes
149 # Config loading classes
150 #-----------------------------------------------------------------------------
150 #-----------------------------------------------------------------------------
151
151
152
152
153 class ConfigLoader(object):
153 class ConfigLoader(object):
154 """A object for loading configurations from just about anywhere.
154 """A object for loading configurations from just about anywhere.
155
155
156 The resulting configuration is packaged as a :class:`Struct`.
156 The resulting configuration is packaged as a :class:`Struct`.
157
157
158 Notes
158 Notes
159 -----
159 -----
160 A :class:`ConfigLoader` does one thing: load a config from a source
160 A :class:`ConfigLoader` does one thing: load a config from a source
161 (file, command line arguments) and returns the data as a :class:`Struct`.
161 (file, command line arguments) and returns the data as a :class:`Struct`.
162 There are lots of things that :class:`ConfigLoader` does not do. It does
162 There are lots of things that :class:`ConfigLoader` does not do. It does
163 not implement complex logic for finding config files. It does not handle
163 not implement complex logic for finding config files. It does not handle
164 default values or merge multiple configs. These things need to be
164 default values or merge multiple configs. These things need to be
165 handled elsewhere.
165 handled elsewhere.
166 """
166 """
167
167
168 def __init__(self):
168 def __init__(self):
169 """A base class for config loaders.
169 """A base class for config loaders.
170
170
171 Examples
171 Examples
172 --------
172 --------
173
173
174 >>> cl = ConfigLoader()
174 >>> cl = ConfigLoader()
175 >>> config = cl.load_config()
175 >>> config = cl.load_config()
176 >>> config
176 >>> config
177 {}
177 {}
178 """
178 """
179 self.clear()
179 self.clear()
180
180
181 def clear(self):
181 def clear(self):
182 self.config = Config()
182 self.config = Config()
183
183
184 def load_config(self):
184 def load_config(self):
185 """Load a config from somewhere, return a Struct.
185 """Load a config from somewhere, return a Struct.
186
186
187 Usually, this will cause self.config to be set and then returned.
187 Usually, this will cause self.config to be set and then returned.
188 """
188 """
189 return self.config
189 return self.config
190
190
191
191
192 class FileConfigLoader(ConfigLoader):
192 class FileConfigLoader(ConfigLoader):
193 """A base class for file based configurations.
193 """A base class for file based configurations.
194
194
195 As we add more file based config loaders, the common logic should go
195 As we add more file based config loaders, the common logic should go
196 here.
196 here.
197 """
197 """
198 pass
198 pass
199
199
200
200
201 class PyFileConfigLoader(FileConfigLoader):
201 class PyFileConfigLoader(FileConfigLoader):
202 """A config loader for pure python files.
202 """A config loader for pure python files.
203
203
204 This calls execfile on a plain python file and looks for attributes
204 This calls execfile on a plain python file and looks for attributes
205 that are all caps. These attribute are added to the config Struct.
205 that are all caps. These attribute are added to the config Struct.
206 """
206 """
207
207
208 def __init__(self, filename, path=None):
208 def __init__(self, filename, path=None):
209 """Build a config loader for a filename and path.
209 """Build a config loader for a filename and path.
210
210
211 Parameters
211 Parameters
212 ----------
212 ----------
213 filename : str
213 filename : str
214 The file name of the config file.
214 The file name of the config file.
215 path : str, list, tuple
215 path : str, list, tuple
216 The path to search for the config file on, or a sequence of
216 The path to search for the config file on, or a sequence of
217 paths to try in order.
217 paths to try in order.
218 """
218 """
219 super(PyFileConfigLoader, self).__init__()
219 super(PyFileConfigLoader, self).__init__()
220 self.filename = filename
220 self.filename = filename
221 self.path = path
221 self.path = path
222 self.full_filename = ''
222 self.full_filename = ''
223 self.data = None
223 self.data = None
224
224
225 def load_config(self):
225 def load_config(self):
226 """Load the config from a file and return it as a Struct."""
226 """Load the config from a file and return it as a Struct."""
227 self._find_file()
227 self._find_file()
228 self._read_file_as_dict()
228 self._read_file_as_dict()
229 self._convert_to_config()
229 self._convert_to_config()
230 return self.config
230 return self.config
231
231
232 def _find_file(self):
232 def _find_file(self):
233 """Try to find the file by searching the paths."""
233 """Try to find the file by searching the paths."""
234 self.full_filename = filefind(self.filename, self.path)
234 self.full_filename = filefind(self.filename, self.path)
235
235
236 def _read_file_as_dict(self):
236 def _read_file_as_dict(self):
237 """Load the config file into self.config, with recursive loading."""
237 """Load the config file into self.config, with recursive loading."""
238 # This closure is made available in the namespace that is used
238 # This closure is made available in the namespace that is used
239 # to exec the config file. This allows users to call
239 # to exec the config file. This allows users to call
240 # load_subconfig('myconfig.py') to load config files recursively.
240 # load_subconfig('myconfig.py') to load config files recursively.
241 # It needs to be a closure because it has references to self.path
241 # It needs to be a closure because it has references to self.path
242 # and self.config. The sub-config is loaded with the same path
242 # and self.config. The sub-config is loaded with the same path
243 # as the parent, but it uses an empty config which is then merged
243 # as the parent, but it uses an empty config which is then merged
244 # with the parents.
244 # with the parents.
245 def load_subconfig(fname):
245 def load_subconfig(fname):
246 loader = PyFileConfigLoader(fname, self.path)
246 loader = PyFileConfigLoader(fname, self.path)
247 sub_config = loader.load_config()
247 try:
248 self.config._merge(sub_config)
248 sub_config = loader.load_config()
249 except IOError:
250 # Pass silently if the sub config is not there. This happens
251 # when a user us using a profile, but not the default config.
252 pass
253 else:
254 self.config._merge(sub_config)
249
255
250 # Again, this needs to be a closure and should be used in config
256 # Again, this needs to be a closure and should be used in config
251 # files to get the config being loaded.
257 # files to get the config being loaded.
252 def get_config():
258 def get_config():
253 return self.config
259 return self.config
254
260
255 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
261 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
256 execfile(self.full_filename, namespace)
262 execfile(self.full_filename, namespace)
257
263
258 def _convert_to_config(self):
264 def _convert_to_config(self):
259 if self.data is None:
265 if self.data is None:
260 ConfigLoaderError('self.data does not exist')
266 ConfigLoaderError('self.data does not exist')
261
267
262
268
263 class CommandLineConfigLoader(ConfigLoader):
269 class CommandLineConfigLoader(ConfigLoader):
264 """A config loader for command line arguments.
270 """A config loader for command line arguments.
265
271
266 As we add more command line based loaders, the common logic should go
272 As we add more command line based loaders, the common logic should go
267 here.
273 here.
268 """
274 """
269
275
270
276
271 class NoConfigDefault(object): pass
277 class NoConfigDefault(object): pass
272 NoConfigDefault = NoConfigDefault()
278 NoConfigDefault = NoConfigDefault()
273
279
274
280
275 class ArgParseConfigLoader(CommandLineConfigLoader):
281 class ArgParseConfigLoader(CommandLineConfigLoader):
276
282
277 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
283 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
278 arguments = ()
284 arguments = ()
279
285
280 def __init__(self, *args, **kw):
286 def __init__(self, *args, **kw):
281 """Create a config loader for use with argparse.
287 """Create a config loader for use with argparse.
282
288
283 The args and kwargs arguments here are passed onto the constructor
289 The args and kwargs arguments here are passed onto the constructor
284 of :class:`argparse.ArgumentParser`.
290 of :class:`argparse.ArgumentParser`.
285 """
291 """
286 super(CommandLineConfigLoader, self).__init__()
292 super(CommandLineConfigLoader, self).__init__()
287 self.args = args
293 self.args = args
288 self.kw = kw
294 self.kw = kw
289
295
290 def load_config(self, args=None):
296 def load_config(self, args=None):
291 """Parse command line arguments and return as a Struct."""
297 """Parse command line arguments and return as a Struct."""
292 self._create_parser()
298 self._create_parser()
293 self._parse_args(args)
299 self._parse_args(args)
294 self._convert_to_config()
300 self._convert_to_config()
295 return self.config
301 return self.config
296
302
297 def get_extra_args(self):
303 def get_extra_args(self):
298 if hasattr(self, 'extra_args'):
304 if hasattr(self, 'extra_args'):
299 return self.extra_args
305 return self.extra_args
300 else:
306 else:
301 return []
307 return []
302
308
303 def _create_parser(self):
309 def _create_parser(self):
304 self.parser = argparse.ArgumentParser(*self.args, **self.kw)
310 self.parser = argparse.ArgumentParser(*self.args, **self.kw)
305 self._add_arguments()
311 self._add_arguments()
306 self._add_other_arguments()
312 self._add_other_arguments()
307
313
308 def _add_other_arguments(self):
314 def _add_other_arguments(self):
309 pass
315 pass
310
316
311 def _add_arguments(self):
317 def _add_arguments(self):
312 for argument in self.arguments:
318 for argument in self.arguments:
313 if not argument[1].has_key('default'):
319 if not argument[1].has_key('default'):
314 argument[1]['default'] = NoConfigDefault
320 argument[1]['default'] = NoConfigDefault
315 self.parser.add_argument(*argument[0],**argument[1])
321 self.parser.add_argument(*argument[0],**argument[1])
316
322
317 def _parse_args(self, args=None):
323 def _parse_args(self, args=None):
318 """self.parser->self.parsed_data"""
324 """self.parser->self.parsed_data"""
319 if args is None:
325 if args is None:
320 self.parsed_data, self.extra_args = self.parser.parse_known_args()
326 self.parsed_data, self.extra_args = self.parser.parse_known_args()
321 else:
327 else:
322 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
328 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
323
329
324 def _convert_to_config(self):
330 def _convert_to_config(self):
325 """self.parsed_data->self.config"""
331 """self.parsed_data->self.config"""
326 for k, v in vars(self.parsed_data).items():
332 for k, v in vars(self.parsed_data).items():
327 if v is not NoConfigDefault:
333 if v is not NoConfigDefault:
328 exec_str = 'self.config.' + k + '= v'
334 exec_str = 'self.config.' + k + '= v'
329 exec exec_str in locals(), globals()
335 exec exec_str in locals(), globals()
330
336
@@ -1,1806 +1,1806 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """General purpose utilities.
2 """General purpose utilities.
3
3
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 these things are also convenient when working at the command line.
5 these things are also convenient when working at the command line.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14
14
15 #****************************************************************************
15 #****************************************************************************
16 # required modules from the Python standard library
16 # required modules from the Python standard library
17 import __main__
17 import __main__
18
18
19 import os
19 import os
20 import platform
20 import platform
21 import re
21 import re
22 import shlex
22 import shlex
23 import shutil
23 import shutil
24 import subprocess
24 import subprocess
25 import sys
25 import sys
26 import time
26 import time
27 import types
27 import types
28 import warnings
28 import warnings
29
29
30 # Curses and termios are Unix-only modules
30 # Curses and termios are Unix-only modules
31 try:
31 try:
32 import curses
32 import curses
33 # We need termios as well, so if its import happens to raise, we bail on
33 # We need termios as well, so if its import happens to raise, we bail on
34 # using curses altogether.
34 # using curses altogether.
35 import termios
35 import termios
36 except ImportError:
36 except ImportError:
37 USE_CURSES = False
37 USE_CURSES = False
38 else:
38 else:
39 # Curses on Solaris may not be complete, so we can't use it there
39 # Curses on Solaris may not be complete, so we can't use it there
40 USE_CURSES = hasattr(curses,'initscr')
40 USE_CURSES = hasattr(curses,'initscr')
41
41
42 # Other IPython utilities
42 # Other IPython utilities
43 import IPython
43 import IPython
44 from IPython.external.Itpl import itpl,printpl
44 from IPython.external.Itpl import itpl,printpl
45 from IPython.utils import platutils
45 from IPython.utils import platutils
46 from IPython.utils.generics import result_display
46 from IPython.utils.generics import result_display
47 from IPython.external.path import path
47 from IPython.external.path import path
48
48
49 try:
49 try:
50 set
50 set
51 except:
51 except:
52 from sets import Set as set
52 from sets import Set as set
53
53
54
54
55 #****************************************************************************
55 #****************************************************************************
56 # Exceptions
56 # Exceptions
57 class Error(Exception):
57 class Error(Exception):
58 """Base class for exceptions in this module."""
58 """Base class for exceptions in this module."""
59 pass
59 pass
60
60
61 #----------------------------------------------------------------------------
61 #----------------------------------------------------------------------------
62 class IOStream:
62 class IOStream:
63 def __init__(self,stream,fallback):
63 def __init__(self,stream,fallback):
64 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
64 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
65 stream = fallback
65 stream = fallback
66 self.stream = stream
66 self.stream = stream
67 self._swrite = stream.write
67 self._swrite = stream.write
68 self.flush = stream.flush
68 self.flush = stream.flush
69
69
70 def write(self,data):
70 def write(self,data):
71 try:
71 try:
72 self._swrite(data)
72 self._swrite(data)
73 except:
73 except:
74 try:
74 try:
75 # print handles some unicode issues which may trip a plain
75 # print handles some unicode issues which may trip a plain
76 # write() call. Attempt to emulate write() by using a
76 # write() call. Attempt to emulate write() by using a
77 # trailing comma
77 # trailing comma
78 print >> self.stream, data,
78 print >> self.stream, data,
79 except:
79 except:
80 # if we get here, something is seriously broken.
80 # if we get here, something is seriously broken.
81 print >> sys.stderr, \
81 print >> sys.stderr, \
82 'ERROR - failed to write data to stream:', self.stream
82 'ERROR - failed to write data to stream:', self.stream
83
83
84 def close(self):
84 def close(self):
85 pass
85 pass
86
86
87
87
88 class IOTerm:
88 class IOTerm:
89 """ Term holds the file or file-like objects for handling I/O operations.
89 """ Term holds the file or file-like objects for handling I/O operations.
90
90
91 These are normally just sys.stdin, sys.stdout and sys.stderr but for
91 These are normally just sys.stdin, sys.stdout and sys.stderr but for
92 Windows they can can replaced to allow editing the strings before they are
92 Windows they can can replaced to allow editing the strings before they are
93 displayed."""
93 displayed."""
94
94
95 # In the future, having IPython channel all its I/O operations through
95 # In the future, having IPython channel all its I/O operations through
96 # this class will make it easier to embed it into other environments which
96 # this class will make it easier to embed it into other environments which
97 # are not a normal terminal (such as a GUI-based shell)
97 # are not a normal terminal (such as a GUI-based shell)
98 def __init__(self,cin=None,cout=None,cerr=None):
98 def __init__(self,cin=None,cout=None,cerr=None):
99 self.cin = IOStream(cin,sys.stdin)
99 self.cin = IOStream(cin,sys.stdin)
100 self.cout = IOStream(cout,sys.stdout)
100 self.cout = IOStream(cout,sys.stdout)
101 self.cerr = IOStream(cerr,sys.stderr)
101 self.cerr = IOStream(cerr,sys.stderr)
102
102
103 # Global variable to be used for all I/O
103 # Global variable to be used for all I/O
104 Term = IOTerm()
104 Term = IOTerm()
105
105
106 import IPython.utils.rlineimpl as readline
106 import IPython.utils.rlineimpl as readline
107 # Remake Term to use the readline i/o facilities
107 # Remake Term to use the readline i/o facilities
108 if sys.platform == 'win32' and readline.have_readline:
108 if sys.platform == 'win32' and readline.have_readline:
109
109
110 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
110 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
111
111
112
112
113 #****************************************************************************
113 #****************************************************************************
114 # Generic warning/error printer, used by everything else
114 # Generic warning/error printer, used by everything else
115 def warn(msg,level=2,exit_val=1):
115 def warn(msg,level=2,exit_val=1):
116 """Standard warning printer. Gives formatting consistency.
116 """Standard warning printer. Gives formatting consistency.
117
117
118 Output is sent to Term.cerr (sys.stderr by default).
118 Output is sent to Term.cerr (sys.stderr by default).
119
119
120 Options:
120 Options:
121
121
122 -level(2): allows finer control:
122 -level(2): allows finer control:
123 0 -> Do nothing, dummy function.
123 0 -> Do nothing, dummy function.
124 1 -> Print message.
124 1 -> Print message.
125 2 -> Print 'WARNING:' + message. (Default level).
125 2 -> Print 'WARNING:' + message. (Default level).
126 3 -> Print 'ERROR:' + message.
126 3 -> Print 'ERROR:' + message.
127 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
127 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
128
128
129 -exit_val (1): exit value returned by sys.exit() for a level 4
129 -exit_val (1): exit value returned by sys.exit() for a level 4
130 warning. Ignored for all other levels."""
130 warning. Ignored for all other levels."""
131
131
132 if level>0:
132 if level>0:
133 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
133 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
134 print >> Term.cerr, '%s%s' % (header[level],msg)
134 print >> Term.cerr, '%s%s' % (header[level],msg)
135 if level == 4:
135 if level == 4:
136 print >> Term.cerr,'Exiting.\n'
136 print >> Term.cerr,'Exiting.\n'
137 sys.exit(exit_val)
137 sys.exit(exit_val)
138
138
139 def info(msg):
139 def info(msg):
140 """Equivalent to warn(msg,level=1)."""
140 """Equivalent to warn(msg,level=1)."""
141
141
142 warn(msg,level=1)
142 warn(msg,level=1)
143
143
144 def error(msg):
144 def error(msg):
145 """Equivalent to warn(msg,level=3)."""
145 """Equivalent to warn(msg,level=3)."""
146
146
147 warn(msg,level=3)
147 warn(msg,level=3)
148
148
149 def fatal(msg,exit_val=1):
149 def fatal(msg,exit_val=1):
150 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
150 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
151
151
152 warn(msg,exit_val=exit_val,level=4)
152 warn(msg,exit_val=exit_val,level=4)
153
153
154 #---------------------------------------------------------------------------
154 #---------------------------------------------------------------------------
155 # Debugging routines
155 # Debugging routines
156 #
156 #
157 def debugx(expr,pre_msg=''):
157 def debugx(expr,pre_msg=''):
158 """Print the value of an expression from the caller's frame.
158 """Print the value of an expression from the caller's frame.
159
159
160 Takes an expression, evaluates it in the caller's frame and prints both
160 Takes an expression, evaluates it in the caller's frame and prints both
161 the given expression and the resulting value (as well as a debug mark
161 the given expression and the resulting value (as well as a debug mark
162 indicating the name of the calling function. The input must be of a form
162 indicating the name of the calling function. The input must be of a form
163 suitable for eval().
163 suitable for eval().
164
164
165 An optional message can be passed, which will be prepended to the printed
165 An optional message can be passed, which will be prepended to the printed
166 expr->value pair."""
166 expr->value pair."""
167
167
168 cf = sys._getframe(1)
168 cf = sys._getframe(1)
169 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
169 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
170 eval(expr,cf.f_globals,cf.f_locals))
170 eval(expr,cf.f_globals,cf.f_locals))
171
171
172 # deactivate it by uncommenting the following line, which makes it a no-op
172 # deactivate it by uncommenting the following line, which makes it a no-op
173 #def debugx(expr,pre_msg=''): pass
173 #def debugx(expr,pre_msg=''): pass
174
174
175 #----------------------------------------------------------------------------
175 #----------------------------------------------------------------------------
176 StringTypes = types.StringTypes
176 StringTypes = types.StringTypes
177
177
178 # Basic timing functionality
178 # Basic timing functionality
179
179
180 # If possible (Unix), use the resource module instead of time.clock()
180 # If possible (Unix), use the resource module instead of time.clock()
181 try:
181 try:
182 import resource
182 import resource
183 def clocku():
183 def clocku():
184 """clocku() -> floating point number
184 """clocku() -> floating point number
185
185
186 Return the *USER* CPU time in seconds since the start of the process.
186 Return the *USER* CPU time in seconds since the start of the process.
187 This is done via a call to resource.getrusage, so it avoids the
187 This is done via a call to resource.getrusage, so it avoids the
188 wraparound problems in time.clock()."""
188 wraparound problems in time.clock()."""
189
189
190 return resource.getrusage(resource.RUSAGE_SELF)[0]
190 return resource.getrusage(resource.RUSAGE_SELF)[0]
191
191
192 def clocks():
192 def clocks():
193 """clocks() -> floating point number
193 """clocks() -> floating point number
194
194
195 Return the *SYSTEM* CPU time in seconds since the start of the process.
195 Return the *SYSTEM* CPU time in seconds since the start of the process.
196 This is done via a call to resource.getrusage, so it avoids the
196 This is done via a call to resource.getrusage, so it avoids the
197 wraparound problems in time.clock()."""
197 wraparound problems in time.clock()."""
198
198
199 return resource.getrusage(resource.RUSAGE_SELF)[1]
199 return resource.getrusage(resource.RUSAGE_SELF)[1]
200
200
201 def clock():
201 def clock():
202 """clock() -> floating point number
202 """clock() -> floating point number
203
203
204 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
204 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
205 the process. This is done via a call to resource.getrusage, so it
205 the process. This is done via a call to resource.getrusage, so it
206 avoids the wraparound problems in time.clock()."""
206 avoids the wraparound problems in time.clock()."""
207
207
208 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
208 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
209 return u+s
209 return u+s
210
210
211 def clock2():
211 def clock2():
212 """clock2() -> (t_user,t_system)
212 """clock2() -> (t_user,t_system)
213
213
214 Similar to clock(), but return a tuple of user/system times."""
214 Similar to clock(), but return a tuple of user/system times."""
215 return resource.getrusage(resource.RUSAGE_SELF)[:2]
215 return resource.getrusage(resource.RUSAGE_SELF)[:2]
216
216
217 except ImportError:
217 except ImportError:
218 # There is no distinction of user/system time under windows, so we just use
218 # There is no distinction of user/system time under windows, so we just use
219 # time.clock() for everything...
219 # time.clock() for everything...
220 clocku = clocks = clock = time.clock
220 clocku = clocks = clock = time.clock
221 def clock2():
221 def clock2():
222 """Under windows, system CPU time can't be measured.
222 """Under windows, system CPU time can't be measured.
223
223
224 This just returns clock() and zero."""
224 This just returns clock() and zero."""
225 return time.clock(),0.0
225 return time.clock(),0.0
226
226
227 def timings_out(reps,func,*args,**kw):
227 def timings_out(reps,func,*args,**kw):
228 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
228 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
229
229
230 Execute a function reps times, return a tuple with the elapsed total
230 Execute a function reps times, return a tuple with the elapsed total
231 CPU time in seconds, the time per call and the function's output.
231 CPU time in seconds, the time per call and the function's output.
232
232
233 Under Unix, the return value is the sum of user+system time consumed by
233 Under Unix, the return value is the sum of user+system time consumed by
234 the process, computed via the resource module. This prevents problems
234 the process, computed via the resource module. This prevents problems
235 related to the wraparound effect which the time.clock() function has.
235 related to the wraparound effect which the time.clock() function has.
236
236
237 Under Windows the return value is in wall clock seconds. See the
237 Under Windows the return value is in wall clock seconds. See the
238 documentation for the time module for more details."""
238 documentation for the time module for more details."""
239
239
240 reps = int(reps)
240 reps = int(reps)
241 assert reps >=1, 'reps must be >= 1'
241 assert reps >=1, 'reps must be >= 1'
242 if reps==1:
242 if reps==1:
243 start = clock()
243 start = clock()
244 out = func(*args,**kw)
244 out = func(*args,**kw)
245 tot_time = clock()-start
245 tot_time = clock()-start
246 else:
246 else:
247 rng = xrange(reps-1) # the last time is executed separately to store output
247 rng = xrange(reps-1) # the last time is executed separately to store output
248 start = clock()
248 start = clock()
249 for dummy in rng: func(*args,**kw)
249 for dummy in rng: func(*args,**kw)
250 out = func(*args,**kw) # one last time
250 out = func(*args,**kw) # one last time
251 tot_time = clock()-start
251 tot_time = clock()-start
252 av_time = tot_time / reps
252 av_time = tot_time / reps
253 return tot_time,av_time,out
253 return tot_time,av_time,out
254
254
255 def timings(reps,func,*args,**kw):
255 def timings(reps,func,*args,**kw):
256 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
256 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
257
257
258 Execute a function reps times, return a tuple with the elapsed total CPU
258 Execute a function reps times, return a tuple with the elapsed total CPU
259 time in seconds and the time per call. These are just the first two values
259 time in seconds and the time per call. These are just the first two values
260 in timings_out()."""
260 in timings_out()."""
261
261
262 return timings_out(reps,func,*args,**kw)[0:2]
262 return timings_out(reps,func,*args,**kw)[0:2]
263
263
264 def timing(func,*args,**kw):
264 def timing(func,*args,**kw):
265 """timing(func,*args,**kw) -> t_total
265 """timing(func,*args,**kw) -> t_total
266
266
267 Execute a function once, return the elapsed total CPU time in
267 Execute a function once, return the elapsed total CPU time in
268 seconds. This is just the first value in timings_out()."""
268 seconds. This is just the first value in timings_out()."""
269
269
270 return timings_out(1,func,*args,**kw)[0]
270 return timings_out(1,func,*args,**kw)[0]
271
271
272 #****************************************************************************
272 #****************************************************************************
273 # file and system
273 # file and system
274
274
275 def arg_split(s,posix=False):
275 def arg_split(s,posix=False):
276 """Split a command line's arguments in a shell-like manner.
276 """Split a command line's arguments in a shell-like manner.
277
277
278 This is a modified version of the standard library's shlex.split()
278 This is a modified version of the standard library's shlex.split()
279 function, but with a default of posix=False for splitting, so that quotes
279 function, but with a default of posix=False for splitting, so that quotes
280 in inputs are respected."""
280 in inputs are respected."""
281
281
282 # XXX - there may be unicode-related problems here!!! I'm not sure that
282 # XXX - there may be unicode-related problems here!!! I'm not sure that
283 # shlex is truly unicode-safe, so it might be necessary to do
283 # shlex is truly unicode-safe, so it might be necessary to do
284 #
284 #
285 # s = s.encode(sys.stdin.encoding)
285 # s = s.encode(sys.stdin.encoding)
286 #
286 #
287 # first, to ensure that shlex gets a normal string. Input from anyone who
287 # first, to ensure that shlex gets a normal string. Input from anyone who
288 # knows more about unicode and shlex than I would be good to have here...
288 # knows more about unicode and shlex than I would be good to have here...
289 lex = shlex.shlex(s, posix=posix)
289 lex = shlex.shlex(s, posix=posix)
290 lex.whitespace_split = True
290 lex.whitespace_split = True
291 return list(lex)
291 return list(lex)
292
292
293 def system(cmd,verbose=0,debug=0,header=''):
293 def system(cmd,verbose=0,debug=0,header=''):
294 """Execute a system command, return its exit status.
294 """Execute a system command, return its exit status.
295
295
296 Options:
296 Options:
297
297
298 - verbose (0): print the command to be executed.
298 - verbose (0): print the command to be executed.
299
299
300 - debug (0): only print, do not actually execute.
300 - debug (0): only print, do not actually execute.
301
301
302 - header (''): Header to print on screen prior to the executed command (it
302 - header (''): Header to print on screen prior to the executed command (it
303 is only prepended to the command, no newlines are added).
303 is only prepended to the command, no newlines are added).
304
304
305 Note: a stateful version of this function is available through the
305 Note: a stateful version of this function is available through the
306 SystemExec class."""
306 SystemExec class."""
307
307
308 stat = 0
308 stat = 0
309 if verbose or debug: print header+cmd
309 if verbose or debug: print header+cmd
310 sys.stdout.flush()
310 sys.stdout.flush()
311 if not debug: stat = os.system(cmd)
311 if not debug: stat = os.system(cmd)
312 return stat
312 return stat
313
313
314 def abbrev_cwd():
314 def abbrev_cwd():
315 """ Return abbreviated version of cwd, e.g. d:mydir """
315 """ Return abbreviated version of cwd, e.g. d:mydir """
316 cwd = os.getcwd().replace('\\','/')
316 cwd = os.getcwd().replace('\\','/')
317 drivepart = ''
317 drivepart = ''
318 tail = cwd
318 tail = cwd
319 if sys.platform == 'win32':
319 if sys.platform == 'win32':
320 if len(cwd) < 4:
320 if len(cwd) < 4:
321 return cwd
321 return cwd
322 drivepart,tail = os.path.splitdrive(cwd)
322 drivepart,tail = os.path.splitdrive(cwd)
323
323
324
324
325 parts = tail.split('/')
325 parts = tail.split('/')
326 if len(parts) > 2:
326 if len(parts) > 2:
327 tail = '/'.join(parts[-2:])
327 tail = '/'.join(parts[-2:])
328
328
329 return (drivepart + (
329 return (drivepart + (
330 cwd == '/' and '/' or tail))
330 cwd == '/' and '/' or tail))
331
331
332
332
333 # This function is used by ipython in a lot of places to make system calls.
333 # This function is used by ipython in a lot of places to make system calls.
334 # We need it to be slightly different under win32, due to the vagaries of
334 # We need it to be slightly different under win32, due to the vagaries of
335 # 'network shares'. A win32 override is below.
335 # 'network shares'. A win32 override is below.
336
336
337 def shell(cmd,verbose=0,debug=0,header=''):
337 def shell(cmd,verbose=0,debug=0,header=''):
338 """Execute a command in the system shell, always return None.
338 """Execute a command in the system shell, always return None.
339
339
340 Options:
340 Options:
341
341
342 - verbose (0): print the command to be executed.
342 - verbose (0): print the command to be executed.
343
343
344 - debug (0): only print, do not actually execute.
344 - debug (0): only print, do not actually execute.
345
345
346 - header (''): Header to print on screen prior to the executed command (it
346 - header (''): Header to print on screen prior to the executed command (it
347 is only prepended to the command, no newlines are added).
347 is only prepended to the command, no newlines are added).
348
348
349 Note: this is similar to genutils.system(), but it returns None so it can
349 Note: this is similar to genutils.system(), but it returns None so it can
350 be conveniently used in interactive loops without getting the return value
350 be conveniently used in interactive loops without getting the return value
351 (typically 0) printed many times."""
351 (typically 0) printed many times."""
352
352
353 stat = 0
353 stat = 0
354 if verbose or debug: print header+cmd
354 if verbose or debug: print header+cmd
355 # flush stdout so we don't mangle python's buffering
355 # flush stdout so we don't mangle python's buffering
356 sys.stdout.flush()
356 sys.stdout.flush()
357
357
358 if not debug:
358 if not debug:
359 platutils.set_term_title("IPy " + cmd)
359 platutils.set_term_title("IPy " + cmd)
360 os.system(cmd)
360 os.system(cmd)
361 platutils.set_term_title("IPy " + abbrev_cwd())
361 platutils.set_term_title("IPy " + abbrev_cwd())
362
362
363 # override shell() for win32 to deal with network shares
363 # override shell() for win32 to deal with network shares
364 if os.name in ('nt','dos'):
364 if os.name in ('nt','dos'):
365
365
366 shell_ori = shell
366 shell_ori = shell
367
367
368 def shell(cmd,verbose=0,debug=0,header=''):
368 def shell(cmd,verbose=0,debug=0,header=''):
369 if os.getcwd().startswith(r"\\"):
369 if os.getcwd().startswith(r"\\"):
370 path = os.getcwd()
370 path = os.getcwd()
371 # change to c drive (cannot be on UNC-share when issuing os.system,
371 # change to c drive (cannot be on UNC-share when issuing os.system,
372 # as cmd.exe cannot handle UNC addresses)
372 # as cmd.exe cannot handle UNC addresses)
373 os.chdir("c:")
373 os.chdir("c:")
374 # issue pushd to the UNC-share and then run the command
374 # issue pushd to the UNC-share and then run the command
375 try:
375 try:
376 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
376 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
377 finally:
377 finally:
378 os.chdir(path)
378 os.chdir(path)
379 else:
379 else:
380 shell_ori(cmd,verbose,debug,header)
380 shell_ori(cmd,verbose,debug,header)
381
381
382 shell.__doc__ = shell_ori.__doc__
382 shell.__doc__ = shell_ori.__doc__
383
383
384 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
384 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
385 """Dummy substitute for perl's backquotes.
385 """Dummy substitute for perl's backquotes.
386
386
387 Executes a command and returns the output.
387 Executes a command and returns the output.
388
388
389 Accepts the same arguments as system(), plus:
389 Accepts the same arguments as system(), plus:
390
390
391 - split(0): if true, the output is returned as a list split on newlines.
391 - split(0): if true, the output is returned as a list split on newlines.
392
392
393 Note: a stateful version of this function is available through the
393 Note: a stateful version of this function is available through the
394 SystemExec class.
394 SystemExec class.
395
395
396 This is pretty much deprecated and rarely used,
396 This is pretty much deprecated and rarely used,
397 genutils.getoutputerror may be what you need.
397 genutils.getoutputerror may be what you need.
398
398
399 """
399 """
400
400
401 if verbose or debug: print header+cmd
401 if verbose or debug: print header+cmd
402 if not debug:
402 if not debug:
403 output = os.popen(cmd).read()
403 output = os.popen(cmd).read()
404 # stipping last \n is here for backwards compat.
404 # stipping last \n is here for backwards compat.
405 if output.endswith('\n'):
405 if output.endswith('\n'):
406 output = output[:-1]
406 output = output[:-1]
407 if split:
407 if split:
408 return output.split('\n')
408 return output.split('\n')
409 else:
409 else:
410 return output
410 return output
411
411
412 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
412 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
413 """Return (standard output,standard error) of executing cmd in a shell.
413 """Return (standard output,standard error) of executing cmd in a shell.
414
414
415 Accepts the same arguments as system(), plus:
415 Accepts the same arguments as system(), plus:
416
416
417 - split(0): if true, each of stdout/err is returned as a list split on
417 - split(0): if true, each of stdout/err is returned as a list split on
418 newlines.
418 newlines.
419
419
420 Note: a stateful version of this function is available through the
420 Note: a stateful version of this function is available through the
421 SystemExec class."""
421 SystemExec class."""
422
422
423 if verbose or debug: print header+cmd
423 if verbose or debug: print header+cmd
424 if not cmd:
424 if not cmd:
425 if split:
425 if split:
426 return [],[]
426 return [],[]
427 else:
427 else:
428 return '',''
428 return '',''
429 if not debug:
429 if not debug:
430 pin,pout,perr = os.popen3(cmd)
430 pin,pout,perr = os.popen3(cmd)
431 tout = pout.read().rstrip()
431 tout = pout.read().rstrip()
432 terr = perr.read().rstrip()
432 terr = perr.read().rstrip()
433 pin.close()
433 pin.close()
434 pout.close()
434 pout.close()
435 perr.close()
435 perr.close()
436 if split:
436 if split:
437 return tout.split('\n'),terr.split('\n')
437 return tout.split('\n'),terr.split('\n')
438 else:
438 else:
439 return tout,terr
439 return tout,terr
440
440
441 # for compatibility with older naming conventions
441 # for compatibility with older naming conventions
442 xsys = system
442 xsys = system
443 bq = getoutput
443 bq = getoutput
444
444
445 class SystemExec:
445 class SystemExec:
446 """Access the system and getoutput functions through a stateful interface.
446 """Access the system and getoutput functions through a stateful interface.
447
447
448 Note: here we refer to the system and getoutput functions from this
448 Note: here we refer to the system and getoutput functions from this
449 library, not the ones from the standard python library.
449 library, not the ones from the standard python library.
450
450
451 This class offers the system and getoutput functions as methods, but the
451 This class offers the system and getoutput functions as methods, but the
452 verbose, debug and header parameters can be set for the instance (at
452 verbose, debug and header parameters can be set for the instance (at
453 creation time or later) so that they don't need to be specified on each
453 creation time or later) so that they don't need to be specified on each
454 call.
454 call.
455
455
456 For efficiency reasons, there's no way to override the parameters on a
456 For efficiency reasons, there's no way to override the parameters on a
457 per-call basis other than by setting instance attributes. If you need
457 per-call basis other than by setting instance attributes. If you need
458 local overrides, it's best to directly call system() or getoutput().
458 local overrides, it's best to directly call system() or getoutput().
459
459
460 The following names are provided as alternate options:
460 The following names are provided as alternate options:
461 - xsys: alias to system
461 - xsys: alias to system
462 - bq: alias to getoutput
462 - bq: alias to getoutput
463
463
464 An instance can then be created as:
464 An instance can then be created as:
465 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
465 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
466 """
466 """
467
467
468 def __init__(self,verbose=0,debug=0,header='',split=0):
468 def __init__(self,verbose=0,debug=0,header='',split=0):
469 """Specify the instance's values for verbose, debug and header."""
469 """Specify the instance's values for verbose, debug and header."""
470 setattr_list(self,'verbose debug header split')
470 setattr_list(self,'verbose debug header split')
471
471
472 def system(self,cmd):
472 def system(self,cmd):
473 """Stateful interface to system(), with the same keyword parameters."""
473 """Stateful interface to system(), with the same keyword parameters."""
474
474
475 system(cmd,self.verbose,self.debug,self.header)
475 system(cmd,self.verbose,self.debug,self.header)
476
476
477 def shell(self,cmd):
477 def shell(self,cmd):
478 """Stateful interface to shell(), with the same keyword parameters."""
478 """Stateful interface to shell(), with the same keyword parameters."""
479
479
480 shell(cmd,self.verbose,self.debug,self.header)
480 shell(cmd,self.verbose,self.debug,self.header)
481
481
482 xsys = system # alias
482 xsys = system # alias
483
483
484 def getoutput(self,cmd):
484 def getoutput(self,cmd):
485 """Stateful interface to getoutput()."""
485 """Stateful interface to getoutput()."""
486
486
487 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
487 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
488
488
489 def getoutputerror(self,cmd):
489 def getoutputerror(self,cmd):
490 """Stateful interface to getoutputerror()."""
490 """Stateful interface to getoutputerror()."""
491
491
492 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
492 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
493
493
494 bq = getoutput # alias
494 bq = getoutput # alias
495
495
496 #-----------------------------------------------------------------------------
496 #-----------------------------------------------------------------------------
497 def mutex_opts(dict,ex_op):
497 def mutex_opts(dict,ex_op):
498 """Check for presence of mutually exclusive keys in a dict.
498 """Check for presence of mutually exclusive keys in a dict.
499
499
500 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
500 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
501 for op1,op2 in ex_op:
501 for op1,op2 in ex_op:
502 if op1 in dict and op2 in dict:
502 if op1 in dict and op2 in dict:
503 raise ValueError,'\n*** ERROR in Arguments *** '\
503 raise ValueError,'\n*** ERROR in Arguments *** '\
504 'Options '+op1+' and '+op2+' are mutually exclusive.'
504 'Options '+op1+' and '+op2+' are mutually exclusive.'
505
505
506 #-----------------------------------------------------------------------------
506 #-----------------------------------------------------------------------------
507 def get_py_filename(name):
507 def get_py_filename(name):
508 """Return a valid python filename in the current directory.
508 """Return a valid python filename in the current directory.
509
509
510 If the given name is not a file, it adds '.py' and searches again.
510 If the given name is not a file, it adds '.py' and searches again.
511 Raises IOError with an informative message if the file isn't found."""
511 Raises IOError with an informative message if the file isn't found."""
512
512
513 name = os.path.expanduser(name)
513 name = os.path.expanduser(name)
514 if not os.path.isfile(name) and not name.endswith('.py'):
514 if not os.path.isfile(name) and not name.endswith('.py'):
515 name += '.py'
515 name += '.py'
516 if os.path.isfile(name):
516 if os.path.isfile(name):
517 return name
517 return name
518 else:
518 else:
519 raise IOError,'File `%s` not found.' % name
519 raise IOError,'File `%s` not found.' % name
520
520
521 #-----------------------------------------------------------------------------
521 #-----------------------------------------------------------------------------
522
522
523
523
524 def filefind(filename, path_dirs=None):
524 def filefind(filename, path_dirs=None):
525 """Find a file by looking through a sequence of paths.
525 """Find a file by looking through a sequence of paths.
526
526
527 This iterates through a sequence of paths looking for a file and returns
527 This iterates through a sequence of paths looking for a file and returns
528 the full, absolute path of the first occurence of the file. If no set of
528 the full, absolute path of the first occurence of the file. If no set of
529 path dirs is given, the filename is tested as is, after running through
529 path dirs is given, the filename is tested as is, after running through
530 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
530 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
531
531
532 filefind('myfile.txt')
532 filefind('myfile.txt')
533
533
534 will find the file in the current working dir, but::
534 will find the file in the current working dir, but::
535
535
536 filefind('~/myfile.txt')
536 filefind('~/myfile.txt')
537
537
538 Will find the file in the users home directory. This function does not
538 Will find the file in the users home directory. This function does not
539 automatically try any paths, such as the cwd or the user's home directory.
539 automatically try any paths, such as the cwd or the user's home directory.
540
540
541 Parameters
541 Parameters
542 ----------
542 ----------
543 filename : str
543 filename : str
544 The filename to look for.
544 The filename to look for.
545 path_dirs : str, None or sequence of str
545 path_dirs : str, None or sequence of str
546 The sequence of paths to look for the file in. If None, the filename
546 The sequence of paths to look for the file in. If None, the filename
547 need to be absolute or be in the cwd. If a string, the string is
547 need to be absolute or be in the cwd. If a string, the string is
548 put into a sequence and the searched. If a sequence, walk through
548 put into a sequence and the searched. If a sequence, walk through
549 each element and join with ``filename``, calling :func:`expandvars`
549 each element and join with ``filename``, calling :func:`expandvars`
550 and :func:`expanduser` before testing for existence.
550 and :func:`expanduser` before testing for existence.
551
551
552 Returns
552 Returns
553 -------
553 -------
554 Raises :exc:`IOError` or returns absolute path to file.
554 Raises :exc:`IOError` or returns absolute path to file.
555 """
555 """
556 if path_dirs is None:
556 if path_dirs is None:
557 path_dirs = ("",)
557 path_dirs = ("",)
558 elif isinstance(path_dirs, basestring):
558 elif isinstance(path_dirs, basestring):
559 path_dirs = (path_dirs,)
559 path_dirs = (path_dirs,)
560 for path in path_dirs:
560 for path in path_dirs:
561 if path == '.': path = os.getcwd()
561 if path == '.': path = os.getcwd()
562 testname = expand_path(os.path.join(path, filename))
562 testname = expand_path(os.path.join(path, filename))
563 if os.path.isfile(testname):
563 if os.path.isfile(testname):
564 return os.path.abspath(testname)
564 return os.path.abspath(testname)
565 raise IOError("File does not exist in any "
565 raise IOError("File does not exist in any "
566 "of the search paths: %r, %r" % \
566 "of the search paths: %r, %r" % \
567 (filename, path_dirs))
567 (filename, path_dirs))
568
568
569
569
570 #----------------------------------------------------------------------------
570 #----------------------------------------------------------------------------
571 def file_read(filename):
571 def file_read(filename):
572 """Read a file and close it. Returns the file source."""
572 """Read a file and close it. Returns the file source."""
573 fobj = open(filename,'r');
573 fobj = open(filename,'r');
574 source = fobj.read();
574 source = fobj.read();
575 fobj.close()
575 fobj.close()
576 return source
576 return source
577
577
578 def file_readlines(filename):
578 def file_readlines(filename):
579 """Read a file and close it. Returns the file source using readlines()."""
579 """Read a file and close it. Returns the file source using readlines()."""
580 fobj = open(filename,'r');
580 fobj = open(filename,'r');
581 lines = fobj.readlines();
581 lines = fobj.readlines();
582 fobj.close()
582 fobj.close()
583 return lines
583 return lines
584
584
585 #----------------------------------------------------------------------------
585 #----------------------------------------------------------------------------
586 def target_outdated(target,deps):
586 def target_outdated(target,deps):
587 """Determine whether a target is out of date.
587 """Determine whether a target is out of date.
588
588
589 target_outdated(target,deps) -> 1/0
589 target_outdated(target,deps) -> 1/0
590
590
591 deps: list of filenames which MUST exist.
591 deps: list of filenames which MUST exist.
592 target: single filename which may or may not exist.
592 target: single filename which may or may not exist.
593
593
594 If target doesn't exist or is older than any file listed in deps, return
594 If target doesn't exist or is older than any file listed in deps, return
595 true, otherwise return false.
595 true, otherwise return false.
596 """
596 """
597 try:
597 try:
598 target_time = os.path.getmtime(target)
598 target_time = os.path.getmtime(target)
599 except os.error:
599 except os.error:
600 return 1
600 return 1
601 for dep in deps:
601 for dep in deps:
602 dep_time = os.path.getmtime(dep)
602 dep_time = os.path.getmtime(dep)
603 if dep_time > target_time:
603 if dep_time > target_time:
604 #print "For target",target,"Dep failed:",dep # dbg
604 #print "For target",target,"Dep failed:",dep # dbg
605 #print "times (dep,tar):",dep_time,target_time # dbg
605 #print "times (dep,tar):",dep_time,target_time # dbg
606 return 1
606 return 1
607 return 0
607 return 0
608
608
609 #-----------------------------------------------------------------------------
609 #-----------------------------------------------------------------------------
610 def target_update(target,deps,cmd):
610 def target_update(target,deps,cmd):
611 """Update a target with a given command given a list of dependencies.
611 """Update a target with a given command given a list of dependencies.
612
612
613 target_update(target,deps,cmd) -> runs cmd if target is outdated.
613 target_update(target,deps,cmd) -> runs cmd if target is outdated.
614
614
615 This is just a wrapper around target_outdated() which calls the given
615 This is just a wrapper around target_outdated() which calls the given
616 command if target is outdated."""
616 command if target is outdated."""
617
617
618 if target_outdated(target,deps):
618 if target_outdated(target,deps):
619 xsys(cmd)
619 xsys(cmd)
620
620
621 #----------------------------------------------------------------------------
621 #----------------------------------------------------------------------------
622 def unquote_ends(istr):
622 def unquote_ends(istr):
623 """Remove a single pair of quotes from the endpoints of a string."""
623 """Remove a single pair of quotes from the endpoints of a string."""
624
624
625 if not istr:
625 if not istr:
626 return istr
626 return istr
627 if (istr[0]=="'" and istr[-1]=="'") or \
627 if (istr[0]=="'" and istr[-1]=="'") or \
628 (istr[0]=='"' and istr[-1]=='"'):
628 (istr[0]=='"' and istr[-1]=='"'):
629 return istr[1:-1]
629 return istr[1:-1]
630 else:
630 else:
631 return istr
631 return istr
632
632
633 #----------------------------------------------------------------------------
633 #----------------------------------------------------------------------------
634 def flag_calls(func):
634 def flag_calls(func):
635 """Wrap a function to detect and flag when it gets called.
635 """Wrap a function to detect and flag when it gets called.
636
636
637 This is a decorator which takes a function and wraps it in a function with
637 This is a decorator which takes a function and wraps it in a function with
638 a 'called' attribute. wrapper.called is initialized to False.
638 a 'called' attribute. wrapper.called is initialized to False.
639
639
640 The wrapper.called attribute is set to False right before each call to the
640 The wrapper.called attribute is set to False right before each call to the
641 wrapped function, so if the call fails it remains False. After the call
641 wrapped function, so if the call fails it remains False. After the call
642 completes, wrapper.called is set to True and the output is returned.
642 completes, wrapper.called is set to True and the output is returned.
643
643
644 Testing for truth in wrapper.called allows you to determine if a call to
644 Testing for truth in wrapper.called allows you to determine if a call to
645 func() was attempted and succeeded."""
645 func() was attempted and succeeded."""
646
646
647 def wrapper(*args,**kw):
647 def wrapper(*args,**kw):
648 wrapper.called = False
648 wrapper.called = False
649 out = func(*args,**kw)
649 out = func(*args,**kw)
650 wrapper.called = True
650 wrapper.called = True
651 return out
651 return out
652
652
653 wrapper.called = False
653 wrapper.called = False
654 wrapper.__doc__ = func.__doc__
654 wrapper.__doc__ = func.__doc__
655 return wrapper
655 return wrapper
656
656
657 #----------------------------------------------------------------------------
657 #----------------------------------------------------------------------------
658 def dhook_wrap(func,*a,**k):
658 def dhook_wrap(func,*a,**k):
659 """Wrap a function call in a sys.displayhook controller.
659 """Wrap a function call in a sys.displayhook controller.
660
660
661 Returns a wrapper around func which calls func, with all its arguments and
661 Returns a wrapper around func which calls func, with all its arguments and
662 keywords unmodified, using the default sys.displayhook. Since IPython
662 keywords unmodified, using the default sys.displayhook. Since IPython
663 modifies sys.displayhook, it breaks the behavior of certain systems that
663 modifies sys.displayhook, it breaks the behavior of certain systems that
664 rely on the default behavior, notably doctest.
664 rely on the default behavior, notably doctest.
665 """
665 """
666
666
667 def f(*a,**k):
667 def f(*a,**k):
668
668
669 dhook_s = sys.displayhook
669 dhook_s = sys.displayhook
670 sys.displayhook = sys.__displayhook__
670 sys.displayhook = sys.__displayhook__
671 try:
671 try:
672 out = func(*a,**k)
672 out = func(*a,**k)
673 finally:
673 finally:
674 sys.displayhook = dhook_s
674 sys.displayhook = dhook_s
675
675
676 return out
676 return out
677
677
678 f.__doc__ = func.__doc__
678 f.__doc__ = func.__doc__
679 return f
679 return f
680
680
681 #----------------------------------------------------------------------------
681 #----------------------------------------------------------------------------
682 def doctest_reload():
682 def doctest_reload():
683 """Properly reload doctest to reuse it interactively.
683 """Properly reload doctest to reuse it interactively.
684
684
685 This routine:
685 This routine:
686
686
687 - imports doctest but does NOT reload it (see below).
687 - imports doctest but does NOT reload it (see below).
688
688
689 - resets its global 'master' attribute to None, so that multiple uses of
689 - resets its global 'master' attribute to None, so that multiple uses of
690 the module interactively don't produce cumulative reports.
690 the module interactively don't produce cumulative reports.
691
691
692 - Monkeypatches its core test runner method to protect it from IPython's
692 - Monkeypatches its core test runner method to protect it from IPython's
693 modified displayhook. Doctest expects the default displayhook behavior
693 modified displayhook. Doctest expects the default displayhook behavior
694 deep down, so our modification breaks it completely. For this reason, a
694 deep down, so our modification breaks it completely. For this reason, a
695 hard monkeypatch seems like a reasonable solution rather than asking
695 hard monkeypatch seems like a reasonable solution rather than asking
696 users to manually use a different doctest runner when under IPython.
696 users to manually use a different doctest runner when under IPython.
697
697
698 Notes
698 Notes
699 -----
699 -----
700
700
701 This function *used to* reload doctest, but this has been disabled because
701 This function *used to* reload doctest, but this has been disabled because
702 reloading doctest unconditionally can cause massive breakage of other
702 reloading doctest unconditionally can cause massive breakage of other
703 doctest-dependent modules already in memory, such as those for IPython's
703 doctest-dependent modules already in memory, such as those for IPython's
704 own testing system. The name wasn't changed to avoid breaking people's
704 own testing system. The name wasn't changed to avoid breaking people's
705 code, but the reload call isn't actually made anymore."""
705 code, but the reload call isn't actually made anymore."""
706
706
707 import doctest
707 import doctest
708 doctest.master = None
708 doctest.master = None
709 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
709 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
710
710
711 #----------------------------------------------------------------------------
711 #----------------------------------------------------------------------------
712 class HomeDirError(Error):
712 class HomeDirError(Error):
713 pass
713 pass
714
714
715 def get_home_dir():
715 def get_home_dir():
716 """Return the closest possible equivalent to a 'home' directory.
716 """Return the closest possible equivalent to a 'home' directory.
717
717
718 * On POSIX, we try $HOME.
718 * On POSIX, we try $HOME.
719 * On Windows we try:
719 * On Windows we try:
720 - %HOMESHARE%
720 - %HOMESHARE%
721 - %HOMEDRIVE\%HOMEPATH%
721 - %HOMEDRIVE\%HOMEPATH%
722 - %USERPROFILE%
722 - %USERPROFILE%
723 - Registry hack
723 - Registry hack
724 * On Dos C:\
724 * On Dos C:\
725
725
726 Currently only Posix and NT are implemented, a HomeDirError exception is
726 Currently only Posix and NT are implemented, a HomeDirError exception is
727 raised for all other OSes.
727 raised for all other OSes.
728 """
728 """
729
729
730 isdir = os.path.isdir
730 isdir = os.path.isdir
731 env = os.environ
731 env = os.environ
732
732
733 # first, check py2exe distribution root directory for _ipython.
733 # first, check py2exe distribution root directory for _ipython.
734 # This overrides all. Normally does not exist.
734 # This overrides all. Normally does not exist.
735
735
736 if hasattr(sys, "frozen"): #Is frozen by py2exe
736 if hasattr(sys, "frozen"): #Is frozen by py2exe
737 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
737 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
738 root, rest = IPython.__file__.lower().split('library.zip')
738 root, rest = IPython.__file__.lower().split('library.zip')
739 else:
739 else:
740 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
740 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
741 root=os.path.abspath(root).rstrip('\\')
741 root=os.path.abspath(root).rstrip('\\')
742 if isdir(os.path.join(root, '_ipython')):
742 if isdir(os.path.join(root, '_ipython')):
743 os.environ["IPYKITROOT"] = root
743 os.environ["IPYKITROOT"] = root
744 return root.decode(sys.getfilesystemencoding())
744 return root.decode(sys.getfilesystemencoding())
745
745
746 if os.name == 'posix':
746 if os.name == 'posix':
747 # Linux, Unix, AIX, OS X
747 # Linux, Unix, AIX, OS X
748 try:
748 try:
749 homedir = env['HOME']
749 homedir = env['HOME']
750 except KeyError:
750 except KeyError:
751 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
751 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
752 else:
752 else:
753 return homedir.decode(sys.getfilesystemencoding())
753 return homedir.decode(sys.getfilesystemencoding())
754 elif os.name == 'nt':
754 elif os.name == 'nt':
755 # Now for win9x, XP, Vista, 7?
755 # Now for win9x, XP, Vista, 7?
756 # For some strange reason all of these return 'nt' for os.name.
756 # For some strange reason all of these return 'nt' for os.name.
757 # First look for a network home directory. This will return the UNC
757 # First look for a network home directory. This will return the UNC
758 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
758 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
759 # is needed when running IPython on cluster where all paths have to
759 # is needed when running IPython on cluster where all paths have to
760 # be UNC.
760 # be UNC.
761 try:
761 try:
762 homedir = env['HOMESHARE']
762 homedir = env['HOMESHARE']
763 except KeyError:
763 except KeyError:
764 pass
764 pass
765 else:
765 else:
766 if isdir(homedir):
766 if isdir(homedir):
767 return homedir.decode(sys.getfilesystemencoding())
767 return homedir.decode(sys.getfilesystemencoding())
768
768
769 # Now look for a local home directory
769 # Now look for a local home directory
770 try:
770 try:
771 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
771 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
772 except KeyError:
772 except KeyError:
773 pass
773 pass
774 else:
774 else:
775 if isdir(homedir):
775 if isdir(homedir):
776 return homedir.decode(sys.getfilesystemencoding())
776 return homedir.decode(sys.getfilesystemencoding())
777
777
778 # Now the users profile directory
778 # Now the users profile directory
779 try:
779 try:
780 homedir = os.path.join(env['USERPROFILE'])
780 homedir = os.path.join(env['USERPROFILE'])
781 except KeyError:
781 except KeyError:
782 pass
782 pass
783 else:
783 else:
784 if isdir(homedir):
784 if isdir(homedir):
785 return homedir.decode(sys.getfilesystemencoding())
785 return homedir.decode(sys.getfilesystemencoding())
786
786
787 # Use the registry to get the 'My Documents' folder.
787 # Use the registry to get the 'My Documents' folder.
788 try:
788 try:
789 import _winreg as wreg
789 import _winreg as wreg
790 key = wreg.OpenKey(
790 key = wreg.OpenKey(
791 wreg.HKEY_CURRENT_USER,
791 wreg.HKEY_CURRENT_USER,
792 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
792 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
793 )
793 )
794 homedir = wreg.QueryValueEx(key,'Personal')[0]
794 homedir = wreg.QueryValueEx(key,'Personal')[0]
795 key.Close()
795 key.Close()
796 except:
796 except:
797 pass
797 pass
798 else:
798 else:
799 if isdir(homedir):
799 if isdir(homedir):
800 return homedir.decode(sys.getfilesystemencoding())
800 return homedir.decode(sys.getfilesystemencoding())
801
801
802 # If all else fails, raise HomeDirError
802 # If all else fails, raise HomeDirError
803 raise HomeDirError('No valid home directory could be found')
803 raise HomeDirError('No valid home directory could be found')
804 elif os.name == 'dos':
804 elif os.name == 'dos':
805 # Desperate, may do absurd things in classic MacOS. May work under DOS.
805 # Desperate, may do absurd things in classic MacOS. May work under DOS.
806 return 'C:\\'.decode(sys.getfilesystemencoding())
806 return 'C:\\'.decode(sys.getfilesystemencoding())
807 else:
807 else:
808 raise HomeDirError('No valid home directory could be found for your OS')
808 raise HomeDirError('No valid home directory could be found for your OS')
809
809
810
810
811 def get_ipython_dir():
811 def get_ipython_dir():
812 """Get the IPython directory for this platform and user.
812 """Get the IPython directory for this platform and user.
813
813
814 This uses the logic in `get_home_dir` to find the home directory
814 This uses the logic in `get_home_dir` to find the home directory
815 and the adds .ipython to the end of the path.
815 and the adds .ipython to the end of the path.
816 """
816 """
817 ipdir_def = '.ipython'
817 ipdir_def = '.ipython'
818 home_dir = get_home_dir()
818 home_dir = get_home_dir()
819 ipdir = os.environ.get(
819 ipdir = os.environ.get(
820 'IPYTHON_DIR', os.environ.get(
820 'IPYTHON_DIR', os.environ.get(
821 'IPYTHONDIR', os.path.join(home_dir, ipdir_def)
821 'IPYTHONDIR', os.path.join(home_dir, ipdir_def)
822 )
822 )
823 )
823 )
824 return ipdir.decode(sys.getfilesystemencoding())
824 return ipdir.decode(sys.getfilesystemencoding())
825
825
826
826
827 #****************************************************************************
827 #****************************************************************************
828 # strings and text
828 # strings and text
829
829
830 class LSString(str):
830 class LSString(str):
831 """String derivative with a special access attributes.
831 """String derivative with a special access attributes.
832
832
833 These are normal strings, but with the special attributes:
833 These are normal strings, but with the special attributes:
834
834
835 .l (or .list) : value as list (split on newlines).
835 .l (or .list) : value as list (split on newlines).
836 .n (or .nlstr): original value (the string itself).
836 .n (or .nlstr): original value (the string itself).
837 .s (or .spstr): value as whitespace-separated string.
837 .s (or .spstr): value as whitespace-separated string.
838 .p (or .paths): list of path objects
838 .p (or .paths): list of path objects
839
839
840 Any values which require transformations are computed only once and
840 Any values which require transformations are computed only once and
841 cached.
841 cached.
842
842
843 Such strings are very useful to efficiently interact with the shell, which
843 Such strings are very useful to efficiently interact with the shell, which
844 typically only understands whitespace-separated options for commands."""
844 typically only understands whitespace-separated options for commands."""
845
845
846 def get_list(self):
846 def get_list(self):
847 try:
847 try:
848 return self.__list
848 return self.__list
849 except AttributeError:
849 except AttributeError:
850 self.__list = self.split('\n')
850 self.__list = self.split('\n')
851 return self.__list
851 return self.__list
852
852
853 l = list = property(get_list)
853 l = list = property(get_list)
854
854
855 def get_spstr(self):
855 def get_spstr(self):
856 try:
856 try:
857 return self.__spstr
857 return self.__spstr
858 except AttributeError:
858 except AttributeError:
859 self.__spstr = self.replace('\n',' ')
859 self.__spstr = self.replace('\n',' ')
860 return self.__spstr
860 return self.__spstr
861
861
862 s = spstr = property(get_spstr)
862 s = spstr = property(get_spstr)
863
863
864 def get_nlstr(self):
864 def get_nlstr(self):
865 return self
865 return self
866
866
867 n = nlstr = property(get_nlstr)
867 n = nlstr = property(get_nlstr)
868
868
869 def get_paths(self):
869 def get_paths(self):
870 try:
870 try:
871 return self.__paths
871 return self.__paths
872 except AttributeError:
872 except AttributeError:
873 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
873 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
874 return self.__paths
874 return self.__paths
875
875
876 p = paths = property(get_paths)
876 p = paths = property(get_paths)
877
877
878 def print_lsstring(arg):
878 def print_lsstring(arg):
879 """ Prettier (non-repr-like) and more informative printer for LSString """
879 """ Prettier (non-repr-like) and more informative printer for LSString """
880 print "LSString (.p, .n, .l, .s available). Value:"
880 print "LSString (.p, .n, .l, .s available). Value:"
881 print arg
881 print arg
882
882
883 print_lsstring = result_display.when_type(LSString)(print_lsstring)
883 print_lsstring = result_display.when_type(LSString)(print_lsstring)
884
884
885 #----------------------------------------------------------------------------
885 #----------------------------------------------------------------------------
886 class SList(list):
886 class SList(list):
887 """List derivative with a special access attributes.
887 """List derivative with a special access attributes.
888
888
889 These are normal lists, but with the special attributes:
889 These are normal lists, but with the special attributes:
890
890
891 .l (or .list) : value as list (the list itself).
891 .l (or .list) : value as list (the list itself).
892 .n (or .nlstr): value as a string, joined on newlines.
892 .n (or .nlstr): value as a string, joined on newlines.
893 .s (or .spstr): value as a string, joined on spaces.
893 .s (or .spstr): value as a string, joined on spaces.
894 .p (or .paths): list of path objects
894 .p (or .paths): list of path objects
895
895
896 Any values which require transformations are computed only once and
896 Any values which require transformations are computed only once and
897 cached."""
897 cached."""
898
898
899 def get_list(self):
899 def get_list(self):
900 return self
900 return self
901
901
902 l = list = property(get_list)
902 l = list = property(get_list)
903
903
904 def get_spstr(self):
904 def get_spstr(self):
905 try:
905 try:
906 return self.__spstr
906 return self.__spstr
907 except AttributeError:
907 except AttributeError:
908 self.__spstr = ' '.join(self)
908 self.__spstr = ' '.join(self)
909 return self.__spstr
909 return self.__spstr
910
910
911 s = spstr = property(get_spstr)
911 s = spstr = property(get_spstr)
912
912
913 def get_nlstr(self):
913 def get_nlstr(self):
914 try:
914 try:
915 return self.__nlstr
915 return self.__nlstr
916 except AttributeError:
916 except AttributeError:
917 self.__nlstr = '\n'.join(self)
917 self.__nlstr = '\n'.join(self)
918 return self.__nlstr
918 return self.__nlstr
919
919
920 n = nlstr = property(get_nlstr)
920 n = nlstr = property(get_nlstr)
921
921
922 def get_paths(self):
922 def get_paths(self):
923 try:
923 try:
924 return self.__paths
924 return self.__paths
925 except AttributeError:
925 except AttributeError:
926 self.__paths = [path(p) for p in self if os.path.exists(p)]
926 self.__paths = [path(p) for p in self if os.path.exists(p)]
927 return self.__paths
927 return self.__paths
928
928
929 p = paths = property(get_paths)
929 p = paths = property(get_paths)
930
930
931 def grep(self, pattern, prune = False, field = None):
931 def grep(self, pattern, prune = False, field = None):
932 """ Return all strings matching 'pattern' (a regex or callable)
932 """ Return all strings matching 'pattern' (a regex or callable)
933
933
934 This is case-insensitive. If prune is true, return all items
934 This is case-insensitive. If prune is true, return all items
935 NOT matching the pattern.
935 NOT matching the pattern.
936
936
937 If field is specified, the match must occur in the specified
937 If field is specified, the match must occur in the specified
938 whitespace-separated field.
938 whitespace-separated field.
939
939
940 Examples::
940 Examples::
941
941
942 a.grep( lambda x: x.startswith('C') )
942 a.grep( lambda x: x.startswith('C') )
943 a.grep('Cha.*log', prune=1)
943 a.grep('Cha.*log', prune=1)
944 a.grep('chm', field=-1)
944 a.grep('chm', field=-1)
945 """
945 """
946
946
947 def match_target(s):
947 def match_target(s):
948 if field is None:
948 if field is None:
949 return s
949 return s
950 parts = s.split()
950 parts = s.split()
951 try:
951 try:
952 tgt = parts[field]
952 tgt = parts[field]
953 return tgt
953 return tgt
954 except IndexError:
954 except IndexError:
955 return ""
955 return ""
956
956
957 if isinstance(pattern, basestring):
957 if isinstance(pattern, basestring):
958 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
958 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
959 else:
959 else:
960 pred = pattern
960 pred = pattern
961 if not prune:
961 if not prune:
962 return SList([el for el in self if pred(match_target(el))])
962 return SList([el for el in self if pred(match_target(el))])
963 else:
963 else:
964 return SList([el for el in self if not pred(match_target(el))])
964 return SList([el for el in self if not pred(match_target(el))])
965 def fields(self, *fields):
965 def fields(self, *fields):
966 """ Collect whitespace-separated fields from string list
966 """ Collect whitespace-separated fields from string list
967
967
968 Allows quick awk-like usage of string lists.
968 Allows quick awk-like usage of string lists.
969
969
970 Example data (in var a, created by 'a = !ls -l')::
970 Example data (in var a, created by 'a = !ls -l')::
971 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
971 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
972 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
972 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
973
973
974 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
974 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
975 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
975 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
976 (note the joining by space).
976 (note the joining by space).
977 a.fields(-1) is ['ChangeLog', 'IPython']
977 a.fields(-1) is ['ChangeLog', 'IPython']
978
978
979 IndexErrors are ignored.
979 IndexErrors are ignored.
980
980
981 Without args, fields() just split()'s the strings.
981 Without args, fields() just split()'s the strings.
982 """
982 """
983 if len(fields) == 0:
983 if len(fields) == 0:
984 return [el.split() for el in self]
984 return [el.split() for el in self]
985
985
986 res = SList()
986 res = SList()
987 for el in [f.split() for f in self]:
987 for el in [f.split() for f in self]:
988 lineparts = []
988 lineparts = []
989
989
990 for fd in fields:
990 for fd in fields:
991 try:
991 try:
992 lineparts.append(el[fd])
992 lineparts.append(el[fd])
993 except IndexError:
993 except IndexError:
994 pass
994 pass
995 if lineparts:
995 if lineparts:
996 res.append(" ".join(lineparts))
996 res.append(" ".join(lineparts))
997
997
998 return res
998 return res
999 def sort(self,field= None, nums = False):
999 def sort(self,field= None, nums = False):
1000 """ sort by specified fields (see fields())
1000 """ sort by specified fields (see fields())
1001
1001
1002 Example::
1002 Example::
1003 a.sort(1, nums = True)
1003 a.sort(1, nums = True)
1004
1004
1005 Sorts a by second field, in numerical order (so that 21 > 3)
1005 Sorts a by second field, in numerical order (so that 21 > 3)
1006
1006
1007 """
1007 """
1008
1008
1009 #decorate, sort, undecorate
1009 #decorate, sort, undecorate
1010 if field is not None:
1010 if field is not None:
1011 dsu = [[SList([line]).fields(field), line] for line in self]
1011 dsu = [[SList([line]).fields(field), line] for line in self]
1012 else:
1012 else:
1013 dsu = [[line, line] for line in self]
1013 dsu = [[line, line] for line in self]
1014 if nums:
1014 if nums:
1015 for i in range(len(dsu)):
1015 for i in range(len(dsu)):
1016 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1016 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1017 try:
1017 try:
1018 n = int(numstr)
1018 n = int(numstr)
1019 except ValueError:
1019 except ValueError:
1020 n = 0;
1020 n = 0;
1021 dsu[i][0] = n
1021 dsu[i][0] = n
1022
1022
1023
1023
1024 dsu.sort()
1024 dsu.sort()
1025 return SList([t[1] for t in dsu])
1025 return SList([t[1] for t in dsu])
1026
1026
1027 def print_slist(arg):
1027 def print_slist(arg):
1028 """ Prettier (non-repr-like) and more informative printer for SList """
1028 """ Prettier (non-repr-like) and more informative printer for SList """
1029 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1029 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1030 if hasattr(arg, 'hideonce') and arg.hideonce:
1030 if hasattr(arg, 'hideonce') and arg.hideonce:
1031 arg.hideonce = False
1031 arg.hideonce = False
1032 return
1032 return
1033
1033
1034 nlprint(arg)
1034 nlprint(arg)
1035
1035
1036 print_slist = result_display.when_type(SList)(print_slist)
1036 print_slist = result_display.when_type(SList)(print_slist)
1037
1037
1038
1038
1039
1039
1040 #----------------------------------------------------------------------------
1040 #----------------------------------------------------------------------------
1041 def esc_quotes(strng):
1041 def esc_quotes(strng):
1042 """Return the input string with single and double quotes escaped out"""
1042 """Return the input string with single and double quotes escaped out"""
1043
1043
1044 return strng.replace('"','\\"').replace("'","\\'")
1044 return strng.replace('"','\\"').replace("'","\\'")
1045
1045
1046 #----------------------------------------------------------------------------
1046 #----------------------------------------------------------------------------
1047 def make_quoted_expr(s):
1047 def make_quoted_expr(s):
1048 """Return string s in appropriate quotes, using raw string if possible.
1048 """Return string s in appropriate quotes, using raw string if possible.
1049
1049
1050 XXX - example removed because it caused encoding errors in documentation
1050 XXX - example removed because it caused encoding errors in documentation
1051 generation. We need a new example that doesn't contain invalid chars.
1051 generation. We need a new example that doesn't contain invalid chars.
1052
1052
1053 Note the use of raw string and padding at the end to allow trailing
1053 Note the use of raw string and padding at the end to allow trailing
1054 backslash.
1054 backslash.
1055 """
1055 """
1056
1056
1057 tail = ''
1057 tail = ''
1058 tailpadding = ''
1058 tailpadding = ''
1059 raw = ''
1059 raw = ''
1060 if "\\" in s:
1060 if "\\" in s:
1061 raw = 'r'
1061 raw = 'r'
1062 if s.endswith('\\'):
1062 if s.endswith('\\'):
1063 tail = '[:-1]'
1063 tail = '[:-1]'
1064 tailpadding = '_'
1064 tailpadding = '_'
1065 if '"' not in s:
1065 if '"' not in s:
1066 quote = '"'
1066 quote = '"'
1067 elif "'" not in s:
1067 elif "'" not in s:
1068 quote = "'"
1068 quote = "'"
1069 elif '"""' not in s and not s.endswith('"'):
1069 elif '"""' not in s and not s.endswith('"'):
1070 quote = '"""'
1070 quote = '"""'
1071 elif "'''" not in s and not s.endswith("'"):
1071 elif "'''" not in s and not s.endswith("'"):
1072 quote = "'''"
1072 quote = "'''"
1073 else:
1073 else:
1074 # give up, backslash-escaped string will do
1074 # give up, backslash-escaped string will do
1075 return '"%s"' % esc_quotes(s)
1075 return '"%s"' % esc_quotes(s)
1076 res = raw + quote + s + tailpadding + quote + tail
1076 res = raw + quote + s + tailpadding + quote + tail
1077 return res
1077 return res
1078
1078
1079
1079
1080 #----------------------------------------------------------------------------
1080 #----------------------------------------------------------------------------
1081 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1081 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1082 """Take multiple lines of input.
1082 """Take multiple lines of input.
1083
1083
1084 A list with each line of input as a separate element is returned when a
1084 A list with each line of input as a separate element is returned when a
1085 termination string is entered (defaults to a single '.'). Input can also
1085 termination string is entered (defaults to a single '.'). Input can also
1086 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1086 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1087
1087
1088 Lines of input which end in \\ are joined into single entries (and a
1088 Lines of input which end in \\ are joined into single entries (and a
1089 secondary continuation prompt is issued as long as the user terminates
1089 secondary continuation prompt is issued as long as the user terminates
1090 lines with \\). This allows entering very long strings which are still
1090 lines with \\). This allows entering very long strings which are still
1091 meant to be treated as single entities.
1091 meant to be treated as single entities.
1092 """
1092 """
1093
1093
1094 try:
1094 try:
1095 if header:
1095 if header:
1096 header += '\n'
1096 header += '\n'
1097 lines = [raw_input(header + ps1)]
1097 lines = [raw_input(header + ps1)]
1098 except EOFError:
1098 except EOFError:
1099 return []
1099 return []
1100 terminate = [terminate_str]
1100 terminate = [terminate_str]
1101 try:
1101 try:
1102 while lines[-1:] != terminate:
1102 while lines[-1:] != terminate:
1103 new_line = raw_input(ps1)
1103 new_line = raw_input(ps1)
1104 while new_line.endswith('\\'):
1104 while new_line.endswith('\\'):
1105 new_line = new_line[:-1] + raw_input(ps2)
1105 new_line = new_line[:-1] + raw_input(ps2)
1106 lines.append(new_line)
1106 lines.append(new_line)
1107
1107
1108 return lines[:-1] # don't return the termination command
1108 return lines[:-1] # don't return the termination command
1109 except EOFError:
1109 except EOFError:
1110 print
1110 print
1111 return lines
1111 return lines
1112
1112
1113 #----------------------------------------------------------------------------
1113 #----------------------------------------------------------------------------
1114 def raw_input_ext(prompt='', ps2='... '):
1114 def raw_input_ext(prompt='', ps2='... '):
1115 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1115 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1116
1116
1117 line = raw_input(prompt)
1117 line = raw_input(prompt)
1118 while line.endswith('\\'):
1118 while line.endswith('\\'):
1119 line = line[:-1] + raw_input(ps2)
1119 line = line[:-1] + raw_input(ps2)
1120 return line
1120 return line
1121
1121
1122 #----------------------------------------------------------------------------
1122 #----------------------------------------------------------------------------
1123 def ask_yes_no(prompt,default=None):
1123 def ask_yes_no(prompt,default=None):
1124 """Asks a question and returns a boolean (y/n) answer.
1124 """Asks a question and returns a boolean (y/n) answer.
1125
1125
1126 If default is given (one of 'y','n'), it is used if the user input is
1126 If default is given (one of 'y','n'), it is used if the user input is
1127 empty. Otherwise the question is repeated until an answer is given.
1127 empty. Otherwise the question is repeated until an answer is given.
1128
1128
1129 An EOF is treated as the default answer. If there is no default, an
1129 An EOF is treated as the default answer. If there is no default, an
1130 exception is raised to prevent infinite loops.
1130 exception is raised to prevent infinite loops.
1131
1131
1132 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1132 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1133
1133
1134 answers = {'y':True,'n':False,'yes':True,'no':False}
1134 answers = {'y':True,'n':False,'yes':True,'no':False}
1135 ans = None
1135 ans = None
1136 while ans not in answers.keys():
1136 while ans not in answers.keys():
1137 try:
1137 try:
1138 ans = raw_input(prompt+' ').lower()
1138 ans = raw_input(prompt+' ').lower()
1139 if not ans: # response was an empty string
1139 if not ans: # response was an empty string
1140 ans = default
1140 ans = default
1141 except KeyboardInterrupt:
1141 except KeyboardInterrupt:
1142 pass
1142 pass
1143 except EOFError:
1143 except EOFError:
1144 if default in answers.keys():
1144 if default in answers.keys():
1145 ans = default
1145 ans = default
1146 print
1146 print
1147 else:
1147 else:
1148 raise
1148 raise
1149
1149
1150 return answers[ans]
1150 return answers[ans]
1151
1151
1152 #----------------------------------------------------------------------------
1152 #----------------------------------------------------------------------------
1153 class EvalDict:
1153 class EvalDict:
1154 """
1154 """
1155 Emulate a dict which evaluates its contents in the caller's frame.
1155 Emulate a dict which evaluates its contents in the caller's frame.
1156
1156
1157 Usage:
1157 Usage:
1158 >>> number = 19
1158 >>> number = 19
1159
1159
1160 >>> text = "python"
1160 >>> text = "python"
1161
1161
1162 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1162 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1163 Python 2.1 rules!
1163 Python 2.1 rules!
1164 """
1164 """
1165
1165
1166 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1166 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1167 # modified (shorter) version of:
1167 # modified (shorter) version of:
1168 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1168 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1169 # Skip Montanaro (skip@pobox.com).
1169 # Skip Montanaro (skip@pobox.com).
1170
1170
1171 def __getitem__(self, name):
1171 def __getitem__(self, name):
1172 frame = sys._getframe(1)
1172 frame = sys._getframe(1)
1173 return eval(name, frame.f_globals, frame.f_locals)
1173 return eval(name, frame.f_globals, frame.f_locals)
1174
1174
1175 EvalString = EvalDict # for backwards compatibility
1175 EvalString = EvalDict # for backwards compatibility
1176 #----------------------------------------------------------------------------
1176 #----------------------------------------------------------------------------
1177 def qw(words,flat=0,sep=None,maxsplit=-1):
1177 def qw(words,flat=0,sep=None,maxsplit=-1):
1178 """Similar to Perl's qw() operator, but with some more options.
1178 """Similar to Perl's qw() operator, but with some more options.
1179
1179
1180 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1180 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1181
1181
1182 words can also be a list itself, and with flat=1, the output will be
1182 words can also be a list itself, and with flat=1, the output will be
1183 recursively flattened.
1183 recursively flattened.
1184
1184
1185 Examples:
1185 Examples:
1186
1186
1187 >>> qw('1 2')
1187 >>> qw('1 2')
1188 ['1', '2']
1188 ['1', '2']
1189
1189
1190 >>> qw(['a b','1 2',['m n','p q']])
1190 >>> qw(['a b','1 2',['m n','p q']])
1191 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1191 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1192
1192
1193 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1193 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1194 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1194 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1195 """
1195 """
1196
1196
1197 if type(words) in StringTypes:
1197 if type(words) in StringTypes:
1198 return [word.strip() for word in words.split(sep,maxsplit)
1198 return [word.strip() for word in words.split(sep,maxsplit)
1199 if word and not word.isspace() ]
1199 if word and not word.isspace() ]
1200 if flat:
1200 if flat:
1201 return flatten(map(qw,words,[1]*len(words)))
1201 return flatten(map(qw,words,[1]*len(words)))
1202 return map(qw,words)
1202 return map(qw,words)
1203
1203
1204 #----------------------------------------------------------------------------
1204 #----------------------------------------------------------------------------
1205 def qwflat(words,sep=None,maxsplit=-1):
1205 def qwflat(words,sep=None,maxsplit=-1):
1206 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1206 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1207 return qw(words,1,sep,maxsplit)
1207 return qw(words,1,sep,maxsplit)
1208
1208
1209 #----------------------------------------------------------------------------
1209 #----------------------------------------------------------------------------
1210 def qw_lol(indata):
1210 def qw_lol(indata):
1211 """qw_lol('a b') -> [['a','b']],
1211 """qw_lol('a b') -> [['a','b']],
1212 otherwise it's just a call to qw().
1212 otherwise it's just a call to qw().
1213
1213
1214 We need this to make sure the modules_some keys *always* end up as a
1214 We need this to make sure the modules_some keys *always* end up as a
1215 list of lists."""
1215 list of lists."""
1216
1216
1217 if type(indata) in StringTypes:
1217 if type(indata) in StringTypes:
1218 return [qw(indata)]
1218 return [qw(indata)]
1219 else:
1219 else:
1220 return qw(indata)
1220 return qw(indata)
1221
1221
1222 #----------------------------------------------------------------------------
1222 #----------------------------------------------------------------------------
1223 def grep(pat,list,case=1):
1223 def grep(pat,list,case=1):
1224 """Simple minded grep-like function.
1224 """Simple minded grep-like function.
1225 grep(pat,list) returns occurrences of pat in list, None on failure.
1225 grep(pat,list) returns occurrences of pat in list, None on failure.
1226
1226
1227 It only does simple string matching, with no support for regexps. Use the
1227 It only does simple string matching, with no support for regexps. Use the
1228 option case=0 for case-insensitive matching."""
1228 option case=0 for case-insensitive matching."""
1229
1229
1230 # This is pretty crude. At least it should implement copying only references
1230 # This is pretty crude. At least it should implement copying only references
1231 # to the original data in case it's big. Now it copies the data for output.
1231 # to the original data in case it's big. Now it copies the data for output.
1232 out=[]
1232 out=[]
1233 if case:
1233 if case:
1234 for term in list:
1234 for term in list:
1235 if term.find(pat)>-1: out.append(term)
1235 if term.find(pat)>-1: out.append(term)
1236 else:
1236 else:
1237 lpat=pat.lower()
1237 lpat=pat.lower()
1238 for term in list:
1238 for term in list:
1239 if term.lower().find(lpat)>-1: out.append(term)
1239 if term.lower().find(lpat)>-1: out.append(term)
1240
1240
1241 if len(out): return out
1241 if len(out): return out
1242 else: return None
1242 else: return None
1243
1243
1244 #----------------------------------------------------------------------------
1244 #----------------------------------------------------------------------------
1245 def dgrep(pat,*opts):
1245 def dgrep(pat,*opts):
1246 """Return grep() on dir()+dir(__builtins__).
1246 """Return grep() on dir()+dir(__builtins__).
1247
1247
1248 A very common use of grep() when working interactively."""
1248 A very common use of grep() when working interactively."""
1249
1249
1250 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1250 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1251
1251
1252 #----------------------------------------------------------------------------
1252 #----------------------------------------------------------------------------
1253 def idgrep(pat):
1253 def idgrep(pat):
1254 """Case-insensitive dgrep()"""
1254 """Case-insensitive dgrep()"""
1255
1255
1256 return dgrep(pat,0)
1256 return dgrep(pat,0)
1257
1257
1258 #----------------------------------------------------------------------------
1258 #----------------------------------------------------------------------------
1259 def igrep(pat,list):
1259 def igrep(pat,list):
1260 """Synonym for case-insensitive grep."""
1260 """Synonym for case-insensitive grep."""
1261
1261
1262 return grep(pat,list,case=0)
1262 return grep(pat,list,case=0)
1263
1263
1264 #----------------------------------------------------------------------------
1264 #----------------------------------------------------------------------------
1265 def indent(str,nspaces=4,ntabs=0):
1265 def indent(str,nspaces=4,ntabs=0):
1266 """Indent a string a given number of spaces or tabstops.
1266 """Indent a string a given number of spaces or tabstops.
1267
1267
1268 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1268 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1269 """
1269 """
1270 if str is None:
1270 if str is None:
1271 return
1271 return
1272 ind = '\t'*ntabs+' '*nspaces
1272 ind = '\t'*ntabs+' '*nspaces
1273 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1273 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1274 if outstr.endswith(os.linesep+ind):
1274 if outstr.endswith(os.linesep+ind):
1275 return outstr[:-len(ind)]
1275 return outstr[:-len(ind)]
1276 else:
1276 else:
1277 return outstr
1277 return outstr
1278
1278
1279 #-----------------------------------------------------------------------------
1279 #-----------------------------------------------------------------------------
1280 def native_line_ends(filename,backup=1):
1280 def native_line_ends(filename,backup=1):
1281 """Convert (in-place) a file to line-ends native to the current OS.
1281 """Convert (in-place) a file to line-ends native to the current OS.
1282
1282
1283 If the optional backup argument is given as false, no backup of the
1283 If the optional backup argument is given as false, no backup of the
1284 original file is left. """
1284 original file is left. """
1285
1285
1286 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1286 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1287
1287
1288 bak_filename = filename + backup_suffixes[os.name]
1288 bak_filename = filename + backup_suffixes[os.name]
1289
1289
1290 original = open(filename).read()
1290 original = open(filename).read()
1291 shutil.copy2(filename,bak_filename)
1291 shutil.copy2(filename,bak_filename)
1292 try:
1292 try:
1293 new = open(filename,'wb')
1293 new = open(filename,'wb')
1294 new.write(os.linesep.join(original.splitlines()))
1294 new.write(os.linesep.join(original.splitlines()))
1295 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1295 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1296 new.close()
1296 new.close()
1297 except:
1297 except:
1298 os.rename(bak_filename,filename)
1298 os.rename(bak_filename,filename)
1299 if not backup:
1299 if not backup:
1300 try:
1300 try:
1301 os.remove(bak_filename)
1301 os.remove(bak_filename)
1302 except:
1302 except:
1303 pass
1303 pass
1304
1304
1305 #****************************************************************************
1305 #****************************************************************************
1306 # lists, dicts and structures
1306 # lists, dicts and structures
1307
1307
1308 def belong(candidates,checklist):
1308 def belong(candidates,checklist):
1309 """Check whether a list of items appear in a given list of options.
1309 """Check whether a list of items appear in a given list of options.
1310
1310
1311 Returns a list of 1 and 0, one for each candidate given."""
1311 Returns a list of 1 and 0, one for each candidate given."""
1312
1312
1313 return [x in checklist for x in candidates]
1313 return [x in checklist for x in candidates]
1314
1314
1315 #----------------------------------------------------------------------------
1315 #----------------------------------------------------------------------------
1316 def uniq_stable(elems):
1316 def uniq_stable(elems):
1317 """uniq_stable(elems) -> list
1317 """uniq_stable(elems) -> list
1318
1318
1319 Return from an iterable, a list of all the unique elements in the input,
1319 Return from an iterable, a list of all the unique elements in the input,
1320 but maintaining the order in which they first appear.
1320 but maintaining the order in which they first appear.
1321
1321
1322 A naive solution to this problem which just makes a dictionary with the
1322 A naive solution to this problem which just makes a dictionary with the
1323 elements as keys fails to respect the stability condition, since
1323 elements as keys fails to respect the stability condition, since
1324 dictionaries are unsorted by nature.
1324 dictionaries are unsorted by nature.
1325
1325
1326 Note: All elements in the input must be valid dictionary keys for this
1326 Note: All elements in the input must be valid dictionary keys for this
1327 routine to work, as it internally uses a dictionary for efficiency
1327 routine to work, as it internally uses a dictionary for efficiency
1328 reasons."""
1328 reasons."""
1329
1329
1330 unique = []
1330 unique = []
1331 unique_dict = {}
1331 unique_dict = {}
1332 for nn in elems:
1332 for nn in elems:
1333 if nn not in unique_dict:
1333 if nn not in unique_dict:
1334 unique.append(nn)
1334 unique.append(nn)
1335 unique_dict[nn] = None
1335 unique_dict[nn] = None
1336 return unique
1336 return unique
1337
1337
1338 #----------------------------------------------------------------------------
1338 #----------------------------------------------------------------------------
1339 class NLprinter:
1339 class NLprinter:
1340 """Print an arbitrarily nested list, indicating index numbers.
1340 """Print an arbitrarily nested list, indicating index numbers.
1341
1341
1342 An instance of this class called nlprint is available and callable as a
1342 An instance of this class called nlprint is available and callable as a
1343 function.
1343 function.
1344
1344
1345 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1345 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1346 and using 'sep' to separate the index from the value. """
1346 and using 'sep' to separate the index from the value. """
1347
1347
1348 def __init__(self):
1348 def __init__(self):
1349 self.depth = 0
1349 self.depth = 0
1350
1350
1351 def __call__(self,lst,pos='',**kw):
1351 def __call__(self,lst,pos='',**kw):
1352 """Prints the nested list numbering levels."""
1352 """Prints the nested list numbering levels."""
1353 kw.setdefault('indent',' ')
1353 kw.setdefault('indent',' ')
1354 kw.setdefault('sep',': ')
1354 kw.setdefault('sep',': ')
1355 kw.setdefault('start',0)
1355 kw.setdefault('start',0)
1356 kw.setdefault('stop',len(lst))
1356 kw.setdefault('stop',len(lst))
1357 # we need to remove start and stop from kw so they don't propagate
1357 # we need to remove start and stop from kw so they don't propagate
1358 # into a recursive call for a nested list.
1358 # into a recursive call for a nested list.
1359 start = kw['start']; del kw['start']
1359 start = kw['start']; del kw['start']
1360 stop = kw['stop']; del kw['stop']
1360 stop = kw['stop']; del kw['stop']
1361 if self.depth == 0 and 'header' in kw.keys():
1361 if self.depth == 0 and 'header' in kw.keys():
1362 print kw['header']
1362 print kw['header']
1363
1363
1364 for idx in range(start,stop):
1364 for idx in range(start,stop):
1365 elem = lst[idx]
1365 elem = lst[idx]
1366 if type(elem)==type([]):
1366 if type(elem)==type([]):
1367 self.depth += 1
1367 self.depth += 1
1368 self.__call__(elem,itpl('$pos$idx,'),**kw)
1368 self.__call__(elem,itpl('$pos$idx,'),**kw)
1369 self.depth -= 1
1369 self.depth -= 1
1370 else:
1370 else:
1371 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1371 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1372
1372
1373 nlprint = NLprinter()
1373 nlprint = NLprinter()
1374 #----------------------------------------------------------------------------
1374 #----------------------------------------------------------------------------
1375 def all_belong(candidates,checklist):
1375 def all_belong(candidates,checklist):
1376 """Check whether a list of items ALL appear in a given list of options.
1376 """Check whether a list of items ALL appear in a given list of options.
1377
1377
1378 Returns a single 1 or 0 value."""
1378 Returns a single 1 or 0 value."""
1379
1379
1380 return 1-(0 in [x in checklist for x in candidates])
1380 return 1-(0 in [x in checklist for x in candidates])
1381
1381
1382 #----------------------------------------------------------------------------
1382 #----------------------------------------------------------------------------
1383 def sort_compare(lst1,lst2,inplace = 1):
1383 def sort_compare(lst1,lst2,inplace = 1):
1384 """Sort and compare two lists.
1384 """Sort and compare two lists.
1385
1385
1386 By default it does it in place, thus modifying the lists. Use inplace = 0
1386 By default it does it in place, thus modifying the lists. Use inplace = 0
1387 to avoid that (at the cost of temporary copy creation)."""
1387 to avoid that (at the cost of temporary copy creation)."""
1388 if not inplace:
1388 if not inplace:
1389 lst1 = lst1[:]
1389 lst1 = lst1[:]
1390 lst2 = lst2[:]
1390 lst2 = lst2[:]
1391 lst1.sort(); lst2.sort()
1391 lst1.sort(); lst2.sort()
1392 return lst1 == lst2
1392 return lst1 == lst2
1393
1393
1394 #----------------------------------------------------------------------------
1394 #----------------------------------------------------------------------------
1395 def list2dict(lst):
1395 def list2dict(lst):
1396 """Takes a list of (key,value) pairs and turns it into a dict."""
1396 """Takes a list of (key,value) pairs and turns it into a dict."""
1397
1397
1398 dic = {}
1398 dic = {}
1399 for k,v in lst: dic[k] = v
1399 for k,v in lst: dic[k] = v
1400 return dic
1400 return dic
1401
1401
1402 #----------------------------------------------------------------------------
1402 #----------------------------------------------------------------------------
1403 def list2dict2(lst,default=''):
1403 def list2dict2(lst,default=''):
1404 """Takes a list and turns it into a dict.
1404 """Takes a list and turns it into a dict.
1405 Much slower than list2dict, but more versatile. This version can take
1405 Much slower than list2dict, but more versatile. This version can take
1406 lists with sublists of arbitrary length (including sclars)."""
1406 lists with sublists of arbitrary length (including sclars)."""
1407
1407
1408 dic = {}
1408 dic = {}
1409 for elem in lst:
1409 for elem in lst:
1410 if type(elem) in (types.ListType,types.TupleType):
1410 if type(elem) in (types.ListType,types.TupleType):
1411 size = len(elem)
1411 size = len(elem)
1412 if size == 0:
1412 if size == 0:
1413 pass
1413 pass
1414 elif size == 1:
1414 elif size == 1:
1415 dic[elem] = default
1415 dic[elem] = default
1416 else:
1416 else:
1417 k,v = elem[0], elem[1:]
1417 k,v = elem[0], elem[1:]
1418 if len(v) == 1: v = v[0]
1418 if len(v) == 1: v = v[0]
1419 dic[k] = v
1419 dic[k] = v
1420 else:
1420 else:
1421 dic[elem] = default
1421 dic[elem] = default
1422 return dic
1422 return dic
1423
1423
1424 #----------------------------------------------------------------------------
1424 #----------------------------------------------------------------------------
1425 def flatten(seq):
1425 def flatten(seq):
1426 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1426 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1427
1427
1428 return [x for subseq in seq for x in subseq]
1428 return [x for subseq in seq for x in subseq]
1429
1429
1430 #----------------------------------------------------------------------------
1430 #----------------------------------------------------------------------------
1431 def get_slice(seq,start=0,stop=None,step=1):
1431 def get_slice(seq,start=0,stop=None,step=1):
1432 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1432 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1433 if stop == None:
1433 if stop == None:
1434 stop = len(seq)
1434 stop = len(seq)
1435 item = lambda i: seq[i]
1435 item = lambda i: seq[i]
1436 return map(item,xrange(start,stop,step))
1436 return map(item,xrange(start,stop,step))
1437
1437
1438 #----------------------------------------------------------------------------
1438 #----------------------------------------------------------------------------
1439 def chop(seq,size):
1439 def chop(seq,size):
1440 """Chop a sequence into chunks of the given size."""
1440 """Chop a sequence into chunks of the given size."""
1441 chunk = lambda i: seq[i:i+size]
1441 chunk = lambda i: seq[i:i+size]
1442 return map(chunk,xrange(0,len(seq),size))
1442 return map(chunk,xrange(0,len(seq),size))
1443
1443
1444 #----------------------------------------------------------------------------
1444 #----------------------------------------------------------------------------
1445 # with is a keyword as of python 2.5, so this function is renamed to withobj
1445 # with is a keyword as of python 2.5, so this function is renamed to withobj
1446 # from its old 'with' name.
1446 # from its old 'with' name.
1447 def with_obj(object, **args):
1447 def with_obj(object, **args):
1448 """Set multiple attributes for an object, similar to Pascal's with.
1448 """Set multiple attributes for an object, similar to Pascal's with.
1449
1449
1450 Example:
1450 Example:
1451 with_obj(jim,
1451 with_obj(jim,
1452 born = 1960,
1452 born = 1960,
1453 haircolour = 'Brown',
1453 haircolour = 'Brown',
1454 eyecolour = 'Green')
1454 eyecolour = 'Green')
1455
1455
1456 Credit: Greg Ewing, in
1456 Credit: Greg Ewing, in
1457 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1457 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1458
1458
1459 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1459 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1460 has become a keyword for Python 2.5, so we had to rename it."""
1460 has become a keyword for Python 2.5, so we had to rename it."""
1461
1461
1462 object.__dict__.update(args)
1462 object.__dict__.update(args)
1463
1463
1464 #----------------------------------------------------------------------------
1464 #----------------------------------------------------------------------------
1465 def setattr_list(obj,alist,nspace = None):
1465 def setattr_list(obj,alist,nspace = None):
1466 """Set a list of attributes for an object taken from a namespace.
1466 """Set a list of attributes for an object taken from a namespace.
1467
1467
1468 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1468 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1469 alist with their values taken from nspace, which must be a dict (something
1469 alist with their values taken from nspace, which must be a dict (something
1470 like locals() will often do) If nspace isn't given, locals() of the
1470 like locals() will often do) If nspace isn't given, locals() of the
1471 *caller* is used, so in most cases you can omit it.
1471 *caller* is used, so in most cases you can omit it.
1472
1472
1473 Note that alist can be given as a string, which will be automatically
1473 Note that alist can be given as a string, which will be automatically
1474 split into a list on whitespace. If given as a list, it must be a list of
1474 split into a list on whitespace. If given as a list, it must be a list of
1475 *strings* (the variable names themselves), not of variables."""
1475 *strings* (the variable names themselves), not of variables."""
1476
1476
1477 # this grabs the local variables from the *previous* call frame -- that is
1477 # this grabs the local variables from the *previous* call frame -- that is
1478 # the locals from the function that called setattr_list().
1478 # the locals from the function that called setattr_list().
1479 # - snipped from weave.inline()
1479 # - snipped from weave.inline()
1480 if nspace is None:
1480 if nspace is None:
1481 call_frame = sys._getframe().f_back
1481 call_frame = sys._getframe().f_back
1482 nspace = call_frame.f_locals
1482 nspace = call_frame.f_locals
1483
1483
1484 if type(alist) in StringTypes:
1484 if type(alist) in StringTypes:
1485 alist = alist.split()
1485 alist = alist.split()
1486 for attr in alist:
1486 for attr in alist:
1487 val = eval(attr,nspace)
1487 val = eval(attr,nspace)
1488 setattr(obj,attr,val)
1488 setattr(obj,attr,val)
1489
1489
1490 #----------------------------------------------------------------------------
1490 #----------------------------------------------------------------------------
1491 def getattr_list(obj,alist,*args):
1491 def getattr_list(obj,alist,*args):
1492 """getattr_list(obj,alist[, default]) -> attribute list.
1492 """getattr_list(obj,alist[, default]) -> attribute list.
1493
1493
1494 Get a list of named attributes for an object. When a default argument is
1494 Get a list of named attributes for an object. When a default argument is
1495 given, it is returned when the attribute doesn't exist; without it, an
1495 given, it is returned when the attribute doesn't exist; without it, an
1496 exception is raised in that case.
1496 exception is raised in that case.
1497
1497
1498 Note that alist can be given as a string, which will be automatically
1498 Note that alist can be given as a string, which will be automatically
1499 split into a list on whitespace. If given as a list, it must be a list of
1499 split into a list on whitespace. If given as a list, it must be a list of
1500 *strings* (the variable names themselves), not of variables."""
1500 *strings* (the variable names themselves), not of variables."""
1501
1501
1502 if type(alist) in StringTypes:
1502 if type(alist) in StringTypes:
1503 alist = alist.split()
1503 alist = alist.split()
1504 if args:
1504 if args:
1505 if len(args)==1:
1505 if len(args)==1:
1506 default = args[0]
1506 default = args[0]
1507 return map(lambda attr: getattr(obj,attr,default),alist)
1507 return map(lambda attr: getattr(obj,attr,default),alist)
1508 else:
1508 else:
1509 raise ValueError,'getattr_list() takes only one optional argument'
1509 raise ValueError,'getattr_list() takes only one optional argument'
1510 else:
1510 else:
1511 return map(lambda attr: getattr(obj,attr),alist)
1511 return map(lambda attr: getattr(obj,attr),alist)
1512
1512
1513 #----------------------------------------------------------------------------
1513 #----------------------------------------------------------------------------
1514 def map_method(method,object_list,*argseq,**kw):
1514 def map_method(method,object_list,*argseq,**kw):
1515 """map_method(method,object_list,*args,**kw) -> list
1515 """map_method(method,object_list,*args,**kw) -> list
1516
1516
1517 Return a list of the results of applying the methods to the items of the
1517 Return a list of the results of applying the methods to the items of the
1518 argument sequence(s). If more than one sequence is given, the method is
1518 argument sequence(s). If more than one sequence is given, the method is
1519 called with an argument list consisting of the corresponding item of each
1519 called with an argument list consisting of the corresponding item of each
1520 sequence. All sequences must be of the same length.
1520 sequence. All sequences must be of the same length.
1521
1521
1522 Keyword arguments are passed verbatim to all objects called.
1522 Keyword arguments are passed verbatim to all objects called.
1523
1523
1524 This is Python code, so it's not nearly as fast as the builtin map()."""
1524 This is Python code, so it's not nearly as fast as the builtin map()."""
1525
1525
1526 out_list = []
1526 out_list = []
1527 idx = 0
1527 idx = 0
1528 for object in object_list:
1528 for object in object_list:
1529 try:
1529 try:
1530 handler = getattr(object, method)
1530 handler = getattr(object, method)
1531 except AttributeError:
1531 except AttributeError:
1532 out_list.append(None)
1532 out_list.append(None)
1533 else:
1533 else:
1534 if argseq:
1534 if argseq:
1535 args = map(lambda lst:lst[idx],argseq)
1535 args = map(lambda lst:lst[idx],argseq)
1536 #print 'ob',object,'hand',handler,'ar',args # dbg
1536 #print 'ob',object,'hand',handler,'ar',args # dbg
1537 out_list.append(handler(args,**kw))
1537 out_list.append(handler(args,**kw))
1538 else:
1538 else:
1539 out_list.append(handler(**kw))
1539 out_list.append(handler(**kw))
1540 idx += 1
1540 idx += 1
1541 return out_list
1541 return out_list
1542
1542
1543 #----------------------------------------------------------------------------
1543 #----------------------------------------------------------------------------
1544 def get_class_members(cls):
1544 def get_class_members(cls):
1545 ret = dir(cls)
1545 ret = dir(cls)
1546 if hasattr(cls,'__bases__'):
1546 if hasattr(cls,'__bases__'):
1547 for base in cls.__bases__:
1547 for base in cls.__bases__:
1548 ret.extend(get_class_members(base))
1548 ret.extend(get_class_members(base))
1549 return ret
1549 return ret
1550
1550
1551 #----------------------------------------------------------------------------
1551 #----------------------------------------------------------------------------
1552 def dir2(obj):
1552 def dir2(obj):
1553 """dir2(obj) -> list of strings
1553 """dir2(obj) -> list of strings
1554
1554
1555 Extended version of the Python builtin dir(), which does a few extra
1555 Extended version of the Python builtin dir(), which does a few extra
1556 checks, and supports common objects with unusual internals that confuse
1556 checks, and supports common objects with unusual internals that confuse
1557 dir(), such as Traits and PyCrust.
1557 dir(), such as Traits and PyCrust.
1558
1558
1559 This version is guaranteed to return only a list of true strings, whereas
1559 This version is guaranteed to return only a list of true strings, whereas
1560 dir() returns anything that objects inject into themselves, even if they
1560 dir() returns anything that objects inject into themselves, even if they
1561 are later not really valid for attribute access (many extension libraries
1561 are later not really valid for attribute access (many extension libraries
1562 have such bugs).
1562 have such bugs).
1563 """
1563 """
1564
1564
1565 # Start building the attribute list via dir(), and then complete it
1565 # Start building the attribute list via dir(), and then complete it
1566 # with a few extra special-purpose calls.
1566 # with a few extra special-purpose calls.
1567 words = dir(obj)
1567 words = dir(obj)
1568
1568
1569 if hasattr(obj,'__class__'):
1569 if hasattr(obj,'__class__'):
1570 words.append('__class__')
1570 words.append('__class__')
1571 words.extend(get_class_members(obj.__class__))
1571 words.extend(get_class_members(obj.__class__))
1572 #if '__base__' in words: 1/0
1572 #if '__base__' in words: 1/0
1573
1573
1574 # Some libraries (such as traits) may introduce duplicates, we want to
1574 # Some libraries (such as traits) may introduce duplicates, we want to
1575 # track and clean this up if it happens
1575 # track and clean this up if it happens
1576 may_have_dupes = False
1576 may_have_dupes = False
1577
1577
1578 # this is the 'dir' function for objects with Enthought's traits
1578 # this is the 'dir' function for objects with Enthought's traits
1579 if hasattr(obj, 'trait_names'):
1579 if hasattr(obj, 'trait_names'):
1580 try:
1580 try:
1581 words.extend(obj.trait_names())
1581 words.extend(obj.trait_names())
1582 may_have_dupes = True
1582 may_have_dupes = True
1583 except TypeError:
1583 except TypeError:
1584 # This will happen if `obj` is a class and not an instance.
1584 # This will happen if `obj` is a class and not an instance.
1585 pass
1585 pass
1586
1586
1587 # Support for PyCrust-style _getAttributeNames magic method.
1587 # Support for PyCrust-style _getAttributeNames magic method.
1588 if hasattr(obj, '_getAttributeNames'):
1588 if hasattr(obj, '_getAttributeNames'):
1589 try:
1589 try:
1590 words.extend(obj._getAttributeNames())
1590 words.extend(obj._getAttributeNames())
1591 may_have_dupes = True
1591 may_have_dupes = True
1592 except TypeError:
1592 except TypeError:
1593 # `obj` is a class and not an instance. Ignore
1593 # `obj` is a class and not an instance. Ignore
1594 # this error.
1594 # this error.
1595 pass
1595 pass
1596
1596
1597 if may_have_dupes:
1597 if may_have_dupes:
1598 # eliminate possible duplicates, as some traits may also
1598 # eliminate possible duplicates, as some traits may also
1599 # appear as normal attributes in the dir() call.
1599 # appear as normal attributes in the dir() call.
1600 words = list(set(words))
1600 words = list(set(words))
1601 words.sort()
1601 words.sort()
1602
1602
1603 # filter out non-string attributes which may be stuffed by dir() calls
1603 # filter out non-string attributes which may be stuffed by dir() calls
1604 # and poor coding in third-party modules
1604 # and poor coding in third-party modules
1605 return [w for w in words if isinstance(w, basestring)]
1605 return [w for w in words if isinstance(w, basestring)]
1606
1606
1607 #----------------------------------------------------------------------------
1607 #----------------------------------------------------------------------------
1608 def import_fail_info(mod_name,fns=None):
1608 def import_fail_info(mod_name,fns=None):
1609 """Inform load failure for a module."""
1609 """Inform load failure for a module."""
1610
1610
1611 if fns == None:
1611 if fns == None:
1612 warn("Loading of %s failed.\n" % (mod_name,))
1612 warn("Loading of %s failed.\n" % (mod_name,))
1613 else:
1613 else:
1614 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1614 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1615
1615
1616 #----------------------------------------------------------------------------
1616 #----------------------------------------------------------------------------
1617 # Proposed popitem() extension, written as a method
1617 # Proposed popitem() extension, written as a method
1618
1618
1619
1619
1620 class NotGiven: pass
1620 class NotGiven: pass
1621
1621
1622 def popkey(dct,key,default=NotGiven):
1622 def popkey(dct,key,default=NotGiven):
1623 """Return dct[key] and delete dct[key].
1623 """Return dct[key] and delete dct[key].
1624
1624
1625 If default is given, return it if dct[key] doesn't exist, otherwise raise
1625 If default is given, return it if dct[key] doesn't exist, otherwise raise
1626 KeyError. """
1626 KeyError. """
1627
1627
1628 try:
1628 try:
1629 val = dct[key]
1629 val = dct[key]
1630 except KeyError:
1630 except KeyError:
1631 if default is NotGiven:
1631 if default is NotGiven:
1632 raise
1632 raise
1633 else:
1633 else:
1634 return default
1634 return default
1635 else:
1635 else:
1636 del dct[key]
1636 del dct[key]
1637 return val
1637 return val
1638
1638
1639 def wrap_deprecated(func, suggest = '<nothing>'):
1639 def wrap_deprecated(func, suggest = '<nothing>'):
1640 def newFunc(*args, **kwargs):
1640 def newFunc(*args, **kwargs):
1641 warnings.warn("Call to deprecated function %s, use %s instead" %
1641 warnings.warn("Call to deprecated function %s, use %s instead" %
1642 ( func.__name__, suggest),
1642 ( func.__name__, suggest),
1643 category=DeprecationWarning,
1643 category=DeprecationWarning,
1644 stacklevel = 2)
1644 stacklevel = 2)
1645 return func(*args, **kwargs)
1645 return func(*args, **kwargs)
1646 return newFunc
1646 return newFunc
1647
1647
1648
1648
1649 def _num_cpus_unix():
1649 def _num_cpus_unix():
1650 """Return the number of active CPUs on a Unix system."""
1650 """Return the number of active CPUs on a Unix system."""
1651 return os.sysconf("SC_NPROCESSORS_ONLN")
1651 return os.sysconf("SC_NPROCESSORS_ONLN")
1652
1652
1653
1653
1654 def _num_cpus_darwin():
1654 def _num_cpus_darwin():
1655 """Return the number of active CPUs on a Darwin system."""
1655 """Return the number of active CPUs on a Darwin system."""
1656 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
1656 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
1657 return p.stdout.read()
1657 return p.stdout.read()
1658
1658
1659
1659
1660 def _num_cpus_windows():
1660 def _num_cpus_windows():
1661 """Return the number of active CPUs on a Windows system."""
1661 """Return the number of active CPUs on a Windows system."""
1662 return os.environ.get("NUMBER_OF_PROCESSORS")
1662 return os.environ.get("NUMBER_OF_PROCESSORS")
1663
1663
1664
1664
1665 def num_cpus():
1665 def num_cpus():
1666 """Return the effective number of CPUs in the system as an integer.
1666 """Return the effective number of CPUs in the system as an integer.
1667
1667
1668 This cross-platform function makes an attempt at finding the total number of
1668 This cross-platform function makes an attempt at finding the total number of
1669 available CPUs in the system, as returned by various underlying system and
1669 available CPUs in the system, as returned by various underlying system and
1670 python calls.
1670 python calls.
1671
1671
1672 If it can't find a sensible answer, it returns 1 (though an error *may* make
1672 If it can't find a sensible answer, it returns 1 (though an error *may* make
1673 it return a large positive number that's actually incorrect).
1673 it return a large positive number that's actually incorrect).
1674 """
1674 """
1675
1675
1676 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
1676 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
1677 # for the names of the keys we needed to look up for this function. This
1677 # for the names of the keys we needed to look up for this function. This
1678 # code was inspired by their equivalent function.
1678 # code was inspired by their equivalent function.
1679
1679
1680 ncpufuncs = {'Linux':_num_cpus_unix,
1680 ncpufuncs = {'Linux':_num_cpus_unix,
1681 'Darwin':_num_cpus_darwin,
1681 'Darwin':_num_cpus_darwin,
1682 'Windows':_num_cpus_windows,
1682 'Windows':_num_cpus_windows,
1683 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
1683 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
1684 # See http://bugs.python.org/issue1082 for details.
1684 # See http://bugs.python.org/issue1082 for details.
1685 'Microsoft':_num_cpus_windows,
1685 'Microsoft':_num_cpus_windows,
1686 }
1686 }
1687
1687
1688 ncpufunc = ncpufuncs.get(platform.system(),
1688 ncpufunc = ncpufuncs.get(platform.system(),
1689 # default to unix version (Solaris, AIX, etc)
1689 # default to unix version (Solaris, AIX, etc)
1690 _num_cpus_unix)
1690 _num_cpus_unix)
1691
1691
1692 try:
1692 try:
1693 ncpus = max(1,int(ncpufunc()))
1693 ncpus = max(1,int(ncpufunc()))
1694 except:
1694 except:
1695 ncpus = 1
1695 ncpus = 1
1696 return ncpus
1696 return ncpus
1697
1697
1698 def extract_vars(*names,**kw):
1698 def extract_vars(*names,**kw):
1699 """Extract a set of variables by name from another frame.
1699 """Extract a set of variables by name from another frame.
1700
1700
1701 :Parameters:
1701 :Parameters:
1702 - `*names`: strings
1702 - `*names`: strings
1703 One or more variable names which will be extracted from the caller's
1703 One or more variable names which will be extracted from the caller's
1704 frame.
1704 frame.
1705
1705
1706 :Keywords:
1706 :Keywords:
1707 - `depth`: integer (0)
1707 - `depth`: integer (0)
1708 How many frames in the stack to walk when looking for your variables.
1708 How many frames in the stack to walk when looking for your variables.
1709
1709
1710
1710
1711 Examples:
1711 Examples:
1712
1712
1713 In [2]: def func(x):
1713 In [2]: def func(x):
1714 ...: y = 1
1714 ...: y = 1
1715 ...: print extract_vars('x','y')
1715 ...: print extract_vars('x','y')
1716 ...:
1716 ...:
1717
1717
1718 In [3]: func('hello')
1718 In [3]: func('hello')
1719 {'y': 1, 'x': 'hello'}
1719 {'y': 1, 'x': 'hello'}
1720 """
1720 """
1721
1721
1722 depth = kw.get('depth',0)
1722 depth = kw.get('depth',0)
1723
1723
1724 callerNS = sys._getframe(depth+1).f_locals
1724 callerNS = sys._getframe(depth+1).f_locals
1725 return dict((k,callerNS[k]) for k in names)
1725 return dict((k,callerNS[k]) for k in names)
1726
1726
1727
1727
1728 def extract_vars_above(*names):
1728 def extract_vars_above(*names):
1729 """Extract a set of variables by name from another frame.
1729 """Extract a set of variables by name from another frame.
1730
1730
1731 Similar to extractVars(), but with a specified depth of 1, so that names
1731 Similar to extractVars(), but with a specified depth of 1, so that names
1732 are exctracted exactly from above the caller.
1732 are exctracted exactly from above the caller.
1733
1733
1734 This is simply a convenience function so that the very common case (for us)
1734 This is simply a convenience function so that the very common case (for us)
1735 of skipping exactly 1 frame doesn't have to construct a special dict for
1735 of skipping exactly 1 frame doesn't have to construct a special dict for
1736 keyword passing."""
1736 keyword passing."""
1737
1737
1738 callerNS = sys._getframe(2).f_locals
1738 callerNS = sys._getframe(2).f_locals
1739 return dict((k,callerNS[k]) for k in names)
1739 return dict((k,callerNS[k]) for k in names)
1740
1740
1741 def expand_path(s):
1741 def expand_path(s):
1742 """Expand $VARS and ~names in a string, like a shell
1742 """Expand $VARS and ~names in a string, like a shell
1743
1743
1744 :Examples:
1744 :Examples:
1745
1745
1746 In [2]: os.environ['FOO']='test'
1746 In [2]: os.environ['FOO']='test'
1747
1747
1748 In [3]: shexp('variable FOO is $FOO')
1748 In [3]: shexp('variable FOO is $FOO')
1749 Out[3]: 'variable FOO is test'
1749 Out[3]: 'variable FOO is test'
1750 """
1750 """
1751 # This is a pretty subtle hack. When expand user is given a UNC path
1751 # This is a pretty subtle hack. When expand user is given a UNC path
1752 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
1752 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
1753 # the $ to get (\\server\share\%username%). I think it considered $
1753 # the $ to get (\\server\share\%username%). I think it considered $
1754 # alone an empty var. But, we need the $ to remains there (it indicates
1754 # alone an empty var. But, we need the $ to remains there (it indicates
1755 # a hidden share).
1755 # a hidden share).
1756 if os.name=='nt':
1756 if os.name=='nt':
1757 s.replace('$\\', 'IPYTHON_TEMP')
1757 s = s.replace('$\\', 'IPYTHON_TEMP')
1758 s2 = os.path.expandvars(os.path.expanduser(s))
1758 s = os.path.expandvars(os.path.expanduser(s))
1759 if os.name=='nt':
1759 if os.name=='nt':
1760 s2.replace('IPYTHON_TEMP', '$\\')
1760 s = s.replace('IPYTHON_TEMP', '$\\')
1761 return s2
1761 return s
1762
1762
1763 def list_strings(arg):
1763 def list_strings(arg):
1764 """Always return a list of strings, given a string or list of strings
1764 """Always return a list of strings, given a string or list of strings
1765 as input.
1765 as input.
1766
1766
1767 :Examples:
1767 :Examples:
1768
1768
1769 In [7]: list_strings('A single string')
1769 In [7]: list_strings('A single string')
1770 Out[7]: ['A single string']
1770 Out[7]: ['A single string']
1771
1771
1772 In [8]: list_strings(['A single string in a list'])
1772 In [8]: list_strings(['A single string in a list'])
1773 Out[8]: ['A single string in a list']
1773 Out[8]: ['A single string in a list']
1774
1774
1775 In [9]: list_strings(['A','list','of','strings'])
1775 In [9]: list_strings(['A','list','of','strings'])
1776 Out[9]: ['A', 'list', 'of', 'strings']
1776 Out[9]: ['A', 'list', 'of', 'strings']
1777 """
1777 """
1778
1778
1779 if isinstance(arg,basestring): return [arg]
1779 if isinstance(arg,basestring): return [arg]
1780 else: return arg
1780 else: return arg
1781
1781
1782
1782
1783 #----------------------------------------------------------------------------
1783 #----------------------------------------------------------------------------
1784 def marquee(txt='',width=78,mark='*'):
1784 def marquee(txt='',width=78,mark='*'):
1785 """Return the input string centered in a 'marquee'.
1785 """Return the input string centered in a 'marquee'.
1786
1786
1787 :Examples:
1787 :Examples:
1788
1788
1789 In [16]: marquee('A test',40)
1789 In [16]: marquee('A test',40)
1790 Out[16]: '**************** A test ****************'
1790 Out[16]: '**************** A test ****************'
1791
1791
1792 In [17]: marquee('A test',40,'-')
1792 In [17]: marquee('A test',40,'-')
1793 Out[17]: '---------------- A test ----------------'
1793 Out[17]: '---------------- A test ----------------'
1794
1794
1795 In [18]: marquee('A test',40,' ')
1795 In [18]: marquee('A test',40,' ')
1796 Out[18]: ' A test '
1796 Out[18]: ' A test '
1797
1797
1798 """
1798 """
1799 if not txt:
1799 if not txt:
1800 return (mark*width)[:width]
1800 return (mark*width)[:width]
1801 nmark = (width-len(txt)-2)/len(mark)/2
1801 nmark = (width-len(txt)-2)/len(mark)/2
1802 if nmark < 0: nmark =0
1802 if nmark < 0: nmark =0
1803 marks = mark*nmark
1803 marks = mark*nmark
1804 return '%s %s %s' % (marks,txt,marks)
1804 return '%s %s %s' % (marks,txt,marks)
1805
1805
1806 #*************************** end of file <genutils.py> **********************
1806 #*************************** end of file <genutils.py> **********************
General Comments 0
You need to be logged in to leave comments. Login now