# # 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