#
# Support for %addon sections.
#
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
from abc import ABCMeta, abstractmethod
from types import SimpleNamespace
from pykickstart.errors import KickstartParseError
from pykickstart.ko import KickstartObject
from pykickstart.sections import Section
from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core.i18n import _
log = get_module_logger(__name__)
__all__ = ["AddonData", "AddonSection", "AddonRegistry"]
class AddonData(KickstartObject, metaclass=ABCMeta):
"""Kickstart data for addon.
This is a common parent class for loading and storing 3rd
party data to kickstart. It is instantiated by kickstart
parser and stored as ksdata.addons. to be used in
the user interfaces.
The following methods have to be implemented:
* handle_header handles arguments of the section
* handle_line is called for every line of the section
* __str__ returns a kickstart representation of the section
"""
@abstractmethod
def handle_header(self, args, line_number=None):
"""Handle the arguments of the %addon line.
This function receives any arguments on the %addon line
after the name. For example, for the line:
%addon com_example_foo --argument='example'
This function would be called with:
args=["--argument='example'"].
:param args: a list of additional arguments
:param line_number: a line number
:raise: KickstartParseError for invalid arguments
"""
pass
@abstractmethod
def handle_line(self, line, line_number=None):
"""Handle one line of the section.
:param line: a line to parse
:param line_number: a line number
:raise: KickstartParseError for invalid lines
"""
pass
def handle_end(self):
"""Handle the end of the section.."""
pass
@abstractmethod
def __str__(self):
"""Generate the kickstart representation.
Generate the %addon section for your addon.
For example:
%addon com_example_foo --argument='example'
My lines.
%end
:return: a string
"""
return ""
class AddonSection(Section):
"""Parser of the %addon sections.
Parses the name of the current %addon section and propagates
all arguments and lines of this section to the addon with the
specified name.
"""
sectionOpen = "%addon"
def __init__(self, handler, **kwargs):
super().__init__(handler, **kwargs)
self.data = None
self.line_number = None
def handleHeader(self, lineno, args):
"""Handle a header of the current %addon section.
This method is called when the opening tag for a section is
seen. Not all sections will need this method, though all
provided with kickstart include one.
:param lineno: a number of the current line
:param args: a list of strings passed as arguments
"""
super().handleHeader(lineno, args)
if not args:
raise KickstartParseError(
_("Missing name of the %addon section."),
lineno=lineno
)
name = args[1]
arguments = args[2:]
data = getattr(self.handler.addons, name, None)
if not data:
raise KickstartParseError(
_("Unknown name of the %addon section."),
lineno=lineno
)
self.data = data
self.line_number = lineno
self.data.handle_header(arguments, self.line_number)
def handleLine(self, line):
"""Handle one line of the current %addon section.
This method is called for every line of a section. Take
whatever action is appropriate. While this method is not
required to be provided, not providing it does not make
a whole lot of sense.
:param line: a complete line, with any trailing newline
"""
if not self.handler:
return
self.line_number += 1
self.data.handle_line(line, self.line_number)
def finalize(self):
"""Handle the end of the current %addon section.
This method is called when the %end tag for a section is
seen.
"""
super().finalize()
self.data.handle_end()
self.data = None
class AddonRegistry(SimpleNamespace):
"""Data holder of the %addon sections.
Provides access to instances of AddonData from the handler.
For example:
handler.addons.com_example_foo
"""
pass