2 # Chris Lumens <clumens@redhat.com>
4 # Copyright 2005, 2006 Red Hat, Inc.
6 # This software may be freely redistributed under the terms of the GNU
7 # general public license.
9 # You should have received a copy of the GNU General Public License
10 # along with this program; if not, write to the Free Software
11 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14 Specialized option handling.
16 This module exports two classes:
18 KSOptionParser - A specialized subclass of OptionParser to be used
19 in BaseVersion subclasses.
21 KSOption - A specialized subclass of Option.
25 from optparse
import *
27 from constants
import *
30 from rhpl
.translate
import _
31 import rhpl
.translate
as translate
33 translate
.textdomain("pykickstart")
35 class KSOptionParser(OptionParser
):
36 """A specialized subclass of optparse.OptionParser to handle extra option
37 attribute checking, work error reporting into the KickstartParseError
38 framework, and to turn off the default help.
40 def exit(self
, status
=0, msg
=None):
44 if self
.lineno
!= None:
45 raise KickstartParseError
, formatErrorMsg(self
.lineno
, msg
=msg
)
47 raise KickstartParseError
, msg
52 for opt
in self
.option_list
:
54 retval
.append(opt
.dest
)
58 def _init_parsing_state (self
):
59 OptionParser
._init
_parsing
_state
(self
)
62 def check_values (self
, values
, args
):
63 def seen(self
, option
):
64 return self
.option_seen
.has_key(option
)
66 def usedTooNew(self
, option
):
67 return option
.introduced
and option
.introduced
> self
.version
69 def usedDeprecated(self
, option
):
70 return option
.deprecated
and option
.deprecated
<= self
.version
72 def usedRemoved(self
, option
):
73 return option
.removed
and option
.removed
<= self
.version
75 for option
in filter(lambda o
: isinstance(o
, Option
), self
.option_list
):
76 if option
.required
and not seen(self
, option
):
77 raise KickstartValueError
, formatErrorMsg(self
.lineno
, _("Option %s is required") % option
)
78 elif seen(self
, option
) and usedTooNew(self
, option
):
79 mapping
= {"option": option
, "intro": option
.introduced
, "version": self
.version
}
80 self
.error(_("The option %(option)s was introduced in version %(intro)s, but you are using kickstart syntax version %(version)s") % mapping
)
81 elif seen(self
, option
) and usedDeprecated(self
, option
):
82 mapping
= {"lineno": self
.lineno
, "option": option
}
83 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)
84 elif seen(self
, option
) and usedRemoved(self
, option
):
85 mapping
= {"option": option
, "removed": option
.removed
, "version": self
.version
}
86 self
.error(_("The option %(option)s was removed in version %(removed)s, but you are using kickstart syntax version %(version)s") % mapping
)
90 def __init__(self
, map={}, lineno
=None, version
=None):
91 """Create a new KSOptionParser instance. Each KickstartCommand
92 subclass should create one instance of KSOptionParser, providing
93 at least the lineno attribute. map and version are not required.
96 map -- A mapping from option strings to different values.
97 lineno -- The line number of the line this KSOptionParser instance
99 version -- The version of the kickstart syntax we are checking
104 self
.version
= version
105 OptionParser
.__init
__(self
, option_class
=KSOption
,
106 add_help_option
=False)
108 # Creates a new Option class that supports several new attributes:
109 # - required: any option with this attribute must be supplied or an exception
111 # - introduced: the kickstart syntax version that this option first appeared
112 # in - an exception will be raised if the option is used and
113 # the specified syntax version is less than the value of this
115 # - deprecated: the kickstart syntax version that this option was deprecated
116 # in - a DeprecationWarning will be thrown if the option is
117 # used and the specified syntax version is greater than the
118 # value of this attribute
119 # - removed: the kickstart syntax version that this option was removed in - an
120 # exception will be raised if the option is used and the specified
121 # syntax version is greated than the value of this attribute
122 # Also creates a new type:
123 # - ksboolean: support various kinds of boolean values on an option
124 # And two new actions:
125 # - map : allows you to define an opt -> val mapping such that dest gets val
127 # - map_extend: allows you to define an opt -> [val1, ... valn] mapping such
128 # that dest gets a list of vals built up when opt is seen
129 class KSOption (Option
):
130 ATTRS
= Option
.ATTRS
+ ['introduced', 'deprecated', 'removed', 'required']
131 ACTIONS
= Option
.ACTIONS
+ ("map", "map_extend",)
132 STORE_ACTIONS
= Option
.STORE_ACTIONS
+ ("map", "map_extend",)
134 TYPES
= Option
.TYPES
+ ("ksboolean",)
135 TYPE_CHECKER
= copy(Option
.TYPE_CHECKER
)
137 def _check_required(self
):
138 if self
.required
and not self
.takes_value():
139 raise OptionError(_("Required flag set for option that doesn't take a value"), self
)
141 def _check_ksboolean(option
, opt
, value
):
142 if value
.lower() in ("on", "yes", "true", "1"):
144 elif value
.lower() in ("off", "no", "false", "0"):
147 mapping
= {"opt": opt
, "value": value
}
148 raise OptionValueError(_("Option %(opt)s: invalid boolean value: %(value)r") % mapping
)
150 # Make sure _check_required() is called from the constructor!
151 CHECK_METHODS
= Option
.CHECK_METHODS
+ [_check_required
]
152 TYPE_CHECKER
["ksboolean"] = _check_ksboolean
154 def process (self
, opt
, value
, values
, parser
):
155 Option
.process(self
, opt
, value
, values
, parser
)
156 parser
.option_seen
[self
] = 1
158 # Override default take_action method to handle our custom actions.
159 def take_action(self
, action
, dest
, opt
, value
, values
, parser
):
161 values
.ensure_value(dest
, parser
.map[opt
.lstrip('-')])
162 elif action
== "map_extend":
163 values
.ensure_value(dest
, []).extend(parser
.map[opt
.lstrip('-')])
165 Option
.take_action(self
, action
, dest
, opt
, value
, values
, parser
)