Merge release-0.28.17 from 'tools/mic'
[platform/upstream/mic.git] / mic / 3rdparty / pykickstart / options.py
1 #
2 # Chris Lumens <clumens@redhat.com>
3 #
4 # Copyright 2005, 2006, 2007 Red Hat, Inc.
5 #
6 # This copyrighted material is made available to anyone wishing to use, modify,
7 # copy, or redistribute it subject to the terms and conditions of the GNU
8 # General Public License v.2.  This program is distributed in the hope that it
9 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
10 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # See the GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  Any Red Hat
16 # trademarks that are incorporated in the source code or documentation are not
17 # subject to the GNU General Public License and may only be used or replicated
18 # with the express permission of Red Hat, Inc. 
19 #
20 """
21 Specialized option handling.
22
23 This module exports two classes:
24
25     KSOptionParser - A specialized subclass of OptionParser to be used
26                      in BaseHandler subclasses.
27
28     KSOption - A specialized subclass of Option.
29 """
30 import warnings
31 from copy import copy
32 from optparse import *
33
34 from constants import *
35 from errors import *
36 from version import *
37
38 import gettext
39 _ = lambda x: gettext.ldgettext("pykickstart", x)
40
41 class KSOptionParser(OptionParser):
42     """A specialized subclass of optparse.OptionParser to handle extra option
43        attribute checking, work error reporting into the KickstartParseError
44        framework, and to turn off the default help.
45     """
46     def exit(self, status=0, msg=None):
47         pass
48
49     def error(self, msg):
50         if self.lineno != None:
51             raise KickstartParseError ( formatErrorMsg(self.lineno, msg=msg))
52         else:
53             raise KickstartParseError ( msg)
54
55     def keys(self):
56         retval = []
57
58         for opt in self.option_list:
59             if opt not in retval:
60                 retval.append(opt.dest)
61
62         return retval
63
64     def _init_parsing_state (self):
65         OptionParser._init_parsing_state(self)
66         self.option_seen = {}
67
68     def check_values (self, values, args):
69         def seen(self, option):
70             return self.option_seen.has_key(option)
71
72         def usedTooNew(self, option):
73             return option.introduced and option.introduced > self.version
74
75         def usedDeprecated(self, option):
76             return option.deprecated
77
78         def usedRemoved(self, option):
79             return option.removed and option.removed <= self.version
80
81         for option in filter(lambda o: isinstance(o, Option), self.option_list):
82             if option.required and not seen(self, option):
83                 raise KickstartValueError (formatErrorMsg(self.lineno, _("Option %s is required") % option))
84             elif seen(self, option) and usedTooNew(self, option):
85                 mapping = {"option": option, "intro": versionToString(option.introduced),
86                            "version": versionToString(self.version)}
87                 self.error(_("The %(option)s option was introduced in version %(intro)s, but you are using kickstart syntax version %(version)s.") % mapping)
88             elif seen(self, option) and usedRemoved(self, option):
89                 mapping = {"option": option, "removed": versionToString(option.removed),
90                            "version": versionToString(self.version)}
91
92                 if option.removed == self.version:
93                     self.error(_("The %(option)s option is no longer supported.") % mapping)
94                 else:
95                     self.error(_("The %(option)s option was removed in version %(removed)s, but you are using kickstart syntax version %(version)s.") % mapping)
96             elif seen(self, option) and usedDeprecated(self, option):
97                 mapping = {"lineno": self.lineno, "option": option}
98                 warnings.warn(_("Ignoring deprecated option on line %(lineno)s:  The %(option)s option has been deprecated and no longer has any effect.  It may be removed from future releases, which will result in a fatal error from kickstart.  Please modify your kickstart file to remove this option.") % mapping, DeprecationWarning)
99
100         return (values, args)
101
102     def parse_args(self, *args, **kwargs):
103         if kwargs.has_key("lineno"):
104             self.lineno = kwargs.pop("lineno")
105
106         return OptionParser.parse_args(self, **kwargs)
107
108     def __init__(self, mapping=None, version=None):
109         """Create a new KSOptionParser instance.  Each KickstartCommand
110            subclass should create one instance of KSOptionParser, providing
111            at least the lineno attribute.  mapping and version are not required.
112            Instance attributes:
113
114            mapping -- A mapping from option strings to different values.
115            version -- The version of the kickstart syntax we are checking
116                       against.
117         """
118         OptionParser.__init__(self, option_class=KSOption,
119                               add_help_option=False,
120                               conflict_handler="resolve")
121         if mapping is None:
122             self.map = {}
123         else:
124             self.map = mapping
125
126         self.lineno = None
127         self.option_seen = {}
128         self.version = version
129
130 def _check_ksboolean(option, opt, value):
131     if value.lower() in ("on", "yes", "true", "1"):
132         return True
133     elif value.lower() in ("off", "no", "false", "0"):
134         return False
135     else:
136         mapping = {"opt": opt, "value": value}
137         raise OptionValueError(_("Option %(opt)s: invalid boolean value: %(value)r") % mapping)
138
139 def _check_string(option, opt, value):
140     #if len(value) > 2 and value.startswith("--"):
141         #mapping = {"opt": opt, "value": value}
142         #raise OptionValueError(_("Option %(opt)s: invalid string value: %(value)r") % mapping)
143    # else:
144     return value
145
146 # Creates a new Option class that supports several new attributes:
147 # - required:  any option with this attribute must be supplied or an exception
148 #              is thrown
149 # - introduced:  the kickstart syntax version that this option first appeared
150 #                in - an exception will be raised if the option is used and
151 #                the specified syntax version is less than the value of this
152 #                attribute
153 # - deprecated:  the kickstart syntax version that this option was deprecated
154 #                in - a DeprecationWarning will be thrown if the option is
155 #                used and the specified syntax version is greater than the
156 #                value of this attribute
157 # - removed:  the kickstart syntax version that this option was removed in - an
158 #             exception will be raised if the option is used and the specified
159 #             syntax version is greated than the value of this attribute
160 # Also creates a new type:
161 # - ksboolean:  support various kinds of boolean values on an option
162 # And two new actions:
163 # - map :  allows you to define an opt -> val mapping such that dest gets val
164 #          when opt is seen
165 # - map_extend:  allows you to define an opt -> [val1, ... valn] mapping such
166 #                that dest gets a list of vals built up when opt is seen
167 class KSOption (Option):
168     ATTRS = Option.ATTRS + ['introduced', 'deprecated', 'removed', 'required']
169     ACTIONS = Option.ACTIONS + ("map", "map_extend",)
170     STORE_ACTIONS = Option.STORE_ACTIONS + ("map", "map_extend",)
171
172     TYPES = Option.TYPES + ("ksboolean", "string")
173     TYPE_CHECKER = copy(Option.TYPE_CHECKER)
174     TYPE_CHECKER["ksboolean"] = _check_ksboolean
175     TYPE_CHECKER["string"] = _check_string
176
177     def _check_required(self):
178         if self.required and not self.takes_value():
179             raise OptionError(_("Required flag set for option that doesn't take a value"), self)
180
181     # Make sure _check_required() is called from the constructor!
182     CHECK_METHODS = Option.CHECK_METHODS + [_check_required]
183
184     def process (self, opt, value, values, parser):
185         Option.process(self, opt, value, values, parser)
186         parser.option_seen[self] = 1
187
188     # Override default take_action method to handle our custom actions.
189     def take_action(self, action, dest, opt, value, values, parser):
190         if action == "map":
191             values.ensure_value(dest, parser.map[opt.lstrip('-')])
192         elif action == "map_extend":
193             values.ensure_value(dest, []).extend(parser.map[opt.lstrip('-')])
194         else:
195             Option.take_action(self, action, dest, opt, value, values, parser)
196
197     def takes_value(self):
198         # Deprecated options don't take a value.
199         return Option.takes_value(self) and not self.deprecated
200
201     def __init__(self, *args, **kwargs):
202         self.deprecated = False
203         self.required = False
204         Option.__init__(self, *args, **kwargs)