##// END OF EJS Templates
Reorganized the directory for ipython/ to have its own dir, which is a bit...
fperez -
r0:6f629fcc
parent child
Show More

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

@@ -0,0 +1,155
1 # -*- coding: utf-8 -*-
2 """Tools for coloring text in ANSI terminals.
3
4 $Id: ColorANSI.py 410 2004-11-04 07:58:17Z fperez $"""
5
6 #*****************************************************************************
7 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
12
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16
17 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
18
19 import os
20 from UserDict import UserDict
21
22 from IPython.Struct import Struct
23
24 def make_color_table(in_class):
25 """Build a set of color attributes in a class.
26
27 Helper function for building the *TermColors classes."""
28
29 color_templates = (
30 ("Black" , "0;30"),
31 ("Red" , "0;31"),
32 ("Green" , "0;32"),
33 ("Brown" , "0;33"),
34 ("Blue" , "0;34"),
35 ("Purple" , "0;35"),
36 ("Cyan" , "0;36"),
37 ("LightGray" , "0;37"),
38 ("DarkGray" , "1;30"),
39 ("LightRed" , "1;31"),
40 ("LightGreen" , "1;32"),
41 ("Yellow" , "1;33"),
42 ("LightBlue" , "1;34"),
43 ("LightPurple" , "1;35"),
44 ("LightCyan" , "1;36"),
45 ("White" , "1;37"), )
46
47 for name,value in color_templates:
48 setattr(in_class,name,in_class._base % value)
49
50 class TermColors:
51 """Color escape sequences.
52
53 This class defines the escape sequences for all the standard (ANSI?)
54 colors in terminals. Also defines a NoColor escape which is just the null
55 string, suitable for defining 'dummy' color schemes in terminals which get
56 confused by color escapes.
57
58 This class should be used as a mixin for building color schemes."""
59
60 NoColor = '' # for color schemes in color-less terminals.
61 Normal = '\033[0m' # Reset normal coloring
62 _base = '\033[%sm' # Template for all other colors
63
64 # Build the actual color table as a set of class attributes:
65 make_color_table(TermColors)
66
67 class InputTermColors:
68 """Color escape sequences for input prompts.
69
70 This class is similar to TermColors, but the escapes are wrapped in \001
71 and \002 so that readline can properly know the length of each line and
72 can wrap lines accordingly. Use this class for any colored text which
73 needs to be used in input prompts, such as in calls to raw_input().
74
75 This class defines the escape sequences for all the standard (ANSI?)
76 colors in terminals. Also defines a NoColor escape which is just the null
77 string, suitable for defining 'dummy' color schemes in terminals which get
78 confused by color escapes.
79
80 This class should be used as a mixin for building color schemes."""
81
82 NoColor = '' # for color schemes in color-less terminals.
83 Normal = '\001\033[0m\002' # Reset normal coloring
84 _base = '\001\033[%sm\002' # Template for all other colors
85
86 # Build the actual color table as a set of class attributes:
87 make_color_table(InputTermColors)
88
89 class ColorScheme:
90 """Generic color scheme class. Just a name and a Struct."""
91 def __init__(self,__scheme_name_,colordict=None,**colormap):
92 self.name = __scheme_name_
93 if colordict is None:
94 self.colors = Struct(**colormap)
95 else:
96 self.colors = Struct(colordict)
97
98 class ColorSchemeTable(UserDict):
99 """General class to handle tables of color schemes.
100
101 It's basically a dict of color schemes with a couple of shorthand
102 attributes and some convenient methods.
103
104 active_scheme_name -> obvious
105 active_colors -> actual color table of the active scheme"""
106
107 def __init__(self,scheme_list=None,default_scheme=''):
108 """Create a table of color schemes.
109
110 The table can be created empty and manually filled or it can be
111 created with a list of valid color schemes AND the specification for
112 the default active scheme.
113 """
114
115 UserDict.__init__(self)
116 if scheme_list is None:
117 self.active_scheme_name = ''
118 self.active_colors = None
119 else:
120 if default_scheme == '':
121 raise ValueError,'you must specify the default color scheme'
122 for scheme in scheme_list:
123 self.add_scheme(scheme)
124 self.set_active_scheme(default_scheme)
125
126 def add_scheme(self,new_scheme):
127 """Add a new color scheme to the table."""
128 if not isinstance(new_scheme,ColorScheme):
129 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
130 self[new_scheme.name] = new_scheme
131
132 def set_active_scheme(self,scheme,case_sensitive=0):
133 """Set the currently active scheme.
134
135 Names are by default compared in a case-insensitive way, but this can
136 be changed by setting the parameter case_sensitive to true."""
137
138 scheme_list = self.keys()
139 if case_sensitive:
140 valid_schemes = scheme_list
141 scheme_test = scheme
142 else:
143 valid_schemes = [s.lower() for s in scheme_list]
144 scheme_test = scheme.lower()
145 try:
146 scheme_idx = valid_schemes.index(scheme_test)
147 except ValueError:
148 raise ValueError,'Unrecognized color scheme: ' + scheme + \
149 '\nValid schemes: '+str(scheme_list).replace("'', ",'')
150 else:
151 active = scheme_list[scheme_idx]
152 self.active_scheme_name = active
153 self.active_colors = self[active].colors
154 # Now allow using '' as an index for the current active scheme
155 self[''] = self[active]
@@ -0,0 +1,116
1 # -*- coding: utf-8 -*-
2 """Configuration loader
3
4 $Id: ConfigLoader.py 525 2005-02-19 10:53:12Z fperez $"""
5
6 #*****************************************************************************
7 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
12
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16
17 import os
18 from pprint import pprint
19 import exceptions
20
21 from IPython import ultraTB
22 from IPython.Struct import Struct
23 from IPython.genutils import *
24
25 class ConfigLoaderError(exceptions.Exception):
26 """Exception for ConfigLoader class."""
27
28 def __init__(self,args=None):
29 self.args = args
30
31 class ConfigLoader:
32
33 """Configuration file loader capable of handling recursive inclusions and
34 with parametrized conflict resolution for multiply found keys."""
35
36 def __init__(self,conflict=None,field_sep=None,reclimit=15):
37
38 """The reclimit parameter controls the number of recursive
39 configuration file inclusions. This way we can stop early on (before
40 python's own recursion limit is hit) if there is a circular
41 inclusion.
42
43 - conflict: dictionary for conflict resolutions (see Struct.merge())
44
45 """
46 self.conflict = conflict
47 self.field_sep = field_sep
48 self.reset(reclimit)
49
50 def reset(self,reclimit=15):
51 self.reclimit = reclimit
52 self.recdepth = 0
53 self.included = []
54
55 def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw):
56 """Load a configuration file, return the resulting Struct.
57
58 Call: load_config(fname,convert=None,conflict=None,recurse_key='')
59
60 - fname: file to load from.
61 - convert: dictionary of type conversions (see read_dict())
62 - recurse_key: keyword in dictionary to trigger recursive file
63 inclusions.
64 """
65
66 if self.recdepth > self.reclimit:
67 raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\
68 'exceeded: ' + `self.recdepth` + \
69 '.\nMaybe you have a circular chain of inclusions?'
70 self.recdepth += 1
71 fname = filefind(fname,incpath)
72 data = Struct()
73 # avoid including the same file more than once
74 if fname in self.included:
75 return data
76 Xinfo = ultraTB.AutoFormattedTB()
77 if convert==None and recurse_key : convert = {qwflat:recurse_key}
78 # for production, change warn to 0:
79 data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1,
80 warn=0,no_empty=0,**kw))
81 # keep track of successfully loaded files
82 self.included.append(fname)
83 if recurse_key in data.keys():
84 for incfilename in data[recurse_key]:
85 found=0
86 try:
87 incfile = filefind(incfilename,incpath)
88 except IOError:
89 if os.name in ['nt','dos']:
90 try:
91 # Try again with '.ini' extension
92 incfilename += '.ini'
93 incfile = filefind(incfilename,incpath)
94 except IOError:
95 found = 0
96 else:
97 found = 1
98 else:
99 found = 0
100 else:
101 found = 1
102 if found:
103 try:
104 data.merge(self.load(incfile,convert,recurse_key,
105 incpath,**kw),
106 self.conflict)
107 except:
108 Xinfo()
109 warn('Problem loading included file: '+
110 `incfilename` + '. Ignoring it...')
111 else:
112 warn('File `%s` not found. Included by %s' % (incfilename,fname))
113
114 return data
115
116 # end ConfigLoader
@@ -0,0 +1,109
1 # -*- coding: utf-8 -*-
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
4 $Id: CrashHandler.py 410 2004-11-04 07:58:17Z fperez $"""
5
6 #*****************************************************************************
7 # Copyright (C) 2001-2004 Fernando Perez. <fperez@colorado.edu>
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
12
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
16 __version__ = Release.version
17
18 #****************************************************************************
19 # Required modules
20
21 # From the standard library
22 import os,sys
23 from pprint import pprint,pformat
24
25 # Homebrewed
26 from IPython.genutils import *
27 from IPython.Itpl import Itpl,itpl,printpl
28 from IPython import ultraTB
29 from IPython.ultraTB import ColorScheme,ColorSchemeTable # too long names
30
31 #****************************************************************************
32 class CrashHandler:
33 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
34
35 def __init__(self,IP):
36 self.IP = IP # IPython instance
37 self.bug_contact = Release.authors['Fernando'][0]
38 self.mailto = Release.authors['Fernando'][1]
39
40 def __call__(self,etype, evalue, etb):
41
42 # Report tracebacks shouldn't use color in general (safer for users)
43 color_scheme = 'NoColor'
44
45 # Use this ONLY for developer debugging (keep commented out for release)
46 #color_scheme = 'Linux' # dbg
47
48 try:
49 rptdir = self.IP.rc.ipythondir
50 except:
51 rptdir = os.getcwd()
52 if not os.path.isdir(rptdir):
53 rptdir = os.getcwd()
54 self.report_name = os.path.join(rptdir,'IPython_crash_report.txt')
55 self.TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,long_header=1)
56 traceback = self.TBhandler.text(etype,evalue,etb,context=31)
57
58 # print traceback to screen
59 print >> sys.stderr, traceback
60
61 # and generate a complete report on disk
62 try:
63 report = open(self.report_name,'w')
64 except:
65 print >> sys.stderr, 'Could not create crash report on disk.'
66 return
67
68 msg = itpl('\n'+'*'*70+'\n'
69 """
70 Oops, IPython crashed. We do our best to make it stable, but...
71
72 A crash report was automatically generated with the following information:
73 - A verbatim copy of the traceback above this text.
74 - A copy of your input history during this session.
75 - Data on your current IPython configuration.
76
77 It was left in the file named:
78 \t'$self.report_name'
79 If you can email this file to the developers, the information in it will help
80 them in understanding and correcting the problem.
81
82 You can mail it to $self.bug_contact at $self.mailto
83 with the subject 'IPython Crash Report'.
84
85 If you want to do it now, the following command will work (under Unix):
86 mail -s 'IPython Crash Report' $self.mailto < $self.report_name
87
88 To ensure accurate tracking of this issue, please file a report about it at:
89 http://www.scipy.net/roundup/ipython (IPython's online bug tracker).
90 """)
91 print >> sys.stderr, msg
92
93 sec_sep = '\n\n'+'*'*75+'\n\n'
94 report.write('*'*75+'\n\n'+'IPython post-mortem report\n\n')
95 report.write('IPython version: %s \n\n' % __version__)
96 report.write('Platform info : os.name -> %s, sys.platform -> %s' %
97 (os.name,sys.platform) )
98 report.write(sec_sep+'Current user configuration structure:\n\n')
99 report.write(pformat(self.IP.rc.dict()))
100 report.write(sec_sep+'Crash traceback:\n\n' + traceback)
101 try:
102 report.write(sec_sep+"History of session input:")
103 for line in self.IP.user_ns['_ih']:
104 report.write(line)
105 report.write('\n*** Last line of input (may not be in above history):\n')
106 report.write(self.IP._last_input_line+'\n')
107 except:
108 pass
109 report.close()
This diff has been collapsed as it changes many lines, (671 lines changed) Show them Hide them
@@ -0,0 +1,671
1 # -*- coding: utf-8 -*-
2 """DPyGetOpt -- Demiurge Python GetOptions Module
3
4 $Id: DPyGetOpt.py 389 2004-10-09 07:59:30Z fperez $
5
6 This module is modeled after perl's Getopt::Long module-- which
7 is, in turn, modeled after GNU's extended getopt() function.
8
9 Upon instantiation, the option specification should be a sequence
10 (list) of option definitions.
11
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
14 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
15 should be accepted.
16
17 Mandatory arguments to options are specified using a postpended
18 '=' + a type specifier. '=s' specifies a mandatory string
19 argument, '=i' specifies a mandatory integer argument, and '=f'
20 specifies a mandatory real number. In all cases, the '=' can be
21 substituted with ':' to specify that the argument is optional.
22
23 Dashes '-' in option names are allowed.
24
25 If an option has the character '@' postpended (after the
26 argumentation specification), it can appear multiple times within
27 each argument list that is processed. The results will be stored
28 in a list.
29
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,
32 and -baz options that appear on within the parsed argument list
33 must have a real number argument and that the accumulated list
34 of values will be available under the name 'foo'
35
36 $Id: DPyGetOpt.py 389 2004-10-09 07:59:30Z fperez $"""
37
38 #*****************************************************************************
39 #
40 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
41 #
42 #
43 # Published under the terms of the MIT license, hereby reproduced:
44 #
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
47 # deal in the Software without restriction, including without limitation the
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
50 # furnished to do so, subject to the following conditions:
51 #
52 # The above copyright notice and this permission notice shall be included in
53 # all copies or substantial portions of the Software.
54 #
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,
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
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
61 # IN THE SOFTWARE.
62 #
63 #*****************************************************************************
64
65 __author__ = 'Bill Bumgarner <bbum@friday.com>'
66 __license__ = 'MIT'
67 __version__ = '1.2'
68
69 # Modified to use re instead of regex and regsub modules.
70 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
71
72 import string
73 import re
74 import sys
75 import types
76
77 arg_error = 'DPyGetOpt Argument Error'
78 spec_error = 'DPyGetOpt Specification Error'
79 term_error = 'DPyGetOpt Termination Error'
80
81 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
82
83 ArgRequired = 'Requires an Argument'
84 ArgOptional = 'Argument Optional'
85
86 # The types modules is not used for these identifiers because there
87 # is no identifier for 'boolean' or 'generic'
88 StringArgType = 'String Argument Type'
89 IntegerArgType = 'Integer Argument Type'
90 RealArgType = 'Real Argument Type'
91 BooleanArgType = 'Boolean Argument Type'
92 GenericArgType = 'Generic Argument Type'
93
94 # dictionary of conversion functions-- boolean and generic options
95 # do not accept arguments and do not need conversion functions;
96 # the identity function is used purely for convenience.
97 ConversionFunctions = {
98 StringArgType : lambda x: x,
99 IntegerArgType : string.atoi,
100 RealArgType : string.atof,
101 BooleanArgType : lambda x: x,
102 GenericArgType : lambda x: x,
103 }
104
105 class DPyGetOpt:
106
107 def __init__(self, spec = None, terminators = ['--']):
108 """
109 Declare and intialize instance variables
110
111 Yes, declaration is not necessary... but one of the things
112 I sorely miss from C/Obj-C is the concept of having an
113 interface definition that clearly declares all instance
114 variables and methods without providing any implementation
115 details. it is a useful reference!
116
117 all instance variables are initialized to 0/Null/None of
118 the appropriate type-- not even the default value...
119 """
120
121 # sys.stderr.write(string.join(spec) + "\n")
122
123 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
124 # be expanded
125 self.freeValues = [] # list, contains free values
126 self.ignoreCase = 0 # boolean, YES if ignoring case
127 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
128 self.optionNames = {} # dict, all option names-- value is index of tuple
129 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
130 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
131 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
132 self.orderMixed = 0 # boolean, YES if options can be mixed with args
133 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
134 self.spec = [] # list, raw specs (in case it must be reparsed)
135 self.terminators = terminators # list, strings that terminate argument processing
136 self.termValues = [] # list, values after terminator
137 self.terminator = None # full name of terminator that ended
138 # option processing
139
140 # set up defaults
141 self.setPosixCompliance()
142 self.setIgnoreCase()
143 self.setAllowAbbreviations()
144
145 # parse spec-- if present
146 if spec:
147 self.parseConfiguration(spec)
148
149 def setPosixCompliance(self, aFlag = 0):
150 """
151 Enables and disables posix compliance.
152
153 When enabled, '+' can be used as an option prefix and free
154 values can be mixed with options.
155 """
156 self.posixCompliance = aFlag
157 self.needsParse = 1
158
159 if self.posixCompliance:
160 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
161 self.orderMixed = 0
162 else:
163 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
164 self.orderMixed = 1
165
166 def isPosixCompliant(self):
167 """
168 Returns the value of the posix compliance flag.
169 """
170 return self.posixCompliance
171
172 def setIgnoreCase(self, aFlag = 1):
173 """
174 Enables and disables ignoring case during option processing.
175 """
176 self.needsParse = 1
177 self.ignoreCase = aFlag
178
179 def ignoreCase(self):
180 """
181 Returns 1 if the option processor will ignore case when
182 processing options.
183 """
184 return self.ignoreCase
185
186 def setAllowAbbreviations(self, aFlag = 1):
187 """
188 Enables and disables the expansion of abbreviations during
189 option processing.
190 """
191 self.allowAbbreviations = aFlag
192
193 def willAllowAbbreviations(self):
194 """
195 Returns 1 if abbreviated options will be automatically
196 expanded to the non-abbreviated form (instead of causing an
197 unrecognized option error).
198 """
199 return self.allowAbbreviations
200
201 def addTerminator(self, newTerm):
202 """
203 Adds newTerm as terminator of option processing.
204
205 Whenever the option processor encounters one of the terminators
206 during option processing, the processing of options terminates
207 immediately, all remaining options are stored in the termValues
208 instance variable and the full name of the terminator is stored
209 in the terminator instance variable.
210 """
211 self.terminators = self.terminators + [newTerm]
212
213 def _addOption(self, oTuple):
214 """
215 Adds the option described by oTuple (name, (type, mode,
216 default), alias) to optionTuples. Adds index keyed under name
217 to optionNames. Raises spec_error if name already in
218 optionNames
219 """
220 (name, (type, mode, default, multi), realName) = oTuple
221
222 # verify name and add to option names dictionary
223 if self.optionNames.has_key(name):
224 if realName:
225 raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \
226 '\' already used for another option or alias.'
227 else:
228 raise spec_error, 'Option named \'' + name + \
229 '\' specified more than once. Specification: ' + option
230
231 # validated. add to optionNames
232 self.optionNames[name] = self.tupleIndex
233 self.tupleIndex = self.tupleIndex + 1
234
235 # add to optionTuples
236 self.optionTuples = self.optionTuples + [oTuple]
237
238 # if type is boolean, add negation
239 if type == BooleanArgType:
240 alias = 'no' + name
241 specTuple = (type, mode, 0, multi)
242 oTuple = (alias, specTuple, name)
243
244 # verify name and add to option names dictionary
245 if self.optionNames.has_key(alias):
246 if realName:
247 raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \
248 '\' already used for another option or alias.'
249 else:
250 raise spec_error, 'Negated option named \'' + name + \
251 '\' specified more than once. Specification: ' + option
252
253 # validated. add to optionNames
254 self.optionNames[alias] = self.tupleIndex
255 self.tupleIndex = self.tupleIndex + 1
256
257 # add to optionTuples
258 self.optionTuples = self.optionTuples + [oTuple]
259
260 def addOptionConfigurationTuple(self, oTuple):
261 (name, argSpec, realName) = oTuple
262 if self.ignoreCase:
263 name = string.lower(name)
264 if realName:
265 realName = string.lower(realName)
266 else:
267 realName = name
268
269 oTuple = (name, argSpec, realName)
270
271 # add option
272 self._addOption(oTuple)
273
274 def addOptionConfigurationTuples(self, oTuple):
275 if type(oTuple) is ListType:
276 for t in oTuple:
277 self.addOptionConfigurationTuple(t)
278 else:
279 self.addOptionConfigurationTuple(oTuple)
280
281 def parseConfiguration(self, spec):
282 # destroy previous stored information + store raw spec
283 self.spec = spec
284 self.optionTuples = []
285 self.optionNames = {}
286 self.tupleIndex = 0
287
288 tupleIndex = 0
289
290 # create some regex's for parsing each spec
291 splitExpr = \
292 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
293 for option in spec:
294 # push to lower case (does not negatively affect
295 # specification)
296 if self.ignoreCase:
297 option = string.lower(option)
298
299 # break into names, specification
300 match = splitExpr.match(option)
301 if match is None:
302 raise spec_error, 'Invalid specification {' + option + '}'
303
304 names = match.group('names')
305 specification = match.group('spec')
306
307 # break name into name, aliases
308 nlist = string.split(names, '|')
309
310 # get name
311 name = nlist[0]
312 aliases = nlist[1:]
313
314 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
315 if not specification:
316 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
317 argType = GenericArgType
318 argMode = None
319 argDefault = 1
320 argMultiple = 0
321 elif specification == '!':
322 argType = BooleanArgType
323 argMode = None
324 argDefault = 1
325 argMultiple = 0
326 else:
327 # parse
328 match = specificationExpr.match(specification)
329 if match is None:
330 # failed to parse, die
331 raise spec_error, 'Invalid configuration for option \'' + option + '\''
332
333 # determine mode
334 required = match.group('required')
335 if required == '=':
336 argMode = ArgRequired
337 elif required == ':':
338 argMode = ArgOptional
339 else:
340 raise spec_error, 'Unknown requirement configuration \'' + required + '\''
341
342 # determine type
343 type = match.group('type')
344 if type == 's':
345 argType = StringArgType
346 argDefault = ''
347 elif type == 'i':
348 argType = IntegerArgType
349 argDefault = 1
350 elif type == 'f' or type == 'n':
351 argType = RealArgType
352 argDefault = 1
353 else:
354 raise spec_error, 'Unknown type specifier \'' + type + '\''
355
356 # determine quantity
357 if match.group('multi') == '@':
358 argMultiple = 1
359 else:
360 argMultiple = 0
361 ## end else (of not specification)
362
363 # construct specification tuple
364 specTuple = (argType, argMode, argDefault, argMultiple)
365
366 # add the option-- option tuple is (name, specTuple, real name)
367 oTuple = (name, specTuple, name)
368 self._addOption(oTuple)
369
370 for alias in aliases:
371 # drop to all lower (if configured to do so)
372 if self.ignoreCase:
373 alias = string.lower(alias)
374 # create configuration tuple
375 oTuple = (alias, specTuple, name)
376 # add
377 self._addOption(oTuple)
378
379 # successfully parsed....
380 self.needsParse = 0
381
382 def _getArgTuple(self, argName):
383 """
384 Returns a list containing all the specification tuples that
385 match argName. If none match, None is returned. If one
386 matches, a list with one tuple is returned. If more than one
387 match, a list containing all the tuples that matched is
388 returned.
389