You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
5.8 KiB

4 years ago
# vim: fileencoding=utf-8
#
from .base_format import Format
4 years ago
from collections import OrderedDict
from pyparsing import Word, Literal, printables, originalTextFor, OneOrMore,\
ParseException, restOfLine, Group, Optional, Regex
4 years ago
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):
4 years ago
processing_methods = [self._parse_comment_line,
self._parse_parameter_line,
self._parse_to_delete_line]
super().__init__(processing_methods)
4 years ago
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()
4 years ago
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):
'''Метод для инициализации парсеров.'''
4 years ago
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'))
4 years ago
cls._parameter_to_delete = (Group(action_symbols('action')
+ parameter_name('name')
)('parameter_name')
+ restOfLine.suppress())
4 years ago
cls._comment_line = originalTextFor(
Literal(cls.comment_symbol)
+ Regex(r'.*'))('comment')
cls._initialized = True
4 years ago
def _parse_parameter_line(self, line):
'''Метод для парсинга строк содержащих параметр.'''
4 years ago
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)
4 years ago
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):
'''Метод для парсинга строк, подлежащих удалению, т.е. для которых
указано имя параметра со знаком !, и опционально присутствует значение
параметра.'''
4 years ago
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)
4 years ago
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):
'''Метод для парсинга строк содержащих комментарий.'''
4 years ago
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