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