##// END OF EJS Templates
Moved path to extensions - pickleshare failed because it imported...
vivainio -
Show More

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

1 NO CONTENT: file renamed from IPython/path.py to IPython/Extensions/path.py
NO CONTENT: file renamed from IPython/path.py to IPython/Extensions/path.py
@@ -1,66 +1,73 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 One of Python's nicest features is its interactive interpreter. This allows
5 One of Python's nicest features is its interactive interpreter. This allows
6 very fast testing of ideas without the overhead of creating test files as is
6 very fast testing of ideas without the overhead of creating test files as is
7 typical in most programming languages. However, the interpreter supplied with
7 typical in most programming languages. However, the interpreter supplied with
8 the standard Python distribution is fairly primitive (and IDLE isn't really
8 the standard Python distribution is fairly primitive (and IDLE isn't really
9 much better).
9 much better).
10
10
11 IPython tries to:
11 IPython tries to:
12
12
13 i - provide an efficient environment for interactive work in Python
13 i - provide an efficient environment for interactive work in Python
14 programming. It tries to address what we see as shortcomings of the standard
14 programming. It tries to address what we see as shortcomings of the standard
15 Python prompt, and adds many features to make interactive work much more
15 Python prompt, and adds many features to make interactive work much more
16 efficient.
16 efficient.
17
17
18 ii - offer a flexible framework so that it can be used as the base
18 ii - offer a flexible framework so that it can be used as the base
19 environment for other projects and problems where Python can be the
19 environment for other projects and problems where Python can be the
20 underlying language. Specifically scientific environments like Mathematica,
20 underlying language. Specifically scientific environments like Mathematica,
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
22 fields. Python is a fabulous language for implementing this kind of system
22 fields. Python is a fabulous language for implementing this kind of system
23 (due to its dynamic and introspective features), and with suitable libraries
23 (due to its dynamic and introspective features), and with suitable libraries
24 entire systems could be built leveraging Python's power.
24 entire systems could be built leveraging Python's power.
25
25
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
27
27
28 IPython requires Python 2.2 or newer.
28 IPython requires Python 2.2 or newer.
29
29
30 $Id: __init__.py 1099 2006-01-29 21:05:57Z vivainio $"""
30 $Id: __init__.py 1110 2006-01-30 20:43:30Z vivainio $"""
31
31
32 #*****************************************************************************
32 #*****************************************************************************
33 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
33 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
34 #
34 #
35 # Distributed under the terms of the BSD License. The full license is in
35 # Distributed under the terms of the BSD License. The full license is in
36 # the file COPYING, distributed as part of this software.
36 # the file COPYING, distributed as part of this software.
37 #*****************************************************************************
37 #*****************************************************************************
38
38
39 # Enforce proper version requirements
39 # Enforce proper version requirements
40 import sys
40 import sys
41
41 if sys.version[0:3] < '2.3':
42 if sys.version[0:3] < '2.3':
42 raise ImportError, 'Python Version 2.3 or above is required.'
43 raise ImportError, 'Python Version 2.3 or above is required.'
44
45 # Make it easy to import extensions - they are always directly on pythonpath.
46 # Therefore, non-IPython modules can be added to Extensions directory
47
48 import os
49 sys.path.append(os.path.dirname(__file__) + "/Extensions")
43
50
44 # Define what gets imported with a 'from IPython import *'
51 # Define what gets imported with a 'from IPython import *'
45 __all__ = ['deep_reload','genutils','ipstruct','ultraTB','DPyGetOpt',
52 __all__ = ['deep_reload','genutils','ipstruct','ultraTB','DPyGetOpt',
46 'Itpl','hooks','ConfigLoader','OutputTrap','Release','Shell',
53 'Itpl','hooks','ConfigLoader','OutputTrap','Release','Shell',
47 'platutils','platutils_win32','platutils_posix','platutils_dummy',
54 'platutils','platutils_win32','platutils_posix','platutils_dummy',
48 'ipapi','path','rlineimpl']
55 'ipapi','rlineimpl']
49
56
50 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
57 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
51 # access to them via IPython.<name>
58 # access to them via IPython.<name>
52 glob,loc = globals(),locals()
59 glob,loc = globals(),locals()
53 for name in __all__:
60 for name in __all__:
54 __import__(name,glob,loc,[])
61 __import__(name,glob,loc,[])
55
62
56 # Release data
63 # Release data
57 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
64 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
58 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
59 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
66 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
60 Release.authors['Nathan'] )
67 Release.authors['Nathan'] )
61 __license__ = Release.license
68 __license__ = Release.license
62 __version__ = Release.version
69 __version__ = Release.version
63 __revision__ = Release.revision
70 __revision__ = Release.revision
64
71
65 # Namespace cleanup
72 # Namespace cleanup
66 del name,glob,loc
73 del name,glob,loc
@@ -1,1761 +1,1761 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 General purpose utilities.
3 General purpose utilities.
4
4
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 these things are also convenient when working at the command line.
6 these things are also convenient when working at the command line.
7
7
8 $Id: genutils.py 1100 2006-01-29 21:27:16Z vivainio $"""
8 $Id: genutils.py 1110 2006-01-30 20:43:30Z vivainio $"""
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 from __future__ import generators # 2.2 compatibility
17 from __future__ import generators # 2.2 compatibility
18
18
19 from IPython import Release
19 from IPython import Release
20 __author__ = '%s <%s>' % Release.authors['Fernando']
20 __author__ = '%s <%s>' % Release.authors['Fernando']
21 __license__ = Release.license
21 __license__ = Release.license
22
22
23 #****************************************************************************
23 #****************************************************************************
24 # required modules from the Python standard library
24 # required modules from the Python standard library
25 import __main__
25 import __main__
26 import commands
26 import commands
27 import os
27 import os
28 import re
28 import re
29 import shlex
29 import shlex
30 import shutil
30 import shutil
31 import sys
31 import sys
32 import tempfile
32 import tempfile
33 import time
33 import time
34 import types
34 import types
35
35
36 # Other IPython utilities
36 # Other IPython utilities
37 from IPython.Itpl import Itpl,itpl,printpl
37 from IPython.Itpl import Itpl,itpl,printpl
38 from IPython import DPyGetOpt
38 from IPython import DPyGetOpt
39 from IPython.path import path
39 from path import path
40 if os.name == "nt":
40 if os.name == "nt":
41 from IPython.winconsole import get_console_size
41 from IPython.winconsole import get_console_size
42
42
43 # Build objects which appeared in Python 2.3 for 2.2, to make ipython
43 # Build objects which appeared in Python 2.3 for 2.2, to make ipython
44 # 2.2-friendly
44 # 2.2-friendly
45 try:
45 try:
46 basestring
46 basestring
47 except NameError:
47 except NameError:
48 import types
48 import types
49 basestring = (types.StringType, types.UnicodeType)
49 basestring = (types.StringType, types.UnicodeType)
50 True = 1==1
50 True = 1==1
51 False = 1==0
51 False = 1==0
52
52
53 def enumerate(obj):
53 def enumerate(obj):
54 i = -1
54 i = -1
55 for item in obj:
55 for item in obj:
56 i += 1
56 i += 1
57 yield i, item
57 yield i, item
58
58
59 # add these to the builtin namespace, so that all modules find them
59 # add these to the builtin namespace, so that all modules find them
60 import __builtin__
60 import __builtin__
61 __builtin__.basestring = basestring
61 __builtin__.basestring = basestring
62 __builtin__.True = True
62 __builtin__.True = True
63 __builtin__.False = False
63 __builtin__.False = False
64 __builtin__.enumerate = enumerate
64 __builtin__.enumerate = enumerate
65
65
66 # Try to use shlex.split for converting an input string into a sys.argv-type
66 # Try to use shlex.split for converting an input string into a sys.argv-type
67 # list. This appeared in Python 2.3, so here's a quick backport for 2.2.
67 # list. This appeared in Python 2.3, so here's a quick backport for 2.2.
68 try:
68 try:
69 shlex_split = shlex.split
69 shlex_split = shlex.split
70 except AttributeError:
70 except AttributeError:
71 _quotesre = re.compile(r'[\'"](.*)[\'"]')
71 _quotesre = re.compile(r'[\'"](.*)[\'"]')
72 _wordchars = ('abcdfeghijklmnopqrstuvwxyz'
72 _wordchars = ('abcdfeghijklmnopqrstuvwxyz'
73 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.~*?'
73 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.~*?'
74 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
74 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
75 'À�ÂÃÄÅÆÇÈÉÊËÌ�Î��ÑÒÓÔÕÖØÙÚÛÜ�Þ%s'
75 'À�ÂÃÄÅÆÇÈÉÊËÌ�Î��ÑÒÓÔÕÖØÙÚÛÜ�Þ%s'
76 % os.sep)
76 % os.sep)
77
77
78 def shlex_split(s):
78 def shlex_split(s):
79 """Simplified backport to Python 2.2 of shlex.split().
79 """Simplified backport to Python 2.2 of shlex.split().
80
80
81 This is a quick and dirty hack, since the shlex module under 2.2 lacks
81 This is a quick and dirty hack, since the shlex module under 2.2 lacks
82 several of the features needed to really match the functionality of
82 several of the features needed to really match the functionality of
83 shlex.split() in 2.3."""
83 shlex.split() in 2.3."""
84
84
85 lex = shlex.shlex(StringIO(s))
85 lex = shlex.shlex(StringIO(s))
86 # Try to get options, extensions and path separators as characters
86 # Try to get options, extensions and path separators as characters
87 lex.wordchars = _wordchars
87 lex.wordchars = _wordchars
88 lex.commenters = ''
88 lex.commenters = ''
89 # Make a list out of the lexer by hand, since in 2.2 it's not an
89 # Make a list out of the lexer by hand, since in 2.2 it's not an
90 # iterator.
90 # iterator.
91 lout = []
91 lout = []
92 while 1:
92 while 1:
93 token = lex.get_token()
93 token = lex.get_token()
94 if token == '':
94 if token == '':
95 break
95 break
96 # Try to handle quoted tokens correctly
96 # Try to handle quoted tokens correctly
97 quotes = _quotesre.match(token)
97 quotes = _quotesre.match(token)
98 if quotes:
98 if quotes:
99 token = quotes.group(1)
99 token = quotes.group(1)
100 lout.append(token)
100 lout.append(token)
101 return lout
101 return lout
102
102
103 #****************************************************************************
103 #****************************************************************************
104 # Exceptions
104 # Exceptions
105 class Error(Exception):
105 class Error(Exception):
106 """Base class for exceptions in this module."""
106 """Base class for exceptions in this module."""
107 pass
107 pass
108
108
109 #----------------------------------------------------------------------------
109 #----------------------------------------------------------------------------
110 class IOStream:
110 class IOStream:
111 def __init__(self,stream,fallback):
111 def __init__(self,stream,fallback):
112 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
112 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
113 stream = fallback
113 stream = fallback
114 self.stream = stream
114 self.stream = stream
115 self._swrite = stream.write
115 self._swrite = stream.write
116 self.flush = stream.flush
116 self.flush = stream.flush
117
117
118 def write(self,data):
118 def write(self,data):
119 try:
119 try:
120 self._swrite(data)
120 self._swrite(data)
121 except:
121 except:
122 try:
122 try:
123 # print handles some unicode issues which may trip a plain
123 # print handles some unicode issues which may trip a plain
124 # write() call. Attempt to emulate write() by using a
124 # write() call. Attempt to emulate write() by using a
125 # trailing comma
125 # trailing comma
126 print >> self.stream, data,
126 print >> self.stream, data,
127 except:
127 except:
128 # if we get here, something is seriously broken.
128 # if we get here, something is seriously broken.
129 print >> sys.stderr, \
129 print >> sys.stderr, \
130 'ERROR - failed to write data to stream:', stream
130 'ERROR - failed to write data to stream:', stream
131
131
132 class IOTerm:
132 class IOTerm:
133 """ Term holds the file or file-like objects for handling I/O operations.
133 """ Term holds the file or file-like objects for handling I/O operations.
134
134
135 These are normally just sys.stdin, sys.stdout and sys.stderr but for
135 These are normally just sys.stdin, sys.stdout and sys.stderr but for
136 Windows they can can replaced to allow editing the strings before they are
136 Windows they can can replaced to allow editing the strings before they are
137 displayed."""
137 displayed."""
138
138
139 # In the future, having IPython channel all its I/O operations through
139 # In the future, having IPython channel all its I/O operations through
140 # this class will make it easier to embed it into other environments which
140 # this class will make it easier to embed it into other environments which
141 # are not a normal terminal (such as a GUI-based shell)
141 # are not a normal terminal (such as a GUI-based shell)
142 def __init__(self,cin=None,cout=None,cerr=None):
142 def __init__(self,cin=None,cout=None,cerr=None):
143 self.cin = IOStream(cin,sys.stdin)
143 self.cin = IOStream(cin,sys.stdin)
144 self.cout = IOStream(cout,sys.stdout)
144 self.cout = IOStream(cout,sys.stdout)
145 self.cerr = IOStream(cerr,sys.stderr)
145 self.cerr = IOStream(cerr,sys.stderr)
146
146
147 # Global variable to be used for all I/O
147 # Global variable to be used for all I/O
148 Term = IOTerm()
148 Term = IOTerm()
149
149
150 import IPython.rlineimpl as readline
150 import IPython.rlineimpl as readline
151 # Remake Term to use the readline i/o facilities
151 # Remake Term to use the readline i/o facilities
152 if sys.platform == 'win32' and readline.have_readline:
152 if sys.platform == 'win32' and readline.have_readline:
153
153
154 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
154 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
155
155
156
156
157 #****************************************************************************
157 #****************************************************************************
158 # Generic warning/error printer, used by everything else
158 # Generic warning/error printer, used by everything else
159 def warn(msg,level=2,exit_val=1):
159 def warn(msg,level=2,exit_val=1):
160 """Standard warning printer. Gives formatting consistency.
160 """Standard warning printer. Gives formatting consistency.
161
161
162 Output is sent to Term.cerr (sys.stderr by default).
162 Output is sent to Term.cerr (sys.stderr by default).
163
163
164 Options:
164 Options:
165
165
166 -level(2): allows finer control:
166 -level(2): allows finer control:
167 0 -> Do nothing, dummy function.
167 0 -> Do nothing, dummy function.
168 1 -> Print message.
168 1 -> Print message.
169 2 -> Print 'WARNING:' + message. (Default level).
169 2 -> Print 'WARNING:' + message. (Default level).
170 3 -> Print 'ERROR:' + message.
170 3 -> Print 'ERROR:' + message.
171 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
171 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
172
172
173 -exit_val (1): exit value returned by sys.exit() for a level 4
173 -exit_val (1): exit value returned by sys.exit() for a level 4
174 warning. Ignored for all other levels."""
174 warning. Ignored for all other levels."""
175
175
176 if level>0:
176 if level>0:
177 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
177 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
178 print >> Term.cerr, '%s%s' % (header[level],msg)
178 print >> Term.cerr, '%s%s' % (header[level],msg)
179 if level == 4:
179 if level == 4:
180 print >> Term.cerr,'Exiting.\n'
180 print >> Term.cerr,'Exiting.\n'
181 sys.exit(exit_val)
181 sys.exit(exit_val)
182
182
183 def info(msg):
183 def info(msg):
184 """Equivalent to warn(msg,level=1)."""
184 """Equivalent to warn(msg,level=1)."""
185
185
186 warn(msg,level=1)
186 warn(msg,level=1)
187
187
188 def error(msg):
188 def error(msg):
189 """Equivalent to warn(msg,level=3)."""
189 """Equivalent to warn(msg,level=3)."""
190
190
191 warn(msg,level=3)
191 warn(msg,level=3)
192
192
193 def fatal(msg,exit_val=1):
193 def fatal(msg,exit_val=1):
194 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
194 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
195
195
196 warn(msg,exit_val=exit_val,level=4)
196 warn(msg,exit_val=exit_val,level=4)
197
197
198 #---------------------------------------------------------------------------
198 #---------------------------------------------------------------------------
199 # Debugging routines
199 # Debugging routines
200 #
200 #
201 def debugx(expr,pre_msg=''):
201 def debugx(expr,pre_msg=''):
202 """Print the value of an expression from the caller's frame.
202 """Print the value of an expression from the caller's frame.
203
203
204 Takes an expression, evaluates it in the caller's frame and prints both
204 Takes an expression, evaluates it in the caller's frame and prints both
205 the given expression and the resulting value (as well as a debug mark
205 the given expression and the resulting value (as well as a debug mark
206 indicating the name of the calling function. The input must be of a form
206 indicating the name of the calling function. The input must be of a form
207 suitable for eval().
207 suitable for eval().
208
208
209 An optional message can be passed, which will be prepended to the printed
209 An optional message can be passed, which will be prepended to the printed
210 expr->value pair."""
210 expr->value pair."""
211
211
212 cf = sys._getframe(1)
212 cf = sys._getframe(1)
213 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
213 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
214 eval(expr,cf.f_globals,cf.f_locals))
214 eval(expr,cf.f_globals,cf.f_locals))
215
215
216 # deactivate it by uncommenting the following line, which makes it a no-op
216 # deactivate it by uncommenting the following line, which makes it a no-op
217 #def debugx(expr,pre_msg=''): pass
217 #def debugx(expr,pre_msg=''): pass
218
218
219 #----------------------------------------------------------------------------
219 #----------------------------------------------------------------------------
220 StringTypes = types.StringTypes
220 StringTypes = types.StringTypes
221
221
222 # Basic timing functionality
222 # Basic timing functionality
223
223
224 # If possible (Unix), use the resource module instead of time.clock()
224 # If possible (Unix), use the resource module instead of time.clock()
225 try:
225 try:
226 import resource
226 import resource
227 def clock():
227 def clock():
228 """clock() -> floating point number
228 """clock() -> floating point number
229
229
230 Return the CPU time in seconds (user time only, system time is
230 Return the CPU time in seconds (user time only, system time is
231 ignored) since the start of the process. This is done via a call to
231 ignored) since the start of the process. This is done via a call to
232 resource.getrusage, so it avoids the wraparound problems in
232 resource.getrusage, so it avoids the wraparound problems in
233 time.clock()."""
233 time.clock()."""
234
234
235 return resource.getrusage(resource.RUSAGE_SELF)[0]
235 return resource.getrusage(resource.RUSAGE_SELF)[0]
236
236
237 def clock2():
237 def clock2():
238 """clock2() -> (t_user,t_system)
238 """clock2() -> (t_user,t_system)
239
239
240 Similar to clock(), but return a tuple of user/system times."""
240 Similar to clock(), but return a tuple of user/system times."""
241 return resource.getrusage(resource.RUSAGE_SELF)[:2]
241 return resource.getrusage(resource.RUSAGE_SELF)[:2]
242
242
243 except ImportError:
243 except ImportError:
244 clock = time.clock
244 clock = time.clock
245 def clock2():
245 def clock2():
246 """Under windows, system CPU time can't be measured.
246 """Under windows, system CPU time can't be measured.
247
247
248 This just returns clock() and zero."""
248 This just returns clock() and zero."""
249 return time.clock(),0.0
249 return time.clock(),0.0
250
250
251 def timings_out(reps,func,*args,**kw):
251 def timings_out(reps,func,*args,**kw):
252 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
252 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
253
253
254 Execute a function reps times, return a tuple with the elapsed total
254 Execute a function reps times, return a tuple with the elapsed total
255 CPU time in seconds, the time per call and the function's output.
255 CPU time in seconds, the time per call and the function's output.
256
256
257 Under Unix, the return value is the sum of user+system time consumed by
257 Under Unix, the return value is the sum of user+system time consumed by
258 the process, computed via the resource module. This prevents problems
258 the process, computed via the resource module. This prevents problems
259 related to the wraparound effect which the time.clock() function has.
259 related to the wraparound effect which the time.clock() function has.
260
260
261 Under Windows the return value is in wall clock seconds. See the
261 Under Windows the return value is in wall clock seconds. See the
262 documentation for the time module for more details."""
262 documentation for the time module for more details."""
263
263
264 reps = int(reps)
264 reps = int(reps)
265 assert reps >=1, 'reps must be >= 1'
265 assert reps >=1, 'reps must be >= 1'
266 if reps==1:
266 if reps==1:
267 start = clock()
267 start = clock()
268 out = func(*args,**kw)
268 out = func(*args,**kw)
269 tot_time = clock()-start
269 tot_time = clock()-start
270 else:
270 else:
271 rng = xrange(reps-1) # the last time is executed separately to store output
271 rng = xrange(reps-1) # the last time is executed separately to store output
272 start = clock()
272 start = clock()
273 for dummy in rng: func(*args,**kw)
273 for dummy in rng: func(*args,**kw)
274 out = func(*args,**kw) # one last time
274 out = func(*args,**kw) # one last time
275 tot_time = clock()-start
275 tot_time = clock()-start
276 av_time = tot_time / reps
276 av_time = tot_time / reps
277 return tot_time,av_time,out
277 return tot_time,av_time,out
278
278
279 def timings(reps,func,*args,**kw):
279 def timings(reps,func,*args,**kw):
280 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
280 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
281
281
282 Execute a function reps times, return a tuple with the elapsed total CPU
282 Execute a function reps times, return a tuple with the elapsed total CPU
283 time in seconds and the time per call. These are just the first two values
283 time in seconds and the time per call. These are just the first two values
284 in timings_out()."""
284 in timings_out()."""
285
285
286 return timings_out(reps,func,*args,**kw)[0:2]
286 return timings_out(reps,func,*args,**kw)[0:2]
287
287
288 def timing(func,*args,**kw):
288 def timing(func,*args,**kw):
289 """timing(func,*args,**kw) -> t_total
289 """timing(func,*args,**kw) -> t_total
290
290
291 Execute a function once, return the elapsed total CPU time in
291 Execute a function once, return the elapsed total CPU time in
292 seconds. This is just the first value in timings_out()."""
292 seconds. This is just the first value in timings_out()."""
293
293
294 return timings_out(1,func,*args,**kw)[0]
294 return timings_out(1,func,*args,**kw)[0]
295
295
296 #****************************************************************************
296 #****************************************************************************
297 # file and system
297 # file and system
298
298
299 def system(cmd,verbose=0,debug=0,header=''):
299 def system(cmd,verbose=0,debug=0,header=''):
300 """Execute a system command, return its exit status.
300 """Execute a system command, return its exit status.
301
301
302 Options:
302 Options:
303
303
304 - verbose (0): print the command to be executed.
304 - verbose (0): print the command to be executed.
305
305
306 - debug (0): only print, do not actually execute.
306 - debug (0): only print, do not actually execute.
307
307
308 - header (''): Header to print on screen prior to the executed command (it
308 - header (''): Header to print on screen prior to the executed command (it
309 is only prepended to the command, no newlines are added).
309 is only prepended to the command, no newlines are added).
310
310
311 Note: a stateful version of this function is available through the
311 Note: a stateful version of this function is available through the
312 SystemExec class."""
312 SystemExec class."""
313
313
314 stat = 0
314 stat = 0
315 if verbose or debug: print header+cmd
315 if verbose or debug: print header+cmd
316 sys.stdout.flush()
316 sys.stdout.flush()
317 if not debug: stat = os.system(cmd)
317 if not debug: stat = os.system(cmd)
318 return stat
318 return stat
319
319
320 # This function is used by ipython in a lot of places to make system calls.
320 # This function is used by ipython in a lot of places to make system calls.
321 # We need it to be slightly different under win32, due to the vagaries of
321 # We need it to be slightly different under win32, due to the vagaries of
322 # 'network shares'. A win32 override is below.
322 # 'network shares'. A win32 override is below.
323
323
324 def shell(cmd,verbose=0,debug=0,header=''):
324 def shell(cmd,verbose=0,debug=0,header=''):
325 """Execute a command in the system shell, always return None.
325 """Execute a command in the system shell, always return None.
326
326
327 Options:
327 Options:
328
328
329 - verbose (0): print the command to be executed.
329 - verbose (0): print the command to be executed.
330
330
331 - debug (0): only print, do not actually execute.
331 - debug (0): only print, do not actually execute.
332
332
333 - header (''): Header to print on screen prior to the executed command (it
333 - header (''): Header to print on screen prior to the executed command (it
334 is only prepended to the command, no newlines are added).
334 is only prepended to the command, no newlines are added).
335
335
336 Note: this is similar to genutils.system(), but it returns None so it can
336 Note: this is similar to genutils.system(), but it returns None so it can
337 be conveniently used in interactive loops without getting the return value
337 be conveniently used in interactive loops without getting the return value
338 (typically 0) printed many times."""
338 (typically 0) printed many times."""
339
339
340 stat = 0
340 stat = 0
341 if verbose or debug: print header+cmd
341 if verbose or debug: print header+cmd
342 # flush stdout so we don't mangle python's buffering
342 # flush stdout so we don't mangle python's buffering
343 sys.stdout.flush()
343 sys.stdout.flush()
344 if not debug:
344 if not debug:
345 os.system(cmd)
345 os.system(cmd)
346
346
347 # override shell() for win32 to deal with network shares
347 # override shell() for win32 to deal with network shares
348 if os.name in ('nt','dos'):
348 if os.name in ('nt','dos'):
349
349
350 shell_ori = shell
350 shell_ori = shell
351
351
352 def shell(cmd,verbose=0,debug=0,header=''):
352 def shell(cmd,verbose=0,debug=0,header=''):
353 if os.getcwd().startswith(r"\\"):
353 if os.getcwd().startswith(r"\\"):
354 path = os.getcwd()
354 path = os.getcwd()
355 # change to c drive (cannot be on UNC-share when issuing os.system,
355 # change to c drive (cannot be on UNC-share when issuing os.system,
356 # as cmd.exe cannot handle UNC addresses)
356 # as cmd.exe cannot handle UNC addresses)
357 os.chdir("c:")
357 os.chdir("c:")
358 # issue pushd to the UNC-share and then run the command
358 # issue pushd to the UNC-share and then run the command
359 try:
359 try:
360 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
360 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
361 finally:
361 finally:
362 os.chdir(path)
362 os.chdir(path)
363 else:
363 else:
364 shell_ori(cmd,verbose,debug,header)
364 shell_ori(cmd,verbose,debug,header)
365
365
366 shell.__doc__ = shell_ori.__doc__
366 shell.__doc__ = shell_ori.__doc__
367
367
368 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
368 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
369 """Dummy substitute for perl's backquotes.
369 """Dummy substitute for perl's backquotes.
370
370
371 Executes a command and returns the output.
371 Executes a command and returns the output.
372
372
373 Accepts the same arguments as system(), plus:
373 Accepts the same arguments as system(), plus:
374
374
375 - split(0): if true, the output is returned as a list split on newlines.
375 - split(0): if true, the output is returned as a list split on newlines.
376
376
377 Note: a stateful version of this function is available through the
377 Note: a stateful version of this function is available through the
378 SystemExec class."""
378 SystemExec class."""
379
379
380 if verbose or debug: print header+cmd
380 if verbose or debug: print header+cmd
381 if not debug:
381 if not debug:
382 output = commands.getoutput(cmd)
382 output = commands.getoutput(cmd)
383 if split:
383 if split:
384 return output.split('\n')
384 return output.split('\n')
385 else:
385 else:
386 return output
386 return output
387
387
388 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
388 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
389 """Return (standard output,standard error) of executing cmd in a shell.
389 """Return (standard output,standard error) of executing cmd in a shell.
390
390
391 Accepts the same arguments as system(), plus:
391 Accepts the same arguments as system(), plus:
392
392
393 - split(0): if true, each of stdout/err is returned as a list split on
393 - split(0): if true, each of stdout/err is returned as a list split on
394 newlines.
394 newlines.
395
395
396 Note: a stateful version of this function is available through the
396 Note: a stateful version of this function is available through the
397 SystemExec class."""
397 SystemExec class."""
398
398
399 if verbose or debug: print header+cmd
399 if verbose or debug: print header+cmd
400 if not cmd:
400 if not cmd:
401 if split:
401 if split:
402 return [],[]
402 return [],[]
403 else:
403 else:
404 return '',''
404 return '',''
405 if not debug:
405 if not debug:
406 pin,pout,perr = os.popen3(cmd)
406 pin,pout,perr = os.popen3(cmd)
407 tout = pout.read().rstrip()
407 tout = pout.read().rstrip()
408 terr = perr.read().rstrip()
408 terr = perr.read().rstrip()
409 pin.close()
409 pin.close()
410 pout.close()
410 pout.close()
411 perr.close()
411 perr.close()
412 if split:
412 if split:
413 return tout.split('\n'),terr.split('\n')
413 return tout.split('\n'),terr.split('\n')
414 else:
414 else:
415 return tout,terr
415 return tout,terr
416
416
417 # for compatibility with older naming conventions
417 # for compatibility with older naming conventions
418 xsys = system
418 xsys = system
419 bq = getoutput
419 bq = getoutput
420
420
421 class SystemExec:
421 class SystemExec:
422 """Access the system and getoutput functions through a stateful interface.
422 """Access the system and getoutput functions through a stateful interface.
423
423
424 Note: here we refer to the system and getoutput functions from this
424 Note: here we refer to the system and getoutput functions from this
425 library, not the ones from the standard python library.
425 library, not the ones from the standard python library.
426
426
427 This class offers the system and getoutput functions as methods, but the
427 This class offers the system and getoutput functions as methods, but the
428 verbose, debug and header parameters can be set for the instance (at
428 verbose, debug and header parameters can be set for the instance (at
429 creation time or later) so that they don't need to be specified on each
429 creation time or later) so that they don't need to be specified on each
430 call.
430 call.
431
431
432 For efficiency reasons, there's no way to override the parameters on a
432 For efficiency reasons, there's no way to override the parameters on a
433 per-call basis other than by setting instance attributes. If you need
433 per-call basis other than by setting instance attributes. If you need
434 local overrides, it's best to directly call system() or getoutput().
434 local overrides, it's best to directly call system() or getoutput().
435
435
436 The following names are provided as alternate options:
436 The following names are provided as alternate options:
437 - xsys: alias to system
437 - xsys: alias to system
438 - bq: alias to getoutput
438 - bq: alias to getoutput
439
439
440 An instance can then be created as:
440 An instance can then be created as:
441 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
441 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
442
442
443 And used as:
443 And used as:
444 >>> sysexec.xsys('pwd')
444 >>> sysexec.xsys('pwd')
445 >>> dirlist = sysexec.bq('ls -l')
445 >>> dirlist = sysexec.bq('ls -l')
446 """
446 """
447
447
448 def __init__(self,verbose=0,debug=0,header='',split=0):
448 def __init__(self,verbose=0,debug=0,header='',split=0):
449 """Specify the instance's values for verbose, debug and header."""
449 """Specify the instance's values for verbose, debug and header."""
450 setattr_list(self,'verbose debug header split')
450 setattr_list(self,'verbose debug header split')
451
451
452 def system(self,cmd):
452 def system(self,cmd):
453 """Stateful interface to system(), with the same keyword parameters."""
453 """Stateful interface to system(), with the same keyword parameters."""
454
454
455 system(cmd,self.verbose,self.debug,self.header)
455 system(cmd,self.verbose,self.debug,self.header)
456
456
457 def shell(self,cmd):
457 def shell(self,cmd):
458 """Stateful interface to shell(), with the same keyword parameters."""
458 """Stateful interface to shell(), with the same keyword parameters."""
459
459
460 shell(cmd,self.verbose,self.debug,self.header)
460 shell(cmd,self.verbose,self.debug,self.header)
461
461
462 xsys = system # alias
462 xsys = system # alias
463
463
464 def getoutput(self,cmd):
464 def getoutput(self,cmd):
465 """Stateful interface to getoutput()."""
465 """Stateful interface to getoutput()."""
466
466
467 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
467 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
468
468
469 def getoutputerror(self,cmd):
469 def getoutputerror(self,cmd):
470 """Stateful interface to getoutputerror()."""
470 """Stateful interface to getoutputerror()."""
471
471
472 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
472 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
473
473
474 bq = getoutput # alias
474 bq = getoutput # alias
475
475
476 #-----------------------------------------------------------------------------
476 #-----------------------------------------------------------------------------
477 def mutex_opts(dict,ex_op):
477 def mutex_opts(dict,ex_op):
478 """Check for presence of mutually exclusive keys in a dict.
478 """Check for presence of mutually exclusive keys in a dict.
479
479
480 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
480 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
481 for op1,op2 in ex_op:
481 for op1,op2 in ex_op:
482 if op1 in dict and op2 in dict:
482 if op1 in dict and op2 in dict:
483 raise ValueError,'\n*** ERROR in Arguments *** '\
483 raise ValueError,'\n*** ERROR in Arguments *** '\
484 'Options '+op1+' and '+op2+' are mutually exclusive.'
484 'Options '+op1+' and '+op2+' are mutually exclusive.'
485
485
486 #-----------------------------------------------------------------------------
486 #-----------------------------------------------------------------------------
487 def get_py_filename(name):
487 def get_py_filename(name):
488 """Return a valid python filename in the current directory.
488 """Return a valid python filename in the current directory.
489
489
490 If the given name is not a file, it adds '.py' and searches again.
490 If the given name is not a file, it adds '.py' and searches again.
491 Raises IOError with an informative message if the file isn't found."""
491 Raises IOError with an informative message if the file isn't found."""
492
492
493 name = os.path.expanduser(name)
493 name = os.path.expanduser(name)
494 if not os.path.isfile(name) and not name.endswith('.py'):
494 if not os.path.isfile(name) and not name.endswith('.py'):
495 name += '.py'
495 name += '.py'
496 if os.path.isfile(name):
496 if os.path.isfile(name):
497 return name
497 return name
498 else:
498 else:
499 raise IOError,'File `%s` not found.' % name
499 raise IOError,'File `%s` not found.' % name
500
500
501 #-----------------------------------------------------------------------------
501 #-----------------------------------------------------------------------------
502 def filefind(fname,alt_dirs = None):
502 def filefind(fname,alt_dirs = None):
503 """Return the given filename either in the current directory, if it
503 """Return the given filename either in the current directory, if it
504 exists, or in a specified list of directories.
504 exists, or in a specified list of directories.
505
505
506 ~ expansion is done on all file and directory names.
506 ~ expansion is done on all file and directory names.
507
507
508 Upon an unsuccessful search, raise an IOError exception."""
508 Upon an unsuccessful search, raise an IOError exception."""
509
509
510 if alt_dirs is None:
510 if alt_dirs is None:
511 try:
511 try:
512 alt_dirs = get_home_dir()
512 alt_dirs = get_home_dir()
513 except HomeDirError:
513 except HomeDirError:
514 alt_dirs = os.getcwd()
514 alt_dirs = os.getcwd()
515 search = [fname] + list_strings(alt_dirs)
515 search = [fname] + list_strings(alt_dirs)
516 search = map(os.path.expanduser,search)
516 search = map(os.path.expanduser,search)
517 #print 'search list for',fname,'list:',search # dbg
517 #print 'search list for',fname,'list:',search # dbg
518 fname = search[0]
518 fname = search[0]
519 if os.path.isfile(fname):
519 if os.path.isfile(fname):
520 return fname
520 return fname
521 for direc in search[1:]:
521 for direc in search[1:]:
522 testname = os.path.join(direc,fname)
522 testname = os.path.join(direc,fname)
523 #print 'testname',testname # dbg
523 #print 'testname',testname # dbg
524 if os.path.isfile(testname):
524 if os.path.isfile(testname):
525 return testname
525 return testname
526 raise IOError,'File' + `fname` + \
526 raise IOError,'File' + `fname` + \
527 ' not found in current or supplied directories:' + `alt_dirs`
527 ' not found in current or supplied directories:' + `alt_dirs`
528
528
529 #----------------------------------------------------------------------------
529 #----------------------------------------------------------------------------
530 def file_read(filename):
530 def file_read(filename):
531 """Read a file and close it. Returns the file source."""
531 """Read a file and close it. Returns the file source."""
532 fobj=open(filename,'r');
532 fobj=open(filename,'r');
533 source = fobj.read();
533 source = fobj.read();
534 fobj.close()
534 fobj.close()
535 return source
535 return source
536
536
537 #----------------------------------------------------------------------------
537 #----------------------------------------------------------------------------
538 def target_outdated(target,deps):
538 def target_outdated(target,deps):
539 """Determine whether a target is out of date.
539 """Determine whether a target is out of date.
540
540
541 target_outdated(target,deps) -> 1/0
541 target_outdated(target,deps) -> 1/0
542
542
543 deps: list of filenames which MUST exist.
543 deps: list of filenames which MUST exist.
544 target: single filename which may or may not exist.
544 target: single filename which may or may not exist.
545
545
546 If target doesn't exist or is older than any file listed in deps, return
546 If target doesn't exist or is older than any file listed in deps, return
547 true, otherwise return false.
547 true, otherwise return false.
548 """
548 """
549 try:
549 try:
550 target_time = os.path.getmtime(target)
550 target_time = os.path.getmtime(target)
551 except os.error:
551 except os.error:
552 return 1
552 return 1
553 for dep in deps:
553 for dep in deps:
554 dep_time = os.path.getmtime(dep)
554 dep_time = os.path.getmtime(dep)
555 if dep_time > target_time:
555 if dep_time > target_time:
556 #print "For target",target,"Dep failed:",dep # dbg
556 #print "For target",target,"Dep failed:",dep # dbg
557 #print "times (dep,tar):",dep_time,target_time # dbg
557 #print "times (dep,tar):",dep_time,target_time # dbg
558 return 1
558 return 1
559 return 0
559 return 0
560
560
561 #-----------------------------------------------------------------------------
561 #-----------------------------------------------------------------------------
562 def target_update(target,deps,cmd):
562 def target_update(target,deps,cmd):
563 """Update a target with a given command given a list of dependencies.
563 """Update a target with a given command given a list of dependencies.
564
564
565 target_update(target,deps,cmd) -> runs cmd if target is outdated.
565 target_update(target,deps,cmd) -> runs cmd if target is outdated.
566
566
567 This is just a wrapper around target_outdated() which calls the given
567 This is just a wrapper around target_outdated() which calls the given
568 command if target is outdated."""
568 command if target is outdated."""
569
569
570 if target_outdated(target,deps):
570 if target_outdated(target,deps):
571 xsys(cmd)
571 xsys(cmd)
572
572
573 #----------------------------------------------------------------------------
573 #----------------------------------------------------------------------------
574 def unquote_ends(istr):
574 def unquote_ends(istr):
575 """Remove a single pair of quotes from the endpoints of a string."""
575 """Remove a single pair of quotes from the endpoints of a string."""
576
576
577 if not istr:
577 if not istr:
578 return istr
578 return istr
579 if (istr[0]=="'" and istr[-1]=="'") or \
579 if (istr[0]=="'" and istr[-1]=="'") or \
580 (istr[0]=='"' and istr[-1]=='"'):
580 (istr[0]=='"' and istr[-1]=='"'):
581 return istr[1:-1]
581 return istr[1:-1]
582 else:
582 else:
583 return istr
583 return istr
584
584
585 #----------------------------------------------------------------------------
585 #----------------------------------------------------------------------------
586 def process_cmdline(argv,names=[],defaults={},usage=''):
586 def process_cmdline(argv,names=[],defaults={},usage=''):
587 """ Process command-line options and arguments.
587 """ Process command-line options and arguments.
588
588
589 Arguments:
589 Arguments:
590
590
591 - argv: list of arguments, typically sys.argv.
591 - argv: list of arguments, typically sys.argv.
592
592
593 - names: list of option names. See DPyGetOpt docs for details on options
593 - names: list of option names. See DPyGetOpt docs for details on options
594 syntax.
594 syntax.
595
595
596 - defaults: dict of default values.
596 - defaults: dict of default values.
597
597
598 - usage: optional usage notice to print if a wrong argument is passed.
598 - usage: optional usage notice to print if a wrong argument is passed.
599
599
600 Return a dict of options and a list of free arguments."""
600 Return a dict of options and a list of free arguments."""
601
601
602 getopt = DPyGetOpt.DPyGetOpt()
602 getopt = DPyGetOpt.DPyGetOpt()
603 getopt.setIgnoreCase(0)
603 getopt.setIgnoreCase(0)
604 getopt.parseConfiguration(names)
604 getopt.parseConfiguration(names)
605
605
606 try:
606 try:
607 getopt.processArguments(argv)
607 getopt.processArguments(argv)
608 except:
608 except:
609 print usage
609 print usage
610 warn(`sys.exc_value`,level=4)
610 warn(`sys.exc_value`,level=4)
611
611
612 defaults.update(getopt.optionValues)
612 defaults.update(getopt.optionValues)
613 args = getopt.freeValues
613 args = getopt.freeValues
614
614
615 return defaults,args
615 return defaults,args
616
616
617 #----------------------------------------------------------------------------
617 #----------------------------------------------------------------------------
618 def optstr2types(ostr):
618 def optstr2types(ostr):
619 """Convert a string of option names to a dict of type mappings.
619 """Convert a string of option names to a dict of type mappings.
620
620
621 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
621 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
622
622
623 This is used to get the types of all the options in a string formatted
623 This is used to get the types of all the options in a string formatted
624 with the conventions of DPyGetOpt. The 'type' None is used for options
624 with the conventions of DPyGetOpt. The 'type' None is used for options
625 which are strings (they need no further conversion). This function's main
625 which are strings (they need no further conversion). This function's main
626 use is to get a typemap for use with read_dict().
626 use is to get a typemap for use with read_dict().
627 """
627 """
628
628
629 typeconv = {None:'',int:'',float:''}
629 typeconv = {None:'',int:'',float:''}
630 typemap = {'s':None,'i':int,'f':float}
630 typemap = {'s':None,'i':int,'f':float}
631 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
631 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
632
632
633 for w in ostr.split():
633 for w in ostr.split():
634 oname,alias,otype = opt_re.match(w).groups()
634 oname,alias,otype = opt_re.match(w).groups()
635 if otype == '' or alias == '!': # simple switches are integers too
635 if otype == '' or alias == '!': # simple switches are integers too
636 otype = 'i'
636 otype = 'i'
637 typeconv[typemap[otype]] += oname + ' '
637 typeconv[typemap[otype]] += oname + ' '
638 return typeconv
638 return typeconv
639
639
640 #----------------------------------------------------------------------------
640 #----------------------------------------------------------------------------
641 def read_dict(filename,type_conv=None,**opt):
641 def read_dict(filename,type_conv=None,**opt):
642
642
643 """Read a dictionary of key=value pairs from an input file, optionally
643 """Read a dictionary of key=value pairs from an input file, optionally
644 performing conversions on the resulting values.
644 performing conversions on the resulting values.
645
645
646 read_dict(filename,type_conv,**opt) -> dict
646 read_dict(filename,type_conv,**opt) -> dict
647
647
648 Only one value per line is accepted, the format should be
648 Only one value per line is accepted, the format should be
649 # optional comments are ignored
649 # optional comments are ignored
650 key value\n
650 key value\n
651
651
652 Args:
652 Args:
653
653
654 - type_conv: A dictionary specifying which keys need to be converted to
654 - type_conv: A dictionary specifying which keys need to be converted to
655 which types. By default all keys are read as strings. This dictionary
655 which types. By default all keys are read as strings. This dictionary
656 should have as its keys valid conversion functions for strings
656 should have as its keys valid conversion functions for strings
657 (int,long,float,complex, or your own). The value for each key
657 (int,long,float,complex, or your own). The value for each key
658 (converter) should be a whitespace separated string containing the names
658 (converter) should be a whitespace separated string containing the names
659 of all the entries in the file to be converted using that function. For
659 of all the entries in the file to be converted using that function. For
660 keys to be left alone, use None as the conversion function (only needed
660 keys to be left alone, use None as the conversion function (only needed
661 with purge=1, see below).
661 with purge=1, see below).
662
662
663 - opt: dictionary with extra options as below (default in parens)
663 - opt: dictionary with extra options as below (default in parens)
664
664
665 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
665 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
666 of the dictionary to be returned. If purge is going to be used, the
666 of the dictionary to be returned. If purge is going to be used, the
667 set of keys to be left as strings also has to be explicitly specified
667 set of keys to be left as strings also has to be explicitly specified
668 using the (non-existent) conversion function None.
668 using the (non-existent) conversion function None.
669
669
670 fs(None): field separator. This is the key/value separator to be used
670 fs(None): field separator. This is the key/value separator to be used
671 when parsing the file. The None default means any whitespace [behavior
671 when parsing the file. The None default means any whitespace [behavior
672 of string.split()].
672 of string.split()].
673
673
674 strip(0): if 1, strip string values of leading/trailinig whitespace.
674 strip(0): if 1, strip string values of leading/trailinig whitespace.
675
675
676 warn(1): warning level if requested keys are not found in file.
676 warn(1): warning level if requested keys are not found in file.
677 - 0: silently ignore.
677 - 0: silently ignore.
678 - 1: inform but proceed.
678 - 1: inform but proceed.
679 - 2: raise KeyError exception.
679 - 2: raise KeyError exception.
680
680
681 no_empty(0): if 1, remove keys with whitespace strings as a value.
681 no_empty(0): if 1, remove keys with whitespace strings as a value.
682
682
683 unique([]): list of keys (or space separated string) which can't be
683 unique([]): list of keys (or space separated string) which can't be
684 repeated. If one such key is found in the file, each new instance
684 repeated. If one such key is found in the file, each new instance
685 overwrites the previous one. For keys not listed here, the behavior is
685 overwrites the previous one. For keys not listed here, the behavior is
686 to make a list of all appearances.
686 to make a list of all appearances.
687
687
688 Example:
688 Example:
689 If the input file test.ini has:
689 If the input file test.ini has:
690 i 3
690 i 3
691 x 4.5
691 x 4.5
692 y 5.5
692 y 5.5
693 s hi ho
693 s hi ho
694 Then:
694 Then:
695
695
696 >>> type_conv={int:'i',float:'x',None:'s'}
696 >>> type_conv={int:'i',float:'x',None:'s'}
697 >>> read_dict('test.ini')
697 >>> read_dict('test.ini')
698 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
698 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
699 >>> read_dict('test.ini',type_conv)
699 >>> read_dict('test.ini',type_conv)
700 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
700 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
701 >>> read_dict('test.ini',type_conv,purge=1)
701 >>> read_dict('test.ini',type_conv,purge=1)
702 {'i': 3, 's': 'hi ho', 'x': 4.5}
702 {'i': 3, 's': 'hi ho', 'x': 4.5}
703 """
703 """
704
704
705 # starting config
705 # starting config
706 opt.setdefault('purge',0)
706 opt.setdefault('purge',0)
707 opt.setdefault('fs',None) # field sep defaults to any whitespace
707 opt.setdefault('fs',None) # field sep defaults to any whitespace
708 opt.setdefault('strip',0)
708 opt.setdefault('strip',0)
709 opt.setdefault('warn',1)
709 opt.setdefault('warn',1)
710 opt.setdefault('no_empty',0)
710 opt.setdefault('no_empty',0)
711 opt.setdefault('unique','')
711 opt.setdefault('unique','')
712 if type(opt['unique']) in StringTypes:
712 if type(opt['unique']) in StringTypes:
713 unique_keys = qw(opt['unique'])
713 unique_keys = qw(opt['unique'])
714 elif type(opt['unique']) in (types.TupleType,types.ListType):
714 elif type(opt['unique']) in (types.TupleType,types.ListType):
715 unique_keys = opt['unique']
715 unique_keys = opt['unique']
716 else:
716 else:
717 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
717 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
718
718
719 dict = {}
719 dict = {}
720 # first read in table of values as strings
720 # first read in table of values as strings
721 file = open(filename,'r')
721 file = open(filename,'r')
722 for line in file.readlines():
722 for line in file.readlines():
723 line = line.strip()
723 line = line.strip()
724 if len(line) and line[0]=='#': continue
724 if len(line) and line[0]=='#': continue
725 if len(line)>0:
725 if len(line)>0:
726 lsplit = line.split(opt['fs'],1)
726 lsplit = line.split(opt['fs'],1)
727 try:
727 try:
728 key,val = lsplit
728 key,val = lsplit
729 except ValueError:
729 except ValueError:
730 key,val = lsplit[0],''
730 key,val = lsplit[0],''
731 key = key.strip()
731 key = key.strip()
732 if opt['strip']: val = val.strip()
732 if opt['strip']: val = val.strip()
733 if val == "''" or val == '""': val = ''
733 if val == "''" or val == '""': val = ''
734 if opt['no_empty'] and (val=='' or val.isspace()):
734 if opt['no_empty'] and (val=='' or val.isspace()):
735 continue
735 continue
736 # if a key is found more than once in the file, build a list
736 # if a key is found more than once in the file, build a list
737 # unless it's in the 'unique' list. In that case, last found in file
737 # unless it's in the 'unique' list. In that case, last found in file
738 # takes precedence. User beware.
738 # takes precedence. User beware.
739 try:
739 try:
740 if dict[key] and key in unique_keys:
740 if dict[key] and key in unique_keys:
741 dict[key] = val
741 dict[key] = val
742 elif type(dict[key]) is types.ListType:
742 elif type(dict[key]) is types.ListType:
743 dict[key].append(val)
743 dict[key].append(val)
744 else:
744 else:
745 dict[key] = [dict[key],val]
745 dict[key] = [dict[key],val]
746 except KeyError:
746 except KeyError:
747 dict[key] = val
747 dict[key] = val
748 # purge if requested
748 # purge if requested
749 if opt['purge']:
749 if opt['purge']:
750 accepted_keys = qwflat(type_conv.values())
750 accepted_keys = qwflat(type_conv.values())
751 for key in dict.keys():
751 for key in dict.keys():
752 if key in accepted_keys: continue
752 if key in accepted_keys: continue
753 del(dict[key])
753 del(dict[key])
754 # now convert if requested
754 # now convert if requested
755 if type_conv==None: return dict
755 if type_conv==None: return dict
756 conversions = type_conv.keys()
756 conversions = type_conv.keys()
757 try: conversions.remove(None)
757 try: conversions.remove(None)
758 except: pass
758 except: pass
759 for convert in conversions:
759 for convert in conversions:
760 for val in qw(type_conv[convert]):
760 for val in qw(type_conv[convert]):
761 try:
761 try:
762 dict[val] = convert(dict[val])
762 dict[val] = convert(dict[val])
763 except KeyError,e:
763 except KeyError,e:
764 if opt['warn'] == 0:
764 if opt['warn'] == 0:
765 pass
765 pass
766 elif opt['warn'] == 1:
766 elif opt['warn'] == 1:
767 print >>sys.stderr, 'Warning: key',val,\
767 print >>sys.stderr, 'Warning: key',val,\
768 'not found in file',filename
768 'not found in file',filename
769 elif opt['warn'] == 2:
769 elif opt['warn'] == 2:
770 raise KeyError,e
770 raise KeyError,e
771 else:
771 else:
772 raise ValueError,'Warning level must be 0,1 or 2'
772 raise ValueError,'Warning level must be 0,1 or 2'
773
773
774 return dict
774 return dict
775
775
776 #----------------------------------------------------------------------------
776 #----------------------------------------------------------------------------
777 def flag_calls(func):
777 def flag_calls(func):
778 """Wrap a function to detect and flag when it gets called.
778 """Wrap a function to detect and flag when it gets called.
779
779
780 This is a decorator which takes a function and wraps it in a function with
780 This is a decorator which takes a function and wraps it in a function with
781 a 'called' attribute. wrapper.called is initialized to False.
781 a 'called' attribute. wrapper.called is initialized to False.
782
782
783 The wrapper.called attribute is set to False right before each call to the
783 The wrapper.called attribute is set to False right before each call to the
784 wrapped function, so if the call fails it remains False. After the call
784 wrapped function, so if the call fails it remains False. After the call
785 completes, wrapper.called is set to True and the output is returned.
785 completes, wrapper.called is set to True and the output is returned.
786
786
787 Testing for truth in wrapper.called allows you to determine if a call to
787 Testing for truth in wrapper.called allows you to determine if a call to
788 func() was attempted and succeeded."""
788 func() was attempted and succeeded."""
789
789
790 def wrapper(*args,**kw):
790 def wrapper(*args,**kw):
791 wrapper.called = False
791 wrapper.called = False
792 out = func(*args,**kw)
792 out = func(*args,**kw)
793 wrapper.called = True
793 wrapper.called = True
794 return out
794 return out
795
795
796 wrapper.called = False
796 wrapper.called = False
797 wrapper.__doc__ = func.__doc__
797 wrapper.__doc__ = func.__doc__
798 return wrapper
798 return wrapper
799
799
800 #----------------------------------------------------------------------------
800 #----------------------------------------------------------------------------
801 class HomeDirError(Error):
801 class HomeDirError(Error):
802 pass
802 pass
803
803
804 def get_home_dir():
804 def get_home_dir():
805 """Return the closest possible equivalent to a 'home' directory.
805 """Return the closest possible equivalent to a 'home' directory.
806
806
807 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
807 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
808
808
809 Currently only Posix and NT are implemented, a HomeDirError exception is
809 Currently only Posix and NT are implemented, a HomeDirError exception is
810 raised for all other OSes. """
810 raised for all other OSes. """
811
811
812 isdir = os.path.isdir
812 isdir = os.path.isdir
813 env = os.environ
813 env = os.environ
814 try:
814 try:
815 homedir = env['HOME']
815 homedir = env['HOME']
816 if not isdir(homedir):
816 if not isdir(homedir):
817 # in case a user stuck some string which does NOT resolve to a
817 # in case a user stuck some string which does NOT resolve to a
818 # valid path, it's as good as if we hadn't foud it
818 # valid path, it's as good as if we hadn't foud it
819 raise KeyError
819 raise KeyError
820 return homedir
820 return homedir
821 except KeyError:
821 except KeyError:
822 if os.name == 'posix':
822 if os.name == 'posix':
823 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
823 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
824 elif os.name == 'nt':
824 elif os.name == 'nt':
825 # For some strange reason, win9x returns 'nt' for os.name.
825 # For some strange reason, win9x returns 'nt' for os.name.
826 try:
826 try:
827 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
827 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
828 if not isdir(homedir):
828 if not isdir(homedir):
829 homedir = os.path.join(env['USERPROFILE'])
829 homedir = os.path.join(env['USERPROFILE'])
830 if not isdir(homedir):
830 if not isdir(homedir):
831 raise HomeDirError
831 raise HomeDirError
832 return homedir
832 return homedir
833 except:
833 except:
834 try:
834 try:
835 # Use the registry to get the 'My Documents' folder.
835 # Use the registry to get the 'My Documents' folder.
836 import _winreg as wreg
836 import _winreg as wreg
837 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
837 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
838 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
838 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
839 homedir = wreg.QueryValueEx(key,'Personal')[0]
839 homedir = wreg.QueryValueEx(key,'Personal')[0]
840 key.Close()
840 key.Close()
841 if not isdir(homedir):
841 if not isdir(homedir):
842 e = ('Invalid "Personal" folder registry key '
842 e = ('Invalid "Personal" folder registry key '
843 'typically "My Documents".\n'
843 'typically "My Documents".\n'
844 'Value: %s\n'
844 'Value: %s\n'
845 'This is not a valid directory on your system.' %
845 'This is not a valid directory on your system.' %
846 homedir)
846 homedir)
847 raise HomeDirError(e)
847 raise HomeDirError(e)
848 return homedir
848 return homedir
849 except HomeDirError:
849 except HomeDirError:
850 raise
850 raise
851 except:
851 except:
852 return 'C:\\'
852 return 'C:\\'
853 elif os.name == 'dos':
853 elif os.name == 'dos':
854 # Desperate, may do absurd things in classic MacOS. May work under DOS.
854 # Desperate, may do absurd things in classic MacOS. May work under DOS.
855 return 'C:\\'
855 return 'C:\\'
856 else:
856 else:
857 raise HomeDirError,'support for your operating system not implemented.'
857 raise HomeDirError,'support for your operating system not implemented.'
858
858
859 #****************************************************************************
859 #****************************************************************************
860 # strings and text
860 # strings and text
861
861
862 class LSString(str):
862 class LSString(str):
863 """String derivative with a special access attributes.
863 """String derivative with a special access attributes.
864
864
865 These are normal strings, but with the special attributes:
865 These are normal strings, but with the special attributes:
866
866
867 .l (or .list) : value as list (split on newlines).
867 .l (or .list) : value as list (split on newlines).
868 .n (or .nlstr): original value (the string itself).
868 .n (or .nlstr): original value (the string itself).
869 .s (or .spstr): value as whitespace-separated string.
869 .s (or .spstr): value as whitespace-separated string.
870
870
871 Any values which require transformations are computed only once and
871 Any values which require transformations are computed only once and
872 cached.
872 cached.
873
873
874 Such strings are very useful to efficiently interact with the shell, which
874 Such strings are very useful to efficiently interact with the shell, which
875 typically only understands whitespace-separated options for commands."""
875 typically only understands whitespace-separated options for commands."""
876
876
877 def get_list(self):
877 def get_list(self):
878 try:
878 try:
879 return self.__list
879 return self.__list
880 except AttributeError:
880 except AttributeError:
881 self.__list = self.split('\n')
881 self.__list = self.split('\n')
882 return self.__list
882 return self.__list
883
883
884 l = list = property(get_list)
884 l = list = property(get_list)
885
885
886 def get_spstr(self):
886 def get_spstr(self):
887 try:
887 try:
888 return self.__spstr
888 return self.__spstr
889 except AttributeError:
889 except AttributeError:
890 self.__spstr = self.replace('\n',' ')
890 self.__spstr = self.replace('\n',' ')
891 return self.__spstr
891 return self.__spstr
892
892
893 s = spstr = property(get_spstr)
893 s = spstr = property(get_spstr)
894
894
895 def get_nlstr(self):
895 def get_nlstr(self):
896 return self
896 return self
897
897
898 n = nlstr = property(get_nlstr)
898 n = nlstr = property(get_nlstr)
899
899
900 def get_paths(self):
900 def get_paths(self):
901 try:
901 try:
902 return self.__paths
902 return self.__paths
903 except AttributeError:
903 except AttributeError:
904 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
904 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
905 return self.__paths
905 return self.__paths
906
906
907 p = paths = property(get_paths)
907 p = paths = property(get_paths)
908
908
909
909
910 #----------------------------------------------------------------------------
910 #----------------------------------------------------------------------------
911 class SList(list):
911 class SList(list):
912 """List derivative with a special access attributes.
912 """List derivative with a special access attributes.
913
913
914 These are normal lists, but with the special attributes:
914 These are normal lists, but with the special attributes:
915
915
916 .l (or .list) : value as list (the list itself).
916 .l (or .list) : value as list (the list itself).
917 .n (or .nlstr): value as a string, joined on newlines.
917 .n (or .nlstr): value as a string, joined on newlines.
918 .s (or .spstr): value as a string, joined on spaces.
918 .s (or .spstr): value as a string, joined on spaces.
919
919
920 Any values which require transformations are computed only once and
920 Any values which require transformations are computed only once and
921 cached."""
921 cached."""
922
922
923 def get_list(self):
923 def get_list(self):
924 return self
924 return self
925
925
926 l = list = property(get_list)
926 l = list = property(get_list)
927
927
928 def get_spstr(self):
928 def get_spstr(self):
929 try:
929 try:
930 return self.__spstr
930 return self.__spstr
931 except AttributeError:
931 except AttributeError:
932 self.__spstr = ' '.join(self)
932 self.__spstr = ' '.join(self)
933 return self.__spstr
933 return self.__spstr
934
934
935 s = spstr = property(get_spstr)
935 s = spstr = property(get_spstr)
936
936
937 def get_nlstr(self):
937 def get_nlstr(self):
938 try:
938 try:
939 return self.__nlstr
939 return self.__nlstr
940 except AttributeError:
940 except AttributeError:
941 self.__nlstr = '\n'.join(self)
941 self.__nlstr = '\n'.join(self)
942 return self.__nlstr
942 return self.__nlstr
943
943
944 n = nlstr = property(get_nlstr)
944 n = nlstr = property(get_nlstr)
945
945
946 def get_paths(self):
946 def get_paths(self):
947 try:
947 try:
948 return self.__paths
948 return self.__paths
949 except AttributeError:
949 except AttributeError:
950 self.__paths = [path(p) for p in self if os.path.exists(p)]
950 self.__paths = [path(p) for p in self if os.path.exists(p)]
951 return self.__paths
951 return self.__paths
952
952
953 p = paths = property(get_paths)
953 p = paths = property(get_paths)
954
954
955 #----------------------------------------------------------------------------
955 #----------------------------------------------------------------------------
956 def esc_quotes(strng):
956 def esc_quotes(strng):
957 """Return the input string with single and double quotes escaped out"""
957 """Return the input string with single and double quotes escaped out"""
958
958
959 return strng.replace('"','\\"').replace("'","\\'")
959 return strng.replace('"','\\"').replace("'","\\'")
960
960
961 #----------------------------------------------------------------------------
961 #----------------------------------------------------------------------------
962 def make_quoted_expr(s):
962 def make_quoted_expr(s):
963 """Return string s in appropriate quotes, using raw string if possible.
963 """Return string s in appropriate quotes, using raw string if possible.
964
964
965 Effectively this turns string: cd \ao\ao\
965 Effectively this turns string: cd \ao\ao\
966 to: r"cd \ao\ao\_"[:-1]
966 to: r"cd \ao\ao\_"[:-1]
967
967
968 Note the use of raw string and padding at the end to allow trailing backslash.
968 Note the use of raw string and padding at the end to allow trailing backslash.
969
969
970 """
970 """
971
971
972 tail = ''
972 tail = ''
973 tailpadding = ''
973 tailpadding = ''
974 raw = ''
974 raw = ''
975 if "\\" in s:
975 if "\\" in s:
976 raw = 'r'
976 raw = 'r'
977 if s.endswith('\\'):
977 if s.endswith('\\'):
978 tail = '[:-1]'
978 tail = '[:-1]'
979 tailpadding = '_'
979 tailpadding = '_'
980 if '"' not in s:
980 if '"' not in s:
981 quote = '"'
981 quote = '"'
982 elif "'" not in s:
982 elif "'" not in s:
983 quote = "'"
983 quote = "'"
984 elif '"""' not in s and not s.endswith('"'):
984 elif '"""' not in s and not s.endswith('"'):
985 quote = '"""'
985 quote = '"""'
986 elif "'''" not in s and not s.endswith("'"):
986 elif "'''" not in s and not s.endswith("'"):
987 quote = "'''"
987 quote = "'''"
988 else:
988 else:
989 # give up, backslash-escaped string will do
989 # give up, backslash-escaped string will do
990 return '"%s"' % esc_quotes(s)
990 return '"%s"' % esc_quotes(s)
991 res = itpl("$raw$quote$s$tailpadding$quote$tail")
991 res = itpl("$raw$quote$s$tailpadding$quote$tail")
992 return res
992 return res
993
993
994
994
995 #----------------------------------------------------------------------------
995 #----------------------------------------------------------------------------
996 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
996 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
997 """Take multiple lines of input.
997 """Take multiple lines of input.
998
998
999 A list with each line of input as a separate element is returned when a
999 A list with each line of input as a separate element is returned when a
1000 termination string is entered (defaults to a single '.'). Input can also
1000 termination string is entered (defaults to a single '.'). Input can also
1001 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1001 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1002
1002
1003 Lines of input which end in \\ are joined into single entries (and a
1003 Lines of input which end in \\ are joined into single entries (and a
1004 secondary continuation prompt is issued as long as the user terminates
1004 secondary continuation prompt is issued as long as the user terminates
1005 lines with \\). This allows entering very long strings which are still
1005 lines with \\). This allows entering very long strings which are still
1006 meant to be treated as single entities.
1006 meant to be treated as single entities.
1007 """
1007 """
1008
1008
1009 try:
1009 try:
1010 if header:
1010 if header:
1011 header += '\n'
1011 header += '\n'
1012 lines = [raw_input(header + ps1)]
1012 lines = [raw_input(header + ps1)]
1013 except EOFError:
1013 except EOFError:
1014 return []
1014 return []
1015 terminate = [terminate_str]
1015 terminate = [terminate_str]
1016 try:
1016 try:
1017 while lines[-1:] != terminate:
1017 while lines[-1:] != terminate:
1018 new_line = raw_input(ps1)
1018 new_line = raw_input(ps1)
1019 while new_line.endswith('\\'):
1019 while new_line.endswith('\\'):
1020 new_line = new_line[:-1] + raw_input(ps2)
1020 new_line = new_line[:-1] + raw_input(ps2)
1021 lines.append(new_line)
1021 lines.append(new_line)
1022
1022
1023 return lines[:-1] # don't return the termination command
1023 return lines[:-1] # don't return the termination command
1024 except EOFError:
1024 except EOFError:
1025 print
1025 print
1026 return lines
1026 return lines
1027
1027
1028 #----------------------------------------------------------------------------
1028 #----------------------------------------------------------------------------
1029 def raw_input_ext(prompt='', ps2='... '):
1029 def raw_input_ext(prompt='', ps2='... '):
1030 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1030 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1031
1031
1032 line = raw_input(prompt)
1032 line = raw_input(prompt)
1033 while line.endswith('\\'):
1033 while line.endswith('\\'):
1034 line = line[:-1] + raw_input(ps2)
1034 line = line[:-1] + raw_input(ps2)
1035 return line
1035 return line
1036
1036
1037 #----------------------------------------------------------------------------
1037 #----------------------------------------------------------------------------
1038 def ask_yes_no(prompt,default=None):
1038 def ask_yes_no(prompt,default=None):
1039 """Asks a question and returns an integer 1/0 (y/n) answer.
1039 """Asks a question and returns an integer 1/0 (y/n) answer.
1040
1040
1041 If default is given (one of 'y','n'), it is used if the user input is
1041 If default is given (one of 'y','n'), it is used if the user input is
1042 empty. Otherwise the question is repeated until an answer is given.
1042 empty. Otherwise the question is repeated until an answer is given.
1043 If EOF occurs 20 times consecutively, the default answer is assumed,
1043 If EOF occurs 20 times consecutively, the default answer is assumed,
1044 or if there is no default, an exception is raised to prevent infinite
1044 or if there is no default, an exception is raised to prevent infinite
1045 loops.
1045 loops.
1046
1046
1047 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1047 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1048
1048
1049 answers = {'y':True,'n':False,'yes':True,'no':False}
1049 answers = {'y':True,'n':False,'yes':True,'no':False}
1050 ans = None
1050 ans = None
1051 eofs, max_eofs = 0, 20
1051 eofs, max_eofs = 0, 20
1052 while ans not in answers.keys():
1052 while ans not in answers.keys():
1053 try:
1053 try:
1054 ans = raw_input(prompt+' ').lower()
1054 ans = raw_input(prompt+' ').lower()
1055 if not ans: # response was an empty string
1055 if not ans: # response was an empty string
1056 ans = default
1056 ans = default
1057 eofs = 0
1057 eofs = 0
1058 except (EOFError,KeyboardInterrupt):
1058 except (EOFError,KeyboardInterrupt):
1059 eofs = eofs + 1
1059 eofs = eofs + 1
1060 if eofs >= max_eofs:
1060 if eofs >= max_eofs:
1061 if default in answers.keys():
1061 if default in answers.keys():
1062 ans = default
1062 ans = default
1063 else:
1063 else:
1064 raise
1064 raise
1065
1065
1066 return answers[ans]
1066 return answers[ans]
1067
1067
1068 #----------------------------------------------------------------------------
1068 #----------------------------------------------------------------------------
1069 def marquee(txt='',width=78,mark='*'):
1069 def marquee(txt='',width=78,mark='*'):
1070 """Return the input string centered in a 'marquee'."""
1070 """Return the input string centered in a 'marquee'."""
1071 if not txt:
1071 if not txt:
1072 return (mark*width)[:width]
1072 return (mark*width)[:width]
1073 nmark = (width-len(txt)-2)/len(mark)/2
1073 nmark = (width-len(txt)-2)/len(mark)/2
1074 if nmark < 0: nmark =0
1074 if nmark < 0: nmark =0
1075 marks = mark*nmark
1075 marks = mark*nmark
1076 return '%s %s %s' % (marks,txt,marks)
1076 return '%s %s %s' % (marks,txt,marks)
1077
1077
1078 #----------------------------------------------------------------------------
1078 #----------------------------------------------------------------------------
1079 class EvalDict:
1079 class EvalDict:
1080 """
1080 """
1081 Emulate a dict which evaluates its contents in the caller's frame.
1081 Emulate a dict which evaluates its contents in the caller's frame.
1082
1082
1083 Usage:
1083 Usage:
1084 >>>number = 19
1084 >>>number = 19
1085 >>>text = "python"
1085 >>>text = "python"
1086 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1086 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1087 """
1087 """
1088
1088
1089 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1089 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1090 # modified (shorter) version of:
1090 # modified (shorter) version of:
1091 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1091 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1092 # Skip Montanaro (skip@pobox.com).
1092 # Skip Montanaro (skip@pobox.com).
1093
1093
1094 def __getitem__(self, name):
1094 def __getitem__(self, name):
1095 frame = sys._getframe(1)
1095 frame = sys._getframe(1)
1096 return eval(name, frame.f_globals, frame.f_locals)
1096 return eval(name, frame.f_globals, frame.f_locals)
1097
1097
1098 EvalString = EvalDict # for backwards compatibility
1098 EvalString = EvalDict # for backwards compatibility
1099 #----------------------------------------------------------------------------
1099 #----------------------------------------------------------------------------
1100 def qw(words,flat=0,sep=None,maxsplit=-1):
1100 def qw(words,flat=0,sep=None,maxsplit=-1):
1101 """Similar to Perl's qw() operator, but with some more options.
1101 """Similar to Perl's qw() operator, but with some more options.
1102
1102
1103 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1103 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1104
1104
1105 words can also be a list itself, and with flat=1, the output will be
1105 words can also be a list itself, and with flat=1, the output will be
1106 recursively flattened. Examples:
1106 recursively flattened. Examples:
1107
1107
1108 >>> qw('1 2')
1108 >>> qw('1 2')
1109 ['1', '2']
1109 ['1', '2']
1110 >>> qw(['a b','1 2',['m n','p q']])
1110 >>> qw(['a b','1 2',['m n','p q']])
1111 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1111 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1112 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1112 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1113 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1113 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1114
1114
1115 if type(words) in StringTypes:
1115 if type(words) in StringTypes:
1116 return [word.strip() for word in words.split(sep,maxsplit)
1116 return [word.strip() for word in words.split(sep,maxsplit)
1117 if word and not word.isspace() ]
1117 if word and not word.isspace() ]
1118 if flat:
1118 if flat:
1119 return flatten(map(qw,words,[1]*len(words)))
1119 return flatten(map(qw,words,[1]*len(words)))
1120 return map(qw,words)
1120 return map(qw,words)
1121
1121
1122 #----------------------------------------------------------------------------
1122 #----------------------------------------------------------------------------
1123 def qwflat(words,sep=None,maxsplit=-1):
1123 def qwflat(words,sep=None,maxsplit=-1):
1124 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1124 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1125 return qw(words,1,sep,maxsplit)
1125 return qw(words,1,sep,maxsplit)
1126
1126
1127 #----------------------------------------------------------------------------
1127 #----------------------------------------------------------------------------
1128 def qw_lol(indata):
1128 def qw_lol(indata):
1129 """qw_lol('a b') -> [['a','b']],
1129 """qw_lol('a b') -> [['a','b']],
1130 otherwise it's just a call to qw().
1130 otherwise it's just a call to qw().
1131
1131
1132 We need this to make sure the modules_some keys *always* end up as a
1132 We need this to make sure the modules_some keys *always* end up as a
1133 list of lists."""
1133 list of lists."""
1134
1134
1135 if type(indata) in StringTypes:
1135 if type(indata) in StringTypes:
1136 return [qw(indata)]
1136 return [qw(indata)]
1137 else:
1137 else:
1138 return qw(indata)
1138 return qw(indata)
1139
1139
1140 #-----------------------------------------------------------------------------
1140 #-----------------------------------------------------------------------------
1141 def list_strings(arg):
1141 def list_strings(arg):
1142 """Always return a list of strings, given a string or list of strings
1142 """Always return a list of strings, given a string or list of strings
1143 as input."""
1143 as input."""
1144
1144
1145 if type(arg) in StringTypes: return [arg]
1145 if type(arg) in StringTypes: return [arg]
1146 else: return arg
1146 else: return arg
1147
1147
1148 #----------------------------------------------------------------------------
1148 #----------------------------------------------------------------------------
1149 def grep(pat,list,case=1):
1149 def grep(pat,list,case=1):
1150 """Simple minded grep-like function.
1150 """Simple minded grep-like function.
1151 grep(pat,list) returns occurrences of pat in list, None on failure.
1151 grep(pat,list) returns occurrences of pat in list, None on failure.
1152
1152
1153 It only does simple string matching, with no support for regexps. Use the
1153 It only does simple string matching, with no support for regexps. Use the
1154 option case=0 for case-insensitive matching."""
1154 option case=0 for case-insensitive matching."""
1155
1155
1156 # This is pretty crude. At least it should implement copying only references
1156 # This is pretty crude. At least it should implement copying only references
1157 # to the original data in case it's big. Now it copies the data for output.
1157 # to the original data in case it's big. Now it copies the data for output.
1158 out=[]
1158 out=[]
1159 if case:
1159 if case:
1160 for term in list:
1160 for term in list:
1161 if term.find(pat)>-1: out.append(term)
1161 if term.find(pat)>-1: out.append(term)
1162 else:
1162 else:
1163 lpat=pat.lower()
1163 lpat=pat.lower()
1164 for term in list:
1164 for term in list:
1165 if term.lower().find(lpat)>-1: out.append(term)
1165 if term.lower().find(lpat)>-1: out.append(term)
1166
1166
1167 if len(out): return out
1167 if len(out): return out
1168 else: return None
1168 else: return None
1169
1169
1170 #----------------------------------------------------------------------------
1170 #----------------------------------------------------------------------------
1171 def dgrep(pat,*opts):
1171 def dgrep(pat,*opts):
1172 """Return grep() on dir()+dir(__builtins__).
1172 """Return grep() on dir()+dir(__builtins__).
1173
1173
1174 A very common use of grep() when working interactively."""
1174 A very common use of grep() when working interactively."""
1175
1175
1176 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1176 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1177
1177
1178 #----------------------------------------------------------------------------
1178 #----------------------------------------------------------------------------
1179 def idgrep(pat):
1179 def idgrep(pat):
1180 """Case-insensitive dgrep()"""
1180 """Case-insensitive dgrep()"""
1181
1181
1182 return dgrep(pat,0)
1182 return dgrep(pat,0)
1183
1183
1184 #----------------------------------------------------------------------------
1184 #----------------------------------------------------------------------------
1185 def igrep(pat,list):
1185 def igrep(pat,list):
1186 """Synonym for case-insensitive grep."""
1186 """Synonym for case-insensitive grep."""
1187
1187
1188 return grep(pat,list,case=0)
1188 return grep(pat,list,case=0)
1189
1189
1190 #----------------------------------------------------------------------------
1190 #----------------------------------------------------------------------------
1191 def indent(str,nspaces=4,ntabs=0):
1191 def indent(str,nspaces=4,ntabs=0):
1192 """Indent a string a given number of spaces or tabstops.
1192 """Indent a string a given number of spaces or tabstops.
1193
1193
1194 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1194 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1195 """
1195 """
1196 if str is None:
1196 if str is None:
1197 return
1197 return
1198 ind = '\t'*ntabs+' '*nspaces
1198 ind = '\t'*ntabs+' '*nspaces
1199 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1199 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1200 if outstr.endswith(os.linesep+ind):
1200 if outstr.endswith(os.linesep+ind):
1201 return outstr[:-len(ind)]
1201 return outstr[:-len(ind)]
1202 else:
1202 else:
1203 return outstr
1203 return outstr
1204
1204
1205 #-----------------------------------------------------------------------------
1205 #-----------------------------------------------------------------------------
1206 def native_line_ends(filename,backup=1):
1206 def native_line_ends(filename,backup=1):
1207 """Convert (in-place) a file to line-ends native to the current OS.
1207 """Convert (in-place) a file to line-ends native to the current OS.
1208
1208
1209 If the optional backup argument is given as false, no backup of the
1209 If the optional backup argument is given as false, no backup of the
1210 original file is left. """
1210 original file is left. """
1211
1211
1212 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1212 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1213
1213
1214 bak_filename = filename + backup_suffixes[os.name]
1214 bak_filename = filename + backup_suffixes[os.name]
1215
1215
1216 original = open(filename).read()
1216 original = open(filename).read()
1217 shutil.copy2(filename,bak_filename)
1217 shutil.copy2(filename,bak_filename)
1218 try:
1218 try:
1219 new = open(filename,'wb')
1219 new = open(filename,'wb')
1220 new.write(os.linesep.join(original.splitlines()))
1220 new.write(os.linesep.join(original.splitlines()))
1221 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1221 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1222 new.close()
1222 new.close()
1223 except:
1223 except:
1224 os.rename(bak_filename,filename)
1224 os.rename(bak_filename,filename)
1225 if not backup:
1225 if not backup:
1226 try:
1226 try:
1227 os.remove(bak_filename)
1227 os.remove(bak_filename)
1228 except:
1228 except:
1229 pass
1229 pass
1230
1230
1231 #----------------------------------------------------------------------------
1231 #----------------------------------------------------------------------------
1232 def get_pager_cmd(pager_cmd = None):
1232 def get_pager_cmd(pager_cmd = None):
1233 """Return a pager command.
1233 """Return a pager command.
1234
1234
1235 Makes some attempts at finding an OS-correct one."""
1235 Makes some attempts at finding an OS-correct one."""
1236
1236
1237 if os.name == 'posix':
1237 if os.name == 'posix':
1238 default_pager_cmd = 'less -r' # -r for color control sequences
1238 default_pager_cmd = 'less -r' # -r for color control sequences
1239 elif os.name in ['nt','dos']:
1239 elif os.name in ['nt','dos']:
1240 default_pager_cmd = 'type'
1240 default_pager_cmd = 'type'
1241
1241
1242 if pager_cmd is None:
1242 if pager_cmd is None:
1243 try:
1243 try:
1244 pager_cmd = os.environ['PAGER']
1244 pager_cmd = os.environ['PAGER']
1245 except:
1245 except:
1246 pager_cmd = default_pager_cmd
1246 pager_cmd = default_pager_cmd
1247 return pager_cmd
1247 return pager_cmd
1248
1248
1249 #-----------------------------------------------------------------------------
1249 #-----------------------------------------------------------------------------
1250 def get_pager_start(pager,start):
1250 def get_pager_start(pager,start):
1251 """Return the string for paging files with an offset.
1251 """Return the string for paging files with an offset.
1252
1252
1253 This is the '+N' argument which less and more (under Unix) accept.
1253 This is the '+N' argument which less and more (under Unix) accept.
1254 """
1254 """
1255
1255
1256 if pager in ['less','more']:
1256 if pager in ['less','more']:
1257 if start:
1257 if start:
1258 start_string = '+' + str(start)
1258 start_string = '+' + str(start)
1259 else:
1259 else:
1260 start_string = ''
1260 start_string = ''
1261 else:
1261 else:
1262 start_string = ''
1262 start_string = ''
1263 return start_string
1263 return start_string
1264
1264
1265 #----------------------------------------------------------------------------
1265 #----------------------------------------------------------------------------
1266 if os.name == "nt":
1266 if os.name == "nt":
1267 import msvcrt
1267 import msvcrt
1268 def page_more():
1268 def page_more():
1269 """ Smart pausing between pages
1269 """ Smart pausing between pages
1270
1270
1271 @return: True if need print more lines, False if quit
1271 @return: True if need print more lines, False if quit
1272 """
1272 """
1273 Term.cout.write('---Return to continue, q to quit--- ')
1273 Term.cout.write('---Return to continue, q to quit--- ')
1274 ans = msvcrt.getch()
1274 ans = msvcrt.getch()
1275 if ans in ("q", "Q"):
1275 if ans in ("q", "Q"):
1276 result = False
1276 result = False
1277 else:
1277 else:
1278 result = True
1278 result = True
1279 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1279 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1280 return result
1280 return result
1281 else:
1281 else:
1282 def page_more():
1282 def page_more():
1283 ans = raw_input('---Return to continue, q to quit--- ')
1283 ans = raw_input('---Return to continue, q to quit--- ')
1284 if ans.lower().startswith('q'):
1284 if ans.lower().startswith('q'):
1285 return False
1285 return False
1286 else:
1286 else:
1287 return True
1287 return True
1288
1288
1289 esc_re = re.compile(r"(\x1b[^m]+m)")
1289 esc_re = re.compile(r"(\x1b[^m]+m)")
1290
1290
1291 def page_dumb(strng,start=0,screen_lines=25):
1291 def page_dumb(strng,start=0,screen_lines=25):
1292 """Very dumb 'pager' in Python, for when nothing else works.
1292 """Very dumb 'pager' in Python, for when nothing else works.
1293
1293
1294 Only moves forward, same interface as page(), except for pager_cmd and
1294 Only moves forward, same interface as page(), except for pager_cmd and
1295 mode."""
1295 mode."""
1296
1296
1297 out_ln = strng.splitlines()[start:]
1297 out_ln = strng.splitlines()[start:]
1298 screens = chop(out_ln,screen_lines-1)
1298 screens = chop(out_ln,screen_lines-1)
1299 if len(screens) == 1:
1299 if len(screens) == 1:
1300 print >>Term.cout, os.linesep.join(screens[0])
1300 print >>Term.cout, os.linesep.join(screens[0])
1301 else:
1301 else:
1302 last_escape = ""
1302 last_escape = ""
1303 for scr in screens[0:-1]:
1303 for scr in screens[0:-1]:
1304 hunk = os.linesep.join(scr)
1304 hunk = os.linesep.join(scr)
1305 print >>Term.cout, last_escape + hunk
1305 print >>Term.cout, last_escape + hunk
1306 if not page_more():
1306 if not page_more():
1307 return
1307 return
1308 esc_list = esc_re.findall(hunk)
1308 esc_list = esc_re.findall(hunk)
1309 if len(esc_list) > 0:
1309 if len(esc_list) > 0:
1310 last_escape = esc_list[-1]
1310 last_escape = esc_list[-1]
1311 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1311 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1312
1312
1313 #----------------------------------------------------------------------------
1313 #----------------------------------------------------------------------------
1314 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1314 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1315 """Print a string, piping through a pager after a certain length.
1315 """Print a string, piping through a pager after a certain length.
1316
1316
1317 The screen_lines parameter specifies the number of *usable* lines of your
1317 The screen_lines parameter specifies the number of *usable* lines of your
1318 terminal screen (total lines minus lines you need to reserve to show other
1318 terminal screen (total lines minus lines you need to reserve to show other
1319 information).
1319 information).
1320
1320
1321 If you set screen_lines to a number <=0, page() will try to auto-determine
1321 If you set screen_lines to a number <=0, page() will try to auto-determine
1322 your screen size and will only use up to (screen_size+screen_lines) for
1322 your screen size and will only use up to (screen_size+screen_lines) for
1323 printing, paging after that. That is, if you want auto-detection but need
1323 printing, paging after that. That is, if you want auto-detection but need
1324 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1324 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1325 auto-detection without any lines reserved simply use screen_lines = 0.
1325 auto-detection without any lines reserved simply use screen_lines = 0.
1326
1326
1327 If a string won't fit in the allowed lines, it is sent through the
1327 If a string won't fit in the allowed lines, it is sent through the
1328 specified pager command. If none given, look for PAGER in the environment,
1328 specified pager command. If none given, look for PAGER in the environment,
1329 and ultimately default to less.
1329 and ultimately default to less.
1330
1330
1331 If no system pager works, the string is sent through a 'dumb pager'
1331 If no system pager works, the string is sent through a 'dumb pager'
1332 written in python, very simplistic.
1332 written in python, very simplistic.
1333 """
1333 """
1334
1334
1335 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1335 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1336 TERM = os.environ.get('TERM','dumb')
1336 TERM = os.environ.get('TERM','dumb')
1337 if TERM in ['dumb','emacs'] and os.name != 'nt':
1337 if TERM in ['dumb','emacs'] and os.name != 'nt':
1338 print strng
1338 print strng
1339 return
1339 return
1340 # chop off the topmost part of the string we don't want to see
1340 # chop off the topmost part of the string we don't want to see
1341 str_lines = strng.split(os.linesep)[start:]
1341 str_lines = strng.split(os.linesep)[start:]
1342 str_toprint = os.linesep.join(str_lines)
1342 str_toprint = os.linesep.join(str_lines)
1343 num_newlines = len(str_lines)
1343 num_newlines = len(str_lines)
1344 len_str = len(str_toprint)
1344 len_str = len(str_toprint)
1345
1345
1346 # Dumb heuristics to guesstimate number of on-screen lines the string
1346 # Dumb heuristics to guesstimate number of on-screen lines the string
1347 # takes. Very basic, but good enough for docstrings in reasonable
1347 # takes. Very basic, but good enough for docstrings in reasonable
1348 # terminals. If someone later feels like refining it, it's not hard.
1348 # terminals. If someone later feels like refining it, it's not hard.
1349 numlines = max(num_newlines,int(len_str/80)+1)
1349 numlines = max(num_newlines,int(len_str/80)+1)
1350
1350
1351 if os.name == "nt":
1351 if os.name == "nt":
1352 screen_lines_def = get_console_size(defaulty=25)[1]
1352 screen_lines_def = get_console_size(defaulty=25)[1]
1353 else:
1353 else:
1354 screen_lines_def = 25 # default value if we can't auto-determine
1354 screen_lines_def = 25 # default value if we can't auto-determine
1355
1355
1356 # auto-determine screen size
1356 # auto-determine screen size
1357 if screen_lines <= 0:
1357 if screen_lines <= 0:
1358 if TERM=='xterm':
1358 if TERM=='xterm':
1359 try:
1359 try:
1360 import curses
1360 import curses
1361 if hasattr(curses,'initscr'):
1361 if hasattr(curses,'initscr'):
1362 use_curses = 1
1362 use_curses = 1
1363 else:
1363 else:
1364 use_curses = 0
1364 use_curses = 0
1365 except ImportError:
1365 except ImportError:
1366 use_curses = 0
1366 use_curses = 0
1367 else:
1367 else:
1368 # curses causes problems on many terminals other than xterm.
1368 # curses causes problems on many terminals other than xterm.
1369 use_curses = 0
1369 use_curses = 0
1370 if use_curses:
1370 if use_curses:
1371 scr = curses.initscr()
1371 scr = curses.initscr()
1372 screen_lines_real,screen_cols = scr.getmaxyx()
1372 screen_lines_real,screen_cols = scr.getmaxyx()
1373 curses.endwin()
1373 curses.endwin()
1374 screen_lines += screen_lines_real
1374 screen_lines += screen_lines_real
1375 #print '***Screen size:',screen_lines_real,'lines x',\
1375 #print '***Screen size:',screen_lines_real,'lines x',\
1376 #screen_cols,'columns.' # dbg
1376 #screen_cols,'columns.' # dbg
1377 else:
1377 else:
1378 screen_lines += screen_lines_def
1378 screen_lines += screen_lines_def
1379
1379
1380 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1380 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1381 if numlines <= screen_lines :
1381 if numlines <= screen_lines :
1382 #print '*** normal print' # dbg
1382 #print '*** normal print' # dbg
1383 print >>Term.cout, str_toprint
1383 print >>Term.cout, str_toprint
1384 else:
1384 else:
1385 # Try to open pager and default to internal one if that fails.
1385 # Try to open pager and default to internal one if that fails.
1386 # All failure modes are tagged as 'retval=1', to match the return
1386 # All failure modes are tagged as 'retval=1', to match the return
1387 # value of a failed system command. If any intermediate attempt
1387 # value of a failed system command. If any intermediate attempt
1388 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1388 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1389 pager_cmd = get_pager_cmd(pager_cmd)
1389 pager_cmd = get_pager_cmd(pager_cmd)
1390 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1390 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1391 if os.name == 'nt':
1391 if os.name == 'nt':
1392 if pager_cmd.startswith('type'):
1392 if pager_cmd.startswith('type'):
1393 # The default WinXP 'type' command is failing on complex strings.
1393 # The default WinXP 'type' command is failing on complex strings.
1394 retval = 1
1394 retval = 1
1395 else:
1395 else:
1396 tmpname = tempfile.mktemp('.txt')
1396 tmpname = tempfile.mktemp('.txt')
1397 tmpfile = file(tmpname,'wt')
1397 tmpfile = file(tmpname,'wt')
1398 tmpfile.write(strng)
1398 tmpfile.write(strng)
1399 tmpfile.close()
1399 tmpfile.close()
1400 cmd = "%s < %s" % (pager_cmd,tmpname)
1400 cmd = "%s < %s" % (pager_cmd,tmpname)
1401 if os.system(cmd):
1401 if os.system(cmd):
1402 retval = 1
1402 retval = 1
1403 else:
1403 else:
1404 retval = None
1404 retval = None
1405 os.remove(tmpname)
1405 os.remove(tmpname)
1406 else:
1406 else:
1407 try:
1407 try:
1408 retval = None
1408 retval = None
1409 # if I use popen4, things hang. No idea why.
1409 # if I use popen4, things hang. No idea why.
1410 #pager,shell_out = os.popen4(pager_cmd)
1410 #pager,shell_out = os.popen4(pager_cmd)
1411 pager = os.popen(pager_cmd,'w')
1411 pager = os.popen(pager_cmd,'w')
1412 pager.write(strng)
1412 pager.write(strng)
1413 pager.close()
1413 pager.close()
1414 retval = pager.close() # success returns None
1414 retval = pager.close() # success returns None
1415 except IOError,msg: # broken pipe when user quits
1415 except IOError,msg: # broken pipe when user quits
1416 if msg.args == (32,'Broken pipe'):
1416 if msg.args == (32,'Broken pipe'):
1417 retval = None
1417 retval = None
1418 else:
1418 else:
1419 retval = 1
1419 retval = 1
1420 except OSError:
1420 except OSError:
1421 # Other strange problems, sometimes seen in Win2k/cygwin
1421 # Other strange problems, sometimes seen in Win2k/cygwin
1422 retval = 1
1422 retval = 1
1423 if retval is not None:
1423 if retval is not None:
1424 page_dumb(strng,screen_lines=screen_lines)
1424 page_dumb(strng,screen_lines=screen_lines)
1425
1425
1426 #----------------------------------------------------------------------------
1426 #----------------------------------------------------------------------------
1427 def page_file(fname,start = 0, pager_cmd = None):
1427 def page_file(fname,start = 0, pager_cmd = None):
1428 """Page a file, using an optional pager command and starting line.
1428 """Page a file, using an optional pager command and starting line.
1429 """
1429 """
1430
1430
1431 pager_cmd = get_pager_cmd(pager_cmd)
1431 pager_cmd = get_pager_cmd(pager_cmd)
1432 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1432 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1433
1433
1434 try:
1434 try:
1435 if os.environ['TERM'] in ['emacs','dumb']:
1435 if os.environ['TERM'] in ['emacs','dumb']:
1436 raise EnvironmentError
1436 raise EnvironmentError
1437 xsys(pager_cmd + ' ' + fname)
1437 xsys(pager_cmd + ' ' + fname)
1438 except:
1438 except:
1439 try:
1439 try:
1440 if start > 0:
1440 if start > 0:
1441 start -= 1
1441 start -= 1
1442 page(open(fname).read(),start)
1442 page(open(fname).read(),start)
1443 except:
1443 except:
1444 print 'Unable to show file',`fname`
1444 print 'Unable to show file',`fname`
1445
1445
1446 #----------------------------------------------------------------------------
1446 #----------------------------------------------------------------------------
1447 def snip_print(str,width = 75,print_full = 0,header = ''):
1447 def snip_print(str,width = 75,print_full = 0,header = ''):
1448 """Print a string snipping the midsection to fit in width.
1448 """Print a string snipping the midsection to fit in width.
1449
1449
1450 print_full: mode control:
1450 print_full: mode control:
1451 - 0: only snip long strings
1451 - 0: only snip long strings
1452 - 1: send to page() directly.
1452 - 1: send to page() directly.
1453 - 2: snip long strings and ask for full length viewing with page()
1453 - 2: snip long strings and ask for full length viewing with page()
1454 Return 1 if snipping was necessary, 0 otherwise."""
1454 Return 1 if snipping was necessary, 0 otherwise."""
1455
1455
1456 if print_full == 1:
1456 if print_full == 1:
1457 page(header+str)
1457 page(header+str)
1458 return 0
1458 return 0
1459
1459
1460 print header,
1460 print header,
1461 if len(str) < width:
1461 if len(str) < width:
1462 print str
1462 print str
1463 snip = 0
1463 snip = 0
1464 else:
1464 else:
1465 whalf = int((width -5)/2)
1465 whalf = int((width -5)/2)
1466 print str[:whalf] + ' <...> ' + str[-whalf:]
1466 print str[:whalf] + ' <...> ' + str[-whalf:]
1467 snip = 1
1467 snip = 1
1468 if snip and print_full == 2:
1468 if snip and print_full == 2:
1469 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1469 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1470 page(str)
1470 page(str)
1471 return snip
1471 return snip
1472
1472
1473 #****************************************************************************
1473 #****************************************************************************
1474 # lists, dicts and structures
1474 # lists, dicts and structures
1475
1475
1476 def belong(candidates,checklist):
1476 def belong(candidates,checklist):
1477 """Check whether a list of items appear in a given list of options.
1477 """Check whether a list of items appear in a given list of options.
1478
1478
1479 Returns a list of 1 and 0, one for each candidate given."""
1479 Returns a list of 1 and 0, one for each candidate given."""
1480
1480
1481 return [x in checklist for x in candidates]
1481 return [x in checklist for x in candidates]
1482
1482
1483 #----------------------------------------------------------------------------
1483 #----------------------------------------------------------------------------
1484 def uniq_stable(elems):
1484 def uniq_stable(elems):
1485 """uniq_stable(elems) -> list
1485 """uniq_stable(elems) -> list
1486
1486
1487 Return from an iterable, a list of all the unique elements in the input,
1487 Return from an iterable, a list of all the unique elements in the input,
1488 but maintaining the order in which they first appear.
1488 but maintaining the order in which they first appear.
1489
1489
1490 A naive solution to this problem which just makes a dictionary with the
1490 A naive solution to this problem which just makes a dictionary with the
1491 elements as keys fails to respect the stability condition, since
1491 elements as keys fails to respect the stability condition, since
1492 dictionaries are unsorted by nature.
1492 dictionaries are unsorted by nature.
1493
1493
1494 Note: All elements in the input must be valid dictionary keys for this
1494 Note: All elements in the input must be valid dictionary keys for this
1495 routine to work, as it internally uses a dictionary for efficiency
1495 routine to work, as it internally uses a dictionary for efficiency
1496 reasons."""
1496 reasons."""
1497
1497
1498 unique = []
1498 unique = []
1499 unique_dict = {}
1499 unique_dict = {}
1500 for nn in elems:
1500 for nn in elems:
1501 if nn not in unique_dict:
1501 if nn not in unique_dict:
1502 unique.append(nn)
1502 unique.append(nn)
1503 unique_dict[nn] = None
1503 unique_dict[nn] = None
1504 return unique
1504 return unique
1505
1505
1506 #----------------------------------------------------------------------------
1506 #----------------------------------------------------------------------------
1507 class NLprinter:
1507 class NLprinter:
1508 """Print an arbitrarily nested list, indicating index numbers.
1508 """Print an arbitrarily nested list, indicating index numbers.
1509
1509
1510 An instance of this class called nlprint is available and callable as a
1510 An instance of this class called nlprint is available and callable as a
1511 function.
1511 function.
1512
1512
1513 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1513 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1514 and using 'sep' to separate the index from the value. """
1514 and using 'sep' to separate the index from the value. """
1515
1515
1516 def __init__(self):
1516 def __init__(self):
1517 self.depth = 0
1517 self.depth = 0
1518
1518
1519 def __call__(self,lst,pos='',**kw):
1519 def __call__(self,lst,pos='',**kw):
1520 """Prints the nested list numbering levels."""
1520 """Prints the nested list numbering levels."""
1521 kw.setdefault('indent',' ')
1521 kw.setdefault('indent',' ')
1522 kw.setdefault('sep',': ')
1522 kw.setdefault('sep',': ')
1523 kw.setdefault('start',0)
1523 kw.setdefault('start',0)
1524 kw.setdefault('stop',len(lst))
1524 kw.setdefault('stop',len(lst))
1525 # we need to remove start and stop from kw so they don't propagate
1525 # we need to remove start and stop from kw so they don't propagate
1526 # into a recursive call for a nested list.
1526 # into a recursive call for a nested list.
1527 start = kw['start']; del kw['start']
1527 start = kw['start']; del kw['start']
1528 stop = kw['stop']; del kw['stop']
1528 stop = kw['stop']; del kw['stop']
1529 if self.depth == 0 and 'header' in kw.keys():
1529 if self.depth == 0 and 'header' in kw.keys():
1530 print kw['header']
1530 print kw['header']
1531
1531
1532 for idx in range(start,stop):
1532 for idx in range(start,stop):
1533 elem = lst[idx]
1533 elem = lst[idx]
1534 if type(elem)==type([]):
1534 if type(elem)==type([]):
1535 self.depth += 1
1535 self.depth += 1
1536 self.__call__(elem,itpl('$pos$idx,'),**kw)
1536 self.__call__(elem,itpl('$pos$idx,'),**kw)
1537 self.depth -= 1
1537 self.depth -= 1
1538 else:
1538 else:
1539 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1539 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1540
1540
1541 nlprint = NLprinter()
1541 nlprint = NLprinter()
1542 #----------------------------------------------------------------------------
1542 #----------------------------------------------------------------------------
1543 def all_belong(candidates,checklist):
1543 def all_belong(candidates,checklist):
1544 """Check whether a list of items ALL appear in a given list of options.
1544 """Check whether a list of items ALL appear in a given list of options.
1545
1545
1546 Returns a single 1 or 0 value."""
1546 Returns a single 1 or 0 value."""
1547
1547
1548 return 1-(0 in [x in checklist for x in candidates])
1548 return 1-(0 in [x in checklist for x in candidates])
1549
1549
1550 #----------------------------------------------------------------------------
1550 #----------------------------------------------------------------------------
1551 def sort_compare(lst1,lst2,inplace = 1):
1551 def sort_compare(lst1,lst2,inplace = 1):
1552 """Sort and compare two lists.
1552 """Sort and compare two lists.
1553
1553
1554 By default it does it in place, thus modifying the lists. Use inplace = 0
1554 By default it does it in place, thus modifying the lists. Use inplace = 0
1555 to avoid that (at the cost of temporary copy creation)."""
1555 to avoid that (at the cost of temporary copy creation)."""
1556 if not inplace:
1556 if not inplace:
1557 lst1 = lst1[:]
1557 lst1 = lst1[:]
1558 lst2 = lst2[:]
1558 lst2 = lst2[:]
1559 lst1.sort(); lst2.sort()
1559 lst1.sort(); lst2.sort()
1560 return lst1 == lst2
1560 return lst1 == lst2
1561
1561
1562 #----------------------------------------------------------------------------
1562 #----------------------------------------------------------------------------
1563 def mkdict(**kwargs):
1563 def mkdict(**kwargs):
1564 """Return a dict from a keyword list.
1564 """Return a dict from a keyword list.
1565
1565
1566 It's just syntactic sugar for making ditcionary creation more convenient:
1566 It's just syntactic sugar for making ditcionary creation more convenient:
1567 # the standard way
1567 # the standard way
1568 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1568 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1569 # a cleaner way
1569 # a cleaner way
1570 >>>data = dict(red=1, green=2, blue=3)
1570 >>>data = dict(red=1, green=2, blue=3)
1571
1571
1572 If you need more than this, look at the Struct() class."""
1572 If you need more than this, look at the Struct() class."""
1573
1573
1574 return kwargs
1574 return kwargs
1575
1575
1576 #----------------------------------------------------------------------------
1576 #----------------------------------------------------------------------------
1577 def list2dict(lst):
1577 def list2dict(lst):
1578 """Takes a list of (key,value) pairs and turns it into a dict."""
1578 """Takes a list of (key,value) pairs and turns it into a dict."""
1579
1579
1580 dic = {}
1580 dic = {}
1581 for k,v in lst: dic[k] = v
1581 for k,v in lst: dic[k] = v
1582 return dic
1582 return dic
1583
1583
1584 #----------------------------------------------------------------------------
1584 #----------------------------------------------------------------------------
1585 def list2dict2(lst,default=''):
1585 def list2dict2(lst,default=''):
1586 """Takes a list and turns it into a dict.
1586 """Takes a list and turns it into a dict.
1587 Much slower than list2dict, but more versatile. This version can take
1587 Much slower than list2dict, but more versatile. This version can take
1588 lists with sublists of arbitrary length (including sclars)."""
1588 lists with sublists of arbitrary length (including sclars)."""
1589
1589
1590 dic = {}
1590 dic = {}
1591 for elem in lst:
1591 for elem in lst:
1592 if type(elem) in (types.ListType,types.TupleType):
1592 if type(elem) in (types.ListType,types.TupleType):
1593 size = len(elem)
1593 size = len(elem)
1594 if size == 0:
1594 if size == 0:
1595 pass
1595 pass
1596 elif size == 1:
1596 elif size == 1:
1597 dic[elem] = default
1597 dic[elem] = default
1598 else:
1598 else:
1599 k,v = elem[0], elem[1:]
1599 k,v = elem[0], elem[1:]
1600 if len(v) == 1: v = v[0]
1600 if len(v) == 1: v = v[0]
1601 dic[k] = v
1601 dic[k] = v
1602 else:
1602 else:
1603 dic[elem] = default
1603 dic[elem] = default
1604 return dic
1604 return dic
1605
1605
1606 #----------------------------------------------------------------------------
1606 #----------------------------------------------------------------------------
1607 def flatten(seq):
1607 def flatten(seq):
1608 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1608 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1609
1609
1610 # bug in python??? (YES. Fixed in 2.2, let's leave the kludgy fix in).
1610 # bug in python??? (YES. Fixed in 2.2, let's leave the kludgy fix in).
1611
1611
1612 # if the x=0 isn't made, a *global* variable x is left over after calling
1612 # if the x=0 isn't made, a *global* variable x is left over after calling
1613 # this function, with the value of the last element in the return
1613 # this function, with the value of the last element in the return
1614 # list. This does seem like a bug big time to me.
1614 # list. This does seem like a bug big time to me.
1615
1615
1616 # the problem is fixed with the x=0, which seems to force the creation of
1616 # the problem is fixed with the x=0, which seems to force the creation of
1617 # a local name
1617 # a local name
1618
1618
1619 x = 0
1619 x = 0
1620 return [x for subseq in seq for x in subseq]
1620 return [x for subseq in seq for x in subseq]
1621
1621
1622 #----------------------------------------------------------------------------
1622 #----------------------------------------------------------------------------
1623 def get_slice(seq,start=0,stop=None,step=1):
1623 def get_slice(seq,start=0,stop=None,step=1):
1624 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1624 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1625 if stop == None:
1625 if stop == None:
1626 stop = len(seq)
1626 stop = len(seq)
1627 item = lambda i: seq[i]
1627 item = lambda i: seq[i]
1628 return map(item,xrange(start,stop,step))
1628 return map(item,xrange(start,stop,step))
1629
1629
1630 #----------------------------------------------------------------------------
1630 #----------------------------------------------------------------------------
1631 def chop(seq,size):
1631 def chop(seq,size):
1632 """Chop a sequence into chunks of the given size."""
1632 """Chop a sequence into chunks of the given size."""
1633 chunk = lambda i: seq[i:i+size]
1633 chunk = lambda i: seq[i:i+size]
1634 return map(chunk,xrange(0,len(seq),size))
1634 return map(chunk,xrange(0,len(seq),size))
1635
1635
1636 #----------------------------------------------------------------------------
1636 #----------------------------------------------------------------------------
1637 def with(object, **args):
1637 def with(object, **args):
1638 """Set multiple attributes for an object, similar to Pascal's with.
1638 """Set multiple attributes for an object, similar to Pascal's with.
1639
1639
1640 Example:
1640 Example:
1641 with(jim,
1641 with(jim,
1642 born = 1960,
1642 born = 1960,
1643 haircolour = 'Brown',
1643 haircolour = 'Brown',
1644 eyecolour = 'Green')
1644 eyecolour = 'Green')
1645
1645
1646 Credit: Greg Ewing, in
1646 Credit: Greg Ewing, in
1647 http://mail.python.org/pipermail/python-list/2001-May/040703.html"""
1647 http://mail.python.org/pipermail/python-list/2001-May/040703.html"""
1648
1648
1649 object.__dict__.update(args)
1649 object.__dict__.update(args)
1650
1650
1651 #----------------------------------------------------------------------------
1651 #----------------------------------------------------------------------------
1652 def setattr_list(obj,alist,nspace = None):
1652 def setattr_list(obj,alist,nspace = None):
1653 """Set a list of attributes for an object taken from a namespace.
1653 """Set a list of attributes for an object taken from a namespace.
1654
1654
1655 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1655 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1656 alist with their values taken from nspace, which must be a dict (something
1656 alist with their values taken from nspace, which must be a dict (something
1657 like locals() will often do) If nspace isn't given, locals() of the
1657 like locals() will often do) If nspace isn't given, locals() of the
1658 *caller* is used, so in most cases you can omit it.
1658 *caller* is used, so in most cases you can omit it.
1659
1659
1660 Note that alist can be given as a string, which will be automatically
1660 Note that alist can be given as a string, which will be automatically
1661 split into a list on whitespace. If given as a list, it must be a list of
1661 split into a list on whitespace. If given as a list, it must be a list of
1662 *strings* (the variable names themselves), not of variables."""
1662 *strings* (the variable names themselves), not of variables."""
1663
1663
1664 # this grabs the local variables from the *previous* call frame -- that is
1664 # this grabs the local variables from the *previous* call frame -- that is
1665 # the locals from the function that called setattr_list().
1665 # the locals from the function that called setattr_list().
1666 # - snipped from weave.inline()
1666 # - snipped from weave.inline()
1667 if nspace is None:
1667 if nspace is None:
1668 call_frame = sys._getframe().f_back
1668 call_frame = sys._getframe().f_back
1669 nspace = call_frame.f_locals
1669 nspace = call_frame.f_locals
1670
1670
1671 if type(alist) in StringTypes:
1671 if type(alist) in StringTypes:
1672 alist = alist.split()
1672 alist = alist.split()
1673 for attr in alist:
1673 for attr in alist:
1674 val = eval(attr,nspace)
1674 val = eval(attr,nspace)
1675 setattr(obj,attr,val)
1675 setattr(obj,attr,val)
1676
1676
1677 #----------------------------------------------------------------------------
1677 #----------------------------------------------------------------------------
1678 def getattr_list(obj,alist,*args):
1678 def getattr_list(obj,alist,*args):
1679 """getattr_list(obj,alist[, default]) -> attribute list.
1679 """getattr_list(obj,alist[, default]) -> attribute list.
1680
1680
1681 Get a list of named attributes for an object. When a default argument is
1681 Get a list of named attributes for an object. When a default argument is
1682 given, it is returned when the attribute doesn't exist; without it, an
1682 given, it is returned when the attribute doesn't exist; without it, an
1683 exception is raised in that case.
1683 exception is raised in that case.
1684
1684
1685 Note that alist can be given as a string, which will be automatically
1685 Note that alist can be given as a string, which will be automatically
1686 split into a list on whitespace. If given as a list, it must be a list of
1686 split into a list on whitespace. If given as a list, it must be a list of
1687 *strings* (the variable names themselves), not of variables."""
1687 *strings* (the variable names themselves), not of variables."""
1688
1688
1689 if type(alist) in StringTypes:
1689 if type(alist) in StringTypes:
1690 alist = alist.split()
1690 alist = alist.split()
1691 if args:
1691 if args:
1692 if len(args)==1:
1692 if len(args)==1:
1693 default = args[0]
1693 default = args[0]
1694 return map(lambda attr: getattr(obj,attr,default),alist)
1694 return map(lambda attr: getattr(obj,attr,default),alist)
1695 else:
1695 else:
1696 raise ValueError,'getattr_list() takes only one optional argument'
1696 raise ValueError,'getattr_list() takes only one optional argument'
1697 else:
1697 else:
1698 return map(lambda attr: getattr(obj,attr),alist)
1698 return map(lambda attr: getattr(obj,attr),alist)
1699
1699
1700 #----------------------------------------------------------------------------
1700 #----------------------------------------------------------------------------
1701 def map_method(method,object_list,*argseq,**kw):
1701 def map_method(method,object_list,*argseq,**kw):
1702 """map_method(method,object_list,*args,**kw) -> list
1702 """map_method(method,object_list,*args,**kw) -> list
1703
1703
1704 Return a list of the results of applying the methods to the items of the
1704 Return a list of the results of applying the methods to the items of the
1705 argument sequence(s). If more than one sequence is given, the method is
1705 argument sequence(s). If more than one sequence is given, the method is
1706 called with an argument list consisting of the corresponding item of each
1706 called with an argument list consisting of the corresponding item of each
1707 sequence. All sequences must be of the same length.
1707 sequence. All sequences must be of the same length.
1708
1708
1709 Keyword arguments are passed verbatim to all objects called.
1709 Keyword arguments are passed verbatim to all objects called.
1710
1710
1711 This is Python code, so it's not nearly as fast as the builtin map()."""
1711 This is Python code, so it's not nearly as fast as the builtin map()."""
1712
1712
1713 out_list = []
1713 out_list = []
1714 idx = 0
1714 idx = 0
1715 for object in object_list:
1715 for object in object_list:
1716 try:
1716 try:
1717 handler = getattr(object, method)
1717 handler = getattr(object, method)
1718 except AttributeError:
1718 except AttributeError:
1719 out_list.append(None)
1719 out_list.append(None)
1720 else:
1720 else:
1721 if argseq:
1721 if argseq:
1722 args = map(lambda lst:lst[idx],argseq)
1722 args = map(lambda lst:lst[idx],argseq)
1723 #print 'ob',object,'hand',handler,'ar',args # dbg
1723 #print 'ob',object,'hand',handler,'ar',args # dbg
1724 out_list.append(handler(args,**kw))
1724 out_list.append(handler(args,**kw))
1725 else:
1725 else:
1726 out_list.append(handler(**kw))
1726 out_list.append(handler(**kw))
1727 idx += 1
1727 idx += 1
1728 return out_list
1728 return out_list
1729
1729
1730 #----------------------------------------------------------------------------
1730 #----------------------------------------------------------------------------
1731 def import_fail_info(mod_name,fns=None):
1731 def import_fail_info(mod_name,fns=None):
1732 """Inform load failure for a module."""
1732 """Inform load failure for a module."""
1733
1733
1734 if fns == None:
1734 if fns == None:
1735 warn("Loading of %s failed.\n" % (mod_name,))
1735 warn("Loading of %s failed.\n" % (mod_name,))
1736 else:
1736 else:
1737 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1737 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1738
1738
1739 #----------------------------------------------------------------------------
1739 #----------------------------------------------------------------------------
1740 # Proposed popitem() extension, written as a method
1740 # Proposed popitem() extension, written as a method
1741
1741
1742 class NotGiven: pass
1742 class NotGiven: pass
1743
1743
1744 def popkey(dct,key,default=NotGiven):
1744 def popkey(dct,key,default=NotGiven):
1745 """Return dct[key] and delete dct[key].
1745 """Return dct[key] and delete dct[key].
1746
1746
1747 If default is given, return it if dct[key] doesn't exist, otherwise raise
1747 If default is given, return it if dct[key] doesn't exist, otherwise raise
1748 KeyError. """
1748 KeyError. """
1749
1749
1750 try:
1750 try:
1751 val = dct[key]
1751 val = dct[key]
1752 except KeyError:
1752 except KeyError:
1753 if default is NotGiven:
1753 if default is NotGiven:
1754 raise
1754 raise
1755 else:
1755 else:
1756 return default
1756 return default
1757 else:
1757 else:
1758 del dct[key]
1758 del dct[key]
1759 return val
1759 return val
1760 #*************************** end of file <genutils.py> **********************
1760 #*************************** end of file <genutils.py> **********************
1761
1761
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now