##// END OF EJS Templates
Apply patch by Paul Mueller <gakusei-AT-dakotacom.net>, to fix deprecated...
fperez -
Show More

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

@@ -1,671 +1,693 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """DPyGetOpt -- Demiurge Python GetOptions Module
2 """DPyGetOpt -- Demiurge Python GetOptions Module
3
3
4 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $
4 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $
5
5
6 This module is modeled after perl's Getopt::Long module-- which
6 This module is modeled after perl's Getopt::Long module-- which
7 is, in turn, modeled after GNU's extended getopt() function.
7 is, in turn, modeled after GNU's extended getopt() function.
8
8
9 Upon instantiation, the option specification should be a sequence
9 Upon instantiation, the option specification should be a sequence
10 (list) of option definitions.
10 (list) of option definitions.
11
11
12 Options that take no arguments should simply contain the name of
12 Options that take no arguments should simply contain the name of
13 the option. If a ! is post-pended, the option can be negated by
13 the option. If a ! is post-pended, the option can be negated by
14 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
14 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
15 should be accepted.
15 should be accepted.
16
16
17 Mandatory arguments to options are specified using a postpended
17 Mandatory arguments to options are specified using a postpended
18 '=' + a type specifier. '=s' specifies a mandatory string
18 '=' + a type specifier. '=s' specifies a mandatory string
19 argument, '=i' specifies a mandatory integer argument, and '=f'
19 argument, '=i' specifies a mandatory integer argument, and '=f'
20 specifies a mandatory real number. In all cases, the '=' can be
20 specifies a mandatory real number. In all cases, the '=' can be
21 substituted with ':' to specify that the argument is optional.
21 substituted with ':' to specify that the argument is optional.
22
22
23 Dashes '-' in option names are allowed.
23 Dashes '-' in option names are allowed.
24
24
25 If an option has the character '@' postpended (after the
25 If an option has the character '@' postpended (after the
26 argumentation specification), it can appear multiple times within
26 argumentation specification), it can appear multiple times within
27 each argument list that is processed. The results will be stored
27 each argument list that is processed. The results will be stored
28 in a list.
28 in a list.
29
29
30 The option name can actually be a list of names separated by '|'
30 The option name can actually be a list of names separated by '|'
31 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
31 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
32 and -baz options that appear on within the parsed argument list
32 and -baz options that appear on within the parsed argument list
33 must have a real number argument and that the accumulated list
33 must have a real number argument and that the accumulated list
34 of values will be available under the name 'foo'
34 of values will be available under the name 'foo'
35
35
36 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $"""
36 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $"""
37
37
38 #*****************************************************************************
38 #*****************************************************************************
39 #
39 #
40 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
40 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
41 #
41 #
42 #
42 #
43 # Published under the terms of the MIT license, hereby reproduced:
43 # Published under the terms of the MIT license, hereby reproduced:
44 #
44 #
45 # Permission is hereby granted, free of charge, to any person obtaining a copy
45 # Permission is hereby granted, free of charge, to any person obtaining a copy
46 # of this software and associated documentation files (the "Software"), to
46 # of this software and associated documentation files (the "Software"), to
47 # deal in the Software without restriction, including without limitation the
47 # deal in the Software without restriction, including without limitation the
48 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
48 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
49 # sell copies of the Software, and to permit persons to whom the Software is
49 # sell copies of the Software, and to permit persons to whom the Software is
50 # furnished to do so, subject to the following conditions:
50 # furnished to do so, subject to the following conditions:
51 #
51 #
52 # The above copyright notice and this permission notice shall be included in
52 # The above copyright notice and this permission notice shall be included in
53 # all copies or substantial portions of the Software.
53 # all copies or substantial portions of the Software.
54 #
54 #
55 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
60 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
61 # IN THE SOFTWARE.
61 # IN THE SOFTWARE.
62 #
62 #
63 #*****************************************************************************
63 #*****************************************************************************
64
64
65 __author__ = 'Bill Bumgarner <bbum@friday.com>'
65 __author__ = 'Bill Bumgarner <bbum@friday.com>'
66 __license__ = 'MIT'
66 __license__ = 'MIT'
67 __version__ = '1.2'
67 __version__ = '1.2'
68
68
69 # Modified to use re instead of regex and regsub modules.
69 # Modified to use re instead of regex and regsub modules.
70 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
70 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
71
71
72 import re
72 import re
73 import string
73 import string
74 import sys
74 import sys
75 import types
75 import types
76
76
77 arg_error = 'DPyGetOpt Argument Error'
77 class Error(Exception):
78 spec_error = 'DPyGetOpt Specification Error'
78 """Base class for exceptions in the DPyGetOpt module."""
79 term_error = 'DPyGetOpt Termination Error'
79
80 class ArgumentError(Error):
81 """Exception indicating an error in the arguments passed to
82 DPyGetOpt.processArguments."""
83
84 class SpecificationError(Error):
85 """Exception indicating an error with an option specification."""
86
87 class TerminationError(Error):
88 """Exception indicating an error with an option processing terminator."""
80
89
81 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
90 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
82
91
83 ArgRequired = 'Requires an Argument'
92 ArgRequired = 'Requires an Argument'
84 ArgOptional = 'Argument Optional'
93 ArgOptional = 'Argument Optional'
85
94
86 # The types modules is not used for these identifiers because there
95 # The types modules is not used for these identifiers because there
87 # is no identifier for 'boolean' or 'generic'
96 # is no identifier for 'boolean' or 'generic'
88 StringArgType = 'String Argument Type'
97 StringArgType = 'String Argument Type'
89 IntegerArgType = 'Integer Argument Type'
98 IntegerArgType = 'Integer Argument Type'
90 RealArgType = 'Real Argument Type'
99 RealArgType = 'Real Argument Type'
91 BooleanArgType = 'Boolean Argument Type'
100 BooleanArgType = 'Boolean Argument Type'
92 GenericArgType = 'Generic Argument Type'
101 GenericArgType = 'Generic Argument Type'
93
102
94 # dictionary of conversion functions-- boolean and generic options
103 # dictionary of conversion functions-- boolean and generic options
95 # do not accept arguments and do not need conversion functions;
104 # do not accept arguments and do not need conversion functions;
96 # the identity function is used purely for convenience.
105 # the identity function is used purely for convenience.
97 ConversionFunctions = {
106 ConversionFunctions = {
98 StringArgType : lambda x: x,
107 StringArgType : lambda x: x,
99 IntegerArgType : string.atoi,
108 IntegerArgType : string.atoi,
100 RealArgType : string.atof,
109 RealArgType : string.atof,
101 BooleanArgType : lambda x: x,
110 BooleanArgType : lambda x: x,
102 GenericArgType : lambda x: x,
111 GenericArgType : lambda x: x,
103 }
112 }
104
113
105 class DPyGetOpt:
114 class DPyGetOpt:
106
115
107 def __init__(self, spec = None, terminators = ['--']):
116 def __init__(self, spec = None, terminators = ['--']):
108 """
117 """
109 Declare and intialize instance variables
118 Declare and intialize instance variables
110
119
111 Yes, declaration is not necessary... but one of the things
120 Yes, declaration is not necessary... but one of the things
112 I sorely miss from C/Obj-C is the concept of having an
121 I sorely miss from C/Obj-C is the concept of having an
113 interface definition that clearly declares all instance
122 interface definition that clearly declares all instance
114 variables and methods without providing any implementation
123 variables and methods without providing any implementation
115 details. it is a useful reference!
124 details. it is a useful reference!
116
125
117 all instance variables are initialized to 0/Null/None of
126 all instance variables are initialized to 0/Null/None of
118 the appropriate type-- not even the default value...
127 the appropriate type-- not even the default value...
119 """
128 """
120
129
121 # sys.stderr.write(string.join(spec) + "\n")
130 # sys.stderr.write(string.join(spec) + "\n")
122
131
123 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
132 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
124 # be expanded
133 # be expanded
125 self.freeValues = [] # list, contains free values
134 self.freeValues = [] # list, contains free values
126 self.ignoreCase = 0 # boolean, YES if ignoring case
135 self.ignoreCase = 0 # boolean, YES if ignoring case
127 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
136 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
128 self.optionNames = {} # dict, all option names-- value is index of tuple
137 self.optionNames = {} # dict, all option names-- value is index of tuple
129 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
138 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
130 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
139 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
131 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
140 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
132 self.orderMixed = 0 # boolean, YES if options can be mixed with args
141 self.orderMixed = 0 # boolean, YES if options can be mixed with args
133 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
142 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
134 self.spec = [] # list, raw specs (in case it must be reparsed)
143 self.spec = [] # list, raw specs (in case it must be reparsed)
135 self.terminators = terminators # list, strings that terminate argument processing
144 self.terminators = terminators # list, strings that terminate argument processing
136 self.termValues = [] # list, values after terminator
145 self.termValues = [] # list, values after terminator
137 self.terminator = None # full name of terminator that ended
146 self.terminator = None # full name of terminator that ended
138 # option processing
147 # option processing
139
148
140 # set up defaults
149 # set up defaults
141 self.setPosixCompliance()
150 self.setPosixCompliance()
142 self.setIgnoreCase()
151 self.setIgnoreCase()
143 self.setAllowAbbreviations()
152 self.setAllowAbbreviations()
144
153
145 # parse spec-- if present
154 # parse spec-- if present
146 if spec:
155 if spec:
147 self.parseConfiguration(spec)
156 self.parseConfiguration(spec)
148
157
149 def setPosixCompliance(self, aFlag = 0):
158 def setPosixCompliance(self, aFlag = 0):
150 """
159 """
151 Enables and disables posix compliance.
160 Enables and disables posix compliance.
152
161
153 When enabled, '+' can be used as an option prefix and free
162 When enabled, '+' can be used as an option prefix and free
154 values can be mixed with options.
163 values can be mixed with options.
155 """
164 """
156 self.posixCompliance = aFlag
165 self.posixCompliance = aFlag
157 self.needsParse = 1
166 self.needsParse = 1
158
167
159 if self.posixCompliance:
168 if self.posixCompliance:
160 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
169 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
161 self.orderMixed = 0
170 self.orderMixed = 0
162 else:
171 else:
163 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
172 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
164 self.orderMixed = 1
173 self.orderMixed = 1
165
174
166 def isPosixCompliant(self):
175 def isPosixCompliant(self):
167 """
176 """
168 Returns the value of the posix compliance flag.
177 Returns the value of the posix compliance flag.
169 """
178 """
170 return self.posixCompliance
179 return self.posixCompliance
171
180
172 def setIgnoreCase(self, aFlag = 1):
181 def setIgnoreCase(self, aFlag = 1):
173 """
182 """
174 Enables and disables ignoring case during option processing.
183 Enables and disables ignoring case during option processing.
175 """
184 """
176 self.needsParse = 1
185 self.needsParse = 1
177 self.ignoreCase = aFlag
186 self.ignoreCase = aFlag
178
187
179 def ignoreCase(self):
188 def ignoreCase(self):
180 """
189 """
181 Returns 1 if the option processor will ignore case when
190 Returns 1 if the option processor will ignore case when
182 processing options.
191 processing options.
183 """
192 """
184 return self.ignoreCase
193 return self.ignoreCase
185
194
186 def setAllowAbbreviations(self, aFlag = 1):
195 def setAllowAbbreviations(self, aFlag = 1):
187 """
196 """
188 Enables and disables the expansion of abbreviations during
197 Enables and disables the expansion of abbreviations during
189 option processing.
198 option processing.
190 """
199 """
191 self.allowAbbreviations = aFlag
200 self.allowAbbreviations = aFlag
192
201
193 def willAllowAbbreviations(self):
202 def willAllowAbbreviations(self):
194 """
203 """
195 Returns 1 if abbreviated options will be automatically
204 Returns 1 if abbreviated options will be automatically
196 expanded to the non-abbreviated form (instead of causing an
205 expanded to the non-abbreviated form (instead of causing an
197 unrecognized option error).
206 unrecognized option error).
198 """
207 """
199 return self.allowAbbreviations
208 return self.allowAbbreviations
200
209
201 def addTerminator(self, newTerm):
210 def addTerminator(self, newTerm):
202 """
211 """
203 Adds newTerm as terminator of option processing.
212 Adds newTerm as terminator of option processing.
204
213
205 Whenever the option processor encounters one of the terminators
214 Whenever the option processor encounters one of the terminators
206 during option processing, the processing of options terminates
215 during option processing, the processing of options terminates
207 immediately, all remaining options are stored in the termValues
216 immediately, all remaining options are stored in the termValues
208 instance variable and the full name of the terminator is stored
217 instance variable and the full name of the terminator is stored
209 in the terminator instance variable.
218 in the terminator instance variable.
210 """
219 """
211 self.terminators = self.terminators + [newTerm]
220 self.terminators = self.terminators + [newTerm]
212
221
213 def _addOption(self, oTuple):
222 def _addOption(self, oTuple):
214 """
223 """
215 Adds the option described by oTuple (name, (type, mode,
224 Adds the option described by oTuple (name, (type, mode,
216 default), alias) to optionTuples. Adds index keyed under name
225 default), alias) to optionTuples. Adds index keyed under name
217 to optionNames. Raises spec_error if name already in
226 to optionNames. Raises SpecificationError if name already in
218 optionNames
227 optionNames
219 """
228 """
220 (name, (type, mode, default, multi), realName) = oTuple
229 (name, (type, mode, default, multi), realName) = oTuple
221
230
222 # verify name and add to option names dictionary
231 # verify name and add to option names dictionary
223 if self.optionNames.has_key(name):
232 if self.optionNames.has_key(name):
224 if realName:
233 if realName:
225 raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \
234 raise SpecificationError('Alias \'' + name + '\' for \'' +
226 '\' already used for another option or alias.'
235 realName +
236 '\' already used for another option or alias.')
227 else:
237 else:
228 raise spec_error, 'Option named \'' + name + \
238 raise SpecificationError('Option named \'' + name +
229 '\' specified more than once. Specification: ' + option
239 '\' specified more than once. Specification: '
240 + option)
230
241
231 # validated. add to optionNames
242 # validated. add to optionNames
232 self.optionNames[name] = self.tupleIndex
243 self.optionNames[name] = self.tupleIndex
233 self.tupleIndex = self.tupleIndex + 1
244 self.tupleIndex = self.tupleIndex + 1
234
245
235 # add to optionTuples
246 # add to optionTuples
236 self.optionTuples = self.optionTuples + [oTuple]
247 self.optionTuples = self.optionTuples + [oTuple]
237
248
238 # if type is boolean, add negation
249 # if type is boolean, add negation
239 if type == BooleanArgType:
250 if type == BooleanArgType:
240 alias = 'no' + name
251 alias = 'no' + name
241 specTuple = (type, mode, 0, multi)
252 specTuple = (type, mode, 0, multi)
242 oTuple = (alias, specTuple, name)
253 oTuple = (alias, specTuple, name)
243
254
244 # verify name and add to option names dictionary
255 # verify name and add to option names dictionary
245 if self.optionNames.has_key(alias):
256 if self.optionNames.has_key(alias):
246 if realName:
257 if realName:
247 raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \
258 raise SpecificationError('Negated alias \'' + name +
248 '\' already used for another option or alias.'
259 '\' for \'' + realName +
260 '\' already used for another option or alias.')
249 else:
261 else:
250 raise spec_error, 'Negated option named \'' + name + \
262 raise SpecificationError('Negated option named \'' + name +
251 '\' specified more than once. Specification: ' + option
263 '\' specified more than once. Specification: '
264 + option)
252
265
253 # validated. add to optionNames
266 # validated. add to optionNames
254 self.optionNames[alias] = self.tupleIndex
267 self.optionNames[alias] = self.tupleIndex
255 self.tupleIndex = self.tupleIndex + 1
268 self.tupleIndex = self.tupleIndex + 1
256
269
257 # add to optionTuples
270 # add to optionTuples
258 self.optionTuples = self.optionTuples + [oTuple]
271 self.optionTuples = self.optionTuples + [oTuple]
259
272
260 def addOptionConfigurationTuple(self, oTuple):
273 def addOptionConfigurationTuple(self, oTuple):
261 (name, argSpec, realName) = oTuple
274 (name, argSpec, realName) = oTuple
262 if self.ignoreCase:
275 if self.ignoreCase:
263 name = string.lower(name)
276 name = string.lower(name)
264 if realName:
277 if realName:
265 realName = string.lower(realName)
278 realName = string.lower(realName)
266 else:
279 else:
267 realName = name
280 realName = name
268
281
269 oTuple = (name, argSpec, realName)
282 oTuple = (name, argSpec, realName)
270
283
271 # add option
284 # add option
272 self._addOption(oTuple)
285 self._addOption(oTuple)
273
286
274 def addOptionConfigurationTuples(self, oTuple):
287 def addOptionConfigurationTuples(self, oTuple):
275 if type(oTuple) is ListType:
288 if type(oTuple) is ListType:
276 for t in oTuple:
289 for t in oTuple:
277 self.addOptionConfigurationTuple(t)
290 self.addOptionConfigurationTuple(t)
278 else:
291 else:
279 self.addOptionConfigurationTuple(oTuple)
292 self.addOptionConfigurationTuple(oTuple)
280
293
281 def parseConfiguration(self, spec):
294 def parseConfiguration(self, spec):
282 # destroy previous stored information + store raw spec
295 # destroy previous stored information + store raw spec
283 self.spec = spec
296 self.spec = spec
284 self.optionTuples = []
297 self.optionTuples = []
285 self.optionNames = {}
298 self.optionNames = {}
286 self.tupleIndex = 0
299 self.tupleIndex = 0
287
300
288 tupleIndex = 0
301 tupleIndex = 0
289
302
290 # create some regex's for parsing each spec
303 # create some regex's for parsing each spec
291 splitExpr = \
304 splitExpr = \
292 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
305 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
293 for option in spec:
306 for option in spec:
294 # push to lower case (does not negatively affect
307 # push to lower case (does not negatively affect
295 # specification)
308 # specification)
296 if self.ignoreCase:
309 if self.ignoreCase:
297 option = string.lower(option)
310 option = string.lower(option)
298
311
299 # break into names, specification
312 # break into names, specification
300 match = splitExpr.match(option)
313 match = splitExpr.match(option)
301 if match is None:
314 if match is None:
302 raise spec_error, 'Invalid specification {' + option + '}'
315 raise SpecificationError('Invalid specification {' + option +
316 '}')
303
317
304 names = match.group('names')
318 names = match.group('names')
305 specification = match.group('spec')
319 specification = match.group('spec')
306
320
307 # break name into name, aliases
321 # break name into name, aliases
308 nlist = string.split(names, '|')
322 nlist = string.split(names, '|')
309
323
310 # get name
324 # get name
311 name = nlist[0]
325 name = nlist[0]
312 aliases = nlist[1:]
326 aliases = nlist[1:]
313
327
314 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
328 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
315 if not specification:
329 if not specification:
316 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
330 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
317 argType = GenericArgType
331 argType = GenericArgType
318 argMode = None
332 argMode = None
319 argDefault = 1
333 argDefault = 1
320 argMultiple = 0
334 argMultiple = 0
321 elif specification == '!':
335 elif specification == '!':
322 argType = BooleanArgType
336 argType = BooleanArgType
323 argMode = None
337 argMode = None
324 argDefault = 1
338 argDefault = 1
325 argMultiple = 0
339 argMultiple = 0
326 else:
340 else:
327 # parse
341 # parse
328 match = specificationExpr.match(specification)
342 match = specificationExpr.match(specification)
329 if match is None:
343 if match is None:
330 # failed to parse, die
344 # failed to parse, die
331 raise spec_error, 'Invalid configuration for option \'' + option + '\''
345 raise SpecificationError('Invalid configuration for option \''
346 + option + '\'')
332
347
333 # determine mode
348 # determine mode
334 required = match.group('required')
349 required = match.group('required')
335 if required == '=':
350 if required == '=':
336 argMode = ArgRequired
351 argMode = ArgRequired
337 elif required == ':':
352 elif required == ':':
338 argMode = ArgOptional
353 argMode = ArgOptional
339 else:
354 else:
340 raise spec_error, 'Unknown requirement configuration \'' + required + '\''
355 raise SpecificationError('Unknown requirement configuration \''
356 + required + '\'')
341
357
342 # determine type
358 # determine type
343 type = match.group('type')
359 type = match.group('type')
344 if type == 's':
360 if type == 's':
345 argType = StringArgType
361 argType = StringArgType
346 argDefault = ''
362 argDefault = ''
347 elif type == 'i':
363 elif type == 'i':
348 argType = IntegerArgType
364 argType = IntegerArgType
349 argDefault = 1
365 argDefault = 1
350 elif type == 'f' or type == 'n':
366 elif type == 'f' or type == 'n':
351 argType = RealArgType
367 argType = RealArgType
352 argDefault = 1
368 argDefault = 1
353 else:
369 else:
354 raise spec_error, 'Unknown type specifier \'' + type + '\''
370 raise SpecificationError('Unknown type specifier \'' +
371 type + '\'')
355
372
356 # determine quantity
373 # determine quantity
357 if match.group('multi') == '@':
374 if match.group('multi') == '@':
358 argMultiple = 1
375 argMultiple = 1
359 else:
376 else:
360 argMultiple = 0
377 argMultiple = 0
361 ## end else (of not specification)
378 ## end else (of not specification)
362
379
363 # construct specification tuple
380 # construct specification tuple
364 specTuple = (argType, argMode, argDefault, argMultiple)
381 specTuple = (argType, argMode, argDefault, argMultiple)
365
382
366 # add the option-- option tuple is (name, specTuple, real name)
383 # add the option-- option tuple is (name, specTuple, real name)
367 oTuple = (name, specTuple, name)
384 oTuple = (name, specTuple, name)
368 self._addOption(oTuple)
385 self._addOption(oTuple)
369
386
370 for alias in aliases:
387 for alias in aliases:
371 # drop to all lower (if configured to do so)
388 # drop to all lower (if configured to do so)
372 if self.ignoreCase:
389 if self.ignoreCase:
373 alias = string.lower(alias)
390 alias = string.lower(alias)
374 # create configuration tuple
391 # create configuration tuple
375 oTuple = (alias, specTuple, name)
392 oTuple = (alias, specTuple, name)
376 # add
393 # add
377 self._addOption(oTuple)
394 self._addOption(oTuple)
378
395
379 # successfully parsed....
396 # successfully parsed....
380 self.needsParse = 0
397 self.needsParse = 0
381
398
382 def _getArgTuple(self, argName):
399 def _getArgTuple(self, argName):
383 """
400 """
384 Returns a list containing all the specification tuples that
401 Returns a list containing all the specification tuples that
385 match argName. If none match, None is returned. If one
402 match argName. If none match, None is returned. If one
386 matches, a list with one tuple is returned. If more than one
403 matches, a list with one tuple is returned. If more than one
387 match, a list containing all the tuples that matched is
404 match, a list containing all the tuples that matched is
388 returned.
405 returned.
389
406
390 In other words, this function does not pass judgement upon the
407 In other words, this function does not pass judgement upon the
391 validity of multiple matches.
408 validity of multiple matches.
392 """
409 """
393 # is it in the optionNames dict?
410 # is it in the optionNames dict?
394
411
395 try:
412 try:
396 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
413 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
397
414
398 # yes, get index
415 # yes, get index
399 tupleIndex = self.optionNames[argName]
416 tupleIndex = self.optionNames[argName]
400 # and return tuple as element of list
417 # and return tuple as element of list
401 return [self.optionTuples[tupleIndex]]
418 return [self.optionTuples[tupleIndex]]
402 except KeyError:
419 except KeyError:
403 # are abbreviations allowed?
420 # are abbreviations allowed?
404 if not self.allowAbbreviations:
421 if not self.allowAbbreviations:
405 # No! terefore, this cannot be valid argument-- nothing found
422 # No! terefore, this cannot be valid argument-- nothing found
406 return None
423 return None
407
424
408 # argName might be an abbreviation (and, abbreviations must
425 # argName might be an abbreviation (and, abbreviations must
409 # be allowed... or this would not have been reached!)
426 # be allowed... or this would not have been reached!)
410
427
411 # create regex for argName
428 # create regex for argName
412 argExpr = re.compile('^' + argName)
429 argExpr = re.compile('^' + argName)
413
430
414 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
431 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
415 self.optionTuples)
432 self.optionTuples)
416
433
417 if not len(tuples):
434 if not len(tuples):
418 return None
435 return None
419 else:
436 else:
420 return tuples
437 return tuples
421
438
422 def _isTerminator(self, optionName):
439 def _isTerminator(self, optionName):
423 """
440 """
424 Returns the full name of the terminator if optionName is a valid
441 Returns the full name of the terminator if optionName is a valid
425 terminator. If it is, sets self.terminator to the full name of
442 terminator. If it is, sets self.terminator to the full name of
426 the terminator.
443 the terminator.
427
444
428 If more than one terminator matched, raises a term_error with a
445 If more than one terminator matched, raises a TerminationError with a
429 string describing the ambiguity.
446 string describing the ambiguity.
430 """
447 """
431
448
432 # sys.stderr.write(optionName + "\n")
449 # sys.stderr.write(optionName + "\n")
433 # sys.stderr.write(repr(self.terminators))
450 # sys.stderr.write(repr(self.terminators))
434
451
435 if optionName in self.terminators:
452 if optionName in self.terminators:
436 self.terminator = optionName
453 self.terminator = optionName
437 elif not self.allowAbbreviations:
454 elif not self.allowAbbreviations:
438 return None
455 return None
439
456
440 # regex thing in bogus
457 # regex thing in bogus
441 # termExpr = regex.compile('^' + optionName)
458 # termExpr = regex.compile('^' + optionName)
442
459
443 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
460 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
444
461
445 if not len(terms):
462 if not len(terms):
446 return None
463 return None
447 elif len(terms) > 1:
464 elif len(terms) > 1:
448 raise term_error, 'Ambiguous terminator \'' + optionName + \
465 raise TerminationError('Ambiguous terminator \'' + optionName +
449 '\' matches ' + repr(terms)
466 '\' matches ' + repr(terms))
450
467
451 self.terminator = terms[0]
468 self.terminator = terms[0]
452 return self.terminator
469 return self.terminator
453
470
454 def processArguments(self, args = None):
471 def processArguments(self, args = None):
455 """
472 """
456 Processes args, a list of arguments (including options).
473 Processes args, a list of arguments (including options).
457
474
458 If args is the same as sys.argv, automatically trims the first
475 If args is the same as sys.argv, automatically trims the first
459 argument (the executable name/path).
476 argument (the executable name/path).
460
477
461 If an exception is not raised, the argument list was parsed
478 If an exception is not raised, the argument list was parsed
462 correctly.
479 correctly.
463
480
464 Upon successful completion, the freeValues instance variable
481 Upon successful completion, the freeValues instance variable
465 will contain all the arguments that were not associated with an
482 will contain all the arguments that were not associated with an
466 option in the order they were encountered. optionValues is a
483 option in the order they were encountered. optionValues is a
467 dictionary containing the value of each option-- the method
484 dictionary containing the value of each option-- the method
468 valueForOption() can be used to query this dictionary.
485 valueForOption() can be used to query this dictionary.
469 terminator will contain the argument encountered that terminated
486 terminator will contain the argument encountered that terminated
470 option processing (or None, if a terminator was never
487 option processing (or None, if a terminator was never
471 encountered) and termValues will contain all of the options that
488 encountered) and termValues will contain all of the options that
472 appeared after the Terminator (or an empty list).
489 appeared after the Terminator (or an empty list).
473 """
490 """
474
491
475 if hasattr(sys, "argv") and args == sys.argv:
492 if hasattr(sys, "argv") and args == sys.argv:
476 args = sys.argv[1:]
493 args = sys.argv[1:]
477
494
478 max = len(args) # maximum index + 1
495 max = len(args) # maximum index + 1
479 self.freeValues = [] # array to hold return values
496 self.freeValues = [] # array to hold return values
480 self.optionValues= {}
497 self.optionValues= {}
481 index = 0 # initial index
498 index = 0 # initial index
482 self.terminator = None
499 self.terminator = None
483 self.termValues = []
500 self.termValues = []
484
501
485 while index < max:
502 while index < max:
486 # obtain argument
503 # obtain argument
487 arg = args[index]
504 arg = args[index]
488 # increment index -- REMEMBER; it is NOW incremented
505 # increment index -- REMEMBER; it is NOW incremented
489 index = index + 1
506 index = index + 1
490
507
491 # terminate immediately if option terminator encountered
508 # terminate immediately if option terminator encountered
492 if self._isTerminator(arg):
509 if self._isTerminator(arg):
493 self.freeValues = self.freeValues + args[index:]
510 self.freeValues = self.freeValues + args[index:]
494 self.termValues = args[index:]
511 self.termValues = args[index:]
495 return
512 return
496
513
497 # is this possibly an option?
514 # is this possibly an option?
498 match = self.optionStartExpr.match(arg)
515 match = self.optionStartExpr.match(arg)
499 if match is None:
516 if match is None:
500 # not an option-- add to freeValues
517 # not an option-- add to freeValues
501 self.freeValues = self.freeValues + [arg]
518 self.freeValues = self.freeValues + [arg]
502 if not self.orderMixed:
519 if not self.orderMixed:
503 # mixing not allowed; add rest of args as freeValues
520 # mixing not allowed; add rest of args as freeValues
504 self.freeValues = self.freeValues + args[index:]
521 self.freeValues = self.freeValues + args[index:]
505 # return to caller
522 # return to caller
506 return
523 return
507 else:
524 else:
508 continue
525 continue
509
526
510 # grab name
527 # grab name
511 optName = match.group('option')
528 optName = match.group('option')
512
529
513 # obtain next argument-- index has already been incremented
530 # obtain next argument-- index has already been incremented
514 nextArg = match.group('arg')
531 nextArg = match.group('arg')
515 if nextArg:
532 if nextArg:
516 nextArg = nextArg[1:]
533 nextArg = nextArg[1:]
517 index = index - 1 # put it back
534 index = index - 1 # put it back
518 else:
535 else:
519 try:
536 try:
520 nextArg = args[index]
537 nextArg = args[index]
521 except:
538 except:
522 nextArg = None
539 nextArg = None
523
540
524 # transpose to lower case, if necessary
541 # transpose to lower case, if necessary
525 if self.ignoreCase:
542 if self.ignoreCase:
526 optName = string.lower(optName)
543 optName = string.lower(optName)
527
544
528 # obtain defining tuple
545 # obtain defining tuple
529 tuples = self._getArgTuple(optName)
546 tuples = self._getArgTuple(optName)
530
547
531 if tuples == None:
548 if tuples == None:
532 raise arg_error, 'Illegal option \'' + arg + '\''
549 raise ArgumentError('Illegal option \'' + arg + '\'')
533 elif len(tuples) > 1:
550 elif len(tuples) > 1:
534 raise arg_error, 'Ambiguous option \'' + arg + '\'; matches ' + \
551 raise ArgumentError('Ambiguous option \'' + arg +
535 repr(map(lambda x: x[0], tuples))
552 '\'; matches ' +
553 repr(map(lambda x: x[0], tuples)))
536 else:
554 else:
537 config = tuples[0]
555 config = tuples[0]
538
556
539 # config is now set to the configuration tuple for the
557 # config is now set to the configuration tuple for the
540 # argument
558 # argument
541 (fullName, spec, realName) = config
559 (fullName, spec, realName) = config
542 (optType, optMode, optDefault, optMultiple) = spec
560 (optType, optMode, optDefault, optMultiple) = spec
543
561
544 # if opt mode required, but nextArg is none, raise an error
562 # if opt mode required, but nextArg is none, raise an error
545 if (optMode == ArgRequired):
563 if (optMode == ArgRequired):
546 if (not nextArg) or self._isTerminator(nextArg):
564 if (not nextArg) or self._isTerminator(nextArg):
547 # print nextArg
565 # print nextArg
548 raise arg_error, 'Option \'' + arg + \
566 raise ArgumentError('Option \'' + arg +
549 '\' requires an argument of type ' + optType
567 '\' requires an argument of type ' +
568 optType)
550
569
551 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
570 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
552 # nextArg defined, option configured to possibly consume arg
571 # nextArg defined, option configured to possibly consume arg
553 try:
572 try:
554 # grab conversion function-- the try is more for internal diagnostics
573 # grab conversion function-- the try is more for internal diagnostics
555 func = ConversionFunctions[optType]
574 func = ConversionFunctions[optType]
556 try:
575 try:
557 optionValue = func(nextArg)
576 optionValue = func(nextArg)
558 index = index + 1
577 index = index + 1
559 except:
578 except:
560 # only raise conversion error if REQUIRED to consume argument
579 # only raise conversion error if REQUIRED to consume argument
561 if optMode == ArgRequired:
580 if optMode == ArgRequired:
562 raise arg_error, 'Invalid argument to option \'' + arg + \
581 raise ArgumentError('Invalid argument to option \''
563 '\'; should be \'' + optType + '\''
582 + arg + '\'; should be \'' +
583 optType + '\'')
564 else:
584 else:
565 optionValue = optDefault
585 optionValue = optDefault
566 except arg_error:
586 except ArgumentError:
567 raise arg_error, sys.exc_value
587 raise
568 except:
588 except:
569 raise arg_error, '(' + arg + \
589 raise ArgumentError('(' + arg +
570 ') Conversion function for \'' + optType + '\' not found.'
590 ') Conversion function for \'' +
591 optType + '\' not found.')
571 else:
592 else:
572 optionValue = optDefault
593 optionValue = optDefault
573
594
574 # add value to options dictionary
595 # add value to options dictionary
575 if optMultiple:
596 if optMultiple:
576 # can be multiple values
597 # can be multiple values
577 try:
598 try:
578 # try to append element
599 # try to append element
579 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
600 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
580 except:
601 except:
581 # failed-- must not exist; add it
602 # failed-- must not exist; add it
582 self.optionValues[realName] = [optionValue]
603 self.optionValues[realName] = [optionValue]
583 else:
604 else:
584 # only one value per
605 # only one value per
585 if self.isPosixCompliant and self.optionValues.has_key(realName):
606 if self.isPosixCompliant and self.optionValues.has_key(realName):
586 raise arg_error, 'Argument \'' + arg + '\' occurs multiple times.'
607 raise ArgumentError('Argument \'' + arg +
608 '\' occurs multiple times.')
587
609
588 self.optionValues[realName] = optionValue
610 self.optionValues[realName] = optionValue
589
611
590 def valueForOption(self, optionName, defaultValue = None):
612 def valueForOption(self, optionName, defaultValue = None):
591 """
613 """
592 Return the value associated with optionName. If optionName was
614 Return the value associated with optionName. If optionName was
593 not encountered during parsing of the arguments, returns the
615 not encountered during parsing of the arguments, returns the
594 defaultValue (which defaults to None).
616 defaultValue (which defaults to None).
595 """
617 """
596 try:
618 try:
597 optionValue = self.optionValues[optionName]
619 optionValue = self.optionValues[optionName]
598 except:
620 except:
599 optionValue = defaultValue
621 optionValue = defaultValue
600
622
601 return optionValue
623 return optionValue
602
624
603 ##
625 ##
604 ## test/example section
626 ## test/example section
605 ##
627 ##
606 test_error = 'Test Run Amok!'
628 test_error = 'Test Run Amok!'
607 def _test():
629 def _test():
608 """
630 """
609 A relatively complete test suite.
631 A relatively complete test suite.
610 """
632 """
611 try:
633 try:
612 DPyGetOpt(['foo', 'bar=s', 'foo'])
634 DPyGetOpt(['foo', 'bar=s', 'foo'])
613 except:
635 except Error, exc:
614 print 'EXCEPTION (should be \'foo\' already used..): ' + sys.exc_value
636 print 'EXCEPTION (should be \'foo\' already used..): %s' % exc
615
637
616 try:
638 try:
617 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
639 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
618 except:
640 except Error, exc:
619 print 'EXCEPTION (should be duplicate alias/name error): ' + sys.exc_value
641 print 'EXCEPTION (should be duplicate alias/name error): %s' % exc
620
642
621 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
643 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
622 try:
644 try:
623 x.processArguments(['-app', '29.3'])
645 x.processArguments(['-app', '29.3'])
624 except:
646 except Error, exc:
625 print 'EXCEPTION (should be ambiguous argument): ' + sys.exc_value
647 print 'EXCEPTION (should be ambiguous argument): %s' % exc
626
648
627 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
649 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
628 try:
650 try:
629 x.processArguments(['-foo', 'anti'])
651 x.processArguments(['-foo', 'anti'])
630 except:
652 except Error, exc:
631 print 'EXCEPTION (should be ambiguous terminator): ' + sys.exc_value
653 print 'EXCEPTION (should be ambiguous terminator): %s' % exc
632
654
633 profile = ['plain-option',
655 profile = ['plain-option',
634 'boolean-option!',
656 'boolean-option!',
635 'list-of-integers=i@',
657 'list-of-integers=i@',
636 'list-real-option|list-real-alias|list-real-pseudonym=f@',
658 'list-real-option|list-real-alias|list-real-pseudonym=f@',
637 'optional-string-option:s',
659 'optional-string-option:s',
638 'abbreviated-string-list=s@']
660 'abbreviated-string-list=s@']
639
661
640 terminators = ['terminator']
662 terminators = ['terminator']
641
663
642 args = ['-plain-option',
664 args = ['-plain-option',
643 '+noboolean-option',
665 '+noboolean-option',
644 '--list-of-integers', '1',
666 '--list-of-integers', '1',
645 '+list-of-integers', '2',
667 '+list-of-integers', '2',
646 '-list-of-integers', '3',
668 '-list-of-integers', '3',
647 'freeargone',
669 'freeargone',
648 '-list-real-option', '1.1',
670 '-list-real-option', '1.1',
649 '+list-real-alias', '1.2',
671 '+list-real-alias', '1.2',
650 '--list-real-pseudonym', '1.3',
672 '--list-real-pseudonym', '1.3',
651 'freeargtwo',
673 'freeargtwo',
652 '-abbreviated-string-list', 'String1',
674 '-abbreviated-string-list', 'String1',
653 '--abbreviated-s', 'String2',
675 '--abbreviated-s', 'String2',
654 '-abbrev', 'String3',
676 '-abbrev', 'String3',
655 '-a', 'String4',
677 '-a', 'String4',
656 '-optional-string-option',
678 '-optional-string-option',
657 'term',
679 'term',
658 'next option should look like an invalid arg',
680 'next option should look like an invalid arg',
659 '-a']
681 '-a']
660
682
661
683
662 print 'Using profile: ' + repr(profile)
684 print 'Using profile: ' + repr(profile)
663 print 'With terminator: ' + repr(terminators)
685 print 'With terminator: ' + repr(terminators)
664 print 'Processing arguments: ' + repr(args)
686 print 'Processing arguments: ' + repr(args)
665
687
666 go = DPyGetOpt(profile, terminators)
688 go = DPyGetOpt(profile, terminators)
667 go.processArguments(args)
689 go.processArguments(args)
668
690
669 print 'Options (and values): ' + repr(go.optionValues)
691 print 'Options (and values): ' + repr(go.optionValues)
670 print 'free args: ' + repr(go.freeValues)
692 print 'free args: ' + repr(go.freeValues)
671 print 'term args: ' + repr(go.termValues)
693 print 'term args: ' + repr(go.termValues)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,1984 +1,1984 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 2847 2007-10-24 15:16:24Z vivainio $"""
8 $Id: genutils.py 2872 2007-11-25 17:58:05Z fperez $"""
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 from IPython import Release
17 from IPython import Release
18 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 __license__ = Release.license
19 __license__ = Release.license
20
20
21 #****************************************************************************
21 #****************************************************************************
22 # required modules from the Python standard library
22 # required modules from the Python standard library
23 import __main__
23 import __main__
24 import commands
24 import commands
25 import doctest
25 import doctest
26 import os
26 import os
27 import re
27 import re
28 import shlex
28 import shlex
29 import shutil
29 import shutil
30 import sys
30 import sys
31 import tempfile
31 import tempfile
32 import time
32 import time
33 import types
33 import types
34 import warnings
34 import warnings
35
35
36 # Other IPython utilities
36 # Other IPython utilities
37 import IPython
37 import IPython
38 from IPython.Itpl import Itpl,itpl,printpl
38 from IPython.Itpl import Itpl,itpl,printpl
39 from IPython import DPyGetOpt, platutils
39 from IPython import DPyGetOpt, platutils
40 from IPython.generics import result_display
40 from IPython.generics import result_display
41 from path import path
41 from path import path
42 if os.name == "nt":
42 if os.name == "nt":
43 from IPython.winconsole import get_console_size
43 from IPython.winconsole import get_console_size
44
44
45 #****************************************************************************
45 #****************************************************************************
46 # Exceptions
46 # Exceptions
47 class Error(Exception):
47 class Error(Exception):
48 """Base class for exceptions in this module."""
48 """Base class for exceptions in this module."""
49 pass
49 pass
50
50
51 #----------------------------------------------------------------------------
51 #----------------------------------------------------------------------------
52 class IOStream:
52 class IOStream:
53 def __init__(self,stream,fallback):
53 def __init__(self,stream,fallback):
54 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
54 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
55 stream = fallback
55 stream = fallback
56 self.stream = stream
56 self.stream = stream
57 self._swrite = stream.write
57 self._swrite = stream.write
58 self.flush = stream.flush
58 self.flush = stream.flush
59
59
60 def write(self,data):
60 def write(self,data):
61 try:
61 try:
62 self._swrite(data)
62 self._swrite(data)
63 except:
63 except:
64 try:
64 try:
65 # print handles some unicode issues which may trip a plain
65 # print handles some unicode issues which may trip a plain
66 # write() call. Attempt to emulate write() by using a
66 # write() call. Attempt to emulate write() by using a
67 # trailing comma
67 # trailing comma
68 print >> self.stream, data,
68 print >> self.stream, data,
69 except:
69 except:
70 # if we get here, something is seriously broken.
70 # if we get here, something is seriously broken.
71 print >> sys.stderr, \
71 print >> sys.stderr, \
72 'ERROR - failed to write data to stream:', self.stream
72 'ERROR - failed to write data to stream:', self.stream
73
73
74 def close(self):
74 def close(self):
75 pass
75 pass
76
76
77
77
78 class IOTerm:
78 class IOTerm:
79 """ Term holds the file or file-like objects for handling I/O operations.
79 """ Term holds the file or file-like objects for handling I/O operations.
80
80
81 These are normally just sys.stdin, sys.stdout and sys.stderr but for
81 These are normally just sys.stdin, sys.stdout and sys.stderr but for
82 Windows they can can replaced to allow editing the strings before they are
82 Windows they can can replaced to allow editing the strings before they are
83 displayed."""
83 displayed."""
84
84
85 # In the future, having IPython channel all its I/O operations through
85 # In the future, having IPython channel all its I/O operations through
86 # this class will make it easier to embed it into other environments which
86 # this class will make it easier to embed it into other environments which
87 # are not a normal terminal (such as a GUI-based shell)
87 # are not a normal terminal (such as a GUI-based shell)
88 def __init__(self,cin=None,cout=None,cerr=None):
88 def __init__(self,cin=None,cout=None,cerr=None):
89 self.cin = IOStream(cin,sys.stdin)
89 self.cin = IOStream(cin,sys.stdin)
90 self.cout = IOStream(cout,sys.stdout)
90 self.cout = IOStream(cout,sys.stdout)
91 self.cerr = IOStream(cerr,sys.stderr)
91 self.cerr = IOStream(cerr,sys.stderr)
92
92
93 # Global variable to be used for all I/O
93 # Global variable to be used for all I/O
94 Term = IOTerm()
94 Term = IOTerm()
95
95
96 import IPython.rlineimpl as readline
96 import IPython.rlineimpl as readline
97 # Remake Term to use the readline i/o facilities
97 # Remake Term to use the readline i/o facilities
98 if sys.platform == 'win32' and readline.have_readline:
98 if sys.platform == 'win32' and readline.have_readline:
99
99
100 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
100 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
101
101
102
102
103 #****************************************************************************
103 #****************************************************************************
104 # Generic warning/error printer, used by everything else
104 # Generic warning/error printer, used by everything else
105 def warn(msg,level=2,exit_val=1):
105 def warn(msg,level=2,exit_val=1):
106 """Standard warning printer. Gives formatting consistency.
106 """Standard warning printer. Gives formatting consistency.
107
107
108 Output is sent to Term.cerr (sys.stderr by default).
108 Output is sent to Term.cerr (sys.stderr by default).
109
109
110 Options:
110 Options:
111
111
112 -level(2): allows finer control:
112 -level(2): allows finer control:
113 0 -> Do nothing, dummy function.
113 0 -> Do nothing, dummy function.
114 1 -> Print message.
114 1 -> Print message.
115 2 -> Print 'WARNING:' + message. (Default level).
115 2 -> Print 'WARNING:' + message. (Default level).
116 3 -> Print 'ERROR:' + message.
116 3 -> Print 'ERROR:' + message.
117 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
117 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
118
118
119 -exit_val (1): exit value returned by sys.exit() for a level 4
119 -exit_val (1): exit value returned by sys.exit() for a level 4
120 warning. Ignored for all other levels."""
120 warning. Ignored for all other levels."""
121
121
122 if level>0:
122 if level>0:
123 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
123 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
124 print >> Term.cerr, '%s%s' % (header[level],msg)
124 print >> Term.cerr, '%s%s' % (header[level],msg)
125 if level == 4:
125 if level == 4:
126 print >> Term.cerr,'Exiting.\n'
126 print >> Term.cerr,'Exiting.\n'
127 sys.exit(exit_val)
127 sys.exit(exit_val)
128
128
129 def info(msg):
129 def info(msg):
130 """Equivalent to warn(msg,level=1)."""
130 """Equivalent to warn(msg,level=1)."""
131
131
132 warn(msg,level=1)
132 warn(msg,level=1)
133
133
134 def error(msg):
134 def error(msg):
135 """Equivalent to warn(msg,level=3)."""
135 """Equivalent to warn(msg,level=3)."""
136
136
137 warn(msg,level=3)
137 warn(msg,level=3)
138
138
139 def fatal(msg,exit_val=1):
139 def fatal(msg,exit_val=1):
140 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
140 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
141
141
142 warn(msg,exit_val=exit_val,level=4)
142 warn(msg,exit_val=exit_val,level=4)
143
143
144 #---------------------------------------------------------------------------
144 #---------------------------------------------------------------------------
145 # Debugging routines
145 # Debugging routines
146 #
146 #
147 def debugx(expr,pre_msg=''):
147 def debugx(expr,pre_msg=''):
148 """Print the value of an expression from the caller's frame.
148 """Print the value of an expression from the caller's frame.
149
149
150 Takes an expression, evaluates it in the caller's frame and prints both
150 Takes an expression, evaluates it in the caller's frame and prints both
151 the given expression and the resulting value (as well as a debug mark
151 the given expression and the resulting value (as well as a debug mark
152 indicating the name of the calling function. The input must be of a form
152 indicating the name of the calling function. The input must be of a form
153 suitable for eval().
153 suitable for eval().
154
154
155 An optional message can be passed, which will be prepended to the printed
155 An optional message can be passed, which will be prepended to the printed
156 expr->value pair."""
156 expr->value pair."""
157
157
158 cf = sys._getframe(1)
158 cf = sys._getframe(1)
159 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
159 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
160 eval(expr,cf.f_globals,cf.f_locals))
160 eval(expr,cf.f_globals,cf.f_locals))
161
161
162 # deactivate it by uncommenting the following line, which makes it a no-op
162 # deactivate it by uncommenting the following line, which makes it a no-op
163 #def debugx(expr,pre_msg=''): pass
163 #def debugx(expr,pre_msg=''): pass
164
164
165 #----------------------------------------------------------------------------
165 #----------------------------------------------------------------------------
166 StringTypes = types.StringTypes
166 StringTypes = types.StringTypes
167
167
168 # Basic timing functionality
168 # Basic timing functionality
169
169
170 # If possible (Unix), use the resource module instead of time.clock()
170 # If possible (Unix), use the resource module instead of time.clock()
171 try:
171 try:
172 import resource
172 import resource
173 def clocku():
173 def clocku():
174 """clocku() -> floating point number
174 """clocku() -> floating point number
175
175
176 Return the *USER* CPU time in seconds since the start of the process.
176 Return the *USER* CPU time in seconds since the start of the process.
177 This is done via a call to resource.getrusage, so it avoids the
177 This is done via a call to resource.getrusage, so it avoids the
178 wraparound problems in time.clock()."""
178 wraparound problems in time.clock()."""
179
179
180 return resource.getrusage(resource.RUSAGE_SELF)[0]
180 return resource.getrusage(resource.RUSAGE_SELF)[0]
181
181
182 def clocks():
182 def clocks():
183 """clocks() -> floating point number
183 """clocks() -> floating point number
184
184
185 Return the *SYSTEM* CPU time in seconds since the start of the process.
185 Return the *SYSTEM* CPU time in seconds since the start of the process.
186 This is done via a call to resource.getrusage, so it avoids the
186 This is done via a call to resource.getrusage, so it avoids the
187 wraparound problems in time.clock()."""
187 wraparound problems in time.clock()."""
188
188
189 return resource.getrusage(resource.RUSAGE_SELF)[1]
189 return resource.getrusage(resource.RUSAGE_SELF)[1]
190
190
191 def clock():
191 def clock():
192 """clock() -> floating point number
192 """clock() -> floating point number
193
193
194 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
194 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
195 the process. This is done via a call to resource.getrusage, so it
195 the process. This is done via a call to resource.getrusage, so it
196 avoids the wraparound problems in time.clock()."""
196 avoids the wraparound problems in time.clock()."""
197
197
198 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
198 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
199 return u+s
199 return u+s
200
200
201 def clock2():
201 def clock2():
202 """clock2() -> (t_user,t_system)
202 """clock2() -> (t_user,t_system)
203
203
204 Similar to clock(), but return a tuple of user/system times."""
204 Similar to clock(), but return a tuple of user/system times."""
205 return resource.getrusage(resource.RUSAGE_SELF)[:2]
205 return resource.getrusage(resource.RUSAGE_SELF)[:2]
206
206
207 except ImportError:
207 except ImportError:
208 # There is no distinction of user/system time under windows, so we just use
208 # There is no distinction of user/system time under windows, so we just use
209 # time.clock() for everything...
209 # time.clock() for everything...
210 clocku = clocks = clock = time.clock
210 clocku = clocks = clock = time.clock
211 def clock2():
211 def clock2():
212 """Under windows, system CPU time can't be measured.
212 """Under windows, system CPU time can't be measured.
213
213
214 This just returns clock() and zero."""
214 This just returns clock() and zero."""
215 return time.clock(),0.0
215 return time.clock(),0.0
216
216
217 def timings_out(reps,func,*args,**kw):
217 def timings_out(reps,func,*args,**kw):
218 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
218 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
219
219
220 Execute a function reps times, return a tuple with the elapsed total
220 Execute a function reps times, return a tuple with the elapsed total
221 CPU time in seconds, the time per call and the function's output.
221 CPU time in seconds, the time per call and the function's output.
222
222
223 Under Unix, the return value is the sum of user+system time consumed by
223 Under Unix, the return value is the sum of user+system time consumed by
224 the process, computed via the resource module. This prevents problems
224 the process, computed via the resource module. This prevents problems
225 related to the wraparound effect which the time.clock() function has.
225 related to the wraparound effect which the time.clock() function has.
226
226
227 Under Windows the return value is in wall clock seconds. See the
227 Under Windows the return value is in wall clock seconds. See the
228 documentation for the time module for more details."""
228 documentation for the time module for more details."""
229
229
230 reps = int(reps)
230 reps = int(reps)
231 assert reps >=1, 'reps must be >= 1'
231 assert reps >=1, 'reps must be >= 1'
232 if reps==1:
232 if reps==1:
233 start = clock()
233 start = clock()
234 out = func(*args,**kw)
234 out = func(*args,**kw)
235 tot_time = clock()-start
235 tot_time = clock()-start
236 else:
236 else:
237 rng = xrange(reps-1) # the last time is executed separately to store output
237 rng = xrange(reps-1) # the last time is executed separately to store output
238 start = clock()
238 start = clock()
239 for dummy in rng: func(*args,**kw)
239 for dummy in rng: func(*args,**kw)
240 out = func(*args,**kw) # one last time
240 out = func(*args,**kw) # one last time
241 tot_time = clock()-start
241 tot_time = clock()-start
242 av_time = tot_time / reps
242 av_time = tot_time / reps
243 return tot_time,av_time,out
243 return tot_time,av_time,out
244
244
245 def timings(reps,func,*args,**kw):
245 def timings(reps,func,*args,**kw):
246 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
246 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
247
247
248 Execute a function reps times, return a tuple with the elapsed total CPU
248 Execute a function reps times, return a tuple with the elapsed total CPU
249 time in seconds and the time per call. These are just the first two values
249 time in seconds and the time per call. These are just the first two values
250 in timings_out()."""
250 in timings_out()."""
251
251
252 return timings_out(reps,func,*args,**kw)[0:2]
252 return timings_out(reps,func,*args,**kw)[0:2]
253
253
254 def timing(func,*args,**kw):
254 def timing(func,*args,**kw):
255 """timing(func,*args,**kw) -> t_total
255 """timing(func,*args,**kw) -> t_total
256
256
257 Execute a function once, return the elapsed total CPU time in
257 Execute a function once, return the elapsed total CPU time in
258 seconds. This is just the first value in timings_out()."""
258 seconds. This is just the first value in timings_out()."""
259
259
260 return timings_out(1,func,*args,**kw)[0]
260 return timings_out(1,func,*args,**kw)[0]
261
261
262 #****************************************************************************
262 #****************************************************************************
263 # file and system
263 # file and system
264
264
265 def arg_split(s,posix=False):
265 def arg_split(s,posix=False):
266 """Split a command line's arguments in a shell-like manner.
266 """Split a command line's arguments in a shell-like manner.
267
267
268 This is a modified version of the standard library's shlex.split()
268 This is a modified version of the standard library's shlex.split()
269 function, but with a default of posix=False for splitting, so that quotes
269 function, but with a default of posix=False for splitting, so that quotes
270 in inputs are respected."""
270 in inputs are respected."""
271
271
272 # XXX - there may be unicode-related problems here!!! I'm not sure that
272 # XXX - there may be unicode-related problems here!!! I'm not sure that
273 # shlex is truly unicode-safe, so it might be necessary to do
273 # shlex is truly unicode-safe, so it might be necessary to do
274 #
274 #
275 # s = s.encode(sys.stdin.encoding)
275 # s = s.encode(sys.stdin.encoding)
276 #
276 #
277 # first, to ensure that shlex gets a normal string. Input from anyone who
277 # first, to ensure that shlex gets a normal string. Input from anyone who
278 # knows more about unicode and shlex than I would be good to have here...
278 # knows more about unicode and shlex than I would be good to have here...
279 lex = shlex.shlex(s, posix=posix)
279 lex = shlex.shlex(s, posix=posix)
280 lex.whitespace_split = True
280 lex.whitespace_split = True
281 return list(lex)
281 return list(lex)
282
282
283 def system(cmd,verbose=0,debug=0,header=''):
283 def system(cmd,verbose=0,debug=0,header=''):
284 """Execute a system command, return its exit status.
284 """Execute a system command, return its exit status.
285
285
286 Options:
286 Options:
287
287
288 - verbose (0): print the command to be executed.
288 - verbose (0): print the command to be executed.
289
289
290 - debug (0): only print, do not actually execute.
290 - debug (0): only print, do not actually execute.
291
291
292 - header (''): Header to print on screen prior to the executed command (it
292 - header (''): Header to print on screen prior to the executed command (it
293 is only prepended to the command, no newlines are added).
293 is only prepended to the command, no newlines are added).
294
294
295 Note: a stateful version of this function is available through the
295 Note: a stateful version of this function is available through the
296 SystemExec class."""
296 SystemExec class."""
297
297
298 stat = 0
298 stat = 0
299 if verbose or debug: print header+cmd
299 if verbose or debug: print header+cmd
300 sys.stdout.flush()
300 sys.stdout.flush()
301 if not debug: stat = os.system(cmd)
301 if not debug: stat = os.system(cmd)
302 return stat
302 return stat
303
303
304 def abbrev_cwd():
304 def abbrev_cwd():
305 """ Return abbreviated version of cwd, e.g. d:mydir """
305 """ Return abbreviated version of cwd, e.g. d:mydir """
306 cwd = os.getcwd()
306 cwd = os.getcwd()
307 drivepart = ''
307 drivepart = ''
308 if sys.platform == 'win32':
308 if sys.platform == 'win32':
309 if len(cwd) < 4:
309 if len(cwd) < 4:
310 return cwd
310 return cwd
311 drivepart = os.path.splitdrive(cwd)[0]
311 drivepart = os.path.splitdrive(cwd)[0]
312 return (drivepart + (
312 return (drivepart + (
313 cwd == '/' and '/' or \
313 cwd == '/' and '/' or \
314 os.path.basename(cwd)))
314 os.path.basename(cwd)))
315
315
316
316
317 # This function is used by ipython in a lot of places to make system calls.
317 # This function is used by ipython in a lot of places to make system calls.
318 # We need it to be slightly different under win32, due to the vagaries of
318 # We need it to be slightly different under win32, due to the vagaries of
319 # 'network shares'. A win32 override is below.
319 # 'network shares'. A win32 override is below.
320
320
321 def shell(cmd,verbose=0,debug=0,header=''):
321 def shell(cmd,verbose=0,debug=0,header=''):
322 """Execute a command in the system shell, always return None.
322 """Execute a command in the system shell, always return None.
323
323
324 Options:
324 Options:
325
325
326 - verbose (0): print the command to be executed.
326 - verbose (0): print the command to be executed.
327
327
328 - debug (0): only print, do not actually execute.
328 - debug (0): only print, do not actually execute.
329
329
330 - header (''): Header to print on screen prior to the executed command (it
330 - header (''): Header to print on screen prior to the executed command (it
331 is only prepended to the command, no newlines are added).
331 is only prepended to the command, no newlines are added).
332
332
333 Note: this is similar to genutils.system(), but it returns None so it can
333 Note: this is similar to genutils.system(), but it returns None so it can
334 be conveniently used in interactive loops without getting the return value
334 be conveniently used in interactive loops without getting the return value
335 (typically 0) printed many times."""
335 (typically 0) printed many times."""
336
336
337 stat = 0
337 stat = 0
338 if verbose or debug: print header+cmd
338 if verbose or debug: print header+cmd
339 # flush stdout so we don't mangle python's buffering
339 # flush stdout so we don't mangle python's buffering
340 sys.stdout.flush()
340 sys.stdout.flush()
341
341
342 if not debug:
342 if not debug:
343 platutils.set_term_title("IPy " + cmd)
343 platutils.set_term_title("IPy " + cmd)
344 os.system(cmd)
344 os.system(cmd)
345 platutils.set_term_title("IPy " + abbrev_cwd())
345 platutils.set_term_title("IPy " + abbrev_cwd())
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 This is pretty much deprecated and rarely used,
380 This is pretty much deprecated and rarely used,
381 genutils.getoutputerror may be what you need.
381 genutils.getoutputerror may be what you need.
382
382
383 """
383 """
384
384
385 if verbose or debug: print header+cmd
385 if verbose or debug: print header+cmd
386 if not debug:
386 if not debug:
387 output = os.popen(cmd).read()
387 output = os.popen(cmd).read()
388 # stipping last \n is here for backwards compat.
388 # stipping last \n is here for backwards compat.
389 if output.endswith('\n'):
389 if output.endswith('\n'):
390 output = output[:-1]
390 output = output[:-1]
391 if split:
391 if split:
392 return output.split('\n')
392 return output.split('\n')
393 else:
393 else:
394 return output
394 return output
395
395
396 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
396 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
397 """Return (standard output,standard error) of executing cmd in a shell.
397 """Return (standard output,standard error) of executing cmd in a shell.
398
398
399 Accepts the same arguments as system(), plus:
399 Accepts the same arguments as system(), plus:
400
400
401 - split(0): if true, each of stdout/err is returned as a list split on
401 - split(0): if true, each of stdout/err is returned as a list split on
402 newlines.
402 newlines.
403
403
404 Note: a stateful version of this function is available through the
404 Note: a stateful version of this function is available through the
405 SystemExec class."""
405 SystemExec class."""
406
406
407 if verbose or debug: print header+cmd
407 if verbose or debug: print header+cmd
408 if not cmd:
408 if not cmd:
409 if split:
409 if split:
410 return [],[]
410 return [],[]
411 else:
411 else:
412 return '',''
412 return '',''
413 if not debug:
413 if not debug:
414 pin,pout,perr = os.popen3(cmd)
414 pin,pout,perr = os.popen3(cmd)
415 tout = pout.read().rstrip()
415 tout = pout.read().rstrip()
416 terr = perr.read().rstrip()
416 terr = perr.read().rstrip()
417 pin.close()
417 pin.close()
418 pout.close()
418 pout.close()
419 perr.close()
419 perr.close()
420 if split:
420 if split:
421 return tout.split('\n'),terr.split('\n')
421 return tout.split('\n'),terr.split('\n')
422 else:
422 else:
423 return tout,terr
423 return tout,terr
424
424
425 # for compatibility with older naming conventions
425 # for compatibility with older naming conventions
426 xsys = system
426 xsys = system
427 bq = getoutput
427 bq = getoutput
428
428
429 class SystemExec:
429 class SystemExec:
430 """Access the system and getoutput functions through a stateful interface.
430 """Access the system and getoutput functions through a stateful interface.
431
431
432 Note: here we refer to the system and getoutput functions from this
432 Note: here we refer to the system and getoutput functions from this
433 library, not the ones from the standard python library.
433 library, not the ones from the standard python library.
434
434
435 This class offers the system and getoutput functions as methods, but the
435 This class offers the system and getoutput functions as methods, but the
436 verbose, debug and header parameters can be set for the instance (at
436 verbose, debug and header parameters can be set for the instance (at
437 creation time or later) so that they don't need to be specified on each
437 creation time or later) so that they don't need to be specified on each
438 call.
438 call.
439
439
440 For efficiency reasons, there's no way to override the parameters on a
440 For efficiency reasons, there's no way to override the parameters on a
441 per-call basis other than by setting instance attributes. If you need
441 per-call basis other than by setting instance attributes. If you need
442 local overrides, it's best to directly call system() or getoutput().
442 local overrides, it's best to directly call system() or getoutput().
443
443
444 The following names are provided as alternate options:
444 The following names are provided as alternate options:
445 - xsys: alias to system
445 - xsys: alias to system
446 - bq: alias to getoutput
446 - bq: alias to getoutput
447
447
448 An instance can then be created as:
448 An instance can then be created as:
449 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
449 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
450
450
451 And used as:
451 And used as:
452 >>> sysexec.xsys('pwd')
452 >>> sysexec.xsys('pwd')
453 >>> dirlist = sysexec.bq('ls -l')
453 >>> dirlist = sysexec.bq('ls -l')
454 """
454 """
455
455
456 def __init__(self,verbose=0,debug=0,header='',split=0):
456 def __init__(self,verbose=0,debug=0,header='',split=0):
457 """Specify the instance's values for verbose, debug and header."""
457 """Specify the instance's values for verbose, debug and header."""
458 setattr_list(self,'verbose debug header split')
458 setattr_list(self,'verbose debug header split')
459
459
460 def system(self,cmd):
460 def system(self,cmd):
461 """Stateful interface to system(), with the same keyword parameters."""
461 """Stateful interface to system(), with the same keyword parameters."""
462
462
463 system(cmd,self.verbose,self.debug,self.header)
463 system(cmd,self.verbose,self.debug,self.header)
464
464
465 def shell(self,cmd):
465 def shell(self,cmd):
466 """Stateful interface to shell(), with the same keyword parameters."""
466 """Stateful interface to shell(), with the same keyword parameters."""
467
467
468 shell(cmd,self.verbose,self.debug,self.header)
468 shell(cmd,self.verbose,self.debug,self.header)
469
469
470 xsys = system # alias
470 xsys = system # alias
471
471
472 def getoutput(self,cmd):
472 def getoutput(self,cmd):
473 """Stateful interface to getoutput()."""
473 """Stateful interface to getoutput()."""
474
474
475 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
475 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
476
476
477 def getoutputerror(self,cmd):
477 def getoutputerror(self,cmd):
478 """Stateful interface to getoutputerror()."""
478 """Stateful interface to getoutputerror()."""
479
479
480 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
480 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
481
481
482 bq = getoutput # alias
482 bq = getoutput # alias
483
483
484 #-----------------------------------------------------------------------------
484 #-----------------------------------------------------------------------------
485 def mutex_opts(dict,ex_op):
485 def mutex_opts(dict,ex_op):
486 """Check for presence of mutually exclusive keys in a dict.
486 """Check for presence of mutually exclusive keys in a dict.
487
487
488 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
488 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
489 for op1,op2 in ex_op:
489 for op1,op2 in ex_op:
490 if op1 in dict and op2 in dict:
490 if op1 in dict and op2 in dict:
491 raise ValueError,'\n*** ERROR in Arguments *** '\
491 raise ValueError,'\n*** ERROR in Arguments *** '\
492 'Options '+op1+' and '+op2+' are mutually exclusive.'
492 'Options '+op1+' and '+op2+' are mutually exclusive.'
493
493
494 #-----------------------------------------------------------------------------
494 #-----------------------------------------------------------------------------
495 def get_py_filename(name):
495 def get_py_filename(name):
496 """Return a valid python filename in the current directory.
496 """Return a valid python filename in the current directory.
497
497
498 If the given name is not a file, it adds '.py' and searches again.
498 If the given name is not a file, it adds '.py' and searches again.
499 Raises IOError with an informative message if the file isn't found."""
499 Raises IOError with an informative message if the file isn't found."""
500
500
501 name = os.path.expanduser(name)
501 name = os.path.expanduser(name)
502 if not os.path.isfile(name) and not name.endswith('.py'):
502 if not os.path.isfile(name) and not name.endswith('.py'):
503 name += '.py'
503 name += '.py'
504 if os.path.isfile(name):
504 if os.path.isfile(name):
505 return name
505 return name
506 else:
506 else:
507 raise IOError,'File `%s` not found.' % name
507 raise IOError,'File `%s` not found.' % name
508
508
509 #-----------------------------------------------------------------------------
509 #-----------------------------------------------------------------------------
510 def filefind(fname,alt_dirs = None):
510 def filefind(fname,alt_dirs = None):
511 """Return the given filename either in the current directory, if it
511 """Return the given filename either in the current directory, if it
512 exists, or in a specified list of directories.
512 exists, or in a specified list of directories.
513
513
514 ~ expansion is done on all file and directory names.
514 ~ expansion is done on all file and directory names.
515
515
516 Upon an unsuccessful search, raise an IOError exception."""
516 Upon an unsuccessful search, raise an IOError exception."""
517
517
518 if alt_dirs is None:
518 if alt_dirs is None:
519 try:
519 try:
520 alt_dirs = get_home_dir()
520 alt_dirs = get_home_dir()
521 except HomeDirError:
521 except HomeDirError:
522 alt_dirs = os.getcwd()
522 alt_dirs = os.getcwd()
523 search = [fname] + list_strings(alt_dirs)
523 search = [fname] + list_strings(alt_dirs)
524 search = map(os.path.expanduser,search)
524 search = map(os.path.expanduser,search)
525 #print 'search list for',fname,'list:',search # dbg
525 #print 'search list for',fname,'list:',search # dbg
526 fname = search[0]
526 fname = search[0]
527 if os.path.isfile(fname):
527 if os.path.isfile(fname):
528 return fname
528 return fname
529 for direc in search[1:]:
529 for direc in search[1:]:
530 testname = os.path.join(direc,fname)
530 testname = os.path.join(direc,fname)
531 #print 'testname',testname # dbg
531 #print 'testname',testname # dbg
532 if os.path.isfile(testname):
532 if os.path.isfile(testname):
533 return testname
533 return testname
534 raise IOError,'File' + `fname` + \
534 raise IOError,'File' + `fname` + \
535 ' not found in current or supplied directories:' + `alt_dirs`
535 ' not found in current or supplied directories:' + `alt_dirs`
536
536
537 #----------------------------------------------------------------------------
537 #----------------------------------------------------------------------------
538 def file_read(filename):
538 def file_read(filename):
539 """Read a file and close it. Returns the file source."""
539 """Read a file and close it. Returns the file source."""
540 fobj = open(filename,'r');
540 fobj = open(filename,'r');
541 source = fobj.read();
541 source = fobj.read();
542 fobj.close()
542 fobj.close()
543 return source
543 return source
544
544
545 def file_readlines(filename):
545 def file_readlines(filename):
546 """Read a file and close it. Returns the file source using readlines()."""
546 """Read a file and close it. Returns the file source using readlines()."""
547 fobj = open(filename,'r');
547 fobj = open(filename,'r');
548 lines = fobj.readlines();
548 lines = fobj.readlines();
549 fobj.close()
549 fobj.close()
550 return lines
550 return lines
551
551
552 #----------------------------------------------------------------------------
552 #----------------------------------------------------------------------------
553 def target_outdated(target,deps):
553 def target_outdated(target,deps):
554 """Determine whether a target is out of date.
554 """Determine whether a target is out of date.
555
555
556 target_outdated(target,deps) -> 1/0
556 target_outdated(target,deps) -> 1/0
557
557
558 deps: list of filenames which MUST exist.
558 deps: list of filenames which MUST exist.
559 target: single filename which may or may not exist.
559 target: single filename which may or may not exist.
560
560
561 If target doesn't exist or is older than any file listed in deps, return
561 If target doesn't exist or is older than any file listed in deps, return
562 true, otherwise return false.
562 true, otherwise return false.
563 """
563 """
564 try:
564 try:
565 target_time = os.path.getmtime(target)
565 target_time = os.path.getmtime(target)
566 except os.error:
566 except os.error:
567 return 1
567 return 1
568 for dep in deps:
568 for dep in deps:
569 dep_time = os.path.getmtime(dep)
569 dep_time = os.path.getmtime(dep)
570 if dep_time > target_time:
570 if dep_time > target_time:
571 #print "For target",target,"Dep failed:",dep # dbg
571 #print "For target",target,"Dep failed:",dep # dbg
572 #print "times (dep,tar):",dep_time,target_time # dbg
572 #print "times (dep,tar):",dep_time,target_time # dbg
573 return 1
573 return 1
574 return 0
574 return 0
575
575
576 #-----------------------------------------------------------------------------
576 #-----------------------------------------------------------------------------
577 def target_update(target,deps,cmd):
577 def target_update(target,deps,cmd):
578 """Update a target with a given command given a list of dependencies.
578 """Update a target with a given command given a list of dependencies.
579
579
580 target_update(target,deps,cmd) -> runs cmd if target is outdated.
580 target_update(target,deps,cmd) -> runs cmd if target is outdated.
581
581
582 This is just a wrapper around target_outdated() which calls the given
582 This is just a wrapper around target_outdated() which calls the given
583 command if target is outdated."""
583 command if target is outdated."""
584
584
585 if target_outdated(target,deps):
585 if target_outdated(target,deps):
586 xsys(cmd)
586 xsys(cmd)
587
587
588 #----------------------------------------------------------------------------
588 #----------------------------------------------------------------------------
589 def unquote_ends(istr):
589 def unquote_ends(istr):
590 """Remove a single pair of quotes from the endpoints of a string."""
590 """Remove a single pair of quotes from the endpoints of a string."""
591
591
592 if not istr:
592 if not istr:
593 return istr
593 return istr
594 if (istr[0]=="'" and istr[-1]=="'") or \
594 if (istr[0]=="'" and istr[-1]=="'") or \
595 (istr[0]=='"' and istr[-1]=='"'):
595 (istr[0]=='"' and istr[-1]=='"'):
596 return istr[1:-1]
596 return istr[1:-1]
597 else:
597 else:
598 return istr
598 return istr
599
599
600 #----------------------------------------------------------------------------
600 #----------------------------------------------------------------------------
601 def process_cmdline(argv,names=[],defaults={},usage=''):
601 def process_cmdline(argv,names=[],defaults={},usage=''):
602 """ Process command-line options and arguments.
602 """ Process command-line options and arguments.
603
603
604 Arguments:
604 Arguments:
605
605
606 - argv: list of arguments, typically sys.argv.
606 - argv: list of arguments, typically sys.argv.
607
607
608 - names: list of option names. See DPyGetOpt docs for details on options
608 - names: list of option names. See DPyGetOpt docs for details on options
609 syntax.
609 syntax.
610
610
611 - defaults: dict of default values.
611 - defaults: dict of default values.
612
612
613 - usage: optional usage notice to print if a wrong argument is passed.
613 - usage: optional usage notice to print if a wrong argument is passed.
614
614
615 Return a dict of options and a list of free arguments."""
615 Return a dict of options and a list of free arguments."""
616
616
617 getopt = DPyGetOpt.DPyGetOpt()
617 getopt = DPyGetOpt.DPyGetOpt()
618 getopt.setIgnoreCase(0)
618 getopt.setIgnoreCase(0)
619 getopt.parseConfiguration(names)
619 getopt.parseConfiguration(names)
620
620
621 try:
621 try:
622 getopt.processArguments(argv)
622 getopt.processArguments(argv)
623 except:
623 except DPyGetOpt.ArgumentError, exc:
624 print usage
624 print usage
625 warn(`sys.exc_value`,level=4)
625 warn('"%s"' % exc,level=4)
626
626
627 defaults.update(getopt.optionValues)
627 defaults.update(getopt.optionValues)
628 args = getopt.freeValues
628 args = getopt.freeValues
629
629
630 return defaults,args
630 return defaults,args
631
631
632 #----------------------------------------------------------------------------
632 #----------------------------------------------------------------------------
633 def optstr2types(ostr):
633 def optstr2types(ostr):
634 """Convert a string of option names to a dict of type mappings.
634 """Convert a string of option names to a dict of type mappings.
635
635
636 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
636 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
637
637
638 This is used to get the types of all the options in a string formatted
638 This is used to get the types of all the options in a string formatted
639 with the conventions of DPyGetOpt. The 'type' None is used for options
639 with the conventions of DPyGetOpt. The 'type' None is used for options
640 which are strings (they need no further conversion). This function's main
640 which are strings (they need no further conversion). This function's main
641 use is to get a typemap for use with read_dict().
641 use is to get a typemap for use with read_dict().
642 """
642 """
643
643
644 typeconv = {None:'',int:'',float:''}
644 typeconv = {None:'',int:'',float:''}
645 typemap = {'s':None,'i':int,'f':float}
645 typemap = {'s':None,'i':int,'f':float}
646 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
646 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
647
647
648 for w in ostr.split():
648 for w in ostr.split():
649 oname,alias,otype = opt_re.match(w).groups()
649 oname,alias,otype = opt_re.match(w).groups()
650 if otype == '' or alias == '!': # simple switches are integers too
650 if otype == '' or alias == '!': # simple switches are integers too
651 otype = 'i'
651 otype = 'i'
652 typeconv[typemap[otype]] += oname + ' '
652 typeconv[typemap[otype]] += oname + ' '
653 return typeconv
653 return typeconv
654
654
655 #----------------------------------------------------------------------------
655 #----------------------------------------------------------------------------
656 def read_dict(filename,type_conv=None,**opt):
656 def read_dict(filename,type_conv=None,**opt):
657
657
658 """Read a dictionary of key=value pairs from an input file, optionally
658 """Read a dictionary of key=value pairs from an input file, optionally
659 performing conversions on the resulting values.
659 performing conversions on the resulting values.
660
660
661 read_dict(filename,type_conv,**opt) -> dict
661 read_dict(filename,type_conv,**opt) -> dict
662
662
663 Only one value per line is accepted, the format should be
663 Only one value per line is accepted, the format should be
664 # optional comments are ignored
664 # optional comments are ignored
665 key value\n
665 key value\n
666
666
667 Args:
667 Args:
668
668
669 - type_conv: A dictionary specifying which keys need to be converted to
669 - type_conv: A dictionary specifying which keys need to be converted to
670 which types. By default all keys are read as strings. This dictionary
670 which types. By default all keys are read as strings. This dictionary
671 should have as its keys valid conversion functions for strings
671 should have as its keys valid conversion functions for strings
672 (int,long,float,complex, or your own). The value for each key
672 (int,long,float,complex, or your own). The value for each key
673 (converter) should be a whitespace separated string containing the names
673 (converter) should be a whitespace separated string containing the names
674 of all the entries in the file to be converted using that function. For
674 of all the entries in the file to be converted using that function. For
675 keys to be left alone, use None as the conversion function (only needed
675 keys to be left alone, use None as the conversion function (only needed
676 with purge=1, see below).
676 with purge=1, see below).
677
677
678 - opt: dictionary with extra options as below (default in parens)
678 - opt: dictionary with extra options as below (default in parens)
679
679
680 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
680 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
681 of the dictionary to be returned. If purge is going to be used, the
681 of the dictionary to be returned. If purge is going to be used, the
682 set of keys to be left as strings also has to be explicitly specified
682 set of keys to be left as strings also has to be explicitly specified
683 using the (non-existent) conversion function None.
683 using the (non-existent) conversion function None.
684
684
685 fs(None): field separator. This is the key/value separator to be used
685 fs(None): field separator. This is the key/value separator to be used
686 when parsing the file. The None default means any whitespace [behavior
686 when parsing the file. The None default means any whitespace [behavior
687 of string.split()].
687 of string.split()].
688
688
689 strip(0): if 1, strip string values of leading/trailinig whitespace.
689 strip(0): if 1, strip string values of leading/trailinig whitespace.
690
690
691 warn(1): warning level if requested keys are not found in file.
691 warn(1): warning level if requested keys are not found in file.
692 - 0: silently ignore.
692 - 0: silently ignore.
693 - 1: inform but proceed.
693 - 1: inform but proceed.
694 - 2: raise KeyError exception.
694 - 2: raise KeyError exception.
695
695
696 no_empty(0): if 1, remove keys with whitespace strings as a value.
696 no_empty(0): if 1, remove keys with whitespace strings as a value.
697
697
698 unique([]): list of keys (or space separated string) which can't be
698 unique([]): list of keys (or space separated string) which can't be
699 repeated. If one such key is found in the file, each new instance
699 repeated. If one such key is found in the file, each new instance
700 overwrites the previous one. For keys not listed here, the behavior is
700 overwrites the previous one. For keys not listed here, the behavior is
701 to make a list of all appearances.
701 to make a list of all appearances.
702
702
703 Example:
703 Example:
704 If the input file test.ini has:
704 If the input file test.ini has:
705 i 3
705 i 3
706 x 4.5
706 x 4.5
707 y 5.5
707 y 5.5
708 s hi ho
708 s hi ho
709 Then:
709 Then:
710
710
711 >>> type_conv={int:'i',float:'x',None:'s'}
711 >>> type_conv={int:'i',float:'x',None:'s'}
712 >>> read_dict('test.ini')
712 >>> read_dict('test.ini')
713 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
713 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
714 >>> read_dict('test.ini',type_conv)
714 >>> read_dict('test.ini',type_conv)
715 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
715 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
716 >>> read_dict('test.ini',type_conv,purge=1)
716 >>> read_dict('test.ini',type_conv,purge=1)
717 {'i': 3, 's': 'hi ho', 'x': 4.5}
717 {'i': 3, 's': 'hi ho', 'x': 4.5}
718 """
718 """
719
719
720 # starting config
720 # starting config
721 opt.setdefault('purge',0)
721 opt.setdefault('purge',0)
722 opt.setdefault('fs',None) # field sep defaults to any whitespace
722 opt.setdefault('fs',None) # field sep defaults to any whitespace
723 opt.setdefault('strip',0)
723 opt.setdefault('strip',0)
724 opt.setdefault('warn',1)
724 opt.setdefault('warn',1)
725 opt.setdefault('no_empty',0)
725 opt.setdefault('no_empty',0)
726 opt.setdefault('unique','')
726 opt.setdefault('unique','')
727 if type(opt['unique']) in StringTypes:
727 if type(opt['unique']) in StringTypes:
728 unique_keys = qw(opt['unique'])
728 unique_keys = qw(opt['unique'])
729 elif type(opt['unique']) in (types.TupleType,types.ListType):
729 elif type(opt['unique']) in (types.TupleType,types.ListType):
730 unique_keys = opt['unique']
730 unique_keys = opt['unique']
731 else:
731 else:
732 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
732 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
733
733
734 dict = {}
734 dict = {}
735 # first read in table of values as strings
735 # first read in table of values as strings
736 file = open(filename,'r')
736 file = open(filename,'r')
737 for line in file.readlines():
737 for line in file.readlines():
738 line = line.strip()
738 line = line.strip()
739 if len(line) and line[0]=='#': continue
739 if len(line) and line[0]=='#': continue
740 if len(line)>0:
740 if len(line)>0:
741 lsplit = line.split(opt['fs'],1)
741 lsplit = line.split(opt['fs'],1)
742 try:
742 try:
743 key,val = lsplit
743 key,val = lsplit
744 except ValueError:
744 except ValueError:
745 key,val = lsplit[0],''
745 key,val = lsplit[0],''
746 key = key.strip()
746 key = key.strip()
747 if opt['strip']: val = val.strip()
747 if opt['strip']: val = val.strip()
748 if val == "''" or val == '""': val = ''
748 if val == "''" or val == '""': val = ''
749 if opt['no_empty'] and (val=='' or val.isspace()):
749 if opt['no_empty'] and (val=='' or val.isspace()):
750 continue
750 continue
751 # if a key is found more than once in the file, build a list
751 # if a key is found more than once in the file, build a list
752 # unless it's in the 'unique' list. In that case, last found in file
752 # unless it's in the 'unique' list. In that case, last found in file
753 # takes precedence. User beware.
753 # takes precedence. User beware.
754 try:
754 try:
755 if dict[key] and key in unique_keys:
755 if dict[key] and key in unique_keys:
756 dict[key] = val
756 dict[key] = val
757 elif type(dict[key]) is types.ListType:
757 elif type(dict[key]) is types.ListType:
758 dict[key].append(val)
758 dict[key].append(val)
759 else:
759 else:
760 dict[key] = [dict[key],val]
760 dict[key] = [dict[key],val]
761 except KeyError:
761 except KeyError:
762 dict[key] = val
762 dict[key] = val
763 # purge if requested
763 # purge if requested
764 if opt['purge']:
764 if opt['purge']:
765 accepted_keys = qwflat(type_conv.values())
765 accepted_keys = qwflat(type_conv.values())
766 for key in dict.keys():
766 for key in dict.keys():
767 if key in accepted_keys: continue
767 if key in accepted_keys: continue
768 del(dict[key])
768 del(dict[key])
769 # now convert if requested
769 # now convert if requested
770 if type_conv==None: return dict
770 if type_conv==None: return dict
771 conversions = type_conv.keys()
771 conversions = type_conv.keys()
772 try: conversions.remove(None)
772 try: conversions.remove(None)
773 except: pass
773 except: pass
774 for convert in conversions:
774 for convert in conversions:
775 for val in qw(type_conv[convert]):
775 for val in qw(type_conv[convert]):
776 try:
776 try:
777 dict[val] = convert(dict[val])
777 dict[val] = convert(dict[val])
778 except KeyError,e:
778 except KeyError,e:
779 if opt['warn'] == 0:
779 if opt['warn'] == 0:
780 pass
780 pass
781 elif opt['warn'] == 1:
781 elif opt['warn'] == 1:
782 print >>sys.stderr, 'Warning: key',val,\
782 print >>sys.stderr, 'Warning: key',val,\
783 'not found in file',filename
783 'not found in file',filename
784 elif opt['warn'] == 2:
784 elif opt['warn'] == 2:
785 raise KeyError,e
785 raise KeyError,e
786 else:
786 else:
787 raise ValueError,'Warning level must be 0,1 or 2'
787 raise ValueError,'Warning level must be 0,1 or 2'
788
788
789 return dict
789 return dict
790
790
791 #----------------------------------------------------------------------------
791 #----------------------------------------------------------------------------
792 def flag_calls(func):
792 def flag_calls(func):
793 """Wrap a function to detect and flag when it gets called.
793 """Wrap a function to detect and flag when it gets called.
794
794
795 This is a decorator which takes a function and wraps it in a function with
795 This is a decorator which takes a function and wraps it in a function with
796 a 'called' attribute. wrapper.called is initialized to False.
796 a 'called' attribute. wrapper.called is initialized to False.
797
797
798 The wrapper.called attribute is set to False right before each call to the
798 The wrapper.called attribute is set to False right before each call to the
799 wrapped function, so if the call fails it remains False. After the call
799 wrapped function, so if the call fails it remains False. After the call
800 completes, wrapper.called is set to True and the output is returned.
800 completes, wrapper.called is set to True and the output is returned.
801
801
802 Testing for truth in wrapper.called allows you to determine if a call to
802 Testing for truth in wrapper.called allows you to determine if a call to
803 func() was attempted and succeeded."""
803 func() was attempted and succeeded."""
804
804
805 def wrapper(*args,**kw):
805 def wrapper(*args,**kw):
806 wrapper.called = False
806 wrapper.called = False
807 out = func(*args,**kw)
807 out = func(*args,**kw)
808 wrapper.called = True
808 wrapper.called = True
809 return out
809 return out
810
810
811 wrapper.called = False
811 wrapper.called = False
812 wrapper.__doc__ = func.__doc__
812 wrapper.__doc__ = func.__doc__
813 return wrapper
813 return wrapper
814
814
815 #----------------------------------------------------------------------------
815 #----------------------------------------------------------------------------
816 def dhook_wrap(func,*a,**k):
816 def dhook_wrap(func,*a,**k):
817 """Wrap a function call in a sys.displayhook controller.
817 """Wrap a function call in a sys.displayhook controller.
818
818
819 Returns a wrapper around func which calls func, with all its arguments and
819 Returns a wrapper around func which calls func, with all its arguments and
820 keywords unmodified, using the default sys.displayhook. Since IPython
820 keywords unmodified, using the default sys.displayhook. Since IPython
821 modifies sys.displayhook, it breaks the behavior of certain systems that
821 modifies sys.displayhook, it breaks the behavior of certain systems that
822 rely on the default behavior, notably doctest.
822 rely on the default behavior, notably doctest.
823 """
823 """
824
824
825 def f(*a,**k):
825 def f(*a,**k):
826
826
827 dhook_s = sys.displayhook
827 dhook_s = sys.displayhook
828 sys.displayhook = sys.__displayhook__
828 sys.displayhook = sys.__displayhook__
829 try:
829 try:
830 out = func(*a,**k)
830 out = func(*a,**k)
831 finally:
831 finally:
832 sys.displayhook = dhook_s
832 sys.displayhook = dhook_s
833
833
834 return out
834 return out
835
835
836 f.__doc__ = func.__doc__
836 f.__doc__ = func.__doc__
837 return f
837 return f
838
838
839 #----------------------------------------------------------------------------
839 #----------------------------------------------------------------------------
840 def doctest_reload():
840 def doctest_reload():
841 """Properly reload doctest to reuse it interactively.
841 """Properly reload doctest to reuse it interactively.
842
842
843 This routine:
843 This routine:
844
844
845 - reloads doctest
845 - reloads doctest
846
846
847 - resets its global 'master' attribute to None, so that multiple uses of
847 - resets its global 'master' attribute to None, so that multiple uses of
848 the module interactively don't produce cumulative reports.
848 the module interactively don't produce cumulative reports.
849
849
850 - Monkeypatches its core test runner method to protect it from IPython's
850 - Monkeypatches its core test runner method to protect it from IPython's
851 modified displayhook. Doctest expects the default displayhook behavior
851 modified displayhook. Doctest expects the default displayhook behavior
852 deep down, so our modification breaks it completely. For this reason, a
852 deep down, so our modification breaks it completely. For this reason, a
853 hard monkeypatch seems like a reasonable solution rather than asking
853 hard monkeypatch seems like a reasonable solution rather than asking
854 users to manually use a different doctest runner when under IPython."""
854 users to manually use a different doctest runner when under IPython."""
855
855
856 import doctest
856 import doctest
857 reload(doctest)
857 reload(doctest)
858 doctest.master=None
858 doctest.master=None
859
859
860 try:
860 try:
861 doctest.DocTestRunner
861 doctest.DocTestRunner
862 except AttributeError:
862 except AttributeError:
863 # This is only for python 2.3 compatibility, remove once we move to
863 # This is only for python 2.3 compatibility, remove once we move to
864 # 2.4 only.
864 # 2.4 only.
865 pass
865 pass
866 else:
866 else:
867 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
867 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
868
868
869 #----------------------------------------------------------------------------
869 #----------------------------------------------------------------------------
870 class HomeDirError(Error):
870 class HomeDirError(Error):
871 pass
871 pass
872
872
873 def get_home_dir():
873 def get_home_dir():
874 """Return the closest possible equivalent to a 'home' directory.
874 """Return the closest possible equivalent to a 'home' directory.
875
875
876 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
876 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
877
877
878 Currently only Posix and NT are implemented, a HomeDirError exception is
878 Currently only Posix and NT are implemented, a HomeDirError exception is
879 raised for all other OSes. """
879 raised for all other OSes. """
880
880
881 isdir = os.path.isdir
881 isdir = os.path.isdir
882 env = os.environ
882 env = os.environ
883
883
884 # first, check py2exe distribution root directory for _ipython.
884 # first, check py2exe distribution root directory for _ipython.
885 # This overrides all. Normally does not exist.
885 # This overrides all. Normally does not exist.
886
886
887 if '\\library.zip\\' in IPython.__file__.lower():
887 if '\\library.zip\\' in IPython.__file__.lower():
888 root, rest = IPython.__file__.lower().split('library.zip')
888 root, rest = IPython.__file__.lower().split('library.zip')
889 if isdir(root + '_ipython'):
889 if isdir(root + '_ipython'):
890 os.environ["IPYKITROOT"] = root.rstrip('\\')
890 os.environ["IPYKITROOT"] = root.rstrip('\\')
891 return root
891 return root
892
892
893 try:
893 try:
894 homedir = env['HOME']
894 homedir = env['HOME']
895 if not isdir(homedir):
895 if not isdir(homedir):
896 # in case a user stuck some string which does NOT resolve to a
896 # in case a user stuck some string which does NOT resolve to a
897 # valid path, it's as good as if we hadn't foud it
897 # valid path, it's as good as if we hadn't foud it
898 raise KeyError
898 raise KeyError
899 return homedir
899 return homedir
900 except KeyError:
900 except KeyError:
901 if os.name == 'posix':
901 if os.name == 'posix':
902 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
902 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
903 elif os.name == 'nt':
903 elif os.name == 'nt':
904 # For some strange reason, win9x returns 'nt' for os.name.
904 # For some strange reason, win9x returns 'nt' for os.name.
905 try:
905 try:
906 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
906 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
907 if not isdir(homedir):
907 if not isdir(homedir):
908 homedir = os.path.join(env['USERPROFILE'])
908 homedir = os.path.join(env['USERPROFILE'])
909 if not isdir(homedir):
909 if not isdir(homedir):
910 raise HomeDirError
910 raise HomeDirError
911 return homedir
911 return homedir
912 except:
912 except:
913 try:
913 try:
914 # Use the registry to get the 'My Documents' folder.
914 # Use the registry to get the 'My Documents' folder.
915 import _winreg as wreg
915 import _winreg as wreg
916 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
916 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
917 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
917 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
918 homedir = wreg.QueryValueEx(key,'Personal')[0]
918 homedir = wreg.QueryValueEx(key,'Personal')[0]
919 key.Close()
919 key.Close()
920 if not isdir(homedir):
920 if not isdir(homedir):
921 e = ('Invalid "Personal" folder registry key '
921 e = ('Invalid "Personal" folder registry key '
922 'typically "My Documents".\n'
922 'typically "My Documents".\n'
923 'Value: %s\n'
923 'Value: %s\n'
924 'This is not a valid directory on your system.' %
924 'This is not a valid directory on your system.' %
925 homedir)
925 homedir)
926 raise HomeDirError(e)
926 raise HomeDirError(e)
927 return homedir
927 return homedir
928 except HomeDirError:
928 except HomeDirError:
929 raise
929 raise
930 except:
930 except:
931 return 'C:\\'
931 return 'C:\\'
932 elif os.name == 'dos':
932 elif os.name == 'dos':
933 # Desperate, may do absurd things in classic MacOS. May work under DOS.
933 # Desperate, may do absurd things in classic MacOS. May work under DOS.
934 return 'C:\\'
934 return 'C:\\'
935 else:
935 else:
936 raise HomeDirError,'support for your operating system not implemented.'
936 raise HomeDirError,'support for your operating system not implemented.'
937
937
938 #****************************************************************************
938 #****************************************************************************
939 # strings and text
939 # strings and text
940
940
941 class LSString(str):
941 class LSString(str):
942 """String derivative with a special access attributes.
942 """String derivative with a special access attributes.
943
943
944 These are normal strings, but with the special attributes:
944 These are normal strings, but with the special attributes:
945
945
946 .l (or .list) : value as list (split on newlines).
946 .l (or .list) : value as list (split on newlines).
947 .n (or .nlstr): original value (the string itself).
947 .n (or .nlstr): original value (the string itself).
948 .s (or .spstr): value as whitespace-separated string.
948 .s (or .spstr): value as whitespace-separated string.
949 .p (or .paths): list of path objects
949 .p (or .paths): list of path objects
950
950
951 Any values which require transformations are computed only once and
951 Any values which require transformations are computed only once and
952 cached.
952 cached.
953
953
954 Such strings are very useful to efficiently interact with the shell, which
954 Such strings are very useful to efficiently interact with the shell, which
955 typically only understands whitespace-separated options for commands."""
955 typically only understands whitespace-separated options for commands."""
956
956
957 def get_list(self):
957 def get_list(self):
958 try:
958 try:
959 return self.__list
959 return self.__list
960 except AttributeError:
960 except AttributeError:
961 self.__list = self.split('\n')
961 self.__list = self.split('\n')
962 return self.__list
962 return self.__list
963
963
964 l = list = property(get_list)
964 l = list = property(get_list)
965
965
966 def get_spstr(self):
966 def get_spstr(self):
967 try:
967 try:
968 return self.__spstr
968 return self.__spstr
969 except AttributeError:
969 except AttributeError:
970 self.__spstr = self.replace('\n',' ')
970 self.__spstr = self.replace('\n',' ')
971 return self.__spstr
971 return self.__spstr
972
972
973 s = spstr = property(get_spstr)
973 s = spstr = property(get_spstr)
974
974
975 def get_nlstr(self):
975 def get_nlstr(self):
976 return self
976 return self
977
977
978 n = nlstr = property(get_nlstr)
978 n = nlstr = property(get_nlstr)
979
979
980 def get_paths(self):
980 def get_paths(self):
981 try:
981 try:
982 return self.__paths
982 return self.__paths
983 except AttributeError:
983 except AttributeError:
984 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
984 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
985 return self.__paths
985 return self.__paths
986
986
987 p = paths = property(get_paths)
987 p = paths = property(get_paths)
988
988
989 def print_lsstring(arg):
989 def print_lsstring(arg):
990 """ Prettier (non-repr-like) and more informative printer for LSString """
990 """ Prettier (non-repr-like) and more informative printer for LSString """
991 print "LSString (.p, .n, .l, .s available). Value:"
991 print "LSString (.p, .n, .l, .s available). Value:"
992 print arg
992 print arg
993
993
994 print_lsstring = result_display.when_type(LSString)(print_lsstring)
994 print_lsstring = result_display.when_type(LSString)(print_lsstring)
995
995
996 #----------------------------------------------------------------------------
996 #----------------------------------------------------------------------------
997 class SList(list):
997 class SList(list):
998 """List derivative with a special access attributes.
998 """List derivative with a special access attributes.
999
999
1000 These are normal lists, but with the special attributes:
1000 These are normal lists, but with the special attributes:
1001
1001
1002 .l (or .list) : value as list (the list itself).
1002 .l (or .list) : value as list (the list itself).
1003 .n (or .nlstr): value as a string, joined on newlines.
1003 .n (or .nlstr): value as a string, joined on newlines.
1004 .s (or .spstr): value as a string, joined on spaces.
1004 .s (or .spstr): value as a string, joined on spaces.
1005 .p (or .paths): list of path objects
1005 .p (or .paths): list of path objects
1006
1006
1007 Any values which require transformations are computed only once and
1007 Any values which require transformations are computed only once and
1008 cached."""
1008 cached."""
1009
1009
1010 def get_list(self):
1010 def get_list(self):
1011 return self
1011 return self
1012
1012
1013 l = list = property(get_list)
1013 l = list = property(get_list)
1014
1014
1015 def get_spstr(self):
1015 def get_spstr(self):
1016 try:
1016 try:
1017 return self.__spstr
1017 return self.__spstr
1018 except AttributeError:
1018 except AttributeError:
1019 self.__spstr = ' '.join(self)
1019 self.__spstr = ' '.join(self)
1020 return self.__spstr
1020 return self.__spstr
1021
1021
1022 s = spstr = property(get_spstr)
1022 s = spstr = property(get_spstr)
1023
1023
1024 def get_nlstr(self):
1024 def get_nlstr(self):
1025 try:
1025 try:
1026 return self.__nlstr
1026 return self.__nlstr
1027 except AttributeError:
1027 except AttributeError:
1028 self.__nlstr = '\n'.join(self)
1028 self.__nlstr = '\n'.join(self)
1029 return self.__nlstr
1029 return self.__nlstr
1030
1030
1031 n = nlstr = property(get_nlstr)
1031 n = nlstr = property(get_nlstr)
1032
1032
1033 def get_paths(self):
1033 def get_paths(self):
1034 try:
1034 try:
1035 return self.__paths
1035 return self.__paths
1036 except AttributeError:
1036 except AttributeError:
1037 self.__paths = [path(p) for p in self if os.path.exists(p)]
1037 self.__paths = [path(p) for p in self if os.path.exists(p)]
1038 return self.__paths
1038 return self.__paths
1039
1039
1040 p = paths = property(get_paths)
1040 p = paths = property(get_paths)
1041
1041
1042 def grep(self, pattern, prune = False):
1042 def grep(self, pattern, prune = False):
1043 """ Return all strings matching 'pattern' (a regex or callable)
1043 """ Return all strings matching 'pattern' (a regex or callable)
1044
1044
1045 This is case-insensitive. If prune is true, return all items
1045 This is case-insensitive. If prune is true, return all items
1046 NOT matching the pattern.
1046 NOT matching the pattern.
1047
1047
1048 Examples::
1048 Examples::
1049
1049
1050 a.grep( lambda x: x.startswith('C') )
1050 a.grep( lambda x: x.startswith('C') )
1051 a.grep('Cha.*log', prune=1)
1051 a.grep('Cha.*log', prune=1)
1052 """
1052 """
1053 if isinstance(pattern, basestring):
1053 if isinstance(pattern, basestring):
1054 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1054 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1055 else:
1055 else:
1056 pred = pattern
1056 pred = pattern
1057 if not prune:
1057 if not prune:
1058 return SList([el for el in self if pred(el)])
1058 return SList([el for el in self if pred(el)])
1059 else:
1059 else:
1060 return SList([el for el in self if not pred(el)])
1060 return SList([el for el in self if not pred(el)])
1061 def fields(self, *fields):
1061 def fields(self, *fields):
1062 """ Collect whitespace-separated fields from string list
1062 """ Collect whitespace-separated fields from string list
1063
1063
1064 Allows quick awk-like usage of string lists.
1064 Allows quick awk-like usage of string lists.
1065
1065
1066 Example data (in var a, created by 'a = !ls -l')::
1066 Example data (in var a, created by 'a = !ls -l')::
1067 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1067 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1068 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1068 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1069
1069
1070 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1070 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1071 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1071 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1072 (note the joining by space).
1072 (note the joining by space).
1073
1073
1074 IndexErrors are ignored.
1074 IndexErrors are ignored.
1075
1075
1076 Without args, fields() just split()'s the strings.
1076 Without args, fields() just split()'s the strings.
1077 """
1077 """
1078 if len(fields) == 0:
1078 if len(fields) == 0:
1079 return [el.split() for el in self]
1079 return [el.split() for el in self]
1080
1080
1081 res = SList()
1081 res = SList()
1082 for el in [f.split() for f in self]:
1082 for el in [f.split() for f in self]:
1083 lineparts = []
1083 lineparts = []
1084
1084
1085 for fd in fields:
1085 for fd in fields:
1086 try:
1086 try:
1087 lineparts.append(el[fd])
1087 lineparts.append(el[fd])
1088 except IndexError:
1088 except IndexError:
1089 pass
1089 pass
1090 if lineparts:
1090 if lineparts:
1091 res.append(" ".join(lineparts))
1091 res.append(" ".join(lineparts))
1092
1092
1093 return res
1093 return res
1094
1094
1095
1095
1096
1096
1097
1097
1098
1098
1099 def print_slist(arg):
1099 def print_slist(arg):
1100 """ Prettier (non-repr-like) and more informative printer for SList """
1100 """ Prettier (non-repr-like) and more informative printer for SList """
1101 print "SList (.p, .n, .l, .s, .grep(), .fields() available). Value:"
1101 print "SList (.p, .n, .l, .s, .grep(), .fields() available). Value:"
1102 nlprint(arg)
1102 nlprint(arg)
1103
1103
1104 print_slist = result_display.when_type(SList)(print_slist)
1104 print_slist = result_display.when_type(SList)(print_slist)
1105
1105
1106
1106
1107
1107
1108 #----------------------------------------------------------------------------
1108 #----------------------------------------------------------------------------
1109 def esc_quotes(strng):
1109 def esc_quotes(strng):
1110 """Return the input string with single and double quotes escaped out"""
1110 """Return the input string with single and double quotes escaped out"""
1111
1111
1112 return strng.replace('"','\\"').replace("'","\\'")
1112 return strng.replace('"','\\"').replace("'","\\'")
1113
1113
1114 #----------------------------------------------------------------------------
1114 #----------------------------------------------------------------------------
1115 def make_quoted_expr(s):
1115 def make_quoted_expr(s):
1116 """Return string s in appropriate quotes, using raw string if possible.
1116 """Return string s in appropriate quotes, using raw string if possible.
1117
1117
1118 Effectively this turns string: cd \ao\ao\
1118 Effectively this turns string: cd \ao\ao\
1119 to: r"cd \ao\ao\_"[:-1]
1119 to: r"cd \ao\ao\_"[:-1]
1120
1120
1121 Note the use of raw string and padding at the end to allow trailing backslash.
1121 Note the use of raw string and padding at the end to allow trailing backslash.
1122
1122
1123 """
1123 """
1124
1124
1125 tail = ''
1125 tail = ''
1126 tailpadding = ''
1126 tailpadding = ''
1127 raw = ''
1127 raw = ''
1128 if "\\" in s:
1128 if "\\" in s:
1129 raw = 'r'
1129 raw = 'r'
1130 if s.endswith('\\'):
1130 if s.endswith('\\'):
1131 tail = '[:-1]'
1131 tail = '[:-1]'
1132 tailpadding = '_'
1132 tailpadding = '_'
1133 if '"' not in s:
1133 if '"' not in s:
1134 quote = '"'
1134 quote = '"'
1135 elif "'" not in s:
1135 elif "'" not in s:
1136 quote = "'"
1136 quote = "'"
1137 elif '"""' not in s and not s.endswith('"'):
1137 elif '"""' not in s and not s.endswith('"'):
1138 quote = '"""'
1138 quote = '"""'
1139 elif "'''" not in s and not s.endswith("'"):
1139 elif "'''" not in s and not s.endswith("'"):
1140 quote = "'''"
1140 quote = "'''"
1141 else:
1141 else:
1142 # give up, backslash-escaped string will do
1142 # give up, backslash-escaped string will do
1143 return '"%s"' % esc_quotes(s)
1143 return '"%s"' % esc_quotes(s)
1144 res = raw + quote + s + tailpadding + quote + tail
1144 res = raw + quote + s + tailpadding + quote + tail
1145 return res
1145 return res
1146
1146
1147
1147
1148 #----------------------------------------------------------------------------
1148 #----------------------------------------------------------------------------
1149 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1149 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1150 """Take multiple lines of input.
1150 """Take multiple lines of input.
1151
1151
1152 A list with each line of input as a separate element is returned when a
1152 A list with each line of input as a separate element is returned when a
1153 termination string is entered (defaults to a single '.'). Input can also
1153 termination string is entered (defaults to a single '.'). Input can also
1154 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1154 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1155
1155
1156 Lines of input which end in \\ are joined into single entries (and a
1156 Lines of input which end in \\ are joined into single entries (and a
1157 secondary continuation prompt is issued as long as the user terminates
1157 secondary continuation prompt is issued as long as the user terminates
1158 lines with \\). This allows entering very long strings which are still
1158 lines with \\). This allows entering very long strings which are still
1159 meant to be treated as single entities.
1159 meant to be treated as single entities.
1160 """
1160 """
1161
1161
1162 try:
1162 try:
1163 if header:
1163 if header:
1164 header += '\n'
1164 header += '\n'
1165 lines = [raw_input(header + ps1)]
1165 lines = [raw_input(header + ps1)]
1166 except EOFError:
1166 except EOFError:
1167 return []
1167 return []
1168 terminate = [terminate_str]
1168 terminate = [terminate_str]
1169 try:
1169 try:
1170 while lines[-1:] != terminate:
1170 while lines[-1:] != terminate:
1171 new_line = raw_input(ps1)
1171 new_line = raw_input(ps1)
1172 while new_line.endswith('\\'):
1172 while new_line.endswith('\\'):
1173 new_line = new_line[:-1] + raw_input(ps2)
1173 new_line = new_line[:-1] + raw_input(ps2)
1174 lines.append(new_line)
1174 lines.append(new_line)
1175
1175
1176 return lines[:-1] # don't return the termination command
1176 return lines[:-1] # don't return the termination command
1177 except EOFError:
1177 except EOFError:
1178 print
1178 print
1179 return lines
1179 return lines
1180
1180
1181 #----------------------------------------------------------------------------
1181 #----------------------------------------------------------------------------
1182 def raw_input_ext(prompt='', ps2='... '):
1182 def raw_input_ext(prompt='', ps2='... '):
1183 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1183 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1184
1184
1185 line = raw_input(prompt)
1185 line = raw_input(prompt)
1186 while line.endswith('\\'):
1186 while line.endswith('\\'):
1187 line = line[:-1] + raw_input(ps2)
1187 line = line[:-1] + raw_input(ps2)
1188 return line
1188 return line
1189
1189
1190 #----------------------------------------------------------------------------
1190 #----------------------------------------------------------------------------
1191 def ask_yes_no(prompt,default=None):
1191 def ask_yes_no(prompt,default=None):
1192 """Asks a question and returns a boolean (y/n) answer.
1192 """Asks a question and returns a boolean (y/n) answer.
1193
1193
1194 If default is given (one of 'y','n'), it is used if the user input is
1194 If default is given (one of 'y','n'), it is used if the user input is
1195 empty. Otherwise the question is repeated until an answer is given.
1195 empty. Otherwise the question is repeated until an answer is given.
1196
1196
1197 An EOF is treated as the default answer. If there is no default, an
1197 An EOF is treated as the default answer. If there is no default, an
1198 exception is raised to prevent infinite loops.
1198 exception is raised to prevent infinite loops.
1199
1199
1200 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1200 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1201
1201
1202 answers = {'y':True,'n':False,'yes':True,'no':False}
1202 answers = {'y':True,'n':False,'yes':True,'no':False}
1203 ans = None
1203 ans = None
1204 while ans not in answers.keys():
1204 while ans not in answers.keys():
1205 try:
1205 try:
1206 ans = raw_input(prompt+' ').lower()
1206 ans = raw_input(prompt+' ').lower()
1207 if not ans: # response was an empty string
1207 if not ans: # response was an empty string
1208 ans = default
1208 ans = default
1209 except KeyboardInterrupt:
1209 except KeyboardInterrupt:
1210 pass
1210 pass
1211 except EOFError:
1211 except EOFError:
1212 if default in answers.keys():
1212 if default in answers.keys():
1213 ans = default
1213 ans = default
1214 print
1214 print
1215 else:
1215 else:
1216 raise
1216 raise
1217
1217
1218 return answers[ans]
1218 return answers[ans]
1219
1219
1220 #----------------------------------------------------------------------------
1220 #----------------------------------------------------------------------------
1221 def marquee(txt='',width=78,mark='*'):
1221 def marquee(txt='',width=78,mark='*'):
1222 """Return the input string centered in a 'marquee'."""
1222 """Return the input string centered in a 'marquee'."""
1223 if not txt:
1223 if not txt:
1224 return (mark*width)[:width]
1224 return (mark*width)[:width]
1225 nmark = (width-len(txt)-2)/len(mark)/2
1225 nmark = (width-len(txt)-2)/len(mark)/2
1226 if nmark < 0: nmark =0
1226 if nmark < 0: nmark =0
1227 marks = mark*nmark
1227 marks = mark*nmark
1228 return '%s %s %s' % (marks,txt,marks)
1228 return '%s %s %s' % (marks,txt,marks)
1229
1229
1230 #----------------------------------------------------------------------------
1230 #----------------------------------------------------------------------------
1231 class EvalDict:
1231 class EvalDict:
1232 """
1232 """
1233 Emulate a dict which evaluates its contents in the caller's frame.
1233 Emulate a dict which evaluates its contents in the caller's frame.
1234
1234
1235 Usage:
1235 Usage:
1236 >>>number = 19
1236 >>>number = 19
1237 >>>text = "python"
1237 >>>text = "python"
1238 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1238 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1239 """
1239 """
1240
1240
1241 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1241 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1242 # modified (shorter) version of:
1242 # modified (shorter) version of:
1243 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1243 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1244 # Skip Montanaro (skip@pobox.com).
1244 # Skip Montanaro (skip@pobox.com).
1245
1245
1246 def __getitem__(self, name):
1246 def __getitem__(self, name):
1247 frame = sys._getframe(1)
1247 frame = sys._getframe(1)
1248 return eval(name, frame.f_globals, frame.f_locals)
1248 return eval(name, frame.f_globals, frame.f_locals)
1249
1249
1250 EvalString = EvalDict # for backwards compatibility
1250 EvalString = EvalDict # for backwards compatibility
1251 #----------------------------------------------------------------------------
1251 #----------------------------------------------------------------------------
1252 def qw(words,flat=0,sep=None,maxsplit=-1):
1252 def qw(words,flat=0,sep=None,maxsplit=-1):
1253 """Similar to Perl's qw() operator, but with some more options.
1253 """Similar to Perl's qw() operator, but with some more options.
1254
1254
1255 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1255 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1256
1256
1257 words can also be a list itself, and with flat=1, the output will be
1257 words can also be a list itself, and with flat=1, the output will be
1258 recursively flattened. Examples:
1258 recursively flattened. Examples:
1259
1259
1260 >>> qw('1 2')
1260 >>> qw('1 2')
1261 ['1', '2']
1261 ['1', '2']
1262 >>> qw(['a b','1 2',['m n','p q']])
1262 >>> qw(['a b','1 2',['m n','p q']])
1263 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1263 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1264 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1264 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1265 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1265 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1266
1266
1267 if type(words) in StringTypes:
1267 if type(words) in StringTypes:
1268 return [word.strip() for word in words.split(sep,maxsplit)
1268 return [word.strip() for word in words.split(sep,maxsplit)
1269 if word and not word.isspace() ]
1269 if word and not word.isspace() ]
1270 if flat:
1270 if flat:
1271 return flatten(map(qw,words,[1]*len(words)))
1271 return flatten(map(qw,words,[1]*len(words)))
1272 return map(qw,words)
1272 return map(qw,words)
1273
1273
1274 #----------------------------------------------------------------------------
1274 #----------------------------------------------------------------------------
1275 def qwflat(words,sep=None,maxsplit=-1):
1275 def qwflat(words,sep=None,maxsplit=-1):
1276 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1276 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1277 return qw(words,1,sep,maxsplit)
1277 return qw(words,1,sep,maxsplit)
1278
1278
1279 #----------------------------------------------------------------------------
1279 #----------------------------------------------------------------------------
1280 def qw_lol(indata):
1280 def qw_lol(indata):
1281 """qw_lol('a b') -> [['a','b']],
1281 """qw_lol('a b') -> [['a','b']],
1282 otherwise it's just a call to qw().
1282 otherwise it's just a call to qw().
1283
1283
1284 We need this to make sure the modules_some keys *always* end up as a
1284 We need this to make sure the modules_some keys *always* end up as a
1285 list of lists."""
1285 list of lists."""
1286
1286
1287 if type(indata) in StringTypes:
1287 if type(indata) in StringTypes:
1288 return [qw(indata)]
1288 return [qw(indata)]
1289 else:
1289 else:
1290 return qw(indata)
1290 return qw(indata)
1291
1291
1292 #-----------------------------------------------------------------------------
1292 #-----------------------------------------------------------------------------
1293 def list_strings(arg):
1293 def list_strings(arg):
1294 """Always return a list of strings, given a string or list of strings
1294 """Always return a list of strings, given a string or list of strings
1295 as input."""
1295 as input."""
1296
1296
1297 if type(arg) in StringTypes: return [arg]
1297 if type(arg) in StringTypes: return [arg]
1298 else: return arg
1298 else: return arg
1299
1299
1300 #----------------------------------------------------------------------------
1300 #----------------------------------------------------------------------------
1301 def grep(pat,list,case=1):
1301 def grep(pat,list,case=1):
1302 """Simple minded grep-like function.
1302 """Simple minded grep-like function.
1303 grep(pat,list) returns occurrences of pat in list, None on failure.
1303 grep(pat,list) returns occurrences of pat in list, None on failure.
1304
1304
1305 It only does simple string matching, with no support for regexps. Use the
1305 It only does simple string matching, with no support for regexps. Use the
1306 option case=0 for case-insensitive matching."""
1306 option case=0 for case-insensitive matching."""
1307
1307
1308 # This is pretty crude. At least it should implement copying only references
1308 # This is pretty crude. At least it should implement copying only references
1309 # to the original data in case it's big. Now it copies the data for output.
1309 # to the original data in case it's big. Now it copies the data for output.
1310 out=[]
1310 out=[]
1311 if case:
1311 if case:
1312 for term in list:
1312 for term in list:
1313 if term.find(pat)>-1: out.append(term)
1313 if term.find(pat)>-1: out.append(term)
1314 else:
1314 else:
1315 lpat=pat.lower()
1315 lpat=pat.lower()
1316 for term in list:
1316 for term in list:
1317 if term.lower().find(lpat)>-1: out.append(term)
1317 if term.lower().find(lpat)>-1: out.append(term)
1318
1318
1319 if len(out): return out
1319 if len(out): return out
1320 else: return None
1320 else: return None
1321
1321
1322 #----------------------------------------------------------------------------
1322 #----------------------------------------------------------------------------
1323 def dgrep(pat,*opts):
1323 def dgrep(pat,*opts):
1324 """Return grep() on dir()+dir(__builtins__).
1324 """Return grep() on dir()+dir(__builtins__).
1325
1325
1326 A very common use of grep() when working interactively."""
1326 A very common use of grep() when working interactively."""
1327
1327
1328 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1328 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1329
1329
1330 #----------------------------------------------------------------------------
1330 #----------------------------------------------------------------------------
1331 def idgrep(pat):
1331 def idgrep(pat):
1332 """Case-insensitive dgrep()"""
1332 """Case-insensitive dgrep()"""
1333
1333
1334 return dgrep(pat,0)
1334 return dgrep(pat,0)
1335
1335
1336 #----------------------------------------------------------------------------
1336 #----------------------------------------------------------------------------
1337 def igrep(pat,list):
1337 def igrep(pat,list):
1338 """Synonym for case-insensitive grep."""
1338 """Synonym for case-insensitive grep."""
1339
1339
1340 return grep(pat,list,case=0)
1340 return grep(pat,list,case=0)
1341
1341
1342 #----------------------------------------------------------------------------
1342 #----------------------------------------------------------------------------
1343 def indent(str,nspaces=4,ntabs=0):
1343 def indent(str,nspaces=4,ntabs=0):
1344 """Indent a string a given number of spaces or tabstops.
1344 """Indent a string a given number of spaces or tabstops.
1345
1345
1346 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1346 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1347 """
1347 """
1348 if str is None:
1348 if str is None:
1349 return
1349 return
1350 ind = '\t'*ntabs+' '*nspaces
1350 ind = '\t'*ntabs+' '*nspaces
1351 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1351 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1352 if outstr.endswith(os.linesep+ind):
1352 if outstr.endswith(os.linesep+ind):
1353 return outstr[:-len(ind)]
1353 return outstr[:-len(ind)]
1354 else:
1354 else:
1355 return outstr
1355 return outstr
1356
1356
1357 #-----------------------------------------------------------------------------
1357 #-----------------------------------------------------------------------------
1358 def native_line_ends(filename,backup=1):
1358 def native_line_ends(filename,backup=1):
1359 """Convert (in-place) a file to line-ends native to the current OS.
1359 """Convert (in-place) a file to line-ends native to the current OS.
1360
1360
1361 If the optional backup argument is given as false, no backup of the
1361 If the optional backup argument is given as false, no backup of the
1362 original file is left. """
1362 original file is left. """
1363
1363
1364 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1364 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1365
1365
1366 bak_filename = filename + backup_suffixes[os.name]
1366 bak_filename = filename + backup_suffixes[os.name]
1367
1367
1368 original = open(filename).read()
1368 original = open(filename).read()
1369 shutil.copy2(filename,bak_filename)
1369 shutil.copy2(filename,bak_filename)
1370 try:
1370 try:
1371 new = open(filename,'wb')
1371 new = open(filename,'wb')
1372 new.write(os.linesep.join(original.splitlines()))
1372 new.write(os.linesep.join(original.splitlines()))
1373 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1373 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1374 new.close()
1374 new.close()
1375 except:
1375 except:
1376 os.rename(bak_filename,filename)
1376 os.rename(bak_filename,filename)
1377 if not backup:
1377 if not backup:
1378 try:
1378 try:
1379 os.remove(bak_filename)
1379 os.remove(bak_filename)
1380 except:
1380 except:
1381 pass
1381 pass
1382
1382
1383 #----------------------------------------------------------------------------
1383 #----------------------------------------------------------------------------
1384 def get_pager_cmd(pager_cmd = None):
1384 def get_pager_cmd(pager_cmd = None):
1385 """Return a pager command.
1385 """Return a pager command.
1386
1386
1387 Makes some attempts at finding an OS-correct one."""
1387 Makes some attempts at finding an OS-correct one."""
1388
1388
1389 if os.name == 'posix':
1389 if os.name == 'posix':
1390 default_pager_cmd = 'less -r' # -r for color control sequences
1390 default_pager_cmd = 'less -r' # -r for color control sequences
1391 elif os.name in ['nt','dos']:
1391 elif os.name in ['nt','dos']:
1392 default_pager_cmd = 'type'
1392 default_pager_cmd = 'type'
1393
1393
1394 if pager_cmd is None:
1394 if pager_cmd is None:
1395 try:
1395 try:
1396 pager_cmd = os.environ['PAGER']
1396 pager_cmd = os.environ['PAGER']
1397 except:
1397 except:
1398 pager_cmd = default_pager_cmd
1398 pager_cmd = default_pager_cmd
1399 return pager_cmd
1399 return pager_cmd
1400
1400
1401 #-----------------------------------------------------------------------------
1401 #-----------------------------------------------------------------------------
1402 def get_pager_start(pager,start):
1402 def get_pager_start(pager,start):
1403 """Return the string for paging files with an offset.
1403 """Return the string for paging files with an offset.
1404
1404
1405 This is the '+N' argument which less and more (under Unix) accept.
1405 This is the '+N' argument which less and more (under Unix) accept.
1406 """
1406 """
1407
1407
1408 if pager in ['less','more']:
1408 if pager in ['less','more']:
1409 if start:
1409 if start:
1410 start_string = '+' + str(start)
1410 start_string = '+' + str(start)
1411 else:
1411 else:
1412 start_string = ''
1412 start_string = ''
1413 else:
1413 else:
1414 start_string = ''
1414 start_string = ''
1415 return start_string
1415 return start_string
1416
1416
1417 #----------------------------------------------------------------------------
1417 #----------------------------------------------------------------------------
1418 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1418 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1419 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1419 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1420 import msvcrt
1420 import msvcrt
1421 def page_more():
1421 def page_more():
1422 """ Smart pausing between pages
1422 """ Smart pausing between pages
1423
1423
1424 @return: True if need print more lines, False if quit
1424 @return: True if need print more lines, False if quit
1425 """
1425 """
1426 Term.cout.write('---Return to continue, q to quit--- ')
1426 Term.cout.write('---Return to continue, q to quit--- ')
1427 ans = msvcrt.getch()
1427 ans = msvcrt.getch()
1428 if ans in ("q", "Q"):
1428 if ans in ("q", "Q"):
1429 result = False
1429 result = False
1430 else:
1430 else:
1431 result = True
1431 result = True
1432 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1432 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1433 return result
1433 return result
1434 else:
1434 else:
1435 def page_more():
1435 def page_more():
1436 ans = raw_input('---Return to continue, q to quit--- ')
1436 ans = raw_input('---Return to continue, q to quit--- ')
1437 if ans.lower().startswith('q'):
1437 if ans.lower().startswith('q'):
1438 return False
1438 return False
1439 else:
1439 else:
1440 return True
1440 return True
1441
1441
1442 esc_re = re.compile(r"(\x1b[^m]+m)")
1442 esc_re = re.compile(r"(\x1b[^m]+m)")
1443
1443
1444 def page_dumb(strng,start=0,screen_lines=25):
1444 def page_dumb(strng,start=0,screen_lines=25):
1445 """Very dumb 'pager' in Python, for when nothing else works.
1445 """Very dumb 'pager' in Python, for when nothing else works.
1446
1446
1447 Only moves forward, same interface as page(), except for pager_cmd and
1447 Only moves forward, same interface as page(), except for pager_cmd and
1448 mode."""
1448 mode."""
1449
1449
1450 out_ln = strng.splitlines()[start:]
1450 out_ln = strng.splitlines()[start:]
1451 screens = chop(out_ln,screen_lines-1)
1451 screens = chop(out_ln,screen_lines-1)
1452 if len(screens) == 1:
1452 if len(screens) == 1:
1453 print >>Term.cout, os.linesep.join(screens[0])
1453 print >>Term.cout, os.linesep.join(screens[0])
1454 else:
1454 else:
1455 last_escape = ""
1455 last_escape = ""
1456 for scr in screens[0:-1]:
1456 for scr in screens[0:-1]:
1457 hunk = os.linesep.join(scr)
1457 hunk = os.linesep.join(scr)
1458 print >>Term.cout, last_escape + hunk
1458 print >>Term.cout, last_escape + hunk
1459 if not page_more():
1459 if not page_more():
1460 return
1460 return
1461 esc_list = esc_re.findall(hunk)
1461 esc_list = esc_re.findall(hunk)
1462 if len(esc_list) > 0:
1462 if len(esc_list) > 0:
1463 last_escape = esc_list[-1]
1463 last_escape = esc_list[-1]
1464 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1464 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1465
1465
1466 #----------------------------------------------------------------------------
1466 #----------------------------------------------------------------------------
1467 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1467 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1468 """Print a string, piping through a pager after a certain length.
1468 """Print a string, piping through a pager after a certain length.
1469
1469
1470 The screen_lines parameter specifies the number of *usable* lines of your
1470 The screen_lines parameter specifies the number of *usable* lines of your
1471 terminal screen (total lines minus lines you need to reserve to show other
1471 terminal screen (total lines minus lines you need to reserve to show other
1472 information).
1472 information).
1473
1473
1474 If you set screen_lines to a number <=0, page() will try to auto-determine
1474 If you set screen_lines to a number <=0, page() will try to auto-determine
1475 your screen size and will only use up to (screen_size+screen_lines) for
1475 your screen size and will only use up to (screen_size+screen_lines) for
1476 printing, paging after that. That is, if you want auto-detection but need
1476 printing, paging after that. That is, if you want auto-detection but need
1477 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1477 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1478 auto-detection without any lines reserved simply use screen_lines = 0.
1478 auto-detection without any lines reserved simply use screen_lines = 0.
1479
1479
1480 If a string won't fit in the allowed lines, it is sent through the
1480 If a string won't fit in the allowed lines, it is sent through the
1481 specified pager command. If none given, look for PAGER in the environment,
1481 specified pager command. If none given, look for PAGER in the environment,
1482 and ultimately default to less.
1482 and ultimately default to less.
1483
1483
1484 If no system pager works, the string is sent through a 'dumb pager'
1484 If no system pager works, the string is sent through a 'dumb pager'
1485 written in python, very simplistic.
1485 written in python, very simplistic.
1486 """
1486 """
1487
1487
1488 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1488 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1489 TERM = os.environ.get('TERM','dumb')
1489 TERM = os.environ.get('TERM','dumb')
1490 if TERM in ['dumb','emacs'] and os.name != 'nt':
1490 if TERM in ['dumb','emacs'] and os.name != 'nt':
1491 print strng
1491 print strng
1492 return
1492 return
1493 # chop off the topmost part of the string we don't want to see
1493 # chop off the topmost part of the string we don't want to see
1494 str_lines = strng.split(os.linesep)[start:]
1494 str_lines = strng.split(os.linesep)[start:]
1495 str_toprint = os.linesep.join(str_lines)
1495 str_toprint = os.linesep.join(str_lines)
1496 num_newlines = len(str_lines)
1496 num_newlines = len(str_lines)
1497 len_str = len(str_toprint)
1497 len_str = len(str_toprint)
1498
1498
1499 # Dumb heuristics to guesstimate number of on-screen lines the string
1499 # Dumb heuristics to guesstimate number of on-screen lines the string
1500 # takes. Very basic, but good enough for docstrings in reasonable
1500 # takes. Very basic, but good enough for docstrings in reasonable
1501 # terminals. If someone later feels like refining it, it's not hard.
1501 # terminals. If someone later feels like refining it, it's not hard.
1502 numlines = max(num_newlines,int(len_str/80)+1)
1502 numlines = max(num_newlines,int(len_str/80)+1)
1503
1503
1504 if os.name == "nt":
1504 if os.name == "nt":
1505 screen_lines_def = get_console_size(defaulty=25)[1]
1505 screen_lines_def = get_console_size(defaulty=25)[1]
1506 else:
1506 else:
1507 screen_lines_def = 25 # default value if we can't auto-determine
1507 screen_lines_def = 25 # default value if we can't auto-determine
1508
1508
1509 # auto-determine screen size
1509 # auto-determine screen size
1510 if screen_lines <= 0:
1510 if screen_lines <= 0:
1511 if TERM=='xterm':
1511 if TERM=='xterm':
1512 try:
1512 try:
1513 import curses
1513 import curses
1514 if hasattr(curses,'initscr'):
1514 if hasattr(curses,'initscr'):
1515 use_curses = 1
1515 use_curses = 1
1516 else:
1516 else:
1517 use_curses = 0
1517 use_curses = 0
1518 except ImportError:
1518 except ImportError:
1519 use_curses = 0
1519 use_curses = 0
1520 else:
1520 else:
1521 # curses causes problems on many terminals other than xterm.
1521 # curses causes problems on many terminals other than xterm.
1522 use_curses = 0
1522 use_curses = 0
1523 if use_curses:
1523 if use_curses:
1524 scr = curses.initscr()
1524 scr = curses.initscr()
1525 screen_lines_real,screen_cols = scr.getmaxyx()
1525 screen_lines_real,screen_cols = scr.getmaxyx()
1526 curses.endwin()
1526 curses.endwin()
1527 screen_lines += screen_lines_real
1527 screen_lines += screen_lines_real
1528 #print '***Screen size:',screen_lines_real,'lines x',\
1528 #print '***Screen size:',screen_lines_real,'lines x',\
1529 #screen_cols,'columns.' # dbg
1529 #screen_cols,'columns.' # dbg
1530 else:
1530 else:
1531 screen_lines += screen_lines_def
1531 screen_lines += screen_lines_def
1532
1532
1533 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1533 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1534 if numlines <= screen_lines :
1534 if numlines <= screen_lines :
1535 #print '*** normal print' # dbg
1535 #print '*** normal print' # dbg
1536 print >>Term.cout, str_toprint
1536 print >>Term.cout, str_toprint
1537 else:
1537 else:
1538 # Try to open pager and default to internal one if that fails.
1538 # Try to open pager and default to internal one if that fails.
1539 # All failure modes are tagged as 'retval=1', to match the return
1539 # All failure modes are tagged as 'retval=1', to match the return
1540 # value of a failed system command. If any intermediate attempt
1540 # value of a failed system command. If any intermediate attempt
1541 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1541 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1542 pager_cmd = get_pager_cmd(pager_cmd)
1542 pager_cmd = get_pager_cmd(pager_cmd)
1543 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1543 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1544 if os.name == 'nt':
1544 if os.name == 'nt':
1545 if pager_cmd.startswith('type'):
1545 if pager_cmd.startswith('type'):
1546 # The default WinXP 'type' command is failing on complex strings.
1546 # The default WinXP 'type' command is failing on complex strings.
1547 retval = 1
1547 retval = 1
1548 else:
1548 else:
1549 tmpname = tempfile.mktemp('.txt')
1549 tmpname = tempfile.mktemp('.txt')
1550 tmpfile = file(tmpname,'wt')
1550 tmpfile = file(tmpname,'wt')
1551 tmpfile.write(strng)
1551 tmpfile.write(strng)
1552 tmpfile.close()
1552 tmpfile.close()
1553 cmd = "%s < %s" % (pager_cmd,tmpname)
1553 cmd = "%s < %s" % (pager_cmd,tmpname)
1554 if os.system(cmd):
1554 if os.system(cmd):
1555 retval = 1
1555 retval = 1
1556 else:
1556 else:
1557 retval = None
1557 retval = None
1558 os.remove(tmpname)
1558 os.remove(tmpname)
1559 else:
1559 else:
1560 try:
1560 try:
1561 retval = None
1561 retval = None
1562 # if I use popen4, things hang. No idea why.
1562 # if I use popen4, things hang. No idea why.
1563 #pager,shell_out = os.popen4(pager_cmd)
1563 #pager,shell_out = os.popen4(pager_cmd)
1564 pager = os.popen(pager_cmd,'w')
1564 pager = os.popen(pager_cmd,'w')
1565 pager.write(strng)
1565 pager.write(strng)
1566 pager.close()
1566 pager.close()
1567 retval = pager.close() # success returns None
1567 retval = pager.close() # success returns None
1568 except IOError,msg: # broken pipe when user quits
1568 except IOError,msg: # broken pipe when user quits
1569 if msg.args == (32,'Broken pipe'):
1569 if msg.args == (32,'Broken pipe'):
1570 retval = None
1570 retval = None
1571 else:
1571 else:
1572 retval = 1
1572 retval = 1
1573 except OSError:
1573 except OSError:
1574 # Other strange problems, sometimes seen in Win2k/cygwin
1574 # Other strange problems, sometimes seen in Win2k/cygwin
1575 retval = 1
1575 retval = 1
1576 if retval is not None:
1576 if retval is not None:
1577 page_dumb(strng,screen_lines=screen_lines)
1577 page_dumb(strng,screen_lines=screen_lines)
1578
1578
1579 #----------------------------------------------------------------------------
1579 #----------------------------------------------------------------------------
1580 def page_file(fname,start = 0, pager_cmd = None):
1580 def page_file(fname,start = 0, pager_cmd = None):
1581 """Page a file, using an optional pager command and starting line.
1581 """Page a file, using an optional pager command and starting line.
1582 """
1582 """
1583
1583
1584 pager_cmd = get_pager_cmd(pager_cmd)
1584 pager_cmd = get_pager_cmd(pager_cmd)
1585 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1585 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1586
1586
1587 try:
1587 try:
1588 if os.environ['TERM'] in ['emacs','dumb']:
1588 if os.environ['TERM'] in ['emacs','dumb']:
1589 raise EnvironmentError
1589 raise EnvironmentError
1590 xsys(pager_cmd + ' ' + fname)
1590 xsys(pager_cmd + ' ' + fname)
1591 except:
1591 except:
1592 try:
1592 try:
1593 if start > 0:
1593 if start > 0:
1594 start -= 1
1594 start -= 1
1595 page(open(fname).read(),start)
1595 page(open(fname).read(),start)
1596 except:
1596 except:
1597 print 'Unable to show file',`fname`
1597 print 'Unable to show file',`fname`
1598
1598
1599 #----------------------------------------------------------------------------
1599 #----------------------------------------------------------------------------
1600 def snip_print(str,width = 75,print_full = 0,header = ''):
1600 def snip_print(str,width = 75,print_full = 0,header = ''):
1601 """Print a string snipping the midsection to fit in width.
1601 """Print a string snipping the midsection to fit in width.
1602
1602
1603 print_full: mode control:
1603 print_full: mode control:
1604 - 0: only snip long strings
1604 - 0: only snip long strings
1605 - 1: send to page() directly.
1605 - 1: send to page() directly.
1606 - 2: snip long strings and ask for full length viewing with page()
1606 - 2: snip long strings and ask for full length viewing with page()
1607 Return 1 if snipping was necessary, 0 otherwise."""
1607 Return 1 if snipping was necessary, 0 otherwise."""
1608
1608
1609 if print_full == 1:
1609 if print_full == 1:
1610 page(header+str)
1610 page(header+str)
1611 return 0
1611 return 0
1612
1612
1613 print header,
1613 print header,
1614 if len(str) < width:
1614 if len(str) < width:
1615 print str
1615 print str
1616 snip = 0
1616 snip = 0
1617 else:
1617 else:
1618 whalf = int((width -5)/2)
1618 whalf = int((width -5)/2)
1619 print str[:whalf] + ' <...> ' + str[-whalf:]
1619 print str[:whalf] + ' <...> ' + str[-whalf:]
1620 snip = 1
1620 snip = 1
1621 if snip and print_full == 2:
1621 if snip and print_full == 2:
1622 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1622 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1623 page(str)
1623 page(str)
1624 return snip
1624 return snip
1625
1625
1626 #****************************************************************************
1626 #****************************************************************************
1627 # lists, dicts and structures
1627 # lists, dicts and structures
1628
1628
1629 def belong(candidates,checklist):
1629 def belong(candidates,checklist):
1630 """Check whether a list of items appear in a given list of options.
1630 """Check whether a list of items appear in a given list of options.
1631
1631
1632 Returns a list of 1 and 0, one for each candidate given."""
1632 Returns a list of 1 and 0, one for each candidate given."""
1633
1633
1634 return [x in checklist for x in candidates]
1634 return [x in checklist for x in candidates]
1635
1635
1636 #----------------------------------------------------------------------------
1636 #----------------------------------------------------------------------------
1637 def uniq_stable(elems):
1637 def uniq_stable(elems):
1638 """uniq_stable(elems) -> list
1638 """uniq_stable(elems) -> list
1639
1639
1640 Return from an iterable, a list of all the unique elements in the input,
1640 Return from an iterable, a list of all the unique elements in the input,
1641 but maintaining the order in which they first appear.
1641 but maintaining the order in which they first appear.
1642
1642
1643 A naive solution to this problem which just makes a dictionary with the
1643 A naive solution to this problem which just makes a dictionary with the
1644 elements as keys fails to respect the stability condition, since
1644 elements as keys fails to respect the stability condition, since
1645 dictionaries are unsorted by nature.
1645 dictionaries are unsorted by nature.
1646
1646
1647 Note: All elements in the input must be valid dictionary keys for this
1647 Note: All elements in the input must be valid dictionary keys for this
1648 routine to work, as it internally uses a dictionary for efficiency
1648 routine to work, as it internally uses a dictionary for efficiency
1649 reasons."""
1649 reasons."""
1650
1650
1651 unique = []
1651 unique = []
1652 unique_dict = {}
1652 unique_dict = {}
1653 for nn in elems:
1653 for nn in elems:
1654 if nn not in unique_dict:
1654 if nn not in unique_dict:
1655 unique.append(nn)
1655 unique.append(nn)
1656 unique_dict[nn] = None
1656 unique_dict[nn] = None
1657 return unique
1657 return unique
1658
1658
1659 #----------------------------------------------------------------------------
1659 #----------------------------------------------------------------------------
1660 class NLprinter:
1660 class NLprinter:
1661 """Print an arbitrarily nested list, indicating index numbers.
1661 """Print an arbitrarily nested list, indicating index numbers.
1662
1662
1663 An instance of this class called nlprint is available and callable as a
1663 An instance of this class called nlprint is available and callable as a
1664 function.
1664 function.
1665
1665
1666 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1666 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1667 and using 'sep' to separate the index from the value. """
1667 and using 'sep' to separate the index from the value. """
1668
1668
1669 def __init__(self):
1669 def __init__(self):
1670 self.depth = 0
1670 self.depth = 0
1671
1671
1672 def __call__(self,lst,pos='',**kw):
1672 def __call__(self,lst,pos='',**kw):
1673 """Prints the nested list numbering levels."""
1673 """Prints the nested list numbering levels."""
1674 kw.setdefault('indent',' ')
1674 kw.setdefault('indent',' ')
1675 kw.setdefault('sep',': ')
1675 kw.setdefault('sep',': ')
1676 kw.setdefault('start',0)
1676 kw.setdefault('start',0)
1677 kw.setdefault('stop',len(lst))
1677 kw.setdefault('stop',len(lst))
1678 # we need to remove start and stop from kw so they don't propagate
1678 # we need to remove start and stop from kw so they don't propagate
1679 # into a recursive call for a nested list.
1679 # into a recursive call for a nested list.
1680 start = kw['start']; del kw['start']
1680 start = kw['start']; del kw['start']
1681 stop = kw['stop']; del kw['stop']
1681 stop = kw['stop']; del kw['stop']
1682 if self.depth == 0 and 'header' in kw.keys():
1682 if self.depth == 0 and 'header' in kw.keys():
1683 print kw['header']
1683 print kw['header']
1684
1684
1685 for idx in range(start,stop):
1685 for idx in range(start,stop):
1686 elem = lst[idx]
1686 elem = lst[idx]
1687 if type(elem)==type([]):
1687 if type(elem)==type([]):
1688 self.depth += 1
1688 self.depth += 1
1689 self.__call__(elem,itpl('$pos$idx,'),**kw)
1689 self.__call__(elem,itpl('$pos$idx,'),**kw)
1690 self.depth -= 1
1690 self.depth -= 1
1691 else:
1691 else:
1692 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1692 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1693
1693
1694 nlprint = NLprinter()
1694 nlprint = NLprinter()
1695 #----------------------------------------------------------------------------
1695 #----------------------------------------------------------------------------
1696 def all_belong(candidates,checklist):
1696 def all_belong(candidates,checklist):
1697 """Check whether a list of items ALL appear in a given list of options.
1697 """Check whether a list of items ALL appear in a given list of options.
1698
1698
1699 Returns a single 1 or 0 value."""
1699 Returns a single 1 or 0 value."""
1700
1700
1701 return 1-(0 in [x in checklist for x in candidates])
1701 return 1-(0 in [x in checklist for x in candidates])
1702
1702
1703 #----------------------------------------------------------------------------
1703 #----------------------------------------------------------------------------
1704 def sort_compare(lst1,lst2,inplace = 1):
1704 def sort_compare(lst1,lst2,inplace = 1):
1705 """Sort and compare two lists.
1705 """Sort and compare two lists.
1706
1706
1707 By default it does it in place, thus modifying the lists. Use inplace = 0
1707 By default it does it in place, thus modifying the lists. Use inplace = 0
1708 to avoid that (at the cost of temporary copy creation)."""
1708 to avoid that (at the cost of temporary copy creation)."""
1709 if not inplace:
1709 if not inplace:
1710 lst1 = lst1[:]
1710 lst1 = lst1[:]
1711 lst2 = lst2[:]
1711 lst2 = lst2[:]
1712 lst1.sort(); lst2.sort()
1712 lst1.sort(); lst2.sort()
1713 return lst1 == lst2
1713 return lst1 == lst2
1714
1714
1715 #----------------------------------------------------------------------------
1715 #----------------------------------------------------------------------------
1716 def mkdict(**kwargs):
1716 def mkdict(**kwargs):
1717 """Return a dict from a keyword list.
1717 """Return a dict from a keyword list.
1718
1718
1719 It's just syntactic sugar for making ditcionary creation more convenient:
1719 It's just syntactic sugar for making ditcionary creation more convenient:
1720 # the standard way
1720 # the standard way
1721 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1721 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1722 # a cleaner way
1722 # a cleaner way
1723 >>>data = dict(red=1, green=2, blue=3)
1723 >>>data = dict(red=1, green=2, blue=3)
1724
1724
1725 If you need more than this, look at the Struct() class."""
1725 If you need more than this, look at the Struct() class."""
1726
1726
1727 return kwargs
1727 return kwargs
1728
1728
1729 #----------------------------------------------------------------------------
1729 #----------------------------------------------------------------------------
1730 def list2dict(lst):
1730 def list2dict(lst):
1731 """Takes a list of (key,value) pairs and turns it into a dict."""
1731 """Takes a list of (key,value) pairs and turns it into a dict."""
1732
1732
1733 dic = {}
1733 dic = {}
1734 for k,v in lst: dic[k] = v
1734 for k,v in lst: dic[k] = v
1735 return dic
1735 return dic
1736
1736
1737 #----------------------------------------------------------------------------
1737 #----------------------------------------------------------------------------
1738 def list2dict2(lst,default=''):
1738 def list2dict2(lst,default=''):
1739 """Takes a list and turns it into a dict.
1739 """Takes a list and turns it into a dict.
1740 Much slower than list2dict, but more versatile. This version can take
1740 Much slower than list2dict, but more versatile. This version can take
1741 lists with sublists of arbitrary length (including sclars)."""
1741 lists with sublists of arbitrary length (including sclars)."""
1742
1742
1743 dic = {}
1743 dic = {}
1744 for elem in lst:
1744 for elem in lst:
1745 if type(elem) in (types.ListType,types.TupleType):
1745 if type(elem) in (types.ListType,types.TupleType):
1746 size = len(elem)
1746 size = len(elem)
1747 if size == 0:
1747 if size == 0:
1748 pass
1748 pass
1749 elif size == 1:
1749 elif size == 1:
1750 dic[elem] = default
1750 dic[elem] = default
1751 else:
1751 else:
1752 k,v = elem[0], elem[1:]
1752 k,v = elem[0], elem[1:]
1753 if len(v) == 1: v = v[0]
1753 if len(v) == 1: v = v[0]
1754 dic[k] = v
1754 dic[k] = v
1755 else:
1755 else:
1756 dic[elem] = default
1756 dic[elem] = default
1757 return dic
1757 return dic
1758
1758
1759 #----------------------------------------------------------------------------
1759 #----------------------------------------------------------------------------
1760 def flatten(seq):
1760 def flatten(seq):
1761 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1761 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1762
1762
1763 return [x for subseq in seq for x in subseq]
1763 return [x for subseq in seq for x in subseq]
1764
1764
1765 #----------------------------------------------------------------------------
1765 #----------------------------------------------------------------------------
1766 def get_slice(seq,start=0,stop=None,step=1):
1766 def get_slice(seq,start=0,stop=None,step=1):
1767 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1767 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1768 if stop == None:
1768 if stop == None:
1769 stop = len(seq)
1769 stop = len(seq)
1770 item = lambda i: seq[i]
1770 item = lambda i: seq[i]
1771 return map(item,xrange(start,stop,step))
1771 return map(item,xrange(start,stop,step))
1772
1772
1773 #----------------------------------------------------------------------------
1773 #----------------------------------------------------------------------------
1774 def chop(seq,size):
1774 def chop(seq,size):
1775 """Chop a sequence into chunks of the given size."""
1775 """Chop a sequence into chunks of the given size."""
1776 chunk = lambda i: seq[i:i+size]
1776 chunk = lambda i: seq[i:i+size]
1777 return map(chunk,xrange(0,len(seq),size))
1777 return map(chunk,xrange(0,len(seq),size))
1778
1778
1779 #----------------------------------------------------------------------------
1779 #----------------------------------------------------------------------------
1780 # with is a keyword as of python 2.5, so this function is renamed to withobj
1780 # with is a keyword as of python 2.5, so this function is renamed to withobj
1781 # from its old 'with' name.
1781 # from its old 'with' name.
1782 def with_obj(object, **args):
1782 def with_obj(object, **args):
1783 """Set multiple attributes for an object, similar to Pascal's with.
1783 """Set multiple attributes for an object, similar to Pascal's with.
1784
1784
1785 Example:
1785 Example:
1786 with_obj(jim,
1786 with_obj(jim,
1787 born = 1960,
1787 born = 1960,
1788 haircolour = 'Brown',
1788 haircolour = 'Brown',
1789 eyecolour = 'Green')
1789 eyecolour = 'Green')
1790
1790
1791 Credit: Greg Ewing, in
1791 Credit: Greg Ewing, in
1792 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1792 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1793
1793
1794 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1794 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1795 has become a keyword for Python 2.5, so we had to rename it."""
1795 has become a keyword for Python 2.5, so we had to rename it."""
1796
1796
1797 object.__dict__.update(args)
1797 object.__dict__.update(args)
1798
1798
1799 #----------------------------------------------------------------------------
1799 #----------------------------------------------------------------------------
1800 def setattr_list(obj,alist,nspace = None):
1800 def setattr_list(obj,alist,nspace = None):
1801 """Set a list of attributes for an object taken from a namespace.
1801 """Set a list of attributes for an object taken from a namespace.
1802
1802
1803 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1803 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1804 alist with their values taken from nspace, which must be a dict (something
1804 alist with their values taken from nspace, which must be a dict (something
1805 like locals() will often do) If nspace isn't given, locals() of the
1805 like locals() will often do) If nspace isn't given, locals() of the
1806 *caller* is used, so in most cases you can omit it.
1806 *caller* is used, so in most cases you can omit it.
1807
1807
1808 Note that alist can be given as a string, which will be automatically
1808 Note that alist can be given as a string, which will be automatically
1809 split into a list on whitespace. If given as a list, it must be a list of
1809 split into a list on whitespace. If given as a list, it must be a list of
1810 *strings* (the variable names themselves), not of variables."""
1810 *strings* (the variable names themselves), not of variables."""
1811
1811
1812 # this grabs the local variables from the *previous* call frame -- that is
1812 # this grabs the local variables from the *previous* call frame -- that is
1813 # the locals from the function that called setattr_list().
1813 # the locals from the function that called setattr_list().
1814 # - snipped from weave.inline()
1814 # - snipped from weave.inline()
1815 if nspace is None:
1815 if nspace is None:
1816 call_frame = sys._getframe().f_back
1816 call_frame = sys._getframe().f_back
1817 nspace = call_frame.f_locals
1817 nspace = call_frame.f_locals
1818
1818
1819 if type(alist) in StringTypes:
1819 if type(alist) in StringTypes:
1820 alist = alist.split()
1820 alist = alist.split()
1821 for attr in alist:
1821 for attr in alist:
1822 val = eval(attr,nspace)
1822 val = eval(attr,nspace)
1823 setattr(obj,attr,val)
1823 setattr(obj,attr,val)
1824
1824
1825 #----------------------------------------------------------------------------
1825 #----------------------------------------------------------------------------
1826 def getattr_list(obj,alist,*args):
1826 def getattr_list(obj,alist,*args):
1827 """getattr_list(obj,alist[, default]) -> attribute list.
1827 """getattr_list(obj,alist[, default]) -> attribute list.
1828
1828
1829 Get a list of named attributes for an object. When a default argument is
1829 Get a list of named attributes for an object. When a default argument is
1830 given, it is returned when the attribute doesn't exist; without it, an
1830 given, it is returned when the attribute doesn't exist; without it, an
1831 exception is raised in that case.
1831 exception is raised in that case.
1832
1832
1833 Note that alist can be given as a string, which will be automatically
1833 Note that alist can be given as a string, which will be automatically
1834 split into a list on whitespace. If given as a list, it must be a list of
1834 split into a list on whitespace. If given as a list, it must be a list of
1835 *strings* (the variable names themselves), not of variables."""
1835 *strings* (the variable names themselves), not of variables."""
1836
1836
1837 if type(alist) in StringTypes:
1837 if type(alist) in StringTypes:
1838 alist = alist.split()
1838 alist = alist.split()
1839 if args:
1839 if args:
1840 if len(args)==1:
1840 if len(args)==1:
1841 default = args[0]
1841 default = args[0]
1842 return map(lambda attr: getattr(obj,attr,default),alist)
1842 return map(lambda attr: getattr(obj,attr,default),alist)
1843 else:
1843 else:
1844 raise ValueError,'getattr_list() takes only one optional argument'
1844 raise ValueError,'getattr_list() takes only one optional argument'
1845 else:
1845 else:
1846 return map(lambda attr: getattr(obj,attr),alist)
1846 return map(lambda attr: getattr(obj,attr),alist)
1847
1847
1848 #----------------------------------------------------------------------------
1848 #----------------------------------------------------------------------------
1849 def map_method(method,object_list,*argseq,**kw):
1849 def map_method(method,object_list,*argseq,**kw):
1850 """map_method(method,object_list,*args,**kw) -> list
1850 """map_method(method,object_list,*args,**kw) -> list
1851
1851
1852 Return a list of the results of applying the methods to the items of the
1852 Return a list of the results of applying the methods to the items of the
1853 argument sequence(s). If more than one sequence is given, the method is
1853 argument sequence(s). If more than one sequence is given, the method is
1854 called with an argument list consisting of the corresponding item of each
1854 called with an argument list consisting of the corresponding item of each
1855 sequence. All sequences must be of the same length.
1855 sequence. All sequences must be of the same length.
1856
1856
1857 Keyword arguments are passed verbatim to all objects called.
1857 Keyword arguments are passed verbatim to all objects called.
1858
1858
1859 This is Python code, so it's not nearly as fast as the builtin map()."""
1859 This is Python code, so it's not nearly as fast as the builtin map()."""
1860
1860
1861 out_list = []
1861 out_list = []
1862 idx = 0
1862 idx = 0
1863 for object in object_list:
1863 for object in object_list:
1864 try:
1864 try:
1865 handler = getattr(object, method)
1865 handler = getattr(object, method)
1866 except AttributeError:
1866 except AttributeError:
1867 out_list.append(None)
1867 out_list.append(None)
1868 else:
1868 else:
1869 if argseq:
1869 if argseq:
1870 args = map(lambda lst:lst[idx],argseq)
1870 args = map(lambda lst:lst[idx],argseq)
1871 #print 'ob',object,'hand',handler,'ar',args # dbg
1871 #print 'ob',object,'hand',handler,'ar',args # dbg
1872 out_list.append(handler(args,**kw))
1872 out_list.append(handler(args,**kw))
1873 else:
1873 else:
1874 out_list.append(handler(**kw))
1874 out_list.append(handler(**kw))
1875 idx += 1
1875 idx += 1
1876 return out_list
1876 return out_list
1877
1877
1878 #----------------------------------------------------------------------------
1878 #----------------------------------------------------------------------------
1879 def get_class_members(cls):
1879 def get_class_members(cls):
1880 ret = dir(cls)
1880 ret = dir(cls)
1881 if hasattr(cls,'__bases__'):
1881 if hasattr(cls,'__bases__'):
1882 for base in cls.__bases__:
1882 for base in cls.__bases__:
1883 ret.extend(get_class_members(base))
1883 ret.extend(get_class_members(base))
1884 return ret
1884 return ret
1885
1885
1886 #----------------------------------------------------------------------------
1886 #----------------------------------------------------------------------------
1887 def dir2(obj):
1887 def dir2(obj):
1888 """dir2(obj) -> list of strings
1888 """dir2(obj) -> list of strings
1889
1889
1890 Extended version of the Python builtin dir(), which does a few extra
1890 Extended version of the Python builtin dir(), which does a few extra
1891 checks, and supports common objects with unusual internals that confuse
1891 checks, and supports common objects with unusual internals that confuse
1892 dir(), such as Traits and PyCrust.
1892 dir(), such as Traits and PyCrust.
1893
1893
1894 This version is guaranteed to return only a list of true strings, whereas
1894 This version is guaranteed to return only a list of true strings, whereas
1895 dir() returns anything that objects inject into themselves, even if they
1895 dir() returns anything that objects inject into themselves, even if they
1896 are later not really valid for attribute access (many extension libraries
1896 are later not really valid for attribute access (many extension libraries
1897 have such bugs).
1897 have such bugs).
1898 """
1898 """
1899
1899
1900 # Start building the attribute list via dir(), and then complete it
1900 # Start building the attribute list via dir(), and then complete it
1901 # with a few extra special-purpose calls.
1901 # with a few extra special-purpose calls.
1902 words = dir(obj)
1902 words = dir(obj)
1903
1903
1904 if hasattr(obj,'__class__'):
1904 if hasattr(obj,'__class__'):
1905 words.append('__class__')
1905 words.append('__class__')
1906 words.extend(get_class_members(obj.__class__))
1906 words.extend(get_class_members(obj.__class__))
1907 #if '__base__' in words: 1/0
1907 #if '__base__' in words: 1/0
1908
1908
1909 # Some libraries (such as traits) may introduce duplicates, we want to
1909 # Some libraries (such as traits) may introduce duplicates, we want to
1910 # track and clean this up if it happens
1910 # track and clean this up if it happens
1911 may_have_dupes = False
1911 may_have_dupes = False
1912
1912
1913 # this is the 'dir' function for objects with Enthought's traits
1913 # this is the 'dir' function for objects with Enthought's traits
1914 if hasattr(obj, 'trait_names'):
1914 if hasattr(obj, 'trait_names'):
1915 try:
1915 try:
1916 words.extend(obj.trait_names())
1916 words.extend(obj.trait_names())
1917 may_have_dupes = True
1917 may_have_dupes = True
1918 except TypeError:
1918 except TypeError:
1919 # This will happen if `obj` is a class and not an instance.
1919 # This will happen if `obj` is a class and not an instance.
1920 pass
1920 pass
1921
1921
1922 # Support for PyCrust-style _getAttributeNames magic method.
1922 # Support for PyCrust-style _getAttributeNames magic method.
1923 if hasattr(obj, '_getAttributeNames'):
1923 if hasattr(obj, '_getAttributeNames'):
1924 try:
1924 try:
1925 words.extend(obj._getAttributeNames())
1925 words.extend(obj._getAttributeNames())
1926 may_have_dupes = True
1926 may_have_dupes = True
1927 except TypeError:
1927 except TypeError:
1928 # `obj` is a class and not an instance. Ignore
1928 # `obj` is a class and not an instance. Ignore
1929 # this error.
1929 # this error.
1930 pass
1930 pass
1931
1931
1932 if may_have_dupes:
1932 if may_have_dupes:
1933 # eliminate possible duplicates, as some traits may also
1933 # eliminate possible duplicates, as some traits may also
1934 # appear as normal attributes in the dir() call.
1934 # appear as normal attributes in the dir() call.
1935 words = list(set(words))
1935 words = list(set(words))
1936 words.sort()
1936 words.sort()
1937
1937
1938 # filter out non-string attributes which may be stuffed by dir() calls
1938 # filter out non-string attributes which may be stuffed by dir() calls
1939 # and poor coding in third-party modules
1939 # and poor coding in third-party modules
1940 return [w for w in words if isinstance(w, basestring)]
1940 return [w for w in words if isinstance(w, basestring)]
1941
1941
1942 #----------------------------------------------------------------------------
1942 #----------------------------------------------------------------------------
1943 def import_fail_info(mod_name,fns=None):
1943 def import_fail_info(mod_name,fns=None):
1944 """Inform load failure for a module."""
1944 """Inform load failure for a module."""
1945
1945
1946 if fns == None:
1946 if fns == None:
1947 warn("Loading of %s failed.\n" % (mod_name,))
1947 warn("Loading of %s failed.\n" % (mod_name,))
1948 else:
1948 else:
1949 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1949 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1950
1950
1951 #----------------------------------------------------------------------------
1951 #----------------------------------------------------------------------------
1952 # Proposed popitem() extension, written as a method
1952 # Proposed popitem() extension, written as a method
1953
1953
1954
1954
1955 class NotGiven: pass
1955 class NotGiven: pass
1956
1956
1957 def popkey(dct,key,default=NotGiven):
1957 def popkey(dct,key,default=NotGiven):
1958 """Return dct[key] and delete dct[key].
1958 """Return dct[key] and delete dct[key].
1959
1959
1960 If default is given, return it if dct[key] doesn't exist, otherwise raise
1960 If default is given, return it if dct[key] doesn't exist, otherwise raise
1961 KeyError. """
1961 KeyError. """
1962
1962
1963 try:
1963 try:
1964 val = dct[key]
1964 val = dct[key]
1965 except KeyError:
1965 except KeyError:
1966 if default is NotGiven:
1966 if default is NotGiven:
1967 raise
1967 raise
1968 else:
1968 else:
1969 return default
1969 return default
1970 else:
1970 else:
1971 del dct[key]
1971 del dct[key]
1972 return val
1972 return val
1973
1973
1974 def wrap_deprecated(func, suggest = '<nothing>'):
1974 def wrap_deprecated(func, suggest = '<nothing>'):
1975 def newFunc(*args, **kwargs):
1975 def newFunc(*args, **kwargs):
1976 warnings.warn("Call to deprecated function %s, use %s instead" %
1976 warnings.warn("Call to deprecated function %s, use %s instead" %
1977 ( func.__name__, suggest),
1977 ( func.__name__, suggest),
1978 category=DeprecationWarning,
1978 category=DeprecationWarning,
1979 stacklevel = 2)
1979 stacklevel = 2)
1980 return func(*args, **kwargs)
1980 return func(*args, **kwargs)
1981 return newFunc
1981 return newFunc
1982
1982
1983 #*************************** end of file <genutils.py> **********************
1983 #*************************** end of file <genutils.py> **********************
1984
1984
@@ -1,763 +1,763 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 Requires Python 2.1 or better.
5 Requires Python 2.1 or better.
6
6
7 This file contains the main make_IPython() starter function.
7 This file contains the main make_IPython() starter function.
8
8
9 $Id: ipmaker.py 2723 2007-09-07 07:44:16Z fperez $"""
9 $Id: ipmaker.py 2872 2007-11-25 17:58:05Z fperez $"""
10
10
11 #*****************************************************************************
11 #*****************************************************************************
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #*****************************************************************************
16 #*****************************************************************************
17
17
18 from IPython import Release
18 from IPython import Release
19 __author__ = '%s <%s>' % Release.authors['Fernando']
19 __author__ = '%s <%s>' % Release.authors['Fernando']
20 __license__ = Release.license
20 __license__ = Release.license
21 __version__ = Release.version
21 __version__ = Release.version
22
22
23 try:
23 try:
24 credits._Printer__data = """
24 credits._Printer__data = """
25 Python: %s
25 Python: %s
26
26
27 IPython: Fernando Perez, Janko Hauser, Nathan Gray, and many users.
27 IPython: Fernando Perez, Janko Hauser, Nathan Gray, and many users.
28 See http://ipython.scipy.org for more information.""" \
28 See http://ipython.scipy.org for more information.""" \
29 % credits._Printer__data
29 % credits._Printer__data
30
30
31 copyright._Printer__data += """
31 copyright._Printer__data += """
32
32
33 Copyright (c) 2001-2004 Fernando Perez, Janko Hauser, Nathan Gray.
33 Copyright (c) 2001-2004 Fernando Perez, Janko Hauser, Nathan Gray.
34 All Rights Reserved."""
34 All Rights Reserved."""
35 except NameError:
35 except NameError:
36 # Can happen if ipython was started with 'python -S', so that site.py is
36 # Can happen if ipython was started with 'python -S', so that site.py is
37 # not loaded
37 # not loaded
38 pass
38 pass
39
39
40 #****************************************************************************
40 #****************************************************************************
41 # Required modules
41 # Required modules
42
42
43 # From the standard library
43 # From the standard library
44 import __main__
44 import __main__
45 import __builtin__
45 import __builtin__
46 import os
46 import os
47 import re
47 import re
48 import sys
48 import sys
49 import types
49 import types
50 from pprint import pprint,pformat
50 from pprint import pprint,pformat
51
51
52 # Our own
52 # Our own
53 from IPython import DPyGetOpt
53 from IPython import DPyGetOpt
54 from IPython.ipstruct import Struct
54 from IPython.ipstruct import Struct
55 from IPython.OutputTrap import OutputTrap
55 from IPython.OutputTrap import OutputTrap
56 from IPython.ConfigLoader import ConfigLoader
56 from IPython.ConfigLoader import ConfigLoader
57 from IPython.iplib import InteractiveShell
57 from IPython.iplib import InteractiveShell
58 from IPython.usage import cmd_line_usage,interactive_usage
58 from IPython.usage import cmd_line_usage,interactive_usage
59 from IPython.genutils import *
59 from IPython.genutils import *
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
62 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
63 rc_override=None,shell_class=InteractiveShell,
63 rc_override=None,shell_class=InteractiveShell,
64 embedded=False,**kw):
64 embedded=False,**kw):
65 """This is a dump of IPython into a single function.
65 """This is a dump of IPython into a single function.
66
66
67 Later it will have to be broken up in a sensible manner.
67 Later it will have to be broken up in a sensible manner.
68
68
69 Arguments:
69 Arguments:
70
70
71 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
71 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
72 script name, b/c DPyGetOpt strips the first argument only for the real
72 script name, b/c DPyGetOpt strips the first argument only for the real
73 sys.argv.
73 sys.argv.
74
74
75 - user_ns: a dict to be used as the user's namespace."""
75 - user_ns: a dict to be used as the user's namespace."""
76
76
77 #----------------------------------------------------------------------
77 #----------------------------------------------------------------------
78 # Defaults and initialization
78 # Defaults and initialization
79
79
80 # For developer debugging, deactivates crash handler and uses pdb.
80 # For developer debugging, deactivates crash handler and uses pdb.
81 DEVDEBUG = False
81 DEVDEBUG = False
82
82
83 if argv is None:
83 if argv is None:
84 argv = sys.argv
84 argv = sys.argv
85
85
86 # __IP is the main global that lives throughout and represents the whole
86 # __IP is the main global that lives throughout and represents the whole
87 # application. If the user redefines it, all bets are off as to what
87 # application. If the user redefines it, all bets are off as to what
88 # happens.
88 # happens.
89
89
90 # __IP is the name of he global which the caller will have accessible as
90 # __IP is the name of he global which the caller will have accessible as
91 # __IP.name. We set its name via the first parameter passed to
91 # __IP.name. We set its name via the first parameter passed to
92 # InteractiveShell:
92 # InteractiveShell:
93
93
94 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
94 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
95 embedded=embedded,**kw)
95 embedded=embedded,**kw)
96
96
97 # Put 'help' in the user namespace
97 # Put 'help' in the user namespace
98 from site import _Helper
98 from site import _Helper
99 IP.user_config_ns = {}
99 IP.user_config_ns = {}
100 IP.user_ns['help'] = _Helper()
100 IP.user_ns['help'] = _Helper()
101
101
102
102
103 if DEVDEBUG:
103 if DEVDEBUG:
104 # For developer debugging only (global flag)
104 # For developer debugging only (global flag)
105 from IPython import ultraTB
105 from IPython import ultraTB
106 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
106 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
107
107
108 IP.BANNER_PARTS = ['Python %s\n'
108 IP.BANNER_PARTS = ['Python %s\n'
109 'Type "copyright", "credits" or "license" '
109 'Type "copyright", "credits" or "license" '
110 'for more information.\n'
110 'for more information.\n'
111 % (sys.version.split('\n')[0],),
111 % (sys.version.split('\n')[0],),
112 "IPython %s -- An enhanced Interactive Python."
112 "IPython %s -- An enhanced Interactive Python."
113 % (__version__,),
113 % (__version__,),
114 """\
114 """\
115 ? -> Introduction and overview of IPython's features.
115 ? -> Introduction and overview of IPython's features.
116 %quickref -> Quick reference.
116 %quickref -> Quick reference.
117 help -> Python's own help system.
117 help -> Python's own help system.
118 object? -> Details about 'object'. ?object also works, ?? prints more.
118 object? -> Details about 'object'. ?object also works, ?? prints more.
119 """ ]
119 """ ]
120
120
121 IP.usage = interactive_usage
121 IP.usage = interactive_usage
122
122
123 # Platform-dependent suffix and directory names. We use _ipython instead
123 # Platform-dependent suffix and directory names. We use _ipython instead
124 # of .ipython under win32 b/c there's software that breaks with .named
124 # of .ipython under win32 b/c there's software that breaks with .named
125 # directories on that platform.
125 # directories on that platform.
126 if os.name == 'posix':
126 if os.name == 'posix':
127 rc_suffix = ''
127 rc_suffix = ''
128 ipdir_def = '.ipython'
128 ipdir_def = '.ipython'
129 else:
129 else:
130 rc_suffix = '.ini'
130 rc_suffix = '.ini'
131 ipdir_def = '_ipython'
131 ipdir_def = '_ipython'
132
132
133 # default directory for configuration
133 # default directory for configuration
134 ipythondir_def = os.path.abspath(os.environ.get('IPYTHONDIR',
134 ipythondir_def = os.path.abspath(os.environ.get('IPYTHONDIR',
135 os.path.join(IP.home_dir,ipdir_def)))
135 os.path.join(IP.home_dir,ipdir_def)))
136
136
137 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
137 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
138
138
139 # we need the directory where IPython itself is installed
139 # we need the directory where IPython itself is installed
140 import IPython
140 import IPython
141 IPython_dir = os.path.dirname(IPython.__file__)
141 IPython_dir = os.path.dirname(IPython.__file__)
142 del IPython
142 del IPython
143
143
144 #-------------------------------------------------------------------------
144 #-------------------------------------------------------------------------
145 # Command line handling
145 # Command line handling
146
146
147 # Valid command line options (uses DPyGetOpt syntax, like Perl's
147 # Valid command line options (uses DPyGetOpt syntax, like Perl's
148 # GetOpt::Long)
148 # GetOpt::Long)
149
149
150 # Any key not listed here gets deleted even if in the file (like session
150 # Any key not listed here gets deleted even if in the file (like session
151 # or profile). That's deliberate, to maintain the rc namespace clean.
151 # or profile). That's deliberate, to maintain the rc namespace clean.
152
152
153 # Each set of options appears twice: under _conv only the names are
153 # Each set of options appears twice: under _conv only the names are
154 # listed, indicating which type they must be converted to when reading the
154 # listed, indicating which type they must be converted to when reading the
155 # ipythonrc file. And under DPyGetOpt they are listed with the regular
155 # ipythonrc file. And under DPyGetOpt they are listed with the regular
156 # DPyGetOpt syntax (=s,=i,:f,etc).
156 # DPyGetOpt syntax (=s,=i,:f,etc).
157
157
158 # Make sure there's a space before each end of line (they get auto-joined!)
158 # Make sure there's a space before each end of line (they get auto-joined!)
159 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
159 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
160 'c=s classic|cl color_info! colors=s confirm_exit! '
160 'c=s classic|cl color_info! colors=s confirm_exit! '
161 'debug! deep_reload! editor=s log|l messages! nosep '
161 'debug! deep_reload! editor=s log|l messages! nosep '
162 'object_info_string_level=i pdb! '
162 'object_info_string_level=i pdb! '
163 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
163 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
164 'pylab_import_all! '
164 'pylab_import_all! '
165 'quick screen_length|sl=i prompts_pad_left=i '
165 'quick screen_length|sl=i prompts_pad_left=i '
166 'logfile|lf=s logplay|lp=s profile|p=s '
166 'logfile|lf=s logplay|lp=s profile|p=s '
167 'readline! readline_merge_completions! '
167 'readline! readline_merge_completions! '
168 'readline_omit__names! '
168 'readline_omit__names! '
169 'rcfile=s separate_in|si=s separate_out|so=s '
169 'rcfile=s separate_in|si=s separate_out|so=s '
170 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
170 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
171 'magic_docstrings system_verbose! '
171 'magic_docstrings system_verbose! '
172 'multi_line_specials! '
172 'multi_line_specials! '
173 'term_title! wxversion=s '
173 'term_title! wxversion=s '
174 'autoedit_syntax!')
174 'autoedit_syntax!')
175
175
176 # Options that can *only* appear at the cmd line (not in rcfiles).
176 # Options that can *only* appear at the cmd line (not in rcfiles).
177
177
178 # The "ignore" option is a kludge so that Emacs buffers don't crash, since
178 # The "ignore" option is a kludge so that Emacs buffers don't crash, since
179 # the 'C-c !' command in emacs automatically appends a -i option at the end.
179 # the 'C-c !' command in emacs automatically appends a -i option at the end.
180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
181 'gthread! qthread! q4thread! wthread! pylab! tk!')
181 'gthread! qthread! q4thread! wthread! pylab! tk!')
182
182
183 # Build the actual name list to be used by DPyGetOpt
183 # Build the actual name list to be used by DPyGetOpt
184 opts_names = qw(cmdline_opts) + qw(cmdline_only)
184 opts_names = qw(cmdline_opts) + qw(cmdline_only)
185
185
186 # Set sensible command line defaults.
186 # Set sensible command line defaults.
187 # This should have everything from cmdline_opts and cmdline_only
187 # This should have everything from cmdline_opts and cmdline_only
188 opts_def = Struct(autocall = 1,
188 opts_def = Struct(autocall = 1,
189 autoedit_syntax = 0,
189 autoedit_syntax = 0,
190 autoindent = 0,
190 autoindent = 0,
191 automagic = 1,
191 automagic = 1,
192 banner = 1,
192 banner = 1,
193 cache_size = 1000,
193 cache_size = 1000,
194 c = '',
194 c = '',
195 classic = 0,
195 classic = 0,
196 colors = 'NoColor',
196 colors = 'NoColor',
197 color_info = 0,
197 color_info = 0,
198 confirm_exit = 1,
198 confirm_exit = 1,
199 debug = 0,
199 debug = 0,
200 deep_reload = 0,
200 deep_reload = 0,
201 editor = '0',
201 editor = '0',
202 help = 0,
202 help = 0,
203 interact = 0,
203 interact = 0,
204 ipythondir = ipythondir_def,
204 ipythondir = ipythondir_def,
205 log = 0,
205 log = 0,
206 logfile = '',
206 logfile = '',
207 logplay = '',
207 logplay = '',
208 multi_line_specials = 1,
208 multi_line_specials = 1,
209 messages = 1,
209 messages = 1,
210 object_info_string_level = 0,
210 object_info_string_level = 0,
211 nosep = 0,
211 nosep = 0,
212 pdb = 0,
212 pdb = 0,
213 pprint = 0,
213 pprint = 0,
214 profile = '',
214 profile = '',
215 prompt_in1 = 'In [\\#]: ',
215 prompt_in1 = 'In [\\#]: ',
216 prompt_in2 = ' .\\D.: ',
216 prompt_in2 = ' .\\D.: ',
217 prompt_out = 'Out[\\#]: ',
217 prompt_out = 'Out[\\#]: ',
218 prompts_pad_left = 1,
218 prompts_pad_left = 1,
219 pylab_import_all = 1,
219 pylab_import_all = 1,
220 quiet = 0,
220 quiet = 0,
221 quick = 0,
221 quick = 0,
222 readline = 1,
222 readline = 1,
223 readline_merge_completions = 1,
223 readline_merge_completions = 1,
224 readline_omit__names = 0,
224 readline_omit__names = 0,
225 rcfile = 'ipythonrc' + rc_suffix,
225 rcfile = 'ipythonrc' + rc_suffix,
226 screen_length = 0,
226 screen_length = 0,
227 separate_in = '\n',
227 separate_in = '\n',
228 separate_out = '\n',
228 separate_out = '\n',
229 separate_out2 = '',
229 separate_out2 = '',
230 system_header = 'IPython system call: ',
230 system_header = 'IPython system call: ',
231 system_verbose = 0,
231 system_verbose = 0,
232 gthread = 0,
232 gthread = 0,
233 qthread = 0,
233 qthread = 0,
234 q4thread = 0,
234 q4thread = 0,
235 wthread = 0,
235 wthread = 0,
236 pylab = 0,
236 pylab = 0,
237 term_title = 1,
237 term_title = 1,
238 tk = 0,
238 tk = 0,
239 upgrade = 0,
239 upgrade = 0,
240 Version = 0,
240 Version = 0,
241 xmode = 'Verbose',
241 xmode = 'Verbose',
242 wildcards_case_sensitive = 1,
242 wildcards_case_sensitive = 1,
243 wxversion = '0',
243 wxversion = '0',
244 magic_docstrings = 0, # undocumented, for doc generation
244 magic_docstrings = 0, # undocumented, for doc generation
245 )
245 )
246
246
247 # Things that will *only* appear in rcfiles (not at the command line).
247 # Things that will *only* appear in rcfiles (not at the command line).
248 # Make sure there's a space before each end of line (they get auto-joined!)
248 # Make sure there's a space before each end of line (they get auto-joined!)
249 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
249 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
250 qw_lol: 'import_some ',
250 qw_lol: 'import_some ',
251 # for things with embedded whitespace:
251 # for things with embedded whitespace:
252 list_strings:'execute alias readline_parse_and_bind ',
252 list_strings:'execute alias readline_parse_and_bind ',
253 # Regular strings need no conversion:
253 # Regular strings need no conversion:
254 None:'readline_remove_delims ',
254 None:'readline_remove_delims ',
255 }
255 }
256 # Default values for these
256 # Default values for these
257 rc_def = Struct(include = [],
257 rc_def = Struct(include = [],
258 import_mod = [],
258 import_mod = [],
259 import_all = [],
259 import_all = [],
260 import_some = [[]],
260 import_some = [[]],
261 execute = [],
261 execute = [],
262 execfile = [],
262 execfile = [],
263 alias = [],
263 alias = [],
264 readline_parse_and_bind = [],
264 readline_parse_and_bind = [],
265 readline_remove_delims = '',
265 readline_remove_delims = '',
266 )
266 )
267
267
268 # Build the type conversion dictionary from the above tables:
268 # Build the type conversion dictionary from the above tables:
269 typeconv = rcfile_opts.copy()
269 typeconv = rcfile_opts.copy()
270 typeconv.update(optstr2types(cmdline_opts))
270 typeconv.update(optstr2types(cmdline_opts))
271
271
272 # FIXME: the None key appears in both, put that back together by hand. Ugly!
272 # FIXME: the None key appears in both, put that back together by hand. Ugly!
273 typeconv[None] += ' ' + rcfile_opts[None]
273 typeconv[None] += ' ' + rcfile_opts[None]
274
274
275 # Remove quotes at ends of all strings (used to protect spaces)
275 # Remove quotes at ends of all strings (used to protect spaces)
276 typeconv[unquote_ends] = typeconv[None]
276 typeconv[unquote_ends] = typeconv[None]
277 del typeconv[None]
277 del typeconv[None]
278
278
279 # Build the list we'll use to make all config decisions with defaults:
279 # Build the list we'll use to make all config decisions with defaults:
280 opts_all = opts_def.copy()
280 opts_all = opts_def.copy()
281 opts_all.update(rc_def)
281 opts_all.update(rc_def)
282
282
283 # Build conflict resolver for recursive loading of config files:
283 # Build conflict resolver for recursive loading of config files:
284 # - preserve means the outermost file maintains the value, it is not
284 # - preserve means the outermost file maintains the value, it is not
285 # overwritten if an included file has the same key.
285 # overwritten if an included file has the same key.
286 # - add_flip applies + to the two values, so it better make sense to add
286 # - add_flip applies + to the two values, so it better make sense to add
287 # those types of keys. But it flips them first so that things loaded
287 # those types of keys. But it flips them first so that things loaded
288 # deeper in the inclusion chain have lower precedence.
288 # deeper in the inclusion chain have lower precedence.
289 conflict = {'preserve': ' '.join([ typeconv[int],
289 conflict = {'preserve': ' '.join([ typeconv[int],
290 typeconv[unquote_ends] ]),
290 typeconv[unquote_ends] ]),
291 'add_flip': ' '.join([ typeconv[qwflat],
291 'add_flip': ' '.join([ typeconv[qwflat],
292 typeconv[qw_lol],
292 typeconv[qw_lol],
293 typeconv[list_strings] ])
293 typeconv[list_strings] ])
294 }
294 }
295
295
296 # Now actually process the command line
296 # Now actually process the command line
297 getopt = DPyGetOpt.DPyGetOpt()
297 getopt = DPyGetOpt.DPyGetOpt()
298 getopt.setIgnoreCase(0)
298 getopt.setIgnoreCase(0)
299
299
300 getopt.parseConfiguration(opts_names)
300 getopt.parseConfiguration(opts_names)
301
301
302 try:
302 try:
303 getopt.processArguments(argv)
303 getopt.processArguments(argv)
304 except:
304 except DPyGetOpt.ArgumentError, exc:
305 print cmd_line_usage
305 print cmd_line_usage
306 warn('\nError in Arguments: ' + `sys.exc_value`)
306 warn('\nError in Arguments: "%s"' % exc)
307 sys.exit(1)
307 sys.exit(1)
308
308
309 # convert the options dict to a struct for much lighter syntax later
309 # convert the options dict to a struct for much lighter syntax later
310 opts = Struct(getopt.optionValues)
310 opts = Struct(getopt.optionValues)
311 args = getopt.freeValues
311 args = getopt.freeValues
312
312
313 # this is the struct (which has default values at this point) with which
313 # this is the struct (which has default values at this point) with which
314 # we make all decisions:
314 # we make all decisions:
315 opts_all.update(opts)
315 opts_all.update(opts)
316
316
317 # Options that force an immediate exit
317 # Options that force an immediate exit
318 if opts_all.help:
318 if opts_all.help:
319 page(cmd_line_usage)
319 page(cmd_line_usage)
320 sys.exit()
320 sys.exit()
321
321
322 if opts_all.Version:
322 if opts_all.Version:
323 print __version__
323 print __version__
324 sys.exit()
324 sys.exit()
325
325
326 if opts_all.magic_docstrings:
326 if opts_all.magic_docstrings:
327 IP.magic_magic('-latex')
327 IP.magic_magic('-latex')
328 sys.exit()
328 sys.exit()
329
329
330 # add personal ipythondir to sys.path so that users can put things in
330 # add personal ipythondir to sys.path so that users can put things in
331 # there for customization
331 # there for customization
332 sys.path.append(os.path.abspath(opts_all.ipythondir))
332 sys.path.append(os.path.abspath(opts_all.ipythondir))
333
333
334 # Create user config directory if it doesn't exist. This must be done
334 # Create user config directory if it doesn't exist. This must be done
335 # *after* getting the cmd line options.
335 # *after* getting the cmd line options.
336 if not os.path.isdir(opts_all.ipythondir):
336 if not os.path.isdir(opts_all.ipythondir):
337 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
337 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
338
338
339 # upgrade user config files while preserving a copy of the originals
339 # upgrade user config files while preserving a copy of the originals
340 if opts_all.upgrade:
340 if opts_all.upgrade:
341 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
341 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
342
342
343 # check mutually exclusive options in the *original* command line
343 # check mutually exclusive options in the *original* command line
344 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
344 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
345 qw('classic profile'),qw('classic rcfile')])
345 qw('classic profile'),qw('classic rcfile')])
346
346
347 #---------------------------------------------------------------------------
347 #---------------------------------------------------------------------------
348 # Log replay
348 # Log replay
349
349
350 # if -logplay, we need to 'become' the other session. That basically means
350 # if -logplay, we need to 'become' the other session. That basically means
351 # replacing the current command line environment with that of the old
351 # replacing the current command line environment with that of the old
352 # session and moving on.
352 # session and moving on.
353
353
354 # this is needed so that later we know we're in session reload mode, as
354 # this is needed so that later we know we're in session reload mode, as
355 # opts_all will get overwritten:
355 # opts_all will get overwritten:
356 load_logplay = 0
356 load_logplay = 0
357
357
358 if opts_all.logplay:
358 if opts_all.logplay:
359 load_logplay = opts_all.logplay
359 load_logplay = opts_all.logplay
360 opts_debug_save = opts_all.debug
360 opts_debug_save = opts_all.debug
361 try:
361 try:
362 logplay = open(opts_all.logplay)
362 logplay = open(opts_all.logplay)
363 except IOError:
363 except IOError:
364 if opts_all.debug: IP.InteractiveTB()
364 if opts_all.debug: IP.InteractiveTB()
365 warn('Could not open logplay file '+`opts_all.logplay`)
365 warn('Could not open logplay file '+`opts_all.logplay`)
366 # restore state as if nothing had happened and move on, but make
366 # restore state as if nothing had happened and move on, but make
367 # sure that later we don't try to actually load the session file
367 # sure that later we don't try to actually load the session file
368 logplay = None
368 logplay = None
369 load_logplay = 0
369 load_logplay = 0
370 del opts_all.logplay
370 del opts_all.logplay
371 else:
371 else:
372 try:
372 try:
373 logplay.readline()
373 logplay.readline()
374 logplay.readline();
374 logplay.readline();
375 # this reloads that session's command line
375 # this reloads that session's command line
376 cmd = logplay.readline()[6:]
376 cmd = logplay.readline()[6:]
377 exec cmd
377 exec cmd
378 # restore the true debug flag given so that the process of
378 # restore the true debug flag given so that the process of
379 # session loading itself can be monitored.
379 # session loading itself can be monitored.
380 opts.debug = opts_debug_save
380 opts.debug = opts_debug_save
381 # save the logplay flag so later we don't overwrite the log
381 # save the logplay flag so later we don't overwrite the log
382 opts.logplay = load_logplay
382 opts.logplay = load_logplay
383 # now we must update our own structure with defaults
383 # now we must update our own structure with defaults
384 opts_all.update(opts)
384 opts_all.update(opts)
385 # now load args
385 # now load args
386 cmd = logplay.readline()[6:]
386 cmd = logplay.readline()[6:]
387 exec cmd
387 exec cmd
388 logplay.close()
388 logplay.close()
389 except:
389 except:
390 logplay.close()
390 logplay.close()
391 if opts_all.debug: IP.InteractiveTB()
391 if opts_all.debug: IP.InteractiveTB()
392 warn("Logplay file lacking full configuration information.\n"
392 warn("Logplay file lacking full configuration information.\n"
393 "I'll try to read it, but some things may not work.")
393 "I'll try to read it, but some things may not work.")
394
394
395 #-------------------------------------------------------------------------
395 #-------------------------------------------------------------------------
396 # set up output traps: catch all output from files, being run, modules
396 # set up output traps: catch all output from files, being run, modules
397 # loaded, etc. Then give it to the user in a clean form at the end.
397 # loaded, etc. Then give it to the user in a clean form at the end.
398
398
399 msg_out = 'Output messages. '
399 msg_out = 'Output messages. '
400 msg_err = 'Error messages. '
400 msg_err = 'Error messages. '
401 msg_sep = '\n'
401 msg_sep = '\n'
402 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
402 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
403 msg_err,msg_sep,debug,
403 msg_err,msg_sep,debug,
404 quiet_out=1),
404 quiet_out=1),
405 user_exec = OutputTrap('User File Execution',msg_out,
405 user_exec = OutputTrap('User File Execution',msg_out,
406 msg_err,msg_sep,debug),
406 msg_err,msg_sep,debug),
407 logplay = OutputTrap('Log Loader',msg_out,
407 logplay = OutputTrap('Log Loader',msg_out,
408 msg_err,msg_sep,debug),
408 msg_err,msg_sep,debug),
409 summary = ''
409 summary = ''
410 )
410 )
411
411
412 #-------------------------------------------------------------------------
412 #-------------------------------------------------------------------------
413 # Process user ipythonrc-type configuration files
413 # Process user ipythonrc-type configuration files
414
414
415 # turn on output trapping and log to msg.config
415 # turn on output trapping and log to msg.config
416 # remember that with debug on, trapping is actually disabled
416 # remember that with debug on, trapping is actually disabled
417 msg.config.trap_all()
417 msg.config.trap_all()
418
418
419 # look for rcfile in current or default directory
419 # look for rcfile in current or default directory
420 try:
420 try:
421 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
421 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
422 except IOError:
422 except IOError:
423 if opts_all.debug: IP.InteractiveTB()
423 if opts_all.debug: IP.InteractiveTB()
424 warn('Configuration file %s not found. Ignoring request.'
424 warn('Configuration file %s not found. Ignoring request.'
425 % (opts_all.rcfile) )
425 % (opts_all.rcfile) )
426
426
427 # 'profiles' are a shorthand notation for config filenames
427 # 'profiles' are a shorthand notation for config filenames
428 profile_handled_by_legacy = False
428 profile_handled_by_legacy = False
429 if opts_all.profile:
429 if opts_all.profile:
430
430
431 try:
431 try:
432 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
432 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
433 + rc_suffix,
433 + rc_suffix,
434 opts_all.ipythondir)
434 opts_all.ipythondir)
435 profile_handled_by_legacy = True
435 profile_handled_by_legacy = True
436 except IOError:
436 except IOError:
437 if opts_all.debug: IP.InteractiveTB()
437 if opts_all.debug: IP.InteractiveTB()
438 opts.profile = '' # remove profile from options if invalid
438 opts.profile = '' # remove profile from options if invalid
439 # We won't warn anymore, primary method is ipy_profile_PROFNAME
439 # We won't warn anymore, primary method is ipy_profile_PROFNAME
440 # which does trigger a warning.
440 # which does trigger a warning.
441
441
442 # load the config file
442 # load the config file
443 rcfiledata = None
443 rcfiledata = None
444 if opts_all.quick:
444 if opts_all.quick:
445 print 'Launching IPython in quick mode. No config file read.'
445 print 'Launching IPython in quick mode. No config file read.'
446 elif opts_all.rcfile:
446 elif opts_all.rcfile:
447 try:
447 try:
448 cfg_loader = ConfigLoader(conflict)
448 cfg_loader = ConfigLoader(conflict)
449 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
449 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
450 'include',opts_all.ipythondir,
450 'include',opts_all.ipythondir,
451 purge = 1,
451 purge = 1,
452 unique = conflict['preserve'])
452 unique = conflict['preserve'])
453 except:
453 except:
454 IP.InteractiveTB()
454 IP.InteractiveTB()
455 warn('Problems loading configuration file '+
455 warn('Problems loading configuration file '+
456 `opts_all.rcfile`+
456 `opts_all.rcfile`+
457 '\nStarting with default -bare bones- configuration.')
457 '\nStarting with default -bare bones- configuration.')
458 else:
458 else:
459 warn('No valid configuration file found in either currrent directory\n'+
459 warn('No valid configuration file found in either currrent directory\n'+
460 'or in the IPython config. directory: '+`opts_all.ipythondir`+
460 'or in the IPython config. directory: '+`opts_all.ipythondir`+
461 '\nProceeding with internal defaults.')
461 '\nProceeding with internal defaults.')
462
462
463 #------------------------------------------------------------------------
463 #------------------------------------------------------------------------
464 # Set exception handlers in mode requested by user.
464 # Set exception handlers in mode requested by user.
465 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
465 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
466 IP.magic_xmode(opts_all.xmode)
466 IP.magic_xmode(opts_all.xmode)
467 otrap.release_out()
467 otrap.release_out()
468
468
469 #------------------------------------------------------------------------
469 #------------------------------------------------------------------------
470 # Execute user config
470 # Execute user config
471
471
472 # Create a valid config structure with the right precedence order:
472 # Create a valid config structure with the right precedence order:
473 # defaults < rcfile < command line. This needs to be in the instance, so
473 # defaults < rcfile < command line. This needs to be in the instance, so
474 # that method calls below that rely on it find it.
474 # that method calls below that rely on it find it.
475 IP.rc = rc_def.copy()
475 IP.rc = rc_def.copy()
476
476
477 # Work with a local alias inside this routine to avoid unnecessary
477 # Work with a local alias inside this routine to avoid unnecessary
478 # attribute lookups.
478 # attribute lookups.
479 IP_rc = IP.rc
479 IP_rc = IP.rc
480
480
481 IP_rc.update(opts_def)
481 IP_rc.update(opts_def)
482 if rcfiledata:
482 if rcfiledata:
483 # now we can update
483 # now we can update
484 IP_rc.update(rcfiledata)
484 IP_rc.update(rcfiledata)
485 IP_rc.update(opts)
485 IP_rc.update(opts)
486 IP_rc.update(rc_override)
486 IP_rc.update(rc_override)
487
487
488 # Store the original cmd line for reference:
488 # Store the original cmd line for reference:
489 IP_rc.opts = opts
489 IP_rc.opts = opts
490 IP_rc.args = args
490 IP_rc.args = args
491
491
492 # create a *runtime* Struct like rc for holding parameters which may be
492 # create a *runtime* Struct like rc for holding parameters which may be
493 # created and/or modified by runtime user extensions.
493 # created and/or modified by runtime user extensions.
494 IP.runtime_rc = Struct()
494 IP.runtime_rc = Struct()
495
495
496 # from this point on, all config should be handled through IP_rc,
496 # from this point on, all config should be handled through IP_rc,
497 # opts* shouldn't be used anymore.
497 # opts* shouldn't be used anymore.
498
498
499
499
500 # update IP_rc with some special things that need manual
500 # update IP_rc with some special things that need manual
501 # tweaks. Basically options which affect other options. I guess this
501 # tweaks. Basically options which affect other options. I guess this
502 # should just be written so that options are fully orthogonal and we
502 # should just be written so that options are fully orthogonal and we
503 # wouldn't worry about this stuff!
503 # wouldn't worry about this stuff!
504
504
505 if IP_rc.classic:
505 if IP_rc.classic:
506 IP_rc.quick = 1
506 IP_rc.quick = 1
507 IP_rc.cache_size = 0
507 IP_rc.cache_size = 0
508 IP_rc.pprint = 0
508 IP_rc.pprint = 0
509 IP_rc.prompt_in1 = '>>> '
509 IP_rc.prompt_in1 = '>>> '
510 IP_rc.prompt_in2 = '... '
510 IP_rc.prompt_in2 = '... '
511 IP_rc.prompt_out = ''
511 IP_rc.prompt_out = ''
512 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
512 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
513 IP_rc.colors = 'NoColor'
513 IP_rc.colors = 'NoColor'
514 IP_rc.xmode = 'Plain'
514 IP_rc.xmode = 'Plain'
515
515
516 IP.pre_config_initialization()
516 IP.pre_config_initialization()
517 # configure readline
517 # configure readline
518 # Define the history file for saving commands in between sessions
518 # Define the history file for saving commands in between sessions
519 if IP_rc.profile:
519 if IP_rc.profile:
520 histfname = 'history-%s' % IP_rc.profile
520 histfname = 'history-%s' % IP_rc.profile
521 else:
521 else:
522 histfname = 'history'
522 histfname = 'history'
523 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
523 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
524
524
525 # update exception handlers with rc file status
525 # update exception handlers with rc file status
526 otrap.trap_out() # I don't want these messages ever.
526 otrap.trap_out() # I don't want these messages ever.
527 IP.magic_xmode(IP_rc.xmode)
527 IP.magic_xmode(IP_rc.xmode)
528 otrap.release_out()
528 otrap.release_out()
529
529
530 # activate logging if requested and not reloading a log
530 # activate logging if requested and not reloading a log
531 if IP_rc.logplay:
531 if IP_rc.logplay:
532 IP.magic_logstart(IP_rc.logplay + ' append')
532 IP.magic_logstart(IP_rc.logplay + ' append')
533 elif IP_rc.logfile:
533 elif IP_rc.logfile:
534 IP.magic_logstart(IP_rc.logfile)
534 IP.magic_logstart(IP_rc.logfile)
535 elif IP_rc.log:
535 elif IP_rc.log:
536 IP.magic_logstart()
536 IP.magic_logstart()
537
537
538 # find user editor so that it we don't have to look it up constantly
538 # find user editor so that it we don't have to look it up constantly
539 if IP_rc.editor.strip()=='0':
539 if IP_rc.editor.strip()=='0':
540 try:
540 try:
541 ed = os.environ['EDITOR']
541 ed = os.environ['EDITOR']
542 except KeyError:
542 except KeyError:
543 if os.name == 'posix':
543 if os.name == 'posix':
544 ed = 'vi' # the only one guaranteed to be there!
544 ed = 'vi' # the only one guaranteed to be there!
545 else:
545 else:
546 ed = 'notepad' # same in Windows!
546 ed = 'notepad' # same in Windows!
547 IP_rc.editor = ed
547 IP_rc.editor = ed
548
548
549 # Keep track of whether this is an embedded instance or not (useful for
549 # Keep track of whether this is an embedded instance or not (useful for
550 # post-mortems).
550 # post-mortems).
551 IP_rc.embedded = IP.embedded
551 IP_rc.embedded = IP.embedded
552
552
553 # Recursive reload
553 # Recursive reload
554 try:
554 try:
555 from IPython import deep_reload
555 from IPython import deep_reload
556 if IP_rc.deep_reload:
556 if IP_rc.deep_reload:
557 __builtin__.reload = deep_reload.reload
557 __builtin__.reload = deep_reload.reload
558 else:
558 else:
559 __builtin__.dreload = deep_reload.reload
559 __builtin__.dreload = deep_reload.reload
560 del deep_reload
560 del deep_reload
561 except ImportError:
561 except ImportError:
562 pass
562 pass
563
563
564 # Save the current state of our namespace so that the interactive shell
564 # Save the current state of our namespace so that the interactive shell
565 # can later know which variables have been created by us from config files
565 # can later know which variables have been created by us from config files
566 # and loading. This way, loading a file (in any way) is treated just like
566 # and loading. This way, loading a file (in any way) is treated just like
567 # defining things on the command line, and %who works as expected.
567 # defining things on the command line, and %who works as expected.
568
568
569 # DON'T do anything that affects the namespace beyond this point!
569 # DON'T do anything that affects the namespace beyond this point!
570 IP.internal_ns.update(__main__.__dict__)
570 IP.internal_ns.update(__main__.__dict__)
571
571
572 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
572 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
573
573
574 # Now run through the different sections of the users's config
574 # Now run through the different sections of the users's config
575 if IP_rc.debug:
575 if IP_rc.debug:
576 print 'Trying to execute the following configuration structure:'
576 print 'Trying to execute the following configuration structure:'
577 print '(Things listed first are deeper in the inclusion tree and get'
577 print '(Things listed first are deeper in the inclusion tree and get'
578 print 'loaded first).\n'
578 print 'loaded first).\n'
579 pprint(IP_rc.__dict__)
579 pprint(IP_rc.__dict__)
580
580
581 for mod in IP_rc.import_mod:
581 for mod in IP_rc.import_mod:
582 try:
582 try:
583 exec 'import '+mod in IP.user_ns
583 exec 'import '+mod in IP.user_ns
584 except :
584 except :
585 IP.InteractiveTB()
585 IP.InteractiveTB()
586 import_fail_info(mod)
586 import_fail_info(mod)
587
587
588 for mod_fn in IP_rc.import_some:
588 for mod_fn in IP_rc.import_some:
589 if not mod_fn == []:
589 if not mod_fn == []:
590 mod,fn = mod_fn[0],','.join(mod_fn[1:])
590 mod,fn = mod_fn[0],','.join(mod_fn[1:])
591 try:
591 try:
592 exec 'from '+mod+' import '+fn in IP.user_ns
592 exec 'from '+mod+' import '+fn in IP.user_ns
593 except :
593 except :
594 IP.InteractiveTB()
594 IP.InteractiveTB()
595 import_fail_info(mod,fn)
595 import_fail_info(mod,fn)
596
596
597 for mod in IP_rc.import_all:
597 for mod in IP_rc.import_all:
598 try:
598 try:
599 exec 'from '+mod+' import *' in IP.user_ns
599 exec 'from '+mod+' import *' in IP.user_ns
600 except :
600 except :
601 IP.InteractiveTB()
601 IP.InteractiveTB()
602 import_fail_info(mod)
602 import_fail_info(mod)
603
603
604 for code in IP_rc.execute:
604 for code in IP_rc.execute:
605 try:
605 try:
606 exec code in IP.user_ns
606 exec code in IP.user_ns
607 except:
607 except:
608 IP.InteractiveTB()
608 IP.InteractiveTB()
609 warn('Failure executing code: ' + `code`)
609 warn('Failure executing code: ' + `code`)
610
610
611 # Execute the files the user wants in ipythonrc
611 # Execute the files the user wants in ipythonrc
612 for file in IP_rc.execfile:
612 for file in IP_rc.execfile:
613 try:
613 try:
614 file = filefind(file,sys.path+[IPython_dir])
614 file = filefind(file,sys.path+[IPython_dir])
615 except IOError:
615 except IOError:
616 warn(itpl('File $file not found. Skipping it.'))
616 warn(itpl('File $file not found. Skipping it.'))
617 else:
617 else:
618 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
618 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
619
619
620 # finally, try importing ipy_*_conf for final configuration
620 # finally, try importing ipy_*_conf for final configuration
621 try:
621 try:
622 import ipy_system_conf
622 import ipy_system_conf
623 except ImportError:
623 except ImportError:
624 if opts_all.debug: IP.InteractiveTB()
624 if opts_all.debug: IP.InteractiveTB()
625 warn("Could not import 'ipy_system_conf'")
625 warn("Could not import 'ipy_system_conf'")
626 except:
626 except:
627 IP.InteractiveTB()
627 IP.InteractiveTB()
628 import_fail_info('ipy_system_conf')
628 import_fail_info('ipy_system_conf')
629
629
630 # only import prof module if ipythonrc-PROF was not found
630 # only import prof module if ipythonrc-PROF was not found
631 if opts_all.profile and not profile_handled_by_legacy:
631 if opts_all.profile and not profile_handled_by_legacy:
632 profmodname = 'ipy_profile_' + opts_all.profile
632 profmodname = 'ipy_profile_' + opts_all.profile
633 try:
633 try:
634 __import__(profmodname)
634 __import__(profmodname)
635 except:
635 except:
636 IP.InteractiveTB()
636 IP.InteractiveTB()
637 print "Error importing",profmodname,"- perhaps you should run %upgrade?"
637 print "Error importing",profmodname,"- perhaps you should run %upgrade?"
638 import_fail_info(profmodname)
638 import_fail_info(profmodname)
639 else:
639 else:
640 import ipy_profile_none
640 import ipy_profile_none
641 try:
641 try:
642 import ipy_user_conf
642 import ipy_user_conf
643
643
644 except:
644 except:
645 conf = opts_all.ipythondir + "/ipy_user_conf.py"
645 conf = opts_all.ipythondir + "/ipy_user_conf.py"
646 IP.InteractiveTB()
646 IP.InteractiveTB()
647 if not os.path.isfile(conf):
647 if not os.path.isfile(conf):
648 warn(conf + ' does not exist, please run %upgrade!')
648 warn(conf + ' does not exist, please run %upgrade!')
649
649
650 import_fail_info("ipy_user_conf")
650 import_fail_info("ipy_user_conf")
651
651
652 # finally, push the argv to options again to ensure highest priority
652 # finally, push the argv to options again to ensure highest priority
653 IP_rc.update(opts)
653 IP_rc.update(opts)
654
654
655 # release stdout and stderr and save config log into a global summary
655 # release stdout and stderr and save config log into a global summary
656 msg.config.release_all()
656 msg.config.release_all()
657 if IP_rc.messages:
657 if IP_rc.messages:
658 msg.summary += msg.config.summary_all()
658 msg.summary += msg.config.summary_all()
659
659
660 #------------------------------------------------------------------------
660 #------------------------------------------------------------------------
661 # Setup interactive session
661 # Setup interactive session
662
662
663 # Now we should be fully configured. We can then execute files or load
663 # Now we should be fully configured. We can then execute files or load
664 # things only needed for interactive use. Then we'll open the shell.
664 # things only needed for interactive use. Then we'll open the shell.
665
665
666 # Take a snapshot of the user namespace before opening the shell. That way
666 # Take a snapshot of the user namespace before opening the shell. That way
667 # we'll be able to identify which things were interactively defined and
667 # we'll be able to identify which things were interactively defined and
668 # which were defined through config files.
668 # which were defined through config files.
669 IP.user_config_ns.update(IP.user_ns)
669 IP.user_config_ns.update(IP.user_ns)
670
670
671 # Force reading a file as if it were a session log. Slower but safer.
671 # Force reading a file as if it were a session log. Slower but safer.
672 if load_logplay:
672 if load_logplay:
673 print 'Replaying log...'
673 print 'Replaying log...'
674 try:
674 try:
675 if IP_rc.debug:
675 if IP_rc.debug:
676 logplay_quiet = 0
676 logplay_quiet = 0
677 else:
677 else:
678 logplay_quiet = 1
678 logplay_quiet = 1
679
679
680 msg.logplay.trap_all()
680 msg.logplay.trap_all()
681 IP.safe_execfile(load_logplay,IP.user_ns,
681 IP.safe_execfile(load_logplay,IP.user_ns,
682 islog = 1, quiet = logplay_quiet)
682 islog = 1, quiet = logplay_quiet)
683 msg.logplay.release_all()
683 msg.logplay.release_all()
684 if IP_rc.messages:
684 if IP_rc.messages:
685 msg.summary += msg.logplay.summary_all()
685 msg.summary += msg.logplay.summary_all()
686 except:
686 except:
687 warn('Problems replaying logfile %s.' % load_logplay)
687 warn('Problems replaying logfile %s.' % load_logplay)
688 IP.InteractiveTB()
688 IP.InteractiveTB()
689
689
690 # Load remaining files in command line
690 # Load remaining files in command line
691 msg.user_exec.trap_all()
691 msg.user_exec.trap_all()
692
692
693 # Do NOT execute files named in the command line as scripts to be loaded
693 # Do NOT execute files named in the command line as scripts to be loaded
694 # by embedded instances. Doing so has the potential for an infinite
694 # by embedded instances. Doing so has the potential for an infinite
695 # recursion if there are exceptions thrown in the process.
695 # recursion if there are exceptions thrown in the process.
696
696
697 # XXX FIXME: the execution of user files should be moved out to after
697 # XXX FIXME: the execution of user files should be moved out to after
698 # ipython is fully initialized, just as if they were run via %run at the
698 # ipython is fully initialized, just as if they were run via %run at the
699 # ipython prompt. This would also give them the benefit of ipython's
699 # ipython prompt. This would also give them the benefit of ipython's
700 # nice tracebacks.
700 # nice tracebacks.
701
701
702 if (not embedded and IP_rc.args and
702 if (not embedded and IP_rc.args and
703 not IP_rc.args[0].lower().endswith('.ipy')):
703 not IP_rc.args[0].lower().endswith('.ipy')):
704 name_save = IP.user_ns['__name__']
704 name_save = IP.user_ns['__name__']
705 IP.user_ns['__name__'] = '__main__'
705 IP.user_ns['__name__'] = '__main__'
706 # Set our own excepthook in case the user code tries to call it
706 # Set our own excepthook in case the user code tries to call it
707 # directly. This prevents triggering the IPython crash handler.
707 # directly. This prevents triggering the IPython crash handler.
708 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
708 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
709
709
710 save_argv = sys.argv[1:] # save it for later restoring
710 save_argv = sys.argv[1:] # save it for later restoring
711
711
712 sys.argv = args
712 sys.argv = args
713
713
714 try:
714 try:
715 IP.safe_execfile(args[0], IP.user_ns)
715 IP.safe_execfile(args[0], IP.user_ns)
716 finally:
716 finally:
717 # Reset our crash handler in place
717 # Reset our crash handler in place
718 sys.excepthook = old_excepthook
718 sys.excepthook = old_excepthook
719 sys.argv[:] = save_argv
719 sys.argv[:] = save_argv
720 IP.user_ns['__name__'] = name_save
720 IP.user_ns['__name__'] = name_save
721
721
722 msg.user_exec.release_all()
722 msg.user_exec.release_all()
723
723
724 if IP_rc.messages:
724 if IP_rc.messages:
725 msg.summary += msg.user_exec.summary_all()
725 msg.summary += msg.user_exec.summary_all()
726
726
727 # since we can't specify a null string on the cmd line, 0 is the equivalent:
727 # since we can't specify a null string on the cmd line, 0 is the equivalent:
728 if IP_rc.nosep:
728 if IP_rc.nosep:
729 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
729 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
730 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
730 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
731 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
731 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
732 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
732 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
733 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
733 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
734 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
734 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
735 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
735 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
736
736
737 # Determine how many lines at the bottom of the screen are needed for
737 # Determine how many lines at the bottom of the screen are needed for
738 # showing prompts, so we can know wheter long strings are to be printed or
738 # showing prompts, so we can know wheter long strings are to be printed or
739 # paged:
739 # paged:
740 num_lines_bot = IP_rc.separate_in.count('\n')+1
740 num_lines_bot = IP_rc.separate_in.count('\n')+1
741 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
741 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
742
742
743 # configure startup banner
743 # configure startup banner
744 if IP_rc.c: # regular python doesn't print the banner with -c
744 if IP_rc.c: # regular python doesn't print the banner with -c
745 IP_rc.banner = 0
745 IP_rc.banner = 0
746 if IP_rc.banner:
746 if IP_rc.banner:
747 BANN_P = IP.BANNER_PARTS
747 BANN_P = IP.BANNER_PARTS
748 else:
748 else:
749 BANN_P = []
749 BANN_P = []
750
750
751 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
751 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
752
752
753 # add message log (possibly empty)
753 # add message log (possibly empty)
754 if msg.summary: BANN_P.append(msg.summary)
754 if msg.summary: BANN_P.append(msg.summary)
755 # Final banner is a string
755 # Final banner is a string
756 IP.BANNER = '\n'.join(BANN_P)
756 IP.BANNER = '\n'.join(BANN_P)
757
757
758 # Finalize the IPython instance. This assumes the rc structure is fully
758 # Finalize the IPython instance. This assumes the rc structure is fully
759 # in place.
759 # in place.
760 IP.post_config_initialization()
760 IP.post_config_initialization()
761
761
762 return IP
762 return IP
763 #************************ end of file <ipmaker.py> **************************
763 #************************ end of file <ipmaker.py> **************************
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