|
|
|
|
# vim: fileencoding=utf-8
|
|
|
|
|
#
|
|
|
|
|
from .base_format import Format
|
|
|
|
|
from ..template_engine import ParametersContainer
|
|
|
|
|
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,
|
|
|
|
|
parameters=ParametersContainer()):
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
@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.lower())
|
|
|
|
|
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.lower())
|
|
|
|
|
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
|