diff --git a/src/rougail/template.py b/src/rougail/template.py
index a38d7e69..a9fce3a0 100644
--- a/src/rougail/template.py
+++ b/src/rougail/template.py
@@ -9,8 +9,8 @@ from shutil import copy
import logging
from typing import Dict, Any
from subprocess import call
-from os import listdir, makedirs
-from os.path import dirname, join, isfile, abspath, normpath
+from os import listdir, makedirs, getcwd, chdir
+from os.path import dirname, join, isfile, abspath, normpath, relpath
from Cheetah.Template import Template as ChtTemplate
from Cheetah.NameMapper import NotFound as CheetahNotFound
@@ -79,7 +79,8 @@ class CheetahTemplate(ChtTemplate):
context,
eosfunc: Dict,
destfilename,
- variable):
+ variable,
+ ):
"""Initialize Creole CheetahTemplate
"""
extra_context = {'is_defined' : IsDefined(context),
@@ -93,11 +94,15 @@ class CheetahTemplate(ChtTemplate):
searchList=[context, eosfunc, extra_context])
# FORK of Cheetah fonction, do not replace '\\' by '/'
- def serverSidePath(self, path=None,
+ def serverSidePath(self,
+ path=None,
normpath=normpath,
abspath=abspath
):
+ # strange...
+ if path is None and isinstance(self, str):
+ path = self
if path:
return normpath(abspath(path))
# return normpath(abspath(path.replace("\\", '/')))
@@ -107,7 +112,6 @@ class CheetahTemplate(ChtTemplate):
return None
-
class CreoleLeader:
def __init__(self, value, follower=None, index=None):
"""
@@ -302,37 +306,43 @@ class CreoleTemplateEngine:
return CreoleExtra(families)
def patch_template(self,
- filename: str):
+ filename: str,
+ tmp_dir: str,
+ patch_dir: str,
+ ) -> None:
"""Apply patch to a template
"""
- patch_cmd = ['patch', '-d', self.tmp_dir, '-N', '-p1']
+ patch_cmd = ['patch', '-d', tmp_dir, '-N', '-p1']
patch_no_debug = ['-s', '-r', '-', '--backup-if-mismatch']
- # patches variante + locaux
- for directory in [join(Config['patch_dir'], 'variante'), Config['patch_dir']]:
- patch_file = join(directory, f'{filename}.patch')
- if isfile(patch_file):
- log.info(_("Patching template '{filename}' with '{patch_file}'"))
- ret = call(patch_cmd + patch_no_debug + ['-i', patch_file])
- if ret:
- patch_cmd_err = ' '.join(patch_cmd + ['-i', patch_file])
- log.error(_(f"Error applying patch: '{patch_file}'\nTo reproduce and fix this error {patch_cmd_err}"))
- copy(filename, self.tmp_dir)
+ patch_file = join(patch_dir, f'{filename}.patch')
+ if isfile(patch_file):
+ log.info(_("Patching template '{filename}' with '{patch_file}'"))
+ rel_patch_file = relpath(patch_file, tmp_dir)
+ ret = call(patch_cmd + patch_no_debug + ['-i', rel_patch_file])
+ if ret:
+ patch_cmd_err = ' '.join(patch_cmd + ['-i', rel_patch_file])
+ log.error(_(f"Error applying patch: '{rel_patch_file}'\nTo reproduce and fix this error {patch_cmd_err}"))
+ copy(join(self.distrib_dir, filename), tmp_dir)
def prepare_template(self,
- filename: str):
+ filename: str,
+ tmp_dir: str,
+ patch_dir: str,
+ ) -> None:
"""Prepare template source file
"""
- log.info(_("Copy template: '{filename}' -> '{self.tmp_dir}'"))
- copy(filename, self.tmp_dir)
- self.patch_template(filename)
+ log.info(_("Copy template: '{filename}' -> '{tmp_dir}'"))
+ copy(filename, tmp_dir)
+ self.patch_template(filename, tmp_dir, patch_dir)
def process(self,
source: str,
true_destfilename: str,
destfilename: str,
filevar: Dict,
- variable: Any):
+ variable: Any,
+ ):
"""Process a cheetah template
"""
# full path of the destination file
@@ -356,7 +366,10 @@ class CreoleTemplateEngine:
def instance_file(self,
filevar: Dict,
- service_name: str) -> None:
+ service_name: str,
+ tmp_dir: str,
+ dest_dir: str,
+ ) -> None:
"""Run templatisation on one file
"""
log.info(_("Instantiating file '{filename}'"))
@@ -370,13 +383,13 @@ class CreoleTemplateEngine:
if variable:
variable = [variable]
for idx, filename in enumerate(filenames):
- destfilename = join(self.dest_dir, filename[1:])
+ destfilename = join(dest_dir, filename[1:])
makedirs(dirname(destfilename), exist_ok=True)
if variable:
var = variable[idx]
else:
var = None
- source = join(self.tmp_dir, filevar['source'])
+ source = join(tmp_dir, filevar['source'])
if filevar['templating']:
self.process(source,
filename,
@@ -389,6 +402,11 @@ class CreoleTemplateEngine:
async def instance_files(self) -> None:
"""Run templatisation on all files
"""
+ ori_dir = getcwd()
+ tmp_dir = relpath(self.tmp_dir, self.distrib_dir)
+ dest_dir = relpath(self.dest_dir, self.distrib_dir)
+ patch_dir = relpath(Config['patch_dir'], self.distrib_dir)
+ chdir(self.distrib_dir)
for option in await self.config.option.list(type='all'):
namespace = await option.option.name()
if namespace == Config['variable_namespace']:
@@ -397,8 +415,8 @@ class CreoleTemplateEngine:
families = await self.load_eole_variables(namespace,
option)
self.rougail_variables_dict[namespace] = families
- for template in listdir(self.distrib_dir):
- self.prepare_template(join(self.distrib_dir, template))
+ for template in listdir('.'):
+ self.prepare_template(template, tmp_dir, patch_dir)
for service_obj in await self.config.option('services').list('all'):
service_name = await service_obj.option.doc()
for fills in await service_obj.list('all'):
@@ -406,15 +424,17 @@ class CreoleTemplateEngine:
for fill_obj in await fills.list('all'):
fill = await fill_obj.value.dict()
filename = fill['source']
- distib_file = join(self.distrib_dir, filename)
- if not isfile(distib_file):
- raise FileNotFound(_(f"File {distib_file} does not exist."))
+ if not isfile(filename):
+ raise FileNotFound(_(f"File {filename} does not exist."))
if fill.get('activate', False):
self.instance_file(fill,
service_name,
+ tmp_dir,
+ dest_dir,
)
else:
log.debug(_("Instantiation of file '{filename}' disabled"))
+ chdir(ori_dir)
async def generate(config: Config,
diff --git a/tests/dictionaries/01base_file_include/00-base.xml b/tests/dictionaries/01base_file_include/00-base.xml
new file mode 100644
index 00000000..f19fa38e
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/00-base.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ non
+
+
+
+
+
+
diff --git a/tests/dictionaries/01base_file_include/__init__.py b/tests/dictionaries/01base_file_include/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/01base_file_include/makedict/base.json b/tests/dictionaries/01base_file_include/makedict/base.json
new file mode 100644
index 00000000..ce547e52
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.general.mode_conteneur_actif": "non", "services.test.files.file.group": "root", "services.test.files.file.mode": "0644", "services.test.files.file.name": "/etc/file", "services.test.files.file.owner": "root", "services.test.files.file.source": "file", "services.test.files.file.templating": true, "services.test.files.file.activate": true}
diff --git a/tests/dictionaries/01base_file_include/result/etc/file b/tests/dictionaries/01base_file_include/result/etc/file
new file mode 100644
index 00000000..d907505b
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/result/etc/file
@@ -0,0 +1 @@
+non
diff --git a/tests/dictionaries/01base_file_include/tiramisu/__init__.py b/tests/dictionaries/01base_file_include/tiramisu/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/01base_file_include/tiramisu/base.py b/tests/dictionaries/01base_file_include/tiramisu/base.py
new file mode 100644
index 00000000..95802381
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/tiramisu/base.py
@@ -0,0 +1,26 @@
+import imp
+func = imp.load_source('func', 'tests/dictionaries/../eosfunc/test.py')
+for key, value in dict(locals()).items():
+ if key != ['imp', 'func']:
+ setattr(func, key, value)
+try:
+ from tiramisu3 import *
+except:
+ from tiramisu import *
+from rougail.tiramisu import ConvertDynOptionDescription
+option_3 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode_conteneur_actif', doc='Description', multi=False, default='non', values=('oui', 'non'))
+option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
+option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
+option_8 = StrOption(name='group', doc='group', multi=False, default='root')
+option_9 = StrOption(name='mode', doc='mode', multi=False, default='0644')
+option_10 = StrOption(name='name', doc='name', multi=False, default='/etc/file')
+option_11 = StrOption(name='owner', doc='owner', multi=False, default='root')
+option_12 = StrOption(name='source', doc='source', multi=False, default='file')
+option_13 = BoolOption(name='templating', doc='templating', multi=False, default=True)
+option_14 = BoolOption(name='activate', doc='activate', multi=False, default=True)
+option_7 = OptionDescription(name='file', doc='file', children=[option_8, option_9, option_10, option_11, option_12, option_13, option_14])
+option_6 = OptionDescription(name='files', doc='files', children=[option_7])
+option_5 = OptionDescription(name='test', doc='test', children=[option_6])
+option_5.impl_set_information("manage", True)
+option_4 = OptionDescription(name='services', doc='services', properties=frozenset({'hidden'}), children=[option_5])
+option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4])
diff --git a/tests/dictionaries/01base_file_include/tmpl/file b/tests/dictionaries/01base_file_include/tmpl/file
new file mode 100644
index 00000000..19f93237
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/tmpl/file
@@ -0,0 +1 @@
+%include "incfile"
diff --git a/tests/dictionaries/01base_file_include/tmpl/incfile b/tests/dictionaries/01base_file_include/tmpl/incfile
new file mode 100644
index 00000000..a29cfeaf
--- /dev/null
+++ b/tests/dictionaries/01base_file_include/tmpl/incfile
@@ -0,0 +1 @@
+%%mode_conteneur_actif
diff --git a/tests/dictionaries/01base_file_patch/00-base.xml b/tests/dictionaries/01base_file_patch/00-base.xml
new file mode 100644
index 00000000..f19fa38e
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/00-base.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ non
+
+
+
+
+
+
diff --git a/tests/dictionaries/01base_file_patch/__init__.py b/tests/dictionaries/01base_file_patch/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/01base_file_patch/makedict/base.json b/tests/dictionaries/01base_file_patch/makedict/base.json
new file mode 100644
index 00000000..ce547e52
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.general.mode_conteneur_actif": "non", "services.test.files.file.group": "root", "services.test.files.file.mode": "0644", "services.test.files.file.name": "/etc/file", "services.test.files.file.owner": "root", "services.test.files.file.source": "file", "services.test.files.file.templating": true, "services.test.files.file.activate": true}
diff --git a/tests/dictionaries/01base_file_patch/patches/file.patch b/tests/dictionaries/01base_file_patch/patches/file.patch
new file mode 100644
index 00000000..db5b04d1
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/patches/file.patch
@@ -0,0 +1,5 @@
+--- tmpl/file 2020-11-20 07:44:38.588472784 +0100
++++ dest/file 2020-11-20 07:44:54.588536011 +0100
+@@ -1 +1 @@
+-unpatched
++patched
diff --git a/tests/dictionaries/01base_file_patch/result/etc/file b/tests/dictionaries/01base_file_patch/result/etc/file
new file mode 100644
index 00000000..893adcd3
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/result/etc/file
@@ -0,0 +1 @@
+patched
diff --git a/tests/dictionaries/01base_file_patch/tiramisu/__init__.py b/tests/dictionaries/01base_file_patch/tiramisu/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/01base_file_patch/tiramisu/base.py b/tests/dictionaries/01base_file_patch/tiramisu/base.py
new file mode 100644
index 00000000..95802381
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/tiramisu/base.py
@@ -0,0 +1,26 @@
+import imp
+func = imp.load_source('func', 'tests/dictionaries/../eosfunc/test.py')
+for key, value in dict(locals()).items():
+ if key != ['imp', 'func']:
+ setattr(func, key, value)
+try:
+ from tiramisu3 import *
+except:
+ from tiramisu import *
+from rougail.tiramisu import ConvertDynOptionDescription
+option_3 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode_conteneur_actif', doc='Description', multi=False, default='non', values=('oui', 'non'))
+option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
+option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
+option_8 = StrOption(name='group', doc='group', multi=False, default='root')
+option_9 = StrOption(name='mode', doc='mode', multi=False, default='0644')
+option_10 = StrOption(name='name', doc='name', multi=False, default='/etc/file')
+option_11 = StrOption(name='owner', doc='owner', multi=False, default='root')
+option_12 = StrOption(name='source', doc='source', multi=False, default='file')
+option_13 = BoolOption(name='templating', doc='templating', multi=False, default=True)
+option_14 = BoolOption(name='activate', doc='activate', multi=False, default=True)
+option_7 = OptionDescription(name='file', doc='file', children=[option_8, option_9, option_10, option_11, option_12, option_13, option_14])
+option_6 = OptionDescription(name='files', doc='files', children=[option_7])
+option_5 = OptionDescription(name='test', doc='test', children=[option_6])
+option_5.impl_set_information("manage", True)
+option_4 = OptionDescription(name='services', doc='services', properties=frozenset({'hidden'}), children=[option_5])
+option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_4])
diff --git a/tests/dictionaries/01base_file_patch/tmpl/file b/tests/dictionaries/01base_file_patch/tmpl/file
new file mode 100644
index 00000000..832551d8
--- /dev/null
+++ b/tests/dictionaries/01base_file_patch/tmpl/file
@@ -0,0 +1 @@
+unpatched
diff --git a/tests/test_1_flattener.py b/tests/test_1_flattener.py
index 24abbc1f..d6b9f7b4 100644
--- a/tests/test_1_flattener.py
+++ b/tests/test_1_flattener.py
@@ -1,4 +1,5 @@
from lxml import etree
+from os import getcwd
from os.path import isfile, join, isdir
from pytest import fixture, raises
from os import listdir
@@ -25,11 +26,14 @@ for test in listdir(dico_dirs):
test_raise.add(test)
excludes = set([])
+#excludes = set(['01base_file_utfchar'])
test_ok -= excludes
test_raise -= excludes
#test_ok = ['10leadership_autoleader']
#test_raise = []
+ORI_DIR = getcwd()
+
debug = False
#debug = True
@@ -80,6 +84,7 @@ def launch_flattener(test_dir, test_ok=False):
if isdir(subfolder):
eolobj.create_or_populate_from_xml('extra1', [subfolder])
eosfunc = join(dico_dirs, '../eosfunc/test.py')
+ Config['patch_dir'] = join(test_dir, 'patches')
eolobj.space_visitor(eosfunc)
tiramisu_objects = eolobj.save()
tiramisu_dir = join(test_dir, 'tiramisu')
@@ -109,14 +114,18 @@ def teardown_module(module):
def test_dictionary(test_dir):
+ assert getcwd() == ORI_DIR
test_dir = join(dico_dirs, test_dir)
launch_flattener(test_dir, True)
+ assert getcwd() == ORI_DIR
def test_error_dictionary(test_dir_error):
+ assert getcwd() == ORI_DIR
test_dir = join(dico_dirs, test_dir_error)
with raises(DictConsistencyError):
launch_flattener(test_dir)
+ assert getcwd() == ORI_DIR
def test_no_dtd():
diff --git a/tests/test_2_makedict.py b/tests/test_2_makedict.py
index a823fe23..05b48895 100644
--- a/tests/test_2_makedict.py
+++ b/tests/test_2_makedict.py
@@ -20,7 +20,7 @@ for test in listdir(dico_dirs):
debug = False
#debug = True
excludes = set([])
-#excludes = set(['70container_services'])
+#excludes = set(['01base_file_utfchar'])
test_ok -= excludes
#test_ok = ['10check_valid_ipnetmask']
diff --git a/tests/test_3_template.py b/tests/test_3_template.py
index dbaf974c..bbb0d944 100644
--- a/tests/test_3_template.py
+++ b/tests/test_3_template.py
@@ -9,7 +9,10 @@ from rougail import template
template_dirs = 'tests/dictionaries'
-test_ok = [f for f in listdir(template_dirs) if not f.startswith('_') and isdir(join(template_dirs, f, 'tmpl'))]
+excludes = set([])
+#excludes = set(['01base_file_utfchar'])
+test_ok = {f for f in listdir(template_dirs) if not f.startswith('_') and isdir(join(template_dirs, f, 'tmpl'))}
+test_ok -= excludes
#test_ok = ['60extra_group']
@@ -55,6 +58,7 @@ async def test_dictionary(test_dir):
if isdir(dest_dir):
rmtree(dest_dir)
mkdir(dest_dir)
+ template.Config['patch_dir'] = join(test_dir, 'patches')
await template.generate(config,
funcs_file,
distrib_dir,