|
|
|
@ -3,6 +3,7 @@
|
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
from jinja2 import Environment, PackageLoader
|
|
|
|
|
from pprint import pprint
|
|
|
|
|
from copy import copy
|
|
|
|
|
try:
|
|
|
|
|
from lxml.etree.ElementTree import fromstring
|
|
|
|
|
except ImportError:
|
|
|
|
@ -96,40 +97,76 @@ class BaseFormat():
|
|
|
|
|
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)
|
|
|
|
|
del(original[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 not isinstance(template[key_value], dict):
|
|
|
|
|
original[item_to_replace] = template[key_value]
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Если обработка комментариев включена -- сохраняем
|
|
|
|
|
# комментарии к заменяемой секции.
|
|
|
|
|
if self._comments_processing:
|
|
|
|
|
if '#' in original[item_to_replace]:
|
|
|
|
|
replaced = OrderedDict({'#':
|
|
|
|
|
original[item_to_replace]['#']}
|
|
|
|
|
)
|
|
|
|
|
replaced.update(template[key_value])
|
|
|
|
|
replacement = OrderedDict({'#':
|
|
|
|
|
original[item_to_replace]
|
|
|
|
|
['#']}
|
|
|
|
|
)
|
|
|
|
|
# накладываем словарь шаблона на пустой словарь, чтобы
|
|
|
|
|
# выполнить все управляющие элементы, которые
|
|
|
|
|
# могут туда попасть.
|
|
|
|
|
self._join(replacement,
|
|
|
|
|
template[key_value],
|
|
|
|
|
self._join_before_in_areas)
|
|
|
|
|
else:
|
|
|
|
|
replaced = template[key_value]
|
|
|
|
|
replacement = OrderedDict()
|
|
|
|
|
self._join(replacement,
|
|
|
|
|
template[key_value],
|
|
|
|
|
self._join_before_in_areas)
|
|
|
|
|
|
|
|
|
|
original[item_to_replace] = replaced
|
|
|
|
|
# Если после наложения шаблона словарь замены оказался
|
|
|
|
|
# пустым -- удаляем соотвествующий элемент в оригинале.
|
|
|
|
|
if (replacement == OrderedDict() or
|
|
|
|
|
replacement.keys() == {'#'}):
|
|
|
|
|
del(original[item_to_replace])
|
|
|
|
|
else:
|
|
|
|
|
original[item_to_replace] = replacement
|
|
|
|
|
else:
|
|
|
|
|
original[item_to_replace] = template[key_value]
|
|
|
|
|
original[item_to_replace] = OrderedDict()
|
|
|
|
|
self._join(original[item_to_replace],
|
|
|
|
|
template[key_value],
|
|
|
|
|
self._join_before_in_areas)
|
|
|
|
|
|
|
|
|
|
if (original[item_to_replace] == OrderedDict() or
|
|
|
|
|
original[item_to_replace].keys() == {'#'}):
|
|
|
|
|
del(original[item_to_replace])
|
|
|
|
|
|
|
|
|
|
elif key_value not in original.keys():
|
|
|
|
|
if isinstance(template[key_value], dict):
|
|
|
|
@ -163,6 +200,89 @@ class BaseFormat():
|
|
|
|
|
original[key_value] = forwarded_items[key_value]
|
|
|
|
|
original.move_to_end(key_value, last=False)
|
|
|
|
|
|
|
|
|
|
def make_template(self, template):
|
|
|
|
|
full_diff, set_to_check = self.compare_dictionaries(
|
|
|
|
|
self._document_dictionary,
|
|
|
|
|
template._document_dictionary
|
|
|
|
|
)
|
|
|
|
|
template_object = copy(self)
|
|
|
|
|
template_object._document_dictionary = full_diff
|
|
|
|
|
return template_object
|
|
|
|
|
|
|
|
|
|
def compare_dictionaries(self, dict_1, dict_2):
|
|
|
|
|
to_remove_dictionary = OrderedDict()
|
|
|
|
|
to_add_dictionary = OrderedDict()
|
|
|
|
|
to_replace_dictionary = OrderedDict()
|
|
|
|
|
unchanged_set = set()
|
|
|
|
|
|
|
|
|
|
to_remove = dict_1.keys() - dict_2.keys()
|
|
|
|
|
|
|
|
|
|
if '#' in to_remove:
|
|
|
|
|
to_remove.remove('#')
|
|
|
|
|
|
|
|
|
|
for key in dict_1:
|
|
|
|
|
if key in to_remove:
|
|
|
|
|
if isinstance(key, tuple):
|
|
|
|
|
new_key = ('!', *key[1:])
|
|
|
|
|
else:
|
|
|
|
|
new_key = '!{}'.format(key)
|
|
|
|
|
if isinstance(dict_1[key], dict):
|
|
|
|
|
to_remove_dictionary.update({new_key: dict_1[key]})
|
|
|
|
|
else:
|
|
|
|
|
if self._comments_processing:
|
|
|
|
|
to_remove_dictionary.update({new_key:
|
|
|
|
|
[dict_1[key][-1]]})
|
|
|
|
|
else:
|
|
|
|
|
to_remove_dictionary.update({new_key: dict_1[key]})
|
|
|
|
|
|
|
|
|
|
to_add = dict_2.keys() - dict_1.keys()
|
|
|
|
|
|
|
|
|
|
if '#' in to_add:
|
|
|
|
|
to_add.remove('#')
|
|
|
|
|
|
|
|
|
|
for key in dict_2:
|
|
|
|
|
if key in to_add:
|
|
|
|
|
if isinstance(dict_2[key], dict):
|
|
|
|
|
section = dict_2[key].copy()
|
|
|
|
|
if '#' in section:
|
|
|
|
|
section.remove('#')
|
|
|
|
|
to_add_dictionary.update({key: section})
|
|
|
|
|
else:
|
|
|
|
|
if self._comments_processing:
|
|
|
|
|
to_add_dictionary.update({key: [dict_2[key][-1]]})
|
|
|
|
|
else:
|
|
|
|
|
to_add_dictionary.update({key: dict_2[key]})
|
|
|
|
|
|
|
|
|
|
intersect = dict_1.keys() & dict_2.keys()
|
|
|
|
|
for key in intersect:
|
|
|
|
|
if (isinstance(dict_1[key], dict) and
|
|
|
|
|
isinstance(dict_2[key], dict) and
|
|
|
|
|
dict_1[key] != dict_2[key]):
|
|
|
|
|
diff, set_to_check = self.compare_dictionaries(dict_1[key],
|
|
|
|
|
dict_2[key])
|
|
|
|
|
if set_to_check:
|
|
|
|
|
to_add_dictionary.update({key: diff})
|
|
|
|
|
else:
|
|
|
|
|
if isinstance(key, tuple):
|
|
|
|
|
new_key = ('-', *key[1:])
|
|
|
|
|
else:
|
|
|
|
|
new_key = '-{}'.format(key)
|
|
|
|
|
to_replace_dictionary.update({new_key:
|
|
|
|
|
dict_2[key]})
|
|
|
|
|
elif dict_1[key] != dict_2[key]:
|
|
|
|
|
if self._comments_processing:
|
|
|
|
|
to_add_dictionary.update({key: [dict_2[key][-1]]})
|
|
|
|
|
else:
|
|
|
|
|
to_add_dictionary.update({key: dict_2[key]})
|
|
|
|
|
else:
|
|
|
|
|
unchanged_set.add(key)
|
|
|
|
|
|
|
|
|
|
full_diff = OrderedDict()
|
|
|
|
|
full_diff.update(**to_remove_dictionary,
|
|
|
|
|
**to_replace_dictionary,
|
|
|
|
|
**to_add_dictionary)
|
|
|
|
|
return full_diff, unchanged_set
|
|
|
|
|
|
|
|
|
|
def get_document_text(self):
|
|
|
|
|
file_loader = PackageLoader('calculate.templates.format',
|
|
|
|
|
self.TEMPLATES_DIRECTORY)
|
|
|
|
|