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.

162 lines
5.7 KiB

# vim: fileencoding=utf-8
#
from .base_format import Format
from calculate.utils.package import (
PackageAtomParser,
PackageNotFound,
PackageAtomError
)
from collections import OrderedDict
from typing import List
import os
class WorldFormat(Format):
FORMAT = 'world'
EXECUTABLE = False
_initialized = False
comment_symbol = '#'
def __init__(self, document_text: str,
template_path: str,
ignore_comments: bool = False,
add_header: bool = False,
already_changed: bool = False,
chroot_path="/",
**kwargs):
processing_methods = []
self._atom_parser = PackageAtomParser(chroot_path=chroot_path)
super().__init__(processing_methods)
self._template_name = os.path.basename(template_path)
self._action_symbols = ["!!", "!"]
self.warnings = []
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._document_dictionary = self._lines_to_dictionary(
document_lines)
def _lines_to_dictionary(self, document_lines: List[str]) -> OrderedDict:
output = OrderedDict()
for line in document_lines:
action = None
for action_symbol in self._action_symbols:
if line.startswith(action_symbol):
action = action_symbol
line = line[len(action_symbol):]
break
name_only = line.split(':')[0]
if "/" not in name_only:
line = f"{self._template_name}/{line}"
atom_dict = self._atom_parser.parse_atom_name(line)
atom_dict['package_atom'] = (
f'{atom_dict["category"]}/{atom_dict["name"]}')
if action == "!!":
action = "!"
print("WITH EXISTANCE CHECK")
try:
self._atom_parser._check_package_existance(atom_dict)
print("PACKAGE WAS FOUND")
except (PackageNotFound, PackageAtomError):
print("PACKAGE WAS NOT FOUND")
self.warnings.append(f"package '{line}' not found")
levels = [atom_dict["category"], atom_dict["name"]]
level = output
for next_level in levels:
if next_level not in level:
level[next_level] = OrderedDict()
level = level[next_level]
level[atom_dict["slot"]] = action
return output
def join_template(self, template):
self._document_dictionary = self._change_categories(
template._document_dictionary,
self._document_dictionary)
def _change_categories(self, template: OrderedDict,
original: OrderedDict) -> OrderedDict:
for category, names in template.items():
if category in original:
original_names = original[category]
else:
original_names = OrderedDict()
changed_names = self._change_names(names, original_names)
if not changed_names:
original.pop(category)
else:
original[category] = changed_names
return original
def _change_names(self, template_names: OrderedDict,
original_names: OrderedDict) -> OrderedDict:
for name, slots in template_names.items():
if name in original_names:
original_slots = original_names[name]
else:
original_slots = OrderedDict()
changed_slots = self._change_slots(slots, original_slots)
if not changed_slots:
original_names.pop(name)
else:
original_names[name] = changed_slots
return original_names
def _change_slots(self, template_slots: OrderedDict,
original_slots: OrderedDict) -> OrderedDict:
for slot, action in template_slots.items():
if slot == "*":
if action == "!":
original_slots.clear()
continue
else:
if action == "!" and slot in original_slots:
original_slots.pop(slot)
continue
if action is None and slot not in original_slots:
original_slots[slot] = None
continue
return original_slots
def _get_document_text(self) -> str:
lines = []
categories = sorted(self._document_dictionary.keys())
for category in categories:
names_dict = self._document_dictionary[category]
names = sorted(names_dict.keys())
for name in names:
slots = sorted(names_dict[name].keys())
for slot in slots:
slot = '' if slot is None else f":{slot}"
lines.append(f"{category}/{name}{slot}")
lines.append('')
return "\n".join(lines)
@property
def document_text(self) -> str:
return "{}{}".format(self.header, self._get_document_text())