Compare commits

..

No commits in common. "44afe0a367684b668454f97c2d5119e4a4cd9935" and "9a709f446ff92dc981dc76aa38c83a786eea15e2" have entirely different histories.

7 changed files with 38 additions and 55 deletions

View file

@ -1,13 +1,3 @@
## 1.2.0a63 (2026-02-11)
### Feat
- cannot use tiramisu_cache directly with commandline
### Fix
- detect if password is set in a forbidden file even if it also in legitimate file
## 1.2.0a62 (2026-02-11) ## 1.2.0a62 (2026-02-11)
### Feat ### Feat

View file

@ -1,6 +1,6 @@
[project] [project]
name = "rougail" name = "rougail"
version = "1.2.0a63" version = "1.2.0a62"
[tool.commitizen] [tool.commitizen]
name = "cz_conventional_commits" name = "cz_conventional_commits"

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail-base" name = "rougail-base"
version = "1.2.0a63" version = "1.2.0a62"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md" readme = "README.md"
description = "A consistency handling system that was initially designed in the configuration management" description = "A consistency handling system that was initially designed in the configuration management"

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail" name = "rougail"
version = "1.2.0a63" version = "1.2.0a62"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
description = "A consistency handling system that was initially designed in the configuration management" description = "A consistency handling system that was initially designed in the configuration management"
classifiers = [ classifiers = [
@ -18,7 +18,7 @@ classifiers = [
dependencies = [ dependencies = [
"ruamel.yaml ~= 0.18.6", "ruamel.yaml ~= 0.18.6",
"pydantic ~= 2.9.2", "pydantic ~= 2.9.2",
"rougail-base == 1.2.0a63", "rougail-base == 1.2.0a62",
] ]
[tool.flit.sdist] [tool.flit.sdist]

View file

@ -1 +1 @@
__version__ = "1.2.0a63" __version__ = "1.2.0a62"

View file

@ -377,7 +377,6 @@ tiramisu_cache:
alternative_name: t alternative_name: t
type: unix_filename type: unix_filename
mandatory: false mandatory: false
commandline: false
params: params:
allow_relative: true allow_relative: true
types: types:

View file

@ -81,12 +81,11 @@ class UserData:
options = datas.get("options", {}) options = datas.get("options", {})
source = datas["source"] source = datas["source"]
for name, data in datas.get("values", {}).items(): for name, data in datas.get("values", {}).items():
self.values.setdefault(name, []).append( self.values[name] = {
{
"source": source, "source": source,
"values": data, "values": data,
"options": options.copy(), "options": options.copy(),
}) }
self.errors.extend(datas.get("errors", [])) self.errors.extend(datas.get("errors", []))
self.warnings.extend(datas.get("warnings", [])) self.warnings.extend(datas.get("warnings", []))
@ -115,7 +114,7 @@ class UserData:
except (ConfigError, PropertiesOptionError): except (ConfigError, PropertiesOptionError):
pass pass
except AttributeError: except AttributeError:
self._not_found_is_dynamic(self.config, path, cache, added, data[-1]) self._not_found_is_dynamic(self.config, path, cache, added, data)
def _not_found_is_dynamic(self, config, path, cache, added, data): def _not_found_is_dynamic(self, config, path, cache, added, data):
"""if path is not found, check if parent is a dynamic family""" """if path is not found, check if parent is a dynamic family"""
@ -183,7 +182,7 @@ class UserData:
) )
# do not add values in variable if has already a value # do not add values in variable if has already a value
if dynamic_variable not in self.values and not dyn_options_values: if dynamic_variable not in self.values and not dyn_options_values:
self.values[dynamic_variable] = [{"values": []}] self.values[dynamic_variable] = {"values": []}
added.append(dynamic_variable) added.append(dynamic_variable)
elif dynamic_variable not in added: elif dynamic_variable not in added:
continue continue
@ -192,8 +191,8 @@ class UserData:
typ = CONVERT_OPTION.get(option_type, {}).get("func") typ = CONVERT_OPTION.get(option_type, {}).get("func")
if typ: if typ:
identifier = typ(identifier) identifier = typ(identifier)
if identifier not in self.values[dynamic_variable][-1]["values"]: if identifier not in self.values[dynamic_variable]["values"]:
self.values[dynamic_variable][-1]["values"].append(identifier) self.values[dynamic_variable]["values"].append(identifier)
cache[current_path] = config, identifier cache[current_path] = config, identifier
break break
@ -203,7 +202,7 @@ class UserData:
if option.ismulti(): if option.ismulti():
if options.get("multi_separator") and not isinstance(value, list): if options.get("multi_separator") and not isinstance(value, list):
value = value.split(options["multi_separator"]) value = value.split(options["multi_separator"])
self.values[path][-1]["values"] = value self.values[path]["values"] = value
if option.issubmulti(): if option.issubmulti():
value = [[val] for val in value] value = [[val] for val in value]
if option.issubmulti(): if option.issubmulti():
@ -213,8 +212,8 @@ class UserData:
elif isinstance(value, list): elif isinstance(value, list):
value = [convert_value(option, val, needs_convert) for val in value] value = [convert_value(option, val, needs_convert) for val in value]
if needs_convert: if needs_convert:
self.values[path][-1]["values"] = value self.values[path]["values"] = value
self.values[path][-1]["options"]["needs_convert"] = needs_convert self.values[path]["options"]["needs_convert"] = needs_convert
elif not isinstance(value, list): elif not isinstance(value, list):
value = convert_value(option, value, needs_convert) value = convert_value(option, value, needs_convert)
return value return value
@ -231,32 +230,29 @@ class UserData:
values_path = option.path(uncalculated=True) values_path = option.path(uncalculated=True)
if values_path not in self.values: if values_path not in self.values:
continue continue
if option.type() == "password": options = self.values[values_path].get("options", {})
one_is_in_error = False if (
for values in self.values[values_path]: options.get("allow_secrets_variables", True) is False
if values.get("options", {}).get("allow_secrets_variables", True) is False: and option.type() == "password"
one_is_in_error = True ):
self.errors.append({ self.errors.append({
_( _(
'the variable contains secrets and should not be defined in {0}' 'the variable contains secrets and should not be defined in {0}'
).format(values["source"]): option._subconfig} ).format(self.values[values_path]["source"]): option._subconfig}
) )
if one_is_in_error: self.values.pop(path)
self.values.pop(values_path) continue
continue
values = self.values[values_path][-1]
options = values.get("options", {})
value = self.convert_value( value = self.convert_value(
path, option, options, values["values"] path, option, options, self.values[values_path]["values"]
) )
index = option.index() index = option.index()
if index is not None: if index is not None:
if isinstance(value, tuple): if isinstance(value, tuple):
values["values"] = [] self.values[values_path]["values"] = []
# for i in range(len(option.parent().leader().value.get())): # for i in range(len(option.parent().leader().value.get())):
for i in range(option.value.len()): for i in range(option.value.len()):
values["values"].append(value) self.values[values_path]["values"].append(value)
value = values["values"] value = self.values[values_path]["values"]
if not isinstance(value, list) or index >= len(value): if not isinstance(value, list) or index >= len(value):
continue continue
value = value[index] value = value[index]
@ -273,15 +269,14 @@ class UserData:
self.set_value(option, value, options, index) self.set_value(option, value, options, index)
value_is_set = True value_is_set = True
except Exception as err: except Exception as err:
pass if path != option.path():
# if path != option.path(): self.values[option.path()] = self.values.pop(values_path)
# self.values[option.path()] = self.values.pop(values_path)
else: else:
# value is correctly set, remove variable to the set # value is correctly set, remove variable to the set
if index is not None: if index is not None:
# if it's a follower waiting for all followers are sets # if it's a follower waiting for all followers are sets
values["values"][index] = undefined self.values[values_path]["values"][index] = undefined
for tmp_value in values["values"]: for tmp_value in self.values[values_path]["values"]:
if tmp_value != undefined: if tmp_value != undefined:
break break
else: else:
@ -310,8 +305,7 @@ class UserData:
def _populate_error_warnings(self): def _populate_error_warnings(self):
# we don't find variable, apply value just to get error or warning messages # we don't find variable, apply value just to get error or warning messages
for path, full_options in self.values.items(): for path, options in self.values.items():
options = full_options[-1]
value = options["values"] value = options["values"]
if options.get("secret_manager"): if options.get("secret_manager"):
option = self.config.forcepermissive.option(path) option = self.config.forcepermissive.option(path)
@ -394,7 +388,7 @@ class UserData:
) )
continue continue
value = self.convert_value( value = self.convert_value(
path, option, self.values[path][-1].get("options", {}), value path, option, self.values[path].get("options", {}), value
) )
if option.isfollower(): if option.isfollower():
if not isinstance(value, tuple): if not isinstance(value, tuple):
@ -565,13 +559,13 @@ class UserData:
if add_validation: if add_validation:
option.property.add("validator") option.property.add("validator")
path = option.path() path = option.path()
if "source" in self.values[path][-1]: if "source" in self.values[path]:
if option.isfollower(): if option.isfollower():
key = f"loaded_from_{index}" key = f"loaded_from_{index}"
else: else:
key = "loaded_from" key = "loaded_from"
value = _("loaded from {0}").format( value = _("loaded from {0}").format(
self.values[path][-1]["source"] self.values[path]["source"]
) )
if options.get("secret_manager"): if options.get("secret_manager"):
# FIXME (true_config ???) # FIXME (true_config ???)