# vim: fileencoding=utf-8 # from .base_format import Format from collections import OrderedDict from pyparsing import Word, Literal, printables, originalTextFor, OneOrMore,\ ParseException, restOfLine, Group, Optional, Regex class OpenRCFormat(Format): FORMAT = 'openrc' EXECUTABLE = False _initialized = False comment_symbol = '#' def __new__(cls, *args, **kwargs): if not cls._initialized: cls._initialize_parser() return super().__new__(cls) def __init__(self, document_text: str, template_path, ignore_comments=False, join_before=False, add_header=False, already_changed=False, **kwargs): processing_methods = [self._parse_comment_line, self._parse_parameter_line, self._parse_to_delete_line] super().__init__(processing_methods) self._ignore_comments = ignore_comments self._comments_processing = True self._last_comments_list = [] if add_header and not ignore_comments: self.header, document_text = self._get_header_and_document_text( document_text, template_path, already_changed=already_changed) else: self.header = '' document_text = document_text.strip() if document_text == '': self._document_dictionary = OrderedDict() else: document_lines = self._get_list_of_logic_lines(document_text) self._lines_to_dictionary(document_lines) def join_template(self, template: "OpenRCFormat") -> None: '''Метод запускающий наложение шаблона.''' self._document_dictionary = self._correct_register(template) self._join(self._document_dictionary, template._document_dictionary, self._join_before) def _correct_register(self, template: "OpenRCFormat") -> dict: '''Метод для корректировки всех регистров.''' corrected_dict = OrderedDict() template_keys = {key[1].lower(): key[1] for key in template._document_dictionary.keys()} for key, value in self._document_dictionary.items(): if key[1].lower() in template_keys: corrected_dict[('', template_keys[key[1].lower()])] = value else: corrected_dict[key] = value return corrected_dict @classmethod def _initialize_parser(cls): '''Метод для инициализации парсеров.''' parameter_name = Word(printables, excludeChars='=') parameter_value = originalTextFor(OneOrMore(Word(printables))) action_symbols = (Literal('!') | Literal('-')) cls._parameter_line = (Group(Optional(action_symbols, default='')('action') + parameter_name('name'))('parameter_name') + Literal('=').suppress() + parameter_value('parameter_value')) cls._parameter_to_delete = (Group(action_symbols('action') + parameter_name('name') )('parameter_name') + restOfLine.suppress()) cls._comment_line = originalTextFor( Literal(cls.comment_symbol) + Regex(r'.*'))('comment') cls._initialized = True def _parse_parameter_line(self, line): '''Метод для парсинга строк содержащих параметр.''' try: self._item_to_add = OrderedDict() parsing_result = self._parameter_line.parseString(line) key_value = (parsing_result.parameter_name.action, parsing_result.parameter_name.name) parameter_value = parsing_result.parameter_value parameter_value = self._last_comments_list + [parameter_value] self._last_comments_list = [] self._item_to_add[key_value] = parameter_value self._ready_to_update = True self._match = True except ParseException: return def _parse_to_delete_line(self, line): '''Метод для парсинга строк, подлежащих удалению, т.е. для которых указано имя параметра со знаком !, и опционально присутствует значение параметра.''' try: self._item_to_add = OrderedDict() parsing_result = self._parameter_to_delete.parseString(line) if parsing_result.parameter_name.action == '-': return key_value = (parsing_result.parameter_name.action, parsing_result.parameter_name.name) parameter_value = self._last_comments_list self._last_comments_list = [] self._item_to_add[key_value] = parameter_value self._ready_to_update = True self._match = True except ParseException: return def _parse_comment_line(self, line): '''Метод для парсинга строк содержащих комментарий.''' try: result = self._comment_line.parseString(line) self._match = True if not self._ignore_comments: self._last_comments_list.append(result.comment) except ParseException: return