From 2fd3c22db9500319533b9296dbf92798b63ff224 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Mon, 23 Jan 2023 22:55:17 +0100 Subject: [PATCH] can templating only one file --- src/rougail/template/base.py | 83 ++++++--- .../70service_engine/xml/00-base.xml | 2 +- tests/test_3_template.py | 159 +++++++++++++----- 3 files changed, 177 insertions(+), 67 deletions(-) diff --git a/src/rougail/template/base.py b/src/rougail/template/base.py index b28c06efd..deb8966fc 100644 --- a/src/rougail/template/base.py +++ b/src/rougail/template/base.py @@ -292,11 +292,11 @@ class RougailBaseTemplate: copy(join(templates_dir, filename), self.tmp_dir) self.patch_template(filename, templates_dir) - def instance_file(self, - filevar: Dict, - type_: str, - service_name: str, - ) -> str: + def _instance_file(self, + filevar: Dict, + type_: str, + service_name: str, + ) -> str: """Run templatisation on one file """ if 'variable' in filevar: @@ -328,7 +328,7 @@ class RougailBaseTemplate: filename, source, true_destfilename, var = data self.log.info(_(f'Instantiating file "{filename}"')) if not true_destfilename.startswith('/'): - raise Exception(f'true_destfilename must starts with a / in function {func}') + raise TemplateError(f'true_destfilename must starts with a / in function {func}') destfilename = join(self.destinations_dir, true_destfilename[1:]) makedirs(dirname(destfilename), exist_ok=True) self.log.info(_(f"{filevar['engine']} processing: '{destfilename}'")) @@ -366,6 +366,47 @@ class RougailBaseTemplate: is_service_namespace, ) + async def instance_file(self, template_name) -> None: + if not self.rougail_variables_dict: + await self.load_variables() + self.prepare_templates() + for service_obj in await self.config.option('services').list('all'): + service_name = await service_obj.option.description() + service_desactived = await service_obj.option('activate').value.get() is False + for fills in await service_obj.list('optiondescription'): + type_ = await fills.option.name() + for fill_obj in await fills.list('all'): + fill = await fill_obj.value.dict() + self.get_default(type_, fill, fill_obj) + await self.get_informations(type_, fill, fill_obj) + if fill['source'] != template_name: + continue + if service_desactived: + raise TemplateError(f'template {template_name} is inside a desactived service') + if 'included' in fill and fill['included'] != 'no': + raise TemplateError(f'template {template_name} is an included file') + if not fill['activate']: + raise TemplateError(f'template {template_name} is desactived') + try: + ori_dir = getcwd() + except FileNotFoundError: + ori_dir = None + chdir(self.tmp_dir) + try: + self._instance_file(fill, + type_, + service_name, + ) + except Exception as err: + if ori_dir is not None: + chdir(ori_dir) + raise err from err + if ori_dir is not None: + chdir(ori_dir) + return + + raise TemplateError(f'Cannot find template {template_name}') + async def instance_files(self) -> None: """Run templatisation on all files """ @@ -377,11 +418,7 @@ class RougailBaseTemplate: try: if not self.rougail_variables_dict: await self.load_variables() - for templates_dir in self.templates_dir: - for template in listdir(templates_dir): - self.prepare_template(template, - templates_dir, - ) + self.prepare_templates() files_to_delete = [] for included in (True, False): for service_obj in await self.config.option('services').list('all'): @@ -393,10 +430,10 @@ class RougailBaseTemplate: if not included: engine = await service_obj.information.get('engine', None) if engine: - self.instance_file({'engine': engine}, - 'service', - service_name, - ) + self._instance_file({'engine': engine}, + 'service', + service_name, + ) target_name = await service_obj.information.get('target', None) if target_name: self.target_service(service_name, @@ -416,10 +453,10 @@ class RougailBaseTemplate: elif included is True: continue if fill['activate']: - destfilenames = self.instance_file(fill, - type_, - service_name, - ) + destfilenames = self._instance_file(fill, + type_, + service_name, + ) if included and fill.get('included', 'no') == 'content': files_to_delete.extend(destfilenames) elif 'name' in fill: @@ -441,6 +478,13 @@ class RougailBaseTemplate: if ori_dir is not None: chdir(ori_dir) + def prepare_templates(self): + for templates_dir in self.templates_dir: + for template in listdir(templates_dir): + self.prepare_template(template, + templates_dir, + ) + def get_default(self, type_: str, dico: dict, @@ -527,7 +571,6 @@ class RougailBaseTemplate: if not isfile(source): # pragma: no cover raise FileNotFound(_(f'Source file "{source}" does not exist in {", ".join(self.templates_dir)}')) tmp_file = join(self.tmp_dir, source) - #self.instance_file(fill, 'files') if variable: var = variable[idx] else: diff --git a/tests/dictionaries/70service_engine/xml/00-base.xml b/tests/dictionaries/70service_engine/xml/00-base.xml index b6704961b..b2028e340 100644 --- a/tests/dictionaries/70service_engine/xml/00-base.xml +++ b/tests/dictionaries/70service_engine/xml/00-base.xml @@ -2,7 +2,7 @@ - + diff --git a/tests/test_3_template.py b/tests/test_3_template.py index 5941770f2..b53bc8ff9 100644 --- a/tests/test_3_template.py +++ b/tests/test_3_template.py @@ -6,6 +6,8 @@ from lxml.etree import parse from tiramisu import Config from rougail import RougailConfig, RougailBaseTemplate, RougailSystemdTemplate +from rougail.error import TemplateError +from jinja2.exceptions import TemplateNotFound template_dirs = 'tests/dictionaries' @@ -15,7 +17,7 @@ test_ok = {f for f in listdir(template_dirs) if not f.startswith('_') and isdir( test_ok -= excludes test_ok = list(test_ok) test_ok.sort() -#test_ok = ['01base_file_include_content'] +#test_ok = ['70service_servicelist_file'] @fixture(scope="module", params=test_ok) @@ -39,7 +41,7 @@ def find_files(dirname: str, files.add(join(*root_file)) -async def template(test_dir, filename, root, engine_name): +async def templates(test_dir, filename, root, engine_name, only_one=False): test_dir = join(template_dirs, test_dir) tmp_dir = join(test_dir, '..', 'tmp') @@ -55,13 +57,7 @@ async def template(test_dir, filename, root, engine_name): funcs_file = join(template_dirs, '../eosfunc/test.py') distrib_dir = join(test_dir, 'tmpl') - if isdir(tmp_dir): - rmtree(tmp_dir) - mkdir(tmp_dir) dest_dir = join(test_dir, 'dest') - if isdir(dest_dir): - rmtree(dest_dir) - mkdir(dest_dir) RougailConfig['patches_dir'] = join(test_dir, 'patches') RougailConfig['templates_dir'] = distrib_dir RougailConfig['tmp_dir'] = tmp_dir @@ -79,39 +75,112 @@ async def template(test_dir, filename, root, engine_name): engine = RougailBaseTemplate(config) else: engine = RougailSystemdTemplate(config) - await engine.instance_files() - list_templates = set() - if isdir(dest_dir): - find_files(dest_dir, + if not only_one: + list_templates = [None] + else: + list_templates = set() + find_files(distrib_dir, [], list_templates, ) - list_results = set() - if isdir(join(test_dir, 'result')): - find_files(join(test_dir, 'result'), - [], - list_results, - ) - if engine_name == 'base' and 'tmpfiles.d/0rougail.conf' in list_results: - list_results.remove('tmpfiles.d/0rougail.conf') - assert list_templates == list_results, f'error with {test_dir}:' - for result in list_results: - template_file = join(dest_dir, result) - assert islink(template_file) == islink(join(test_dir, 'result', result)) - if islink(template_file): - assert readlink(template_file) == readlink(join(test_dir, 'result', result)) - continue - if not isfile(template_file): - raise Exception(f'{template_file} is not generated') - with open(join(test_dir, 'result', result), 'r') as fh: - result_file = fh.read() - with open(template_file, 'r') as fh: - generated_file = fh.read() - assert result_file == generated_file, f'{template_file} content : \n{generated_file}\nexpected: \nresult_file\n' - if isdir(dest_dir): - rmtree(dest_dir) - if isdir(tmp_dir): - rmtree(tmp_dir) + for template in list_templates: + if isdir(tmp_dir): + rmtree(tmp_dir) + mkdir(tmp_dir) + if isdir(dest_dir): + rmtree(dest_dir) + mkdir(dest_dir) + if template is None: + await engine.instance_files() + list_results = set() + if isdir(join(test_dir, 'result')): + find_files(join(test_dir, 'result'), + [], + list_results, + ) + else: + list_results = set() + included = False + activate = True + for service in await config.option('services').option.list('all'): + names = [await o.option.name() for o in await service.option.list('optiondescription')] + if 'files' in names: + for file in await service.option('files').list('optiondescription'): + if not await file.option('source').value.get() == template: + continue + included = await file.information.get('included', 'no') != 'no' + values = await file.option('name').value.get() + if isinstance(values, list): + for value in values: + list_results.add(value[1:]) + else: + list_results.add(values[1:]) + if not await file.option('activate').value.get(): + activate = False + # if template is an overrides + if not list_results and 'overrides' in names: + for override in await service.option('overrides').list('optiondescription'): + if await override.option.description() == template: + return + # if template is a service + if not list_results and template == await service.option.description() and await service.information.get('engine', None): + return + #this file is include and not declared + if template.startswith('inc') and not list_results: + return + try: + await engine.instance_file(template) + except TemplateError as err: + + if 'No such file or directory' in str(err): + continue + if included or not activate: + continue + raise err from err + except TemplateNotFound: + continue + assert activate, 'template should be desactivate' + assert not included, 'include file should not be templated' +# else: +# assert list_results, "should find file" + + list_files = set() + if isdir(dest_dir): + find_files(dest_dir, + [], + list_files, + ) + if engine_name == 'base' and 'tmpfiles.d/0rougail.conf' in list_results: + list_results.remove('tmpfiles.d/0rougail.conf') + assert list_files == list_results, f'error with {test_dir}:' + for result in list_results: + template_file = join(dest_dir, result) + assert islink(template_file) == islink(join(test_dir, 'result', result)) + if islink(template_file): + assert readlink(template_file) == readlink(join(test_dir, 'result', result)) + continue + if not isfile(template_file): + raise Exception(f'{template_file} is not generated') + with open(join(test_dir, 'result', result), 'r') as fh: + result_file = fh.read() + with open(template_file, 'r') as fh: + generated_file = fh.read() + assert result_file == generated_file, f'{template_file} content : \n{generated_file}\nexpected: \nresult_file\n' + if isdir(dest_dir): + rmtree(dest_dir) + if isdir(tmp_dir): + rmtree(tmp_dir) + + +@mark.asyncio +async def test_templates(test_dir): + for engine in ['base', 'systemd']: + not_file = join(template_dirs, test_dir, 'no_' + engine) + if isfile(not_file): + with raises(Exception) as err: + await templates(test_dir, 'base', '1', engine) + else: + await templates(test_dir, 'base', '1', engine) @mark.asyncio @@ -119,10 +188,8 @@ async def test_template(test_dir): for engine in ['base', 'systemd']: not_file = join(template_dirs, test_dir, 'no_' + engine) if isfile(not_file): - with raises(Exception) as err: - await template(test_dir, 'base', '1', engine) - else: - await template(test_dir, 'base', '1', engine) + continue + await templates(test_dir, 'base', '1', engine, only_one=True) @mark.asyncio @@ -131,9 +198,9 @@ async def test_template_multi_1(test_dir): not_file = join(template_dirs, test_dir, 'no_' + engine) if isfile(not_file): with raises(Exception) as err: - await template(test_dir, 'multi', '1', engine) + await templates(test_dir, 'multi', '1', engine) else: - await template(test_dir, 'multi', '1', engine) + await templates(test_dir, 'multi', '1', engine) @mark.asyncio @@ -142,6 +209,6 @@ async def test_template_multi_2(test_dir): not_file = join(template_dirs, test_dir, 'no_' + engine) if isfile(not_file): with raises(Exception) as err: - await template(test_dir, 'multi', '1', engine) + await templates(test_dir, 'multi', '1', engine) else: - await template(test_dir, 'multi', '1', engine) + await templates(test_dir, 'multi', '1', engine)