From 7be62270e608fcba9db819bd1beab6b4ecb92d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=81?= Date: Thu, 14 May 2020 18:31:47 +0300 Subject: [PATCH] The template type conflict solver is implemented. The cl_ignore_files variable is added. --- calculate/templates/template_processor.py | 48 +++++-- template_action_draft.py | 123 ++++++++++++++---- tests/templates/test_directory_processor.py | 3 +- .../testfiles/test_root/etc/dir/file.conf | 6 +- 4 files changed, 139 insertions(+), 41 deletions(-) diff --git a/calculate/templates/template_processor.py b/calculate/templates/template_processor.py index 2b90920..f8434be 100644 --- a/calculate/templates/template_processor.py +++ b/calculate/templates/template_processor.py @@ -4,6 +4,7 @@ import os import re import stat import shutil +import fnmatch import copy from pprint import pprint from ..utils.files import join_paths @@ -501,12 +502,14 @@ class DirectoryProcessor: debug_mode=False): self.action = action self.debug_mode = debug_mode - self.cl_chroot_path = datavars_module.main.cl_chroot_path - self.without_execution = without_execution self.datavars_module = datavars_module self.output = output_module + + self.cl_chroot_path = datavars_module.main.cl_chroot_path + self.cl_ignore_files = self.get_cl_ignore_files() + self.template_action = TemplateAction(output_module=self.output, chroot_path=self.cl_chroot_path) @@ -536,6 +539,17 @@ class DirectoryProcessor: self.packages_to_merge = [] self.packages_file_trees = {} + def get_cl_ignore_files(self): + if 'cl_ignore_files' in self.datavars_module.main: + cl_ignore_files = self.datavars_module.main.cl_ignore_files + cl_ignore_files_list = [] + + for pattern in cl_ignore_files.split(','): + cl_ignore_files_list.append(pattern.strip()) + return cl_ignore_files_list + else: + return [] + def process_template_directories(self): # Проходим каталоги из main.cl_template.path @@ -613,6 +627,14 @@ class DirectoryProcessor: return base_directory, directories_queue + def check_file_name(self, filename: str): + '''Метод для проверки соответствия имени файла содержимому переменной + main.cl_ignore_files.''' + for pattern in self.cl_ignore_files: + if not fnmatch.fnmatch(filename, pattern): + return False + return True + def walk_directory_tree(self, current_directory_path, target_path, directory_parameters, directory_tree={}): template_files = [] @@ -629,11 +651,14 @@ class DirectoryProcessor: self.template_engine.change_directory(current_directory_path) for node in entries: - # Временное, вместо этого добавить переменную ignore_files. - if node.name.endswith('.swp'): + if self.check_file_name(node.name): continue - if node.is_dir(): + if node.is_symlink(): + self.output.set_warning('symlink: {} is ignored'. + format(node.path)) + continue + elif node.is_dir(): template_directories.append(node.path) elif node.is_file(): template_files.append(node.name) @@ -675,14 +700,12 @@ class DirectoryProcessor: if self.fill_trees and self.check_package_and_action( directory_parameters, current_directory_path, - DIR, directory_tree=directory_tree): current_target_path = os.path.join(current_target_path, directory_name) elif self.fill_trees and self.check_package_and_action( - directory_parameters, - current_directory_path, - DIR): + directory_parameters, + current_directory_path): current_target_path = os.path.join(current_target_path, directory_name) else: @@ -711,7 +734,6 @@ class DirectoryProcessor: if not self.check_package_and_action( directory_parameters, current_directory_path, - DIR, directory_tree=directory_tree): # Обновляем дерево директорий для данного пакета. if (directory_tree[directory_name] is None and @@ -788,13 +810,13 @@ class DirectoryProcessor: if self.fill_trees and not self.check_package_and_action( directory_parameters, - template_path, FILE, + template_path, directory_tree=directory_tree[directory_name]): continue elif not self.fill_trees and not self.check_package_and_action( directory_parameters, - template_path, FILE): + template_path): continue # Если есть параметр merge добавляем в список @@ -864,7 +886,7 @@ class DirectoryProcessor: return def check_package_and_action(self, parameters, template_path, - template_type, directory_tree=None): + directory_tree=None): if parameters.append != 'skip': if not parameters.action: self.output.set_warning( diff --git a/template_action_draft.py b/template_action_draft.py index 9438659..59b2172 100644 --- a/template_action_draft.py +++ b/template_action_draft.py @@ -12,7 +12,7 @@ parameter_1 = {{ vars_1.value_1 }} !parameter_2 ''' -backup_template_text = '''{% calculate append = 'join' -%} +backup_template_text = '''{% calculate append = 'join', format = 'samba' -%} [section one] parameter_1 = value parameter_2 = value_2 @@ -37,23 +37,87 @@ class TemplateActionError(Exception): pass -class TargetFile: +class TemplateTypeConflict(Exception): + pass + + +class TemplateWrapper: type_checks = {DIR: os.path.isdir, - FILE: os.path.isfile, - LINK: os.path.islink} + FILE: os.path.isfile} - def __init__(self, target_file_path, template_type, package=None): - self._file_path = target_file_path - self._package = package + def __init__(self, target_file_path, parameters, template_type, + template_text=''): + self._target_path = target_file_path - if not os.path.exists(target_file_path): - pass + self.parameters = parameters + + self.template_type = template_type + + self.template_text = template_text + + self.remove_original = False + + # Если по этому пути что-то есть -- проверяем конфликты. + if os.path.exists(target_file_path): + for file_type, checker in self.type_checks.items(): + if checker(target_path): + self.target_type = file_type + break + self.target_is_link = os.path.islink(target_path) + else: + self.target_type = None + + self.check_conflicts(self) + + def check_conflicts(self): + '''Проверка конфликтов типов.''' + if self.parameters.append == 'link': + if self.parameters.force: + self.remove_original = True + return + elif self.target_type == DIR: + raise TemplateTypeConflict( + "The target is a directory while the" + " template has append = 'link'.") + else: + raise TemplateTypeConflict( + "The target is a file while the" + " template has append = 'link'.") + + if self.template_type == DIR: + if self.parameters.force: + self.remove_original = True + return + elif self.target_type == FILE: + raise TemplateTypeConflict("The target is a file while the" + " template is a directory.") + elif self.target_is_link and self.target_type == DIR: + self._target_path = os.readlink(self._target_path) + return + else: + return + + if self.template_type == FILE: + if self.parameters.force: + if self.target_type == DIR: + self.remove_original = True + return + elif self.target_is_link and self.target_type == FILE: + self._target_path = os.readlink(self._target_path) + return + else: + return + elif self.target_type == FILE: + return + else: + raise TemplateTypeConflict("The target file is a directory" + " while the template is a file.") - def check_conflicts(self, parameters): + def append_template(): pass -class TemplateActionDraft: +class TemplateExecutor: def __init__(self, datavars_module=Variables(), chroot_path='/'): self.datavars_module = datavars_module @@ -73,21 +137,20 @@ class TemplateActionDraft: self.formats_classes = ParametersProcessor.available_formats - def use_directory_template(self, target_path, parameters): + def use_template(self, target_path, parameters, template_type, + template_text=''): print('Template parameters:') parameters.print_parameters_for_debug() - self.template_parameters = parameters - self.directory_appends[self.template_parameters.append](target_path) - - def use_file_template(self, target_path, parameters, template_text=''): - print('Template parameters:') - parameters.print_parameters_for_debug() - - self.template_parameters = parameters - self.template_text = template_text + try: + template_object = TemplateWrapper(target_path, parameters, + template_type, + template_text=template_text) + except TemplateTypeConflict as error: + pass - self.file_appends[self.template_parameters.append](target_path) + self.directory_appends[template_object.parameters.append]( + template_object) def _append_join_directory(self, target_path): print("append = 'join'") @@ -222,6 +285,9 @@ class TemplateActionDraft: print('RESULT:') print(original_object.document_text) + with open(target_path, 'w') as target_file: + target_file.write(original_object.document_text) + def _append_clear_file(self, target_path): print("append = 'clear'") try: @@ -233,13 +299,22 @@ class TemplateActionDraft: return False +# Применение основного шаблона: template_engine.process_template_from_string(template_text, FILE) template_parameters = template_engine.parameters template_text = template_engine.template_text -template_action_obj = TemplateActionDraft(datavars_module=DATAVARS_MODULE, - chroot_path=CHROOT_PATH) +template_action_obj = TemplateExecutor(datavars_module=DATAVARS_MODULE, + chroot_path=CHROOT_PATH) result = template_action_obj.use_file_template(target_path, template_parameters, template_text=template_text) +print('MAIN TEST TEMPLATE IS USED') +# Применение шаблона бэкапа: +template_engine.process_template_from_string(backup_template_text, FILE) +result = template_action_obj.use_file_template( + target_path, + template_engine.parameters, + template_text=template_engine.template_text) +print('BACKUP TEMPLATE IS USED') diff --git a/tests/templates/test_directory_processor.py b/tests/templates/test_directory_processor.py index 5d733a8..8513d2f 100644 --- a/tests/templates/test_directory_processor.py +++ b/tests/templates/test_directory_processor.py @@ -35,7 +35,8 @@ main = Variables({'cl_template_path': 'templates'), os.path.join(TEST_ROOT_PATH, 'var/calculate/templates')), - 'cl_chroot_path': TEST_ROOT_PATH}) + 'cl_chroot_path': TEST_ROOT_PATH, + 'cl_ignore_files': '*.swp'}) test = ({'test_root': TEST_ROOT_PATH}) diff --git a/tests/templates/testfiles/test_root/etc/dir/file.conf b/tests/templates/testfiles/test_root/etc/dir/file.conf index e289472..051a1eb 100644 --- a/tests/templates/testfiles/test_root/etc/dir/file.conf +++ b/tests/templates/testfiles/test_root/etc/dir/file.conf @@ -1,5 +1,5 @@ [section one] -parameter_1 = value - + parameter_1 = value + parameter_2 = value_2 [section two] -parameter_3 = value_3 + parameter_3 = value_3