Apply a couple more 2to3 fixes, still avoiding the hard ones.(#985310).
[pykickstart.git] / pykickstart / sections.py
blob01f700368fe26dd38ec0be3662fe4d6d92ba8676
2 # sections.py: Kickstart file sections.
4 # Chris Lumens <clumens@redhat.com>
6 # Copyright 2011-2014 Red Hat, Inc.
8 # This copyrighted material is made available to anyone wishing to use, modify,
9 # copy, or redistribute it subject to the terms and conditions of the GNU
10 # General Public License v.2. This program is distributed in the hope that it
11 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
12 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 # See the GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 51
17 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
18 # trademarks that are incorporated in the source code or documentation are not
19 # subject to the GNU General Public License and may only be used or replicated
20 # with the express permission of Red Hat, Inc.
22 """
23 This module exports the classes that define a section of a kickstart file. A
24 section is a chunk of the file starting with a %tag and ending with a %end.
25 Examples of sections include %packages, %pre, and %post.
27 You may use this module to define your own custom sections which will be
28 treated just the same as a predefined one by the kickstart parser. All that
29 is necessary is to create a new subclass of Section and call
30 parser.registerSection with an instance of your new class.
31 """
32 from pykickstart.constants import KS_SCRIPT_PRE, KS_SCRIPT_POST, KS_SCRIPT_TRACEBACK, \
33 KS_MISSING_IGNORE, KS_MISSING_PROMPT
34 from pykickstart.errors import KickstartParseError, formatErrorMsg
35 from pykickstart.options import KSOptionParser
36 from pykickstart.version import FC4, F7, F9, F18, F21
38 import gettext
39 _ = lambda x: gettext.ldgettext("pykickstart", x)
41 class Section(object):
42 """The base class for defining kickstart sections. You are free to
43 subclass this as appropriate.
45 Class attributes:
47 allLines -- Does this section require the parser to call handleLine
48 for every line in the section, even blanks and comments?
49 sectionOpen -- The string that denotes the start of this section. You
50 must start your tag with a percent sign.
51 timesSeen -- This attribute is for informational purposes only. It is
52 incremented every time handleHeader is called to keep
53 track of the number of times a section of this type is
54 seen.
55 """
56 allLines = False
57 sectionOpen = ""
58 timesSeen = 0
60 def __init__(self, handler, **kwargs):
61 """Create a new Script instance. At the least, you must pass in an
62 instance of a baseHandler subclass.
64 Valid kwargs:
66 dataObj --
67 """
68 self.handler = handler
70 self.version = self.handler.version
72 self.dataObj = kwargs.get("dataObj", None)
74 def finalize(self):
75 """This method is called when the %end tag for a section is seen. It
76 is not required to be provided.
77 """
78 pass
80 def handleLine(self, line):
81 """This method is called for every line of a section. Take whatever
82 action is appropriate. While this method is not required to be
83 provided, not providing it does not make a whole lot of sense.
85 Arguments:
87 line -- The complete line, with any trailing newline.
88 """
89 pass
91 # pylint: disable=unused-argument
92 def handleHeader(self, lineno, args):
93 """This method is called when the opening tag for a section is seen.
94 Not all sections will need this method, though all provided with
95 kickstart include one.
97 Arguments:
99 args -- A list of all strings passed as arguments to the section
100 opening tag.
102 self.timesSeen += 1
104 @property
105 def seen(self):
106 """This property is given for consistency with KickstartCommand objects
107 only. It simply returns whether timesSeen is non-zero.
109 return self.timesSeen > 0
111 class NullSection(Section):
112 """This defines a section that pykickstart will recognize but do nothing
113 with. If the parser runs across a %section that has no object registered,
114 it will raise an error. Sometimes, you may want to simply ignore those
115 sections instead. This class is useful for that purpose.
117 def __init__(self, *args, **kwargs):
118 """Create a new NullSection instance. You must pass a sectionOpen
119 parameter (including a leading '%') for the section you wish to
120 ignore.
122 Section.__init__(self, *args, **kwargs)
123 self.sectionOpen = kwargs.get("sectionOpen")
125 class ScriptSection(Section):
126 allLines = True
128 def __init__(self, *args, **kwargs):
129 Section.__init__(self, *args, **kwargs)
130 self._script = {}
131 self._resetScript()
133 def _getParser(self):
134 op = KSOptionParser(self.version)
135 op.add_option("--erroronfail", dest="errorOnFail", action="store_true",
136 default=False)
137 op.add_option("--interpreter", dest="interpreter", default="/bin/sh")
138 op.add_option("--log", "--logfile", dest="log")
139 return op
141 def _resetScript(self):
142 self._script = {"interp": "/bin/sh", "log": None, "errorOnFail": False,
143 "lineno": None, "chroot": False, "body": []}
145 def handleLine(self, line):
146 self._script["body"].append(line)
148 def finalize(self):
149 if " ".join(self._script["body"]).strip() == "":
150 return
152 kwargs = {"interp": self._script["interp"],
153 "inChroot": self._script["chroot"],
154 "lineno": self._script["lineno"],
155 "logfile": self._script["log"],
156 "errorOnFail": self._script["errorOnFail"],
157 "type": self._script["type"]}
159 s = self.dataObj (self._script["body"], **kwargs)
160 self._resetScript()
162 if self.handler:
163 self.handler.scripts.append(s)
165 def handleHeader(self, lineno, args):
166 """Process the arguments to a %pre/%post/%traceback header for later
167 setting on a Script instance once the end of the script is found.
168 This method may be overridden in a subclass if necessary.
170 Section.handleHeader(self, lineno, args)
171 op = self._getParser()
173 (opts, _extra) = op.parse_args(args=args[1:], lineno=lineno)
175 self._script["interp"] = opts.interpreter
176 self._script["lineno"] = lineno
177 self._script["log"] = opts.log
178 self._script["errorOnFail"] = opts.errorOnFail
179 if hasattr(opts, "nochroot"):
180 self._script["chroot"] = not opts.nochroot
182 class PreScriptSection(ScriptSection):
183 sectionOpen = "%pre"
185 def _resetScript(self):
186 ScriptSection._resetScript(self)
187 self._script["type"] = KS_SCRIPT_PRE
189 class PostScriptSection(ScriptSection):
190 sectionOpen = "%post"
192 def _getParser(self):
193 op = ScriptSection._getParser(self)
194 op.add_option("--nochroot", dest="nochroot", action="store_true",
195 default=False)
196 return op
198 def _resetScript(self):
199 ScriptSection._resetScript(self)
200 self._script["chroot"] = True
201 self._script["type"] = KS_SCRIPT_POST
203 class TracebackScriptSection(ScriptSection):
204 sectionOpen = "%traceback"
206 def _resetScript(self):
207 ScriptSection._resetScript(self)
208 self._script["type"] = KS_SCRIPT_TRACEBACK
210 class PackageSection(Section):
211 sectionOpen = "%packages"
213 def handleLine(self, line):
214 if not self.handler:
215 return
217 h = line.partition('#')[0]
218 line = h.rstrip()
220 self.handler.packages.add([line])
222 def handleHeader(self, lineno, args):
223 """Process the arguments to the %packages header and set attributes
224 on the Version's Packages instance appropriate. This method may be
225 overridden in a subclass if necessary.
227 Section.handleHeader(self, lineno, args)
228 op = KSOptionParser(version=self.version)
229 op.add_option("--excludedocs", dest="excludedocs", action="store_true",
230 default=False)
231 op.add_option("--ignoremissing", dest="ignoremissing",
232 action="store_true", default=False)
233 op.add_option("--nobase", dest="nobase", action="store_true",
234 default=False, deprecated=F18)
235 op.add_option("--nocore", dest="nocore", action="store_true",
236 default=False, introduced=F21)
237 op.add_option("--ignoredeps", dest="resolveDeps", action="store_false",
238 deprecated=FC4, removed=F9)
239 op.add_option("--resolvedeps", dest="resolveDeps", action="store_true",
240 deprecated=FC4, removed=F9)
241 op.add_option("--default", dest="defaultPackages", action="store_true",
242 default=False, introduced=F7)
243 op.add_option("--instLangs", dest="instLangs", type="string",
244 default="", introduced=F9)
245 op.add_option("--multilib", dest="multiLib", action="store_true",
246 default=False, introduced=F18)
248 (opts, _extra) = op.parse_args(args=args[1:], lineno=lineno)
250 if opts.defaultPackages and opts.nobase:
251 raise KickstartParseError(formatErrorMsg(lineno, msg=_("--default and --nobase cannot be used together")))
252 elif opts.defaultPackages and opts.nocore:
253 raise KickstartParseError(formatErrorMsg(lineno, msg=_("--default and --nocore cannot be used together")))
255 self.handler.packages.excludeDocs = opts.excludedocs
256 self.handler.packages.addBase = not opts.nobase
257 if opts.ignoremissing:
258 self.handler.packages.handleMissing = KS_MISSING_IGNORE
259 else:
260 self.handler.packages.handleMissing = KS_MISSING_PROMPT
262 if opts.defaultPackages:
263 self.handler.packages.default = True
265 if opts.instLangs:
266 self.handler.packages.instLangs = opts.instLangs
268 self.handler.packages.nocore = opts.nocore
269 self.handler.packages.multiLib = opts.multiLib
270 self.handler.packages.seen = True