276 lines
9.5 KiB
Python
276 lines
9.5 KiB
Python
"""
|
|
Silique (https://www.silique.fr)
|
|
Copyright (C) 2022-2025
|
|
|
|
This program is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU Lesser General Public License as published by the
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
from typing import Any, Optional
|
|
|
|
# from tiramisu import owners
|
|
from rougail.utils import undefined
|
|
|
|
from .i18n import _
|
|
|
|
|
|
class CommonOutput:
|
|
|
|
def __init__(
|
|
self,
|
|
rougailconfig,
|
|
) -> None:
|
|
self.set_config(rougailconfig)
|
|
self.variable_default_enable = False
|
|
self.variable_hidden_enable = False
|
|
self.value_modified_enable = False
|
|
self.value_unmodified_enable = False
|
|
self.value_default_enable = False
|
|
|
|
def set_config(self, rougailconfig):
|
|
pass
|
|
|
|
def run(self, nodes):
|
|
if nodes.children:
|
|
root = self.parse(nodes)
|
|
return self._run(root)
|
|
return 0, ''
|
|
|
|
def parse(self, node, parent=None, level=0):
|
|
if node.hidden:
|
|
self.variable_hidden_enable = True
|
|
color = self.variable_hidden_color
|
|
else:
|
|
if node.hidden != None:
|
|
self.variable_default_enable = True
|
|
color = self.variable_normal_color
|
|
family_output = self.colorize(
|
|
[
|
|
{
|
|
"value": node.description,
|
|
"color": color,
|
|
"loaded_from": None,
|
|
}
|
|
]
|
|
)
|
|
subparent = self.get_parent(parent, family_output, level)
|
|
for child in node.children:
|
|
if child["type"] == "node":
|
|
self.parse(child["node"], subparent, level+1)
|
|
else:
|
|
if child["hidden"]:
|
|
self.variable_hidden_enable = True
|
|
variable_color = self.variable_hidden_color
|
|
else:
|
|
self.variable_default_enable = True
|
|
variable_color = self.variable_normal_color
|
|
if child["values"][0]["is_default"]:
|
|
self.value_unmodified_enable = True
|
|
color = self.value_unmodified_color
|
|
else:
|
|
self.value_modified_enable = True
|
|
color = self.value_modified_color
|
|
child["values"][0]["color"] = color
|
|
if len(child["values"]) > 1:
|
|
self.value_default_enable = True
|
|
value = self.colorize(
|
|
child["values"],
|
|
)
|
|
description = self.colorize(
|
|
[
|
|
{
|
|
"value": child["description"],
|
|
"color": variable_color,
|
|
"loaded_from": None,
|
|
}
|
|
]
|
|
)
|
|
self.add_variable(subparent, description, value, child["icon"], level+1)
|
|
return subparent
|
|
|
|
def header(self):
|
|
raise NotImplementedError()
|
|
#
|
|
# def display_errors(
|
|
# self,
|
|
# tree,
|
|
# errors,
|
|
# ) -> None:
|
|
# errors_dict = {}
|
|
# for error in errors:
|
|
# self.error_warn_to_dict(error, errors_dict, self.msg_to_error)
|
|
# self.parse_error_warning(tree, errors_dict, self.display_error)
|
|
# return self.pouet(tree)
|
|
# self.error_end()
|
|
#
|
|
# def display_warnings(
|
|
# self,
|
|
# warnings_dict,
|
|
# warnings,
|
|
# ) -> None:
|
|
###### self.parse_error_warning(tree, warnings_dict, self.display_warning)
|
|
## self.warning_end()
|
|
|
|
def error_warn_to_dict(self, error, errors_dict, level):
|
|
if isinstance(error, dict):
|
|
for msg, subconfig in error.items():
|
|
description = subconfig.option.impl_get_display_name(subconfig)
|
|
self.subconfig_to_dict(subconfig, errors_dict).setdefault(None, {}).setdefault(description, []).append((msg, level))
|
|
else:
|
|
errors_dict.setdefault(None, []).append(error)
|
|
#
|
|
# def msg_to_error(self, msg):
|
|
# return msg
|
|
#
|
|
# def msg_to_warning(self, msg):
|
|
# return msg
|
|
|
|
def subconfig_to_dict(self, subconfig: "Subconfig", errors_dict: dict) -> dict:
|
|
#FIXME a tester : mandatories dans une arborescence (voir si ca n'ecrase pas)
|
|
parents = []
|
|
parent = subconfig
|
|
while True:
|
|
parent = parent.parent
|
|
if parent is None:
|
|
break
|
|
parents.insert(0, parent)
|
|
current_dict = errors_dict
|
|
for child in parents[1:]:
|
|
description = child.option.impl_get_display_name(child)
|
|
current_dict = current_dict.setdefault(description, {})
|
|
return current_dict
|
|
|
|
def parse_error_warning(self, tree, error, display, default_color, level=0):
|
|
self._parse_error_warning(tree, error, display, level, default_color)
|
|
return self.display(tree)
|
|
|
|
def _parse_error_warning(self, tree, error, display, level, default_color):
|
|
if isinstance(error, list):
|
|
for err in error:
|
|
self._parse_error_warning(tree, err, display, level+1, default_color)
|
|
elif isinstance(error, dict):
|
|
for key, value in error.items():
|
|
if key is None:
|
|
# it's variables, no more families
|
|
self._parse_error_warning(tree, value, display, level, default_color)
|
|
else:
|
|
if isinstance(value, list) and len(value) == 1:
|
|
self._parse_error_warning(tree, (key, *value[0]), display, level+1, default_color)
|
|
else:
|
|
sub_tree = self._parse_error_warning(tree, key, display, level+1, default_color)
|
|
self._parse_error_warning(sub_tree, value, display, level+1, default_color)
|
|
else:
|
|
return display(level, tree, error, default_color)
|
|
|
|
def warning_end(self):
|
|
pass
|
|
|
|
def add_family(
|
|
self,
|
|
family,
|
|
level,
|
|
) -> 'OutputFamily':
|
|
properties = family.property.get()
|
|
if "hidden" in properties:
|
|
self.root_family.variable_hidden_enable = True
|
|
color = self.variable_hidden_color
|
|
else:
|
|
self.root_family.variable_default_enable = True
|
|
color = None
|
|
family_output = self.colorize(
|
|
[
|
|
{
|
|
"value": family.description(),
|
|
"color": color,
|
|
"loaded_from": None,
|
|
}
|
|
]
|
|
)
|
|
return self.__class__(
|
|
family_output,
|
|
self.get_tree(),
|
|
self.root,
|
|
level + 1,
|
|
root_family = self.root_family,
|
|
)
|
|
|
|
def colorize(
|
|
self,
|
|
values,
|
|
option=None,
|
|
) -> str:
|
|
multi = False
|
|
ret = []
|
|
default = []
|
|
empty_multi = False
|
|
for idx, data in enumerate(values):
|
|
value = data["value"]
|
|
if isinstance(value, list):
|
|
multi = True
|
|
if not value:
|
|
empty_multi = True
|
|
value = ["[]"]
|
|
else:
|
|
value = [value]
|
|
for vidx, val in enumerate(value):
|
|
if len(ret) == vidx:
|
|
ret.append("")
|
|
default.append(False)
|
|
if idx:
|
|
if not default[vidx]:
|
|
if ret[vidx]:
|
|
ret[vidx] += " "
|
|
ret[vidx] += "("
|
|
default[vidx] = True
|
|
else:
|
|
ret[vidx] += " "
|
|
ret[vidx] += ":hourglass_flowing_sand: "
|
|
if option:
|
|
val = self.convert_value(
|
|
option,
|
|
val,
|
|
)
|
|
color = data.get("color", self.value_default_color)
|
|
if color is not None:
|
|
ret[vidx] += self.set_color(color, val)
|
|
else:
|
|
ret[vidx] += val
|
|
loaded_from = data["loaded_from"]
|
|
if loaded_from:
|
|
ret[vidx] += f" ◀ {loaded_from}"
|
|
for idx in range(len(ret)):
|
|
if default[idx]:
|
|
ret[idx] += ")"
|
|
if not multi or empty_multi:
|
|
if not ret:
|
|
return ""
|
|
return ret[0]
|
|
return ret
|
|
|
|
def get_subconfig_with_default_value(self, config):
|
|
default_owner = config.owner.default()
|
|
if default_owner == owners.default:
|
|
return self.root.config
|
|
if not self.root.config_owner_is_path:
|
|
meta_config = self.root.config
|
|
while True:
|
|
meta_config = meta_config.parent()
|
|
if not meta_config.owner.isdefault():
|
|
break
|
|
else:
|
|
meta_config = self.root.metaconfig
|
|
for child in default_owner.split(".")[1:]:
|
|
meta_config = meta_config.config(child)
|
|
return meta_config
|
|
|
|
def end(self):
|
|
pass
|