diff --git a/calculate/scripts/scripts.py b/calculate/scripts/scripts.py index c7d9218..ccc7ea2 100644 --- a/calculate/scripts/scripts.py +++ b/calculate/scripts/scripts.py @@ -46,18 +46,18 @@ class Script: в себе. Создает экземпляры лаунчеров.''' def __init__(self, script_id: str, args: List[Any] = [], - success_message: str = None, - failed_message: str = None, - interrupt_message: str = None): + success_message: Union[str, None] = None, + failed_message: Union[str, None] = None, + interrupt_message: Union[str, None] = None): self._id: str = script_id self.__items: List[Union['Task', 'Block', 'Handler', 'Run']] = None self.__tasks_is_set: bool = False self.__args: list = args - self.__success_message: str = success_message - self.__failed_message: str = failed_message - self.__interrupt_message: str = interrupt_message + self.__success_message: Union[str, None] = success_message + self.__failed_message: Union[str, None] = failed_message + self.__interrupt_message: Union[str, None] = interrupt_message @property def id(self) -> str: diff --git a/calculate/templates/template_engine.py b/calculate/templates/template_engine.py index 4939428..82e9823 100644 --- a/calculate/templates/template_engine.py +++ b/calculate/templates/template_engine.py @@ -18,10 +18,13 @@ import copy import re import os import stat +from typing import Union, Any, List from ..utils.package import ( + PackageAtomName, PackageAtomParser, PackageAtomError, + Package, NOTEXIST, Version ) @@ -123,48 +126,51 @@ class Variables(MutableMapping): class ParametersProcessor: '''Класс для проверки и разбора параметров шаблона.''' - available_parameters = {'name', 'path', 'append', 'chmod', 'chown', - 'autoupdate', 'env', 'force', 'source', 'format', - 'unbound', 'mirror', 'run', 'exec', 'env', - 'package', 'merge', 'postmerge', 'action', - 'rebuild', 'restart', 'stop', 'start', 'handler', - 'notify', 'group'} + available_parameters: set = {'name', 'path', 'append', 'chmod', 'chown', + 'autoupdate', 'env', 'force', 'source', + 'format', 'unbound', 'mirror', 'run', 'exec', + 'env', 'package', 'merge', 'postmerge', + 'action', 'rebuild', 'restart', 'stop', + 'start', 'handler', 'notify', 'group'} - inheritable_parameters = {'chmod', 'chown', 'autoupdate', 'env', - 'package', 'action', 'handler', 'group'} + inheritable_parameters: set = {'chmod', 'chown', 'autoupdate', 'env', + 'package', 'action', 'handler', 'group'} # Параметры по умолчанию для файлов -- # будут заполняться из __datavars__ - file_default_parameters = {} + file_default_parameters: dict = {} # Параметры по умолчанию для директорий -- # будут заполняться из __datavars__ - directory_default_parameters = {} + directory_default_parameters: dict = {} - available_appends = set() + available_appends: set = set() - available_formats = dict() + available_formats: dict = dict() - format_is_inspected = False + format_is_inspected: bool = False chmod_value_regular = re.compile( r'([r-][w-][x-])([r-][w-][x-])([r-][w-][x-])') - def __init__(self, parameters_container=None, - chroot_path='/', - datavars_module=Variables(), - for_package=None): - self.chroot_path = chroot_path + def __init__(self, + parameters_container: Union["ParametersContainer", + None] = None, + chroot_path: str = '/', + datavars_module: Union[Datavars, Variables] = Variables(), + for_package: Union[Package, None] = None): + self.chroot_path: str = chroot_path - self.template_type = DIR + self.template_type: int = DIR - self.datavars_module = datavars_module + self.datavars_module: Union[Datavars, Variables] = datavars_module - self._parameters_container = parameters_container + self._parameters_container: ParametersContainer = parameters_container - self.package_atom_parser = PackageAtomParser(chroot_path=chroot_path) + self.package_atom_parser: PackageAtomParser =\ + PackageAtomParser(chroot_path=chroot_path) - self._groups = {} + self._groups: dict = {} try: groups = list(datavars_module.main.cl.groups._variables.keys()) for group in groups: @@ -179,7 +185,7 @@ class ParametersProcessor: self._inspect_formats_package() - self._for_package = None + self._for_package: Union[Package, None] = for_package # Если добавляемый параметр нуждается в проверке -- добавляем сюда # метод для проверки. @@ -222,20 +228,22 @@ class ParametersProcessor: # указываем здесь эти условия. self.inherit_conditions = {'chmod': self.is_chmod_inheritable} - def set_parameters_container(self, parameters_container): + def set_parameters_container(self, + parameters_container: "ParametersContainer" + ) -> None: '''Метод для установки текущего контейнера параметров.''' self._parameters_container = parameters_container self._added_parameters = set() @property - def for_package(self): + def for_package(self) -> Union[Package, None]: return self._for_package @for_package.setter - def for_package(self, package): + def for_package(self, package: Package): self._for_package = package - def __getattr__(self, parameter_name): + def __getattr__(self, parameter_name: str) -> Any: if parameter_name not in self.available_parameters: raise IncorrectParameter("Unknown parameter: '{}'". format(parameter_name)) @@ -244,8 +252,9 @@ class ParametersProcessor: else: return self._parameters_container[parameter_name] - def check_template_parameter(self, parameter_name, parameter_value, - template_type, lineno): + def check_template_parameter(self, parameter_name: str, + parameter_value: Any, + template_type: int, lineno: int) -> None: '''Метод, проверяющий указанный параметр.''' self.lineno = lineno self.template_type = template_type @@ -280,7 +289,7 @@ class ParametersProcessor: self._parameters_container.set_parameter( {parameter_name: checked_value}) - def check_postparse_parameters(self): + def check_postparse_parameters(self) -> None: '''Метод, запускающий проверку параметров после их разбора.''' for parameter, parameter_checker in\ self.postparse_checkers_list.items(): @@ -292,7 +301,8 @@ class ParametersProcessor: self._parameters_container.change_parameter(parameter, result) - def check_template_parameters(self, parameters, template_type, lineno): + def check_template_parameters(self, parameters: dict, + template_type: int, lineno: int) -> None: '''Метод, запускающий проверку указанных параметров.''' self.template_type = template_type self.lineno = lineno @@ -326,14 +336,14 @@ class ParametersProcessor: # Методы для проверки параметров во время разбора шаблона. - def check_package_parameter(self, parameter_value): + def check_package_parameter(self, parameter_value: Any) -> str: if not isinstance(parameter_value, str): raise IncorrectParameter("'package' parameter must have value of" " the 'str' type, not" f" {type(parameter_value)}") return parameter_value - def check_group_parameter(self, parameter_value): + def check_group_parameter(self, parameter_value: Any) -> List[str]: if isinstance(parameter_value, str): result = [group.strip() for group in parameter_value.split(',')] elif isinstance(parameter_value, (list, tuple)): @@ -350,13 +360,14 @@ class ParametersProcessor: f" {', '.join(self._groups.keys())}") return result - def check_append_parameter(self, parameter_value): + def check_append_parameter(self, parameter_value: Any) -> str: if parameter_value not in self.available_appends: raise IncorrectParameter("Unacceptable value '{}' of parameter" " 'append'".format(parameter_value)) return parameter_value - def check_merge_parameter(self, parameter_value): + def check_merge_parameter(self, parameter_value: Any + ) -> List[PackageAtomName]: packages_list = [] packages_names = parameter_value.split(',') @@ -369,15 +380,15 @@ class ParametersProcessor: return packages_list - def check_rebuild_parameter(self, parameter_value): - if isinstance(parameter_value, bool): + def check_rebuild_parameter(self, parameter_value: Any) -> bool: + if not isinstance(parameter_value, bool): raise IncorrectParameter("'rebuild' parameter value is not bool") elif 'package' not in self._parameters_container: raise IncorrectParameter(("'rebuild' parameter is set without " "'package' parameter")) return parameter_value - def check_restart_parameter(self, parameter_value): + def check_restart_parameter(self, parameter_value: Any) -> str: if parameter_value and isinstance(parameter_value, str): return parameter_value else: @@ -614,6 +625,8 @@ class ParametersProcessor: " in handler templates.") def check_postparse_package(self, parameter_value): + print('check package value:', parameter_value) + print('groups:', self._groups) groups = [] package_atom = PackageAtomParser.parse_atom_name(parameter_value) @@ -637,18 +650,24 @@ class ParametersProcessor: raise IncorrectParameter(error.message) elif self._check_package_group(package_atom, self._groups[group]): - self._parameters_container.remove_parameter('package') + print('successfully checked') + if (self._parameters_container is not None + and self._parameters_container.package): + self._parameters_container.remove_parameter('package') return raise ConditionFailed(f"package '{parameter_value}'" " does not match the template condition", - self.lineno) + self.lineno if hasattr(self, 'lineno') else 0) def _check_package_group(self, package: dict, group_packages: list): '''Метод для проверки соответствия описания пакета, заданного словарем, какому-либо описанию пакета, заданного в переменных groups.''' + print(f'CHECK\n{package}') for group_package in group_packages: + print(f'WITH GROUP PACKAGE {group_package}') for parameter in ['category', 'name', 'version', 'slot']: + print(f"checkin' {parameter}") if package[parameter] is not None: if (group_package[parameter] is None or group_package[parameter] != package[parameter]): diff --git a/calculate/templates/template_processor.py b/calculate/templates/template_processor.py index 2918fc5..5ffdbf7 100644 --- a/calculate/templates/template_processor.py +++ b/calculate/templates/template_processor.py @@ -36,6 +36,14 @@ from calculate.variables.datavars import ( TableType, VariableNotFoundError ) +from typing import ( + Union, + Dict, + List, + Tuple, + Iterator, + Callable + ) from calculate.variables.loader import Datavars from .format.base_format import Format from ..utils.io_module import IOModule @@ -70,15 +78,15 @@ class TemplateCollisionError(Exception): class CalculateConfigFile: '''Класс для работы с файлом /var/lib/calculate/config.''' - def __init__(self, cl_config_path='/var/lib/calculate/config', - cl_chroot_path='/'): - self.chroot_path = cl_chroot_path + def __init__(self, cl_config_path: str = '/var/lib/calculate/config', + cl_chroot_path: str = '/'): + self.chroot_path: str = cl_chroot_path - self.cl_config_path = cl_config_path + self.cl_config_path: str = cl_config_path - self._config_dictionary = self._get_cl_config_dictionary() + self._config_dictionary: OrderedDict = self._get_cl_config_dictionary() - self._unsaved_changes = False + self._unsaved_changes: bool = False def __contains__(self, file_path: str) -> bool: file_path = self._remove_chroot(file_path) @@ -158,12 +166,13 @@ class TemplateWrapper: '''Класс связывающий шаблон с целевым файлом и определяющий параметры наложения шаблона, обусловленные состоянием целевого файла.''' - type_checks = {DIR: os.path.isdir, - FILE: os.path.isfile} + type_checks: Dict[int, + Callable[[str], bool]] = {DIR: os.path.isdir, + FILE: os.path.isfile} - _protected_is_set = False - _protected_set = set() - _unprotected_set = set() + _protected_is_set: bool = False + _protected_set: set = set() + _unprotected_set: set = set() def __new__(cls, *args, **kwargs): if not cls._protected_is_set: @@ -175,63 +184,64 @@ class TemplateWrapper: cls._set_protected(chroot_path) return super().__new__(cls) - def __init__(self, target_file_path, - parameters, - template_type, - template_path, - template_text='', - target_package=None, - chroot_path='/', - config_archive_path='/var/lib/calculate/config-archive', - dbpkg=True): - self.target_path = target_file_path - self.template_path = template_path - self.chroot_path = chroot_path - self.config_archive_path = config_archive_path - - self.target_package_name = None - self.package_atom_parser = PackageAtomParser( + def __init__( + self, target_file_path: str, + parameters: ParametersContainer, + template_type: int, + template_path: str, + template_text: str = '', + target_package: Union[Package, None] = None, + chroot_path: str = '/', + config_archive_path: str = '/var/lib/calculate/config-archive', + dbpkg: bool = True): + self.target_path: str = target_file_path + self.template_path: str = template_path + self.chroot_path: str = chroot_path + self.config_archive_path: str = config_archive_path + + self.target_package_name: Union[PackageAtomName, None] = None + self.package_atom_parser: PackageAtomParser = PackageAtomParser( chroot_path=self.chroot_path) # Вспомогательный флаг, включается, если по целевому пути лежит файл, # для которого не определился никакой пакет. - self.target_without_package = False + self.target_without_package: bool = False - self.parameters = parameters + self.parameters: ParametersContainer = parameters - self.output_path = self.target_path - self.input_path = None + self.output_path: str = self.target_path + self.input_path: Union[str, None] = None - self.template_type = template_type - self.template_text = template_text + self.template_type: int = template_type + self.template_text: str = template_text - self.contents_matching = True - self.ca_is_missed = False + self.contents_matching: bool = True + self.ca_is_missed: bool = False # Флаг, указывающий, что нужно удалить файл из target_path перед # применением шаблона. - self.remove_original = False + self.remove_original: bool = False # Флаг, указывающий, что целевой путь был изменен. - self.target_path_is_changed = False + self.target_path_is_changed: bool = False # Флаг, указывающий, что файл по целевому пути является ссылкой. - self.target_is_link = False + self.target_is_link: bool = False # Пакет, к которому относится файл. - self.target_package = target_package + self.target_package: Package = target_package # Флаг, разрешающий работу с CONTENTS. Если False, то выключает # protected для всех файлов блокирует все операции с CONTENTS и ._cfg. - self.dbpkg = dbpkg + self.dbpkg: bool = dbpkg # Флаг, указывающий, что файл является PROTECTED. - self.protected = False + self.protected: bool = False # Временный флаг для определения того, является ли шаблон userspace. - self.is_userspace = False + self.is_userspace: bool = False - self.format_class = None + self.format_class: Union[Format, None] = None if self.parameters.run or self.parameters.exec: # Если есть параметр run или exec, то кроме текста шаблона ничего @@ -410,8 +420,8 @@ class TemplateWrapper: self.target_package_name = parameter_package elif file_package != parameter_package and self.template_type != DIR: - target_name = self._check_packages_slots(parameter_package, - file_package) + target_name = self._compare_packages(parameter_package, + file_package) if (target_name is not None and self.target_package is not None and self.target_package.package_name == target_name): target_name = self.target_package.package_name @@ -453,7 +463,10 @@ class TemplateWrapper: self.target_package = Package(self.target_package_name, chroot_path=self.chroot_path) - def _check_packages_slots(self, lpackage, rpackage): + def _compare_packages(self, lpackage: PackageAtomName, + rpackage: PackageAtomName + ) -> Union[None, PackageAtomName]: + '''Метод, сравнивающий пакеты по их именам, возвращает старший.''' if lpackage.category != rpackage.category: return None @@ -606,7 +619,7 @@ class TemplateWrapper: if self.template_type == DIR and self.target_package is not None: self.target_package.clear_dir(self.target_path) - def add_to_contents(self, file_md5=None) -> None: + def add_to_contents(self, file_md5: Union[str, None] = None) -> None: '''Метод для добавления целевого файла в CONTENTS.''' if self.target_package is None: return @@ -684,60 +697,65 @@ class TemplateWrapper: class TemplateExecutor: '''Класс исполнительного модуля.''' - def __init__(self, datavars_module=Variables(), chroot_path='/', - cl_config_archive='/var/lib/calculate/config-archive', - cl_config_path='/var/lib/calculate/config', - execute_archive_path='/var/lib/calculate/.execute/', - dbpkg=True): + def __init__(self, + datavars_module: Union[Datavars, Variables] = Variables(), + chroot_path: str = '/', + cl_config_archive: str = '/var/lib/calculate/config-archive', + cl_config_path: str = '/var/lib/calculate/config', + execute_archive_path: str = '/var/lib/calculate/.execute/', + dbpkg: bool = True): # TODO добавить список измененных файлов. - self.datavars_module = datavars_module + self.datavars_module: Union[Datavars, Variables] = datavars_module - self.chroot_path = chroot_path + self.chroot_path: str = chroot_path # Объект для проверки файловых систем. Пока не инициализируем. - self.mounts = None + self.mounts: Union[Mounts, None] = None # Директория для хранения полученных при обработке exec скриптов. - self.execute_archive_path = execute_archive_path - self.execute_files = OrderedDict() + self.execute_archive_path: str = execute_archive_path + self.execute_files: OrderedDict = OrderedDict() - self.dbpkg = dbpkg + self.dbpkg: bool = dbpkg # Словарь с измененными файлами и статусами их изменений. - self.changed_files = {} + self.changed_files: dict = {} # Список целевых путей измененных файлов. Нужен для корректного # формирования calculate-заголовка. - self.processed_targets = [] + self.processed_targets: list = [] - self.directory_default_parameters =\ + # TODO разобраться с этим. + # Значения параметров по умолчанию, пока не используются. + self.directory_default_parameters: dict =\ ParametersProcessor.directory_default_parameters - self.file_default_parameters =\ + self.file_default_parameters: dict =\ ParametersProcessor.file_default_parameters # Отображение имен действий для директорий на методы их реализующие. - self.directory_appends = {'join': self._append_join_directory, - 'remove': self._append_remove_directory, - 'skip': self._append_skip_directory, - 'clear': self._append_clear_directory, - 'link': self._append_link_directory, - 'replace': self._append_replace_directory} + self.directory_appends: dict = { + 'join': self._append_join_directory, + 'remove': self._append_remove_directory, + 'skip': self._append_skip_directory, + 'clear': self._append_clear_directory, + 'link': self._append_link_directory, + 'replace': self._append_replace_directory} # Отображение имен действий для файлов на методы их реализующие. - self.file_appends = {'join': self._append_join_file, - 'after': self._append_after_file, - 'before': self._append_before_file, - 'replace': self._append_replace_file, - 'remove': self._append_remove_file, - 'skip': self._append_skip_file, - 'clear': self._append_clear_file, - 'link': self._append_link_file} - - self.formats_classes = ParametersProcessor.available_formats - self.calculate_config_file = CalculateConfigFile( + self.file_appends: dict = {'join': self._append_join_file, + 'after': self._append_after_file, + 'before': self._append_before_file, + 'replace': self._append_replace_file, + 'remove': self._append_remove_file, + 'skip': self._append_skip_file, + 'clear': self._append_clear_file, + 'link': self._append_link_file} + + self.formats_classes: set = ParametersProcessor.available_formats + self.calculate_config_file: CalculateConfigFile = CalculateConfigFile( cl_config_path=cl_config_path, cl_chroot_path=chroot_path) - self.cl_config_archive_path = cl_config_archive + self.cl_config_archive_path: str = cl_config_archive Format.CALCULATE_VERSION = CALCULATE_VERSION @property @@ -750,8 +768,9 @@ class TemplateExecutor: def execute_template(self, target_path: str, parameters: ParametersContainer, template_type: int, - template_path: str, template_text='', - save_changes=True, target_package=None) -> dict: + template_path: str, template_text: str = '', + save_changes: bool = True, + target_package: Union[Package, None] = None) -> dict: '''Метод для запуска выполнения шаблонов.''' # Словарь с данными о результате работы исполнительного метода. self.executor_output = {'target_path': None, @@ -831,7 +850,7 @@ class TemplateExecutor: return self.executor_output - def save_changes(self): + def save_changes(self) -> None: '''Метод для сохранения чего-нибудь после выполнения всех шаблонов.''' # Пока сохраняем только получившееся содержимое config-файла. self.calculate_config_file.save_changes() @@ -851,8 +870,8 @@ class TemplateExecutor: if self.dbpkg: template_object.add_to_contents() - def _append_remove_directory(self, - template_object: TemplateWrapper) -> None: + def _append_remove_directory(self, template_object: TemplateWrapper + ) -> None: '''Метод описывающий действия для append = "remove", если шаблон -- директория. Удаляет директорию со всем содержимым, если она есть.''' if template_object.target_type is not None: @@ -964,7 +983,8 @@ class TemplateExecutor: template_object.clear_dir_contents() def _append_join_file(self, template_object: TemplateWrapper, - join_before=False, replace=False) -> None: + join_before: bool = False, replace: bool = False + ) -> None: '''Метод описывающий действия при append = "join", если шаблон -- файл. Объединяет шаблон с целевым файлом.''' output_path = template_object.output_path @@ -1178,7 +1198,8 @@ class TemplateExecutor: self.calculate_config_file.remove_file(template_object.target_path) def _copy_from_source(self, template_object: TemplateWrapper, - chown=None, chmod=None) -> str: + chown: Union[dict, None] = None, + chmod: Union[int, None] = None) -> str: '''Метод для копирования файла, указанного в source.''' output_path = template_object.output_path source_path = template_object.input_path @@ -1361,7 +1382,7 @@ class TemplateExecutor: return hashlib.md5(source_path.encode()).hexdigest() def _create_directory(self, template_object: TemplateWrapper, - path_to_create=None) -> None: + path_to_create: Union[str, None] = None) -> None: '''Метод для создания директории и, при необходимости, изменения владельца и доступа все директорий на пути к целевой.''' if path_to_create is None: @@ -1817,7 +1838,7 @@ class TemplateExecutor: return hasattr(error, 'errno') and error.errno == errno.EACCES and\ 'var/calculate/remote' in path_to_check - def _is_vfat(self, path_to_check): + def _is_vfat(self, path_to_check: str): '''Метод, проверяющий является ли файловая система vfat. Нужно для того, чтобы знать о возможности применения chown, chmod и т.д.''' # Инициализируем объект для проверки примонтированных файловых систем. @@ -1833,7 +1854,7 @@ class TemplateExecutor: class DirectoryTree: '''Класс реализующий дерево каталогов для пакета.''' - def __init__(self, base_directory): + def __init__(self, base_directory: str): self.base_directory = base_directory self._tree = {} @@ -1856,7 +1877,7 @@ class DirectoryTree: def show_tree(self) -> None: pprint(self._tree) - def get_directory_tree(self, directory: str): + def get_directory_tree(self, directory: str) -> "DirectoryTree": '''Метод для получения нового дерева из ветви данного дерева, соответствующей некоторому каталогу, содержащемуся в корне данного дерева.''' @@ -1872,10 +1893,10 @@ class DirectoryTree: else: return None - def __setitem__(self, name: str, value): + def __setitem__(self, name: str, value: Union[None, dict]) -> None: self._tree[name] = value - def __iter__(self): + def __iter__(self) -> Iterator[str]: if self._tree is not None: return iter(self._tree.keys()) else: @@ -1890,35 +1911,40 @@ class DirectoryTree: class DirectoryProcessor: '''Класс обработчика директорий шаблонов.''' - def __init__(self, action: str, datavars_module=Variables(), package='', - output_module=IOModule(), dbpkg=True, - namespace: NamespaceNode = None, **groups): + def __init__(self, action: str, + datavars_module: Union[Datavars, Variables] = Variables(), + install: Union[str, PackageAtomName] = '', + output_module: IOModule = IOModule(), dbpkg: bool = True, + namespace: NamespaceNode = None, **groups: dict): if isinstance(action, list): self.action = action else: self.action = [action] - self.output = output_module - self.datavars_module = datavars_module - self._namespace = namespace + self.output: IOModule = output_module + self.datavars_module: Variables = datavars_module + self._namespace: NamespaceNode = namespace # Корневая директория. + self.cl_chroot_path: str if 'cl_chroot_path' in datavars_module.main: self.cl_chroot_path = datavars_module.main.cl_chroot_path else: self.cl_chroot_path = '/' - # Корневая директория. + # Корневой путь шаблонов. + self.templates_root: str if 'cl_root_path' in datavars_module.main: self.templates_root = join_paths(self.cl_chroot_path, datavars_module.main.cl_root_path) else: self.templates_root = self.cl_chroot_path - self.cl_ignore_files = self._get_cl_ignore_files() + self.cl_ignore_files: List[str] = self._get_cl_ignore_files() # Путь к файлу config с хэш-суммами файлов, для которых уже # предлагались изменения. + self.cl_config_path: str if 'cl_config_path' in datavars_module.main: self.cl_config_path = self._add_chroot_path( self.datavars_module.main.cl_config_path) @@ -1928,6 +1954,7 @@ class DirectoryProcessor: # Путь к директории config-archive для хранения оригинальной ветки # конфигурационных файлов. + self.cl_config_archive: str if 'cl_config_archive' in datavars_module.main: self.cl_config_archive = self._add_chroot_path( self.datavars_module.main.cl_config_archive) @@ -1937,6 +1964,7 @@ class DirectoryProcessor: # Путь к директории .execute для хранения хранения файлов скриптов, # полученных из шаблонов с параметром exec. + self.cl_exec_dir_path: str if 'cl_exec_dir_path' in datavars_module.main: self.cl_exec_dir_path = self._add_chroot_path( self.datavars_module.main.cl_exec_dir_path) @@ -1945,7 +1973,7 @@ class DirectoryProcessor: '/var/lib/calculate/.execute/') # Инициализируем исполнительный модуль. - self.template_executor = TemplateExecutor( + self.template_executor: TemplateExecutor = TemplateExecutor( datavars_module=self.datavars_module, chroot_path=self.cl_chroot_path, cl_config_archive=self.cl_config_archive, @@ -1966,22 +1994,23 @@ class DirectoryProcessor: self._make_current_template_var() # Инициализируем шаблонизатор. - self.template_engine = TemplateEngine( + self.template_engine: TemplateEngine = TemplateEngine( datavars_module=self.datavars_module, chroot_path=self.cl_chroot_path, appends_set=self.template_executor.available_appends) # Разбираем atom имя пакета, для которого накладываем шаблоны. - self.for_package = False - if package: - if isinstance(package, PackageAtomName): - self.for_package = package - elif isinstance(package, str): + self.for_package: Union[PackageAtomName, None] = None + if install: + if isinstance(install, PackageAtomName): + self.for_package = install + elif isinstance(install, str): try: self.for_package = self.template_engine.\ - parameters_processor.check_postparse_package(package) + parameters_processor.check_postparse_package( + install) except ConditionFailed as error: - # ConfitionFailed потому что для проверки значения пакета, + # ConditionFailed потому что для проверки значения пакета, # используется тот же метод, что проверяет параметр package # в шаблонах, а в них этот параметр играет роль условия. self.output.set_error(str(error)) @@ -1990,6 +2019,7 @@ class DirectoryProcessor: # Получаем список директорий шаблонов. # TODO переменная список. + self.template_paths: List[str] if isinstance(self.datavars_module, (Datavars, NamespaceNode)): var_type = self.datavars_module.main[ 'cl_template_path'].variable_type @@ -2012,11 +2042,11 @@ class DirectoryProcessor: self.packages_file_trees = OrderedDict() # Список обработчиков. - self._handlers = {} - self._handlers_queue = [] - self._handling = None + self._handlers: Dict[tuple] = {} + self._handlers_queue: List[str] = [] + self._handling: Union[str, None] = None - def _get_cl_ignore_files(self) -> list: + def _get_cl_ignore_files(self) -> List[str]: '''Метод для получения из соответствующей переменной списка паттернов для обнаружения игнорируемых в ходе обработки шаблонов файлов.''' if 'cl_ignore_files' in self.datavars_module.main: @@ -2050,7 +2080,7 @@ class DirectoryProcessor: package_atom: str) -> None: try: groups_namespace = self.datavars_module.main.cl.groups - except VariableNotFoundError: + except (VariableNotFoundError, AttributeError): namespaces = ['cl', 'groups'] groups_namespace = self.datavars_module.main for namespace in namespaces: @@ -2065,6 +2095,9 @@ class DirectoryProcessor: groups_namespace[namespace] = Variables() groups_namespace = groups_namespace[namespace] + print('GROUPS NAMESPACE:') + print(groups_namespace) + atom_dict = PackageAtomParser.parse_atom_name(package_atom) if isinstance(self.datavars_module, (Datavars, NamespaceNode)): if group_name not in groups_namespace: @@ -2074,24 +2107,59 @@ class DirectoryProcessor: else: group_var = groups_namespace[group_name] group_table = group_var.get_value().get_table() - if not self.check_existance_in_group(atom_dict, group_table): + check_result = self.check_existance_in_group(atom_dict, + group_table) + if check_result == -2: group_table.append(atom_dict) + elif check_result >= 0: + group_table[check_result] = atom_dict + + if check_result != -1: group_var.source = group_table else: if group_name not in groups_namespace: groups_namespace[group_name] = [atom_dict] else: group_table = groups_namespace[group_name] - if not self.check_existance_in_group(atom_dict, group_table): + check_result = self.check_existance_in_group(atom_dict, + group_table) + if check_result == -2: group_table.append(atom_dict) + elif check_result >= 0: + group_table[check_result] = atom_dict + + if check_result != -1: groups_namespace[group_name] = group_table - def check_existance_in_group(self, atom_dict: dict, group: list): + def check_existance_in_group(self, atom_dict: dict, group: list) -> bool: + '''Метод для проверки наличия в таблице групп указанного пакета, а + также для сравнения данных о пакете из таблицы и из атом словаря. + Возвращает: + -2 -- если пакета нет; + -1 -- если присутствует и полностью совпадает; + >=0 -- если имеющиеся в таблице данные о пакете должены быть заменены + на указанные. В этом случае возвращается индекс старых данных в + таблице. ''' + index = 0 + for group_atom in group: - for field in ['category', 'name', 'version', 'slot']: - if atom_dict[field] != group_atom[field]: - continue - return True + if (atom_dict['category'] != group_atom['category'] and + atom_dict['name'] != group_atom['name']): + index += 1 + continue + + if (atom_dict['slot'] is not None and + group_atom['slot'] is not None): + if atom_dict['slot'] != group_atom['slot']: + return -2 + + if atom_dict['version'] is not None: + if (group_atom['version'] is None or + atom_dict['version'] != group_atom['version']): + return index + + return -1 + return -2 def _make_current_template_var(self) -> None: var_path = ['main', 'cl'] @@ -2120,6 +2188,7 @@ class DirectoryProcessor: # Режим заполнения очередей директорий пакетов, необходимых для более # быстрой обработки параметра merge. self.fill_trees = bool(self.for_package) + if self.for_package: if self.for_package is NonePackage: package = self.for_package @@ -2129,6 +2198,7 @@ class DirectoryProcessor: else: package = None + self.base_directory: str for directory_path in self.template_paths: self.base_directory = directory_path.strip() entries = os.scandir(self.base_directory) @@ -2163,11 +2233,12 @@ class DirectoryProcessor: self.template_executor.save_changes() return self.template_executor.changed_files - def _execute_handlers(self): + def _execute_handlers(self) -> None: '''Метод для запуска обработчиков добавленных в очередь обработчиков с помощью параметра notify.''' self.output.set_info('Processing handlers...') index = 0 + while index < len(self._handlers_queue): handler = self._handlers_queue[index] index += 1 @@ -2219,7 +2290,7 @@ class DirectoryProcessor: FILE, handler_path, template_text=handler_text) - def _merge_packages(self): + def _merge_packages(self) -> None: '''Метод для выполнения шаблонов относящихся к пакетам, указанным во всех встреченных значениях параметра merge.''' not_merged_packages = [] @@ -2283,7 +2354,7 @@ class DirectoryProcessor: else: self.output.set_success('All packages are merged.') - def _run_exec_files(self): + def _run_exec_files(self) -> None: '''Метод для выполнения скриптов, полученных в результате обработки шаблонов с параметром exec.''' for exec_file_path, exec_info in\ @@ -2306,28 +2377,11 @@ class DirectoryProcessor: except TemplateExecutorError as error: self.output.set_error(str(error)) - def _get_directories_queue(self, path: str) -> tuple: - '''Уже не актуальный метод для построение очередей из путей к - шаблонам. Хотя возможно еще пригодится.''' - directories_queue = [] - - for base_dir in self.template_paths: - base_dir = base_dir.strip() - if path.startswith(base_dir): - base_directory = base_dir - break - - while path != base_directory: - path, dir_name = os.path.split(path) - directories_queue.append(dir_name) - - return base_directory, directories_queue - def _walk_directory_tree(self, current_directory_path: str, current_target_path: str, - directory_parameters: ParametersContainer(), - directory_tree={}, - package=None) -> None: + directory_parameters: ParametersContainer, + directory_tree: Union[dict, DirectoryTree] = {}, + package: Union[Package, None] = None) -> None: '''Метод для рекурсивного обхода директорий с шаблонами, а также, при необходимости, заполнения деревьев директорий шаблонов, с помощью которых далее выполняются шаблоны пакетов из merge.''' @@ -2389,6 +2443,7 @@ class DirectoryProcessor: directory_tree = {} return + # Хэндлеры, вложенные в другие хэндлеры не разрешены. if self._handling is not None and directory_parameters.handler: if directory_parameters.handler != self._handling: self.output.set_error("'handler' parameter is not" @@ -2403,6 +2458,8 @@ class DirectoryProcessor: if pkg not in self.processed_packages: self.packages_to_merge.add(pkg) + # Если присутствует параметр notify, в котором указаны хэндлеры для + # последующего выполнения -- добавляем их в очередь. if directory_parameters.notify: for handler_id in directory_parameters.notify: if handler_id not in self._handlers_queue: @@ -2425,6 +2482,7 @@ class DirectoryProcessor: current_target_path = os.path.join(current_target_path, directory_name) + # Для директорий по умолчанию append = join. if not directory_parameters.append: directory_parameters.set_parameter({'append': 'join'}) @@ -2459,7 +2517,7 @@ class DirectoryProcessor: template_path = os.path.join(current_directory_path, template_name) - # Применяем к файлу шаблона шаблонизатор. + # Обрабатываем файл шаблона шаблонизатором. template_text = self._parse_template(template_parameters, template_name, FILE, current_directory_path) @@ -2507,6 +2565,8 @@ class DirectoryProcessor: if pkg not in self.processed_packages: self.packages_to_merge.add(pkg) + # Если присутствует параметр notify, в котором указаны хэндлеры для + # последующего выполнения -- добавляем их в очередь. if template_parameters.notify: for handler_id in template_parameters.notify: if handler_id not in self._handlers_queue: @@ -2572,7 +2632,8 @@ class DirectoryProcessor: directory_tree = {} return - def _scan_directory(self, directory_path: str) -> tuple: + def _scan_directory(self, directory_path: str + ) -> Tuple[List[str], List[str]]: '''Метод для получения и фильтрования списка файлов и директорий, содержащихся в директории шаблонов.''' template_files = [] @@ -2604,9 +2665,11 @@ class DirectoryProcessor: return False return True - def _get_files_and_dirs_from_tree(self, template_files, - template_directories, - directory_tree: DirectoryTree): + def _get_files_and_dirs_from_tree(self, template_files: List[str], + template_directories: List[str], + directory_tree: DirectoryTree + ) -> Tuple[List[str], + List[DirectoryTree]]: '''Метод для получения списков файлов и директорий из дерева директорий.''' tree_files = [] @@ -2622,8 +2685,8 @@ class DirectoryProcessor: return tree_directories, tree_files - def _make_target_path(self, target_path, template_name, - parameters): + def _make_target_path(self, target_path: str, template_name: str, + parameters: ParametersContainer) -> str: '''Метод для получения пути к целевому файлу с учетом наличия параметров name, path и append = skip.''' # Если есть параметр name -- меняем имя шаблона. @@ -2642,10 +2705,10 @@ class DirectoryProcessor: template_name) return target_path - def _parse_template(self, parameters, - template_name, - template_type, - template_directory): + def _parse_template(self, parameters: ParametersContainer, + template_name: str, + template_type: int, + template_directory: str) -> Union[str, bool]: '''Метод для разбора шаблонов, получения значений их параметров и их текста после отработки шаблонизитора.''' if template_type == DIR: @@ -2657,6 +2720,7 @@ class DirectoryProcessor: self.datavars_module.main.cl['current_template'].set(template_path) else: self.datavars_module.main.cl['current_template'] = template_path + try: self.template_engine.process_template(template_name, template_type, @@ -2673,12 +2737,13 @@ class DirectoryProcessor: template_path)) return False - def _execute_template(self, target_path, - parameters, - template_type, - template_path, - template_text='', - package=None): + def _execute_template(self, target_path: str, + parameters: ParametersContainer, + template_type: int, + template_path: str, + template_text: str = '', + package: Union[Package, None] = None + ) -> Union[bool, str]: '''Метод для наложения шаблонов и обработки информации полученной после наложения.''' try: @@ -2727,7 +2792,8 @@ class DirectoryProcessor: format(template_path)) return target_path - def _update_package_tree(self, package, current_level_tree): + def _update_package_tree(self, package: Package, + current_level_tree: Union[None, dict]) -> None: '''Метод для обновления деревьев директорий пакетов, необходимых для обработки шаблонов пакетов из значения параметра merge.''' # Если текущему уровню соответствует заглушка None или он содержит @@ -2743,12 +2809,13 @@ class DirectoryProcessor: # Если для данного пакета еще нет дерева -- # копируем для него текущее. directory_tree = DirectoryTree(self.base_directory) - directory_tree.update_tree( - copy.deepcopy(self.directory_tree)) + directory_tree.update_tree(copy.deepcopy(self.directory_tree)) self.packages_file_trees[package] = directory_tree - def _check_package_and_action(self, parameters, template_path, - directory_tree=None): + def _check_package_and_action(self, parameters: ParametersContainer, + template_path: str, + directory_tree: Union[dict, None] = None + ) -> bool: '''Метод для проверки параметров action и package во время обработки каталогов с шаблонами. Если среди аргументов указано также дерево каталогов, то в случае несовпадения значений package для файла @@ -2790,6 +2857,9 @@ class DirectoryProcessor: if parameters.package != self.for_package: if directory_tree is not None: + # Если есть дерево, которое собирается для текущих шаблонов + # и параметр package шаблона не совпадает с текущим, + # ставим заглушку, в качестве которой используется None. template_name = os.path.basename(template_path) directory_tree[template_name] = None self.output.set_warning( @@ -2804,17 +2874,17 @@ class DirectoryProcessor: return True @contextmanager - def _start_handling(self, handler): + def _start_handling(self, handler_id: str): '''Метод для перевода обработчика каталогов в режим обработки хэндлеров.''' try: - self._handling = handler + self._handling = handler_id yield self finally: self._handling = None @contextmanager - def _set_current_package(self, package): + def _set_current_package(self, package: Package): '''Метод для указания в шаблонизаторе пакета, для которого в данный момент проводим настройку. Пока не используется.''' try: diff --git a/run_templates.py b/run_templates.py index c6b09b8..bcf3770 100644 --- a/run_templates.py +++ b/run_templates.py @@ -11,7 +11,7 @@ def main(): parser = argparse.ArgumentParser('Run templates.') parser.add_argument('-a', '--action', action='append', type=str, nargs='+', help="action parameter value.") - parser.add_argument('-p', '--package', type=str, + parser.add_argument('-p', '--install', type=str, help="atom name of a target package.") parser.add_argument('--dbpkg', action='store_true', help=("flag for switching template engine's mode from" @@ -27,8 +27,10 @@ def main(): datavars = Datavars() io_module = IOModule() - if args.package == 'None': + if args.install is None: package = NonePackage + elif args.install.strip().casefold() == 'all': + package = None else: package = args.package diff --git a/tests/templates/test_directory_processor.py b/tests/templates/test_directory_processor.py index a4c5a44..97811c3 100644 --- a/tests/templates/test_directory_processor.py +++ b/tests/templates/test_directory_processor.py @@ -663,7 +663,7 @@ class TestDirectoryProcessor: 'templates_17') directory_processor = DirectoryProcessor('install', datavars_module=datavars, - package=other_package_name) + install=other_package_name) directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -689,7 +689,7 @@ class TestDirectoryProcessor: 'templates_18') directory_processor = DirectoryProcessor('install', datavars_module=datavars, - package=other_package_name) + install=other_package_name) directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -777,7 +777,7 @@ class TestDirectoryProcessor: 'templates_21') directory_processor = DirectoryProcessor('install', datavars_module=datavars, - package=other_package_name) + install=other_package_name) directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -820,7 +820,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/other-package') + install='test-category/other-package') directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -863,7 +863,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/other-package') + install='test-category/other-package') directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -1109,7 +1109,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) @@ -1205,7 +1205,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() @@ -1233,9 +1233,9 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package', - build='test-category/build-package-2.1:0[use_1,use_2]', - uninstall='test-category/unmerged-package-1.0.1:1[use_1,use_2]' + install='test-category/test-package', + build='test-category/build-package-2.1:0[use_1 use_2]', + uninstall='test-category/unmerged-package-1.0.1:1[use_1 use_2]' ) assert 'build' in datavars.main.cl.groups assert 'uninstall' in datavars.main.cl.groups @@ -1257,6 +1257,7 @@ class TestDirectoryProcessor: 'etc/dir_51'): 'N', join_paths(CHROOT_PATH, 'etc/dir_51/file_0'): 'N'} + datavars.main.cl['groups'] = Variables({}) def test_group_parameter_with_merge_parameter(self): datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, @@ -1264,9 +1265,9 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package', - build='test-category/build-package-2.1:0[use_1,use_2]', - uninstall='test-category/unmerged-package-1.0.1:1[use_1,use_2]' + install='test-category/test-package', + build='test-category/build-package-2.1:0[use_1 use_2]', + uninstall='test-category/unmerged-package-1.0.1:1[use_1 use_2]' ) assert 'build' in datavars.main.cl.groups assert 'uninstall' in datavars.main.cl.groups @@ -1287,6 +1288,7 @@ class TestDirectoryProcessor: 'etc/dir_56'): 'N', join_paths(CHROOT_PATH, 'etc/dir_56/file_0'): 'N'} + # datavars.main.cl['groups'] = Variables({}) def test_solving_collisions_for_the_same_packages_from_different_slots(self): datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, @@ -1294,7 +1296,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) header = ('#' + '-' * 79 + '\n' + @@ -1361,7 +1363,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package:1' + install='test-category/test-package:1' ) output_text = "options {\n parameter-0 yes;\n};\n" @@ -1389,7 +1391,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/copy.gif')) @@ -1400,7 +1402,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_60/file_0')) @@ -1413,7 +1415,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_61/file_0')) @@ -1443,7 +1445,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_62/file_0')) @@ -1458,7 +1460,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_63/file_0')) @@ -1469,7 +1471,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'update', datavars_module=datavars, - package='test-category/test-package' + install='test-category/test-package' ) directory_processor.process_template_directories() assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_65/file_0')) @@ -1481,7 +1483,7 @@ class TestDirectoryProcessor: directory_processor = DirectoryProcessor( 'install', datavars_module=datavars, - package='test-category/test-package', + install='test-category/test-package', output_module=io ) directory_processor.process_template_directories() @@ -1491,6 +1493,47 @@ class TestDirectoryProcessor: "Warning: package 'test-category/new-package-0.1.1'" " not found for action 'install'.") + def test_group_and_package_parameter_for_unexisting_package(self): + datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, + 'templates_49') + directory_processor = DirectoryProcessor( + 'merge', + datavars_module=datavars, + uninstall='test-category/unmerged-package-1.0.1:1[use_1 use_2]' + ) + directory_processor.process_template_directories() + assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_67/file_0')) + + def test_group_and_some_templates_ignored(self): + datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, + 'templates_50') + directory_processor = DirectoryProcessor( + 'unmerge', + datavars_module=datavars, + uninstall='test-category/unmerged-package-1.0.1:1[use_1 use_2]' + ) + directory_processor.process_template_directories() + assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_68/file_0')) + assert not os.path.exists(join_paths(CHROOT_PATH, + '/etc/dir_69/file_0')) + + def test_group_with_NonePackage(self): + datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, + 'templates_51') + directory_processor = DirectoryProcessor( + 'unmerge', + datavars_module=datavars, + install=NonePackage, + uninstall='test-category/unmerged-package-1.0.1:1[use_1 use_2]', + build='test-category/build-package' + ) + directory_processor.process_template_directories() + assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_70/file_0')) + assert not os.path.exists(join_paths(CHROOT_PATH, + '/etc/dir_71/file_0')) + assert not os.path.exists(join_paths(CHROOT_PATH, + '/etc/dir_72/file_0')) + def test_view_tree(self): list_path = join_paths(CHROOT_PATH, '/etc') show_tree(list_path) diff --git a/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0001_file_12.backup b/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0001_file_12.backup deleted file mode 100644 index 3bae35e..0000000 --- a/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0001_file_12.backup +++ /dev/null @@ -1,9 +0,0 @@ -#------------------------------------------------------------------------------- -# Modified by Calculate Utilities 4.0 -# Processed template files: -# /path/to/template -#------------------------------------------------------------------------------- -section-name { - parameter-1 yes; - parameter-2 no; -}; diff --git a/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0002_file_12.backup b/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0002_file_12.backup deleted file mode 100644 index 4ade9c7..0000000 --- a/tests/templates/testfiles/test_dir_processor_root/etc.backup/._cfg0002_file_12.backup +++ /dev/null @@ -1,9 +0,0 @@ -#------------------------------------------------------------------------------- -# Modified by Calculate Utilities 4.0 -# Processed template files: -# /home/divanov/Home/development/calculate-lib/tests/templates/testfiles/test_dir_processor_root/templates_28/root/file_12 -#------------------------------------------------------------------------------- -section-name { - parameter-1 yes; - parameter-3 10; -}; diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_40/install/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_40/install/.calculate_directory index e07d6d9..7ae6970 100644 --- a/tests/templates/testfiles/test_dir_processor_root/templates_40/install/.calculate_directory +++ b/tests/templates/testfiles/test_dir_processor_root/templates_40/install/.calculate_directory @@ -1 +1 @@ -{% calculate append = 'skip', path = '/etc', action = 'install' %} +{% calculate append = 'skip', action = 'install' %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/.calculate_directory new file mode 100644 index 0000000..6c66099 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/.calculate_directory @@ -0,0 +1 @@ +{% calculate action = "merge", append = "skip" %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/.calculate_directory new file mode 100644 index 0000000..165778d --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/.calculate_directory @@ -0,0 +1 @@ +{% calculate append = "skip", group = "uninstall" %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/script b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/script new file mode 100644 index 0000000..11bdb5e --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_49/merge/dir_67/script @@ -0,0 +1,12 @@ +{% calculate run = '/usr/bin/python' %} +import os + +text = '''Please, take this and run +far away, far away from me +I am tainted +And happyness, and peace of mind +Was never meant for me.''' + +os.mkdir('./dir_67') +with open('./dir_67/file_0', 'w') as output_file: + output_file.write(text) diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/.calculate_directory new file mode 100644 index 0000000..b254397 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/.calculate_directory @@ -0,0 +1 @@ +{% calculate action = "unmerge", append = "skip" %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/.calculate_directory new file mode 100644 index 0000000..d5b613b --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/.calculate_directory @@ -0,0 +1,2 @@ +{% calculate append = "skip", group = "uninstall", +package = 'test-category/unmerged-package' %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/script b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/script new file mode 100644 index 0000000..44a37d8 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_68/script @@ -0,0 +1,12 @@ +{% calculate run = '/usr/bin/python' %} +import os + +text = '''Please, take this and run +far away, far away from me +I am tainted +And happyness, and peace of mind +Was never meant for me.''' + +os.mkdir('./dir_68') +with open('./dir_68/file_0', 'w') as output_file: + output_file.write(text) diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/.calculate_directory new file mode 100644 index 0000000..bace83f --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/.calculate_directory @@ -0,0 +1,2 @@ +{% calculate append = "skip", group = "uninstall", +package = 'test-category/build-package'%} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/script b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/script new file mode 100644 index 0000000..fdef7ba --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_50/unmerge/dir_69/script @@ -0,0 +1,12 @@ +{% calculate run = '/usr/bin/python' %} +import os + +text = '''Please, take this and run +far away, far away from me +I am tainted +And happyness, and peace of mind +Was never meant for me.''' + +os.mkdir('./dir_69') +with open('./dir_69/file_0', 'w') as output_file: + output_file.write(text) diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/.calculate_directory new file mode 100644 index 0000000..b254397 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/.calculate_directory @@ -0,0 +1 @@ +{% calculate action = "unmerge", append = "skip" %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/.calculate_directory new file mode 100644 index 0000000..d5b613b --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/.calculate_directory @@ -0,0 +1,2 @@ +{% calculate append = "skip", group = "uninstall", +package = 'test-category/unmerged-package' %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/script b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/script new file mode 100644 index 0000000..5527483 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_70/script @@ -0,0 +1,12 @@ +{% calculate run = '/usr/bin/python' %} +import os + +text = '''Please, take this and run +far away, far away from me +I am tainted +And happyness, and peace of mind +Was never meant for me.''' + +os.mkdir('./dir_70') +with open('./dir_70/file_0', 'w') as output_file: + output_file.write(text) diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/.calculate_directory new file mode 100644 index 0000000..bace83f --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/.calculate_directory @@ -0,0 +1,2 @@ +{% calculate append = "skip", group = "uninstall", +package = 'test-category/build-package'%} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/script b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/script new file mode 100644 index 0000000..4137e99 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_71/script @@ -0,0 +1,12 @@ +{% calculate run = '/usr/bin/python' %} +import os + +text = '''Please, take this and run +far away, far away from me +I am tainted +And happyness, and peace of mind +Was never meant for me.''' + +os.mkdir('./dir_71') +with open('./dir_71/file_0', 'w') as output_file: + output_file.write(text) diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/.calculate_directory b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/.calculate_directory new file mode 100644 index 0000000..0be1eab --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/.calculate_directory @@ -0,0 +1 @@ +{% calculate append = 'join', package = 'test-category/test-package' %} diff --git a/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/file_0 b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/file_0 new file mode 100644 index 0000000..5f69740 --- /dev/null +++ b/tests/templates/testfiles/test_dir_processor_root/templates_51/merge/dir_72/file_0 @@ -0,0 +1 @@ +{% calculate format = 'raw', append = 'join' %}