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.

189 lines
7.3 KiB

# vim: fileencoding=utf-8
#
from collections import OrderedDict
from jinja2 import Environment, PackageLoader
from pprint import pprint
try:
from lxml.etree.ElementTree import fromstring
except ImportError:
from xml.etree.ElementTree import fromstring
class BaseFormat():
def __init__(self, processing_methods):
self._processing_methods = processing_methods
self._document_dictionary = OrderedDict()
self._item_to_add = OrderedDict()
self._format = 'none'
self.TEMPLATES_DIRECTORY = 'templates'
self._fatal_error_flag = False
self._ready_to_update = False
self._match = False
self._need_finish = False
self._comments_processing = False
self._join_before = False
self._join_before_in_areas = False
# для отладки.
self._line_timer = 0
def _lines_to_dictionary(self, document_lines):
# print('Lines processing...')
for line in document_lines:
# print(self._line_timer, '\t', line)
for processing_method in self._processing_methods:
processing_method(line)
if self._fatal_error_flag:
# Действия если файл невозможно разобрать.
print('Can not parse file.')
self._document_dictionary = OrderedDict()
return
if self._is_match():
if self._is_ready_to_update():
self._document_dictionary.update(self._item_to_add)
break
else:
# Действия если не удалось разобрать строку.
print('Line', self._line_timer,
'is not correct. Can not parse file.')
self._document_dictionary = OrderedDict()
return
self._line_timer += 1
if self._need_finish:
self._finish_method()
def _parse_xml_to_dictionary(self, xml_document_text):
root = fromstring(xml_document_text)
self._document_dictionary = self._processing_methods[root.tag](root)
def print_dictionary(self):
pprint(self._document_dictionary)
def join_template(self, template):
self._join(self._document_dictionary,
template._document_dictionary,
self._join_before)
def _get_list_of_logic_lines(self, text):
list_of_lines = []
lines_to_join = []
for line in text.splitlines():
line = line.strip()
if line == '':
continue
if not line.endswith("\\"):
lines_to_join.append(line)
joined_line = "".join(lines_to_join)
list_of_lines.append(joined_line)
lines_to_join = []
else:
lines_to_join.append(line[:-1])
return list_of_lines
def _join(self, original, template, join_before):
if template == OrderedDict():
return
if join_before:
forwarded_items = OrderedDict()
for key_value in template:
if key_value[0] == '!':
# Удаление соответствующего элемента из original.
if isinstance(key_value, tuple):
item_to_delete = ('',) + key_value[1:]
elif isinstance(key_value, str):
item_to_delete = key_value[1:]
if item_to_delete in original.keys():
original.pop(item_to_delete)
elif key_value[0] == '-':
# Замена соответствующего элемента из original.
if isinstance(key_value, tuple):
item_to_replace = ('',) + key_value[1:]
elif isinstance(key_value, str):
item_to_replace = key_value[1:]
if item_to_replace not in original.keys():
continue
if isinstance(template[key_value], dict) and\
template[key_value] == OrderedDict():
original.pop(item_to_replace)
continue
if self._comments_processing:
if '#' in original[item_to_replace]:
replaced = OrderedDict({'#':
original[item_to_replace]['#']}
)
replaced.update(template[key_value])
else:
replaced = template[key_value]
original[item_to_replace] = replaced
else:
original[item_to_replace] = template[key_value]
elif key_value not in original.keys():
if isinstance(template[key_value], dict):
dictionary_to_add = OrderedDict()
self._join(dictionary_to_add,
template[key_value],
self._join_before_in_areas)
if dictionary_to_add != OrderedDict():
if not join_before:
original[key_value] = dictionary_to_add
else:
forwarded_items[key_value] = dictionary_to_add
else:
if not join_before:
original[key_value] = template[key_value]
else:
forwarded_items[key_value] = template[key_value]
else:
if isinstance(original[key_value], dict) and \
isinstance(template[key_value], dict):
self._join(original[key_value],
template[key_value],
self._join_before_in_areas)
else:
if self._comments_processing:
original[key_value][-1] = template[key_value][-1]
else:
original[key_value] = template[key_value]
if join_before:
for key_value in reversed(forwarded_items.keys()):
original[key_value] = forwarded_items[key_value]
original.move_to_end(key_value, last=False)
def get_document_text(self):
file_loader = PackageLoader('calculate.templates.format',
self.TEMPLATES_DIRECTORY)
formats_environment = Environment(loader=file_loader,
trim_blocks=True,
lstrip_blocks=True)
formats_environment.globals.update(zip=zip)
formats_environment.add_extension('jinja2.ext.do')
template = formats_environment.get_template(self._format)
document_text = template.render(
document_dictionary=self._document_dictionary
)
return document_text
def _finish_method(self):
pass
def _is_ready_to_update(self):
is_ready, self._match = self._ready_to_update, False
return is_ready
def _is_match(self):
is_match, self._match = self._match, False
return is_match