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