diff --git a/src/rougail/template/base.py b/src/rougail/template/base.py
index ccb49cdbe..fc794a4ad 100644
--- a/src/rougail/template/base.py
+++ b/src/rougail/template/base.py
@@ -62,7 +62,7 @@ log.addHandler(logging.NullHandler())
INFORMATIONS = {'files': ['source', 'mode', 'engine', 'included'],
'overrides': ['name', 'source', 'engine'],
- 'service_names': ['doc', 'engine', 'type'],
+ 'service_names': ['doc', 'engine', 'type', 'target', 'undisable'],
}
DEFAULT = {'files': ['owner', 'group'],
'overrides': [],
@@ -178,6 +178,10 @@ class RougailLeader:
def index(self, value):
return self._value.index(value)
+ def __str__(self):
+ followers_name = list(self._follower)
+ return f'RougailLeader({followers_name[0]}) => {followers_name[1:]}'
+
class RougailExtra:
"""Object that implement access to extra variable
@@ -212,7 +216,7 @@ class RougailExtra:
return self._suboption.items()
def __str__(self):
- return self._name
+ return f'RougailExtra("{self._name}") => {self._suboption}'
class RougailBaseTemplate:
@@ -233,7 +237,12 @@ class RougailBaseTemplate:
templates_dir = [templates_dir]
for templ_dir in templates_dir:
self.templates_dir.append(abspath(templ_dir))
- self.patches_dir = abspath(rougailconfig['patches_dir'])
+ patches_dir = rougailconfig['patches_dir']
+ if not isinstance(patches_dir, list):
+ patches_dir = [patches_dir]
+ self.patches_dir = []
+ for p_dir in patches_dir:
+ self.patches_dir.append(abspath(p_dir))
eos = {}
functions_file = rougailconfig['functions_file']
if not isinstance(functions_file, list):
@@ -259,16 +268,17 @@ class RougailBaseTemplate:
patch_cmd = ['patch', '-d', self.tmp_dir, '-N', '-p1', '-f']
patch_no_debug = ['-s', '-r', '-', '--backup-if-mismatch']
- patch_file = join(self.patches_dir, f'{filename}.patch')
- if isfile(patch_file):
- self.log.info(_("Patching template '{filename}' with '{patch_file}'"))
- ret = call(patch_cmd + patch_no_debug + ['-i', patch_file])
- if ret: # pragma: no cover
- patch_cmd_err = ' '.join(patch_cmd + ['-i', patch_file])
- msg = _(f"Error applying patch: '{patch_file}'\n"
- f"To reproduce and fix this error {patch_cmd_err}")
- self.log.error(_(msg))
- copy(join(templates_dir, filename), self.tmp_dir)
+ for patches_dir in self.patches_dir:
+ patch_file = join(patches_dir, f'{filename}.patch')
+ if isfile(patch_file):
+ self.log.info(_("Patching template '{filename}' with '{patch_file}'"))
+ ret = call(patch_cmd + patch_no_debug + ['-i', patch_file])
+ if ret: # pragma: no cover
+ patch_cmd_err = ' '.join(patch_cmd + ['-i', patch_file])
+ msg = _(f"Error applying patch: '{patch_file}'\n"
+ f"To reproduce and fix this error {patch_cmd_err}")
+ self.log.error(_(msg))
+ copy(join(templates_dir, filename), self.tmp_dir)
def prepare_template(self,
filename: str,
@@ -362,65 +372,70 @@ class RougailBaseTemplate:
except FileNotFoundError:
ori_dir = None
chdir(self.tmp_dir)
- 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,
- )
- files_to_delete = []
- for included in (True, False):
- for service_obj in await self.config.option('services').list('all'):
- service_name = await service_obj.option.description()
- if await service_obj.option('activate').value.get() is False:
- if included is False and not await service_obj.information.get('undisable', False):
- self.desactive_service(service_name)
- continue
- if not included:
- engine = await service_obj.information.get('engine', None)
- if engine:
- 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,
- target_name,
- engine is None,
- )
- 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 'included' in fill:
- if (fill['included'] == 'no' and included is True) or \
- (fill['included'] != 'no' and included is False):
+ 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,
+ )
+ files_to_delete = []
+ for included in (True, False):
+ for service_obj in await self.config.option('services').list('all'):
+ service_name = await service_obj.option.description()
+ if await service_obj.option('activate').value.get() is False:
+ if included is False and not await service_obj.information.get('undisable', False):
+ self.desactive_service(service_name)
+ continue
+ if not included:
+ engine = await service_obj.information.get('engine', None)
+ if engine:
+ 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,
+ target_name,
+ engine is None,
+ )
+ 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 'included' in fill:
+ if (fill['included'] == 'no' and included is True) or \
+ (fill['included'] != 'no' and included is False):
+ continue
+ elif included is True:
continue
- elif included is True:
- continue
- if fill['activate']:
- 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:
- self.log.debug(_(f"Instantiation of file '{fill['name']}' disabled"))
- self.post_instance_service(service_name)
- for filename in files_to_delete:
- unlink(filename)
- parent = filename
- while True:
- parent = dirname(parent)
- if listdir(parent):
- break
- rmdir(parent)
- self.post_instance()
+ if fill['activate']:
+ 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:
+ self.log.debug(_(f"Instantiation of file '{fill['name']}' disabled"))
+ self.post_instance_service(service_name)
+ for filename in files_to_delete:
+ unlink(filename)
+ parent = filename
+ while True:
+ parent = dirname(parent)
+ if listdir(parent):
+ break
+ rmdir(parent)
+ self.post_instance()
+ except Exception as err:
+ if ori_dir is not None:
+ chdir(ori_dir)
+ raise err
if ori_dir is not None:
chdir(ori_dir)
@@ -443,12 +458,21 @@ class RougailBaseTemplate:
obj: 'Option',
) -> None:
for key in INFORMATIONS.get(type_, []):
- default_key = f'default_{type_}_{key}'
- if default_key in RougailConfig:
- default_value = RougailConfig[default_key]
+ if key == 'target':
+ default_value = None
+ elif key == 'undisable':
+ default_value = False
+ elif key == 'engine' and type_ == 'service_names':
+ default_value = None
else:
- default_value = undefined
- dico[key] = await obj.information.get(key, default_value)
+ default_key = f'default_{type_}_{key}'
+ if default_key in RougailConfig:
+ default_value = RougailConfig[default_key]
+ else:
+ default_value = undefined
+ value = await obj.information.get(key, default_value)
+ if key not in ['target', 'undisable'] or value != default_value:
+ dico[key] = await obj.information.get(key, default_value)
def desactive_service(self,
*args,
@@ -547,7 +571,7 @@ class RougailBaseTemplate:
await suboption.option.name(),
path,
)
- variables[leadership_name] = RougailExtra(await optiondescription.option.name(), {leader_name: leader}, await optiondescription.option.path())
+ variables[leadership_name] = RougailExtra(await option.option.name(), {leader_name: leader}, await option.option.path())
else:
if is_service_namespace == 'root':
new_is_service_namespace = 'service_name'
@@ -567,16 +591,7 @@ class RougailBaseTemplate:
if is_variable_namespace:
value = await option.value.get()
self.rougail_variables_dict[await option.option.name()] = value
- if await option.option.issymlinkoption() and await option.option.isfollower():
- value = []
- if isinstance(self.config, TiramisuOption):
- path = (await option.option.path())[len_root_path:]
- else:
- path = await option.option.path()
- for index in range(await option.value.len()):
- value.append(await self.config.option(path, index).value.get())
- else:
- value = await option.value.get()
+ value = await option.value.get()
variables[await option.option.name()] = value
if isinstance(is_service_namespace, str) and is_service_namespace + 's' in INFORMATIONS:
self.get_default(is_service_namespace + 's',
diff --git a/tests/dictionaries/80remove_fill_no_fill/__init__.py b/tests/dictionaries/80remove_fill_no_fill/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/dictionaries/80remove_fill_no_fill/errno_89 b/tests/dictionaries/80remove_fill_no_fill/errno_89
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/dictionaries/80remove_fill_no_fill/xml/00-base.xml b/tests/dictionaries/80remove_fill_no_fill/xml/00-base.xml
new file mode 100644
index 000000000..f5c5edc5f
--- /dev/null
+++ b/tests/dictionaries/80remove_fill_no_fill/xml/00-base.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ oui
+
+
+ non
+
+
+
+
diff --git a/tests/dictionaries/80remove_fill_no_fill/xml/01-base.xml b/tests/dictionaries/80remove_fill_no_fill/xml/01-base.xml
new file mode 100644
index 000000000..88d820af8
--- /dev/null
+++ b/tests/dictionaries/80remove_fill_no_fill/xml/01-base.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/80remove_fill_no_fill/yml/00-base.yml b/tests/dictionaries/80remove_fill_no_fill/yml/00-base.yml
new file mode 100644
index 000000000..5916d3e46
--- /dev/null
+++ b/tests/dictionaries/80remove_fill_no_fill/yml/00-base.yml
@@ -0,0 +1,16 @@
+version: '0.10'
+variables:
+- family:
+ - name: general
+ variables:
+ - variable:
+ - name: mode_conteneur_actif
+ type: string
+ description: No change
+ value:
+ - text: oui
+ - name: mode_conteneur_actif1
+ type: string
+ description: No change
+ value:
+ - text: non
diff --git a/tests/dictionaries/80remove_fill_no_fill/yml/01-base.yml b/tests/dictionaries/80remove_fill_no_fill/yml/01-base.yml
new file mode 100644
index 000000000..144cc714d
--- /dev/null
+++ b/tests/dictionaries/80remove_fill_no_fill/yml/01-base.yml
@@ -0,0 +1,9 @@
+version: '0.10'
+variables:
+- family:
+ - name: general
+ variables:
+ - variable:
+ - name: mode_conteneur_actif
+ redefine: true
+ remove_fill: true