fix: black

This commit is contained in:
egarette@silique.fr 2024-11-01 10:58:53 +01:00
parent 7a4414bf13
commit 7fb47d1105
5 changed files with 276 additions and 239 deletions

View file

@ -5,12 +5,11 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail.output_exporter" name = "rougail.output_exporter"
version = "0.0.0" version = "0.0.0"
authors = [ authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
{name = "Emmanuel Garette", email = "gnunux@gnunux.info"},
]
description = "Rougail output exporter"
readme = "README.md" readme = "README.md"
description = "Rougail output exporter"
requires-python = ">=3.8" requires-python = ">=3.8"
license = {file = "LICENSE"}
classifiers = [ classifiers = [
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python", "Programming Language :: Python",
@ -39,3 +38,4 @@ tag_format = "$version"
version_scheme = "pep440" version_scheme = "pep440"
version_provider = "pep621" version_provider = "pep621"
update_changelog_on_bump = true update_changelog_on_bump = true
changelog_merge_prerelease = true

View file

@ -23,22 +23,26 @@ from .i18n import _
class RougailOutputExporter: class RougailOutputExporter:
def __init__(self, def __init__(
config: 'Config', self,
rougailconfig: "RougailConfig"=None, config: "Config",
user_data_errors: Optional[list]=None, rougailconfig: "RougailConfig" = None,
user_data_warnings: Optional[list]=None, user_data_errors: Optional[list] = None,
) -> None: user_data_warnings: Optional[list] = None,
) -> None:
if rougailconfig is None: if rougailconfig is None:
from rougail import RougailConfig from rougail import RougailConfig
rougailconfig = RougailConfig rougailconfig = RougailConfig
outputs = OutPuts().get() outputs = OutPuts().get()
output = rougailconfig['exporter.output_format'] output = rougailconfig["exporter.output_format"]
if output not in outputs: if output not in outputs:
raise Exception(f'cannot find output "{output}", available outputs: {list(outputs)}') raise Exception(
f'cannot find output "{output}", available outputs: {list(outputs)}'
)
self.rougailconfig = rougailconfig self.rougailconfig = rougailconfig
self.config = config self.config = config
self.read_write = self.rougailconfig['exporter.read_write'] self.read_write = self.rougailconfig["exporter.read_write"]
self.errors = [] self.errors = []
self.warnings = [] self.warnings = []
if user_data_errors is None: if user_data_errors is None:
@ -51,31 +55,37 @@ class RougailOutputExporter:
self.root = self.formater.root() self.root = self.formater.root()
def mandatory(self): def mandatory(self):
if not self.rougailconfig['exporter.mandatory']: if not self.rougailconfig["exporter.mandatory"]:
return return
title = False title = False
options_with_error = [] options_with_error = []
try: try:
mandatories = self.config.value.mandatory() mandatories = self.config.value.mandatory()
except (ConfigError, PropertiesOptionError) as err: except (ConfigError, PropertiesOptionError) as err:
self.errors.append(f'Error in config: {err}') self.errors.append(f"Error in config: {err}")
return return
for option in mandatories: for option in mandatories:
try: try:
option.value.get() option.value.get()
if not title: if not title:
#self.errors.append("Les variables suivantes sont obligatoires mais n'ont pas de valeur :") # self.errors.append("Les variables suivantes sont obligatoires mais n'ont pas de valeur :")
self.errors.append(_("The following variables are mandatory but have no value:")) self.errors.append(
_("The following variables are mandatory but have no value:")
)
title = True title = True
self.errors.append(f' - {option.description()}') self.errors.append(f" - {option.description()}")
except PropertiesOptionError: except PropertiesOptionError:
options_with_error.append(option) options_with_error.append(option)
if not title: if not title:
for idx, option in enumerate(options_with_error): for idx, option in enumerate(options_with_error):
if not idx: if not idx:
#self.errors.append("Les variables suivantes sont inaccessibles mais sont vides et obligatoires :") # self.errors.append("Les variables suivantes sont inaccessibles mais sont vides et obligatoires :")
self.errors.append(_("The following variables are inaccessible but are empty and mandatory :")) self.errors.append(
self.errors.append(f' - {option.description()}') _(
"The following variables are inaccessible but are empty and mandatory :"
)
)
self.errors.append(f" - {option.description()}")
def exporter(self) -> bool: def exporter(self) -> bool:
self.config.property.read_write() self.config.property.read_write()
@ -93,9 +103,10 @@ class RougailOutputExporter:
if warnings: if warnings:
self.formater.warnings(warnings) self.formater.warnings(warnings)
self.formater.header() self.formater.header()
self.parse_options(self.config, self.parse_options(
self.root, self.config,
) self.root,
)
self.formater.end() self.formater.end()
return True return True
@ -106,36 +117,41 @@ class RougailOutputExporter:
self.exporter() self.exporter()
return self.print() return self.print()
def parse_options(self, def parse_options(
conf, self,
parent, conf,
): parent,
):
for option in conf: for option in conf:
if option.isoptiondescription(): if option.isoptiondescription():
family = parent.add_family(option) family = parent.add_family(option)
if option.isleadership(): if option.isleadership():
self.parse_leadership(option, self.parse_leadership(
family, option,
) family,
)
else: else:
self.parse_options(option, self.parse_options(
family, option,
) family,
)
else: else:
parent.add_variable(option) parent.add_variable(option)
def parse_leadership(self, def parse_leadership(
conf, self,
parent, conf,
): parent,
):
leader, *followers = list(conf) leader, *followers = list(conf)
leader_values = leader.value.get() leader_values = leader.value.get()
for idx, leader_value in enumerate(leader_values): for idx, leader_value in enumerate(leader_values):
leader_obj = parent.add_family(leader) leader_obj = parent.add_family(leader)
leader_obj.add_variable(leader, leader_obj.add_variable(
value=leader_value, leader,
leader_index=idx, value=leader_value,
) leader_index=idx,
)
for follower in followers: for follower in followers:
if follower.index() != idx: if follower.index() != idx:
continue continue
@ -145,4 +161,4 @@ class RougailOutputExporter:
RougailOutput = RougailOutputExporter RougailOutput = RougailOutputExporter
__all__ = ('RougailOutputExporter',) __all__ = ("RougailOutputExporter",)

View file

@ -17,6 +17,7 @@ details.
You should have received a copy of the GNU Lesser General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from pathlib import Path from pathlib import Path
from rougail.utils import load_modules from rougail.utils import load_modules
@ -25,18 +26,20 @@ OUTPUTS = None
def get_outputs() -> None: def get_outputs() -> None:
module_name = 'rougail.output_exporter.output' module_name = "rougail.output_exporter.output"
outputs = {} outputs = {}
for path in (Path(__file__).parent / 'output').iterdir(): for path in (Path(__file__).parent / "output").iterdir():
name = path.name name = path.name
if not name.endswith(".py") or name.endswith("__.py"): if not name.endswith(".py") or name.endswith("__.py"):
continue continue
module = load_modules(module_name + '.' + name, str(path)) module = load_modules(module_name + "." + name, str(path))
if "Formater" not in dir(module): if "Formater" not in dir(module):
continue continue
level = module.Formater.level level = module.Formater.level
if level in outputs: if level in outputs:
raise Exception(f'duplicated level rougail-exporter for output "{level}": {module.Formater.name} and {outputs[level].name}') raise Exception(
f'duplicated level rougail-exporter for output "{level}": {module.Formater.name} and {outputs[level].name}'
)
outputs[module.Formater.level] = module.Formater outputs[module.Formater.level] = module.Formater
return {outputs[level].name: outputs[level] for level in sorted(outputs)} return {outputs[level].name: outputs[level] for level in sorted(outputs)}
@ -55,9 +58,10 @@ class OutPuts: # pylint: disable=R0903
return OUTPUTS return OUTPUTS
def get_rougail_config(*, def get_rougail_config(
backward_compatibility=True, *,
) -> dict: backward_compatibility=True,
) -> dict:
outputs = tuple(OutPuts().get()) outputs = tuple(OutPuts().get())
options = """ options = """
exporter: exporter:
@ -88,14 +92,17 @@ exporter:
alternative_name: eo alternative_name: eo
default: DEFAULT default: DEFAULT
choices: choices:
""".replace('DEFAULT', outputs[0]) """.replace(
"DEFAULT", outputs[0]
)
for output in outputs: for output in outputs:
options += f" - {output}\n" options += f" - {output}\n"
return {'name': 'exporter', return {
'process': 'output', "name": "exporter",
'options': options, "process": "output",
'level': 40, "options": options,
} "level": 40,
}
__all__ = ("OutPuts", 'get_rougail_config') __all__ = ("OutPuts", "get_rougail_config")

View file

@ -2,23 +2,23 @@
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify it
it under the terms of the GNU General Public License as published by under the terms of the GNU Lesser General Public License as published by the
the Free Software Foundation, either version 3 of the License, or Free Software Foundation, either version 3 of the License, or (at your
(at your option) any later version. option) any later version.
Mtools is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful, but WITHOUT
but WITHOUT ANY WARRANTY; without even the implied warranty of ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
GNU General Public License for more details. details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU Lesser General Public License
along with Mtools. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from gettext import translation from gettext import translation
from pathlib import Path from pathlib import Path
t = translation('rougail_output_exporter', str(Path(__file__).parent / 'locale')) t = translation("rougail_output_exporter", str(Path(__file__).parent / "locale"), fallback=True)
_ = t.gettext _ = t.gettext

View file

@ -28,67 +28,72 @@ from ...i18n import _
class Formater: class Formater:
name = 'console' name = "console"
level = 10 level = 10
variable_hidden_color = 'orange1' variable_hidden_color = "orange1"
variable_advanced_color = 'bright_blue' variable_advanced_color = "bright_blue"
variable_advanced_and_modified_color = 'red1' variable_advanced_and_modified_color = "red1"
value_unmodified_color = 'gold1' value_unmodified_color = "gold1"
value_default_color = 'green' value_default_color = "green"
def __init__(self, def __init__(
rougailconfig: 'RougailConfig', self,
) -> None: rougailconfig: "RougailConfig",
) -> None:
self.console = Console(force_terminal=True) self.console = Console(force_terminal=True)
self.rougailconfig = rougailconfig self.rougailconfig = rougailconfig
self.read_write = self.rougailconfig['exporter.read_write'] self.read_write = self.rougailconfig["exporter.read_write"]
self.show_secrets = self.rougailconfig['exporter.show_secrets'] self.show_secrets = self.rougailconfig["exporter.show_secrets"]
self.out = [] self.out = []
def header(self): def header(self):
header_variable = 'Variable\n' header_variable = "Variable\n"
#header_variable += f'[{self.variable_advanced_color}]Variable non documentée[/{self.variable_advanced_color}]\n' # header_variable += f'[{self.variable_advanced_color}]Variable non documentée[/{self.variable_advanced_color}]\n'
#header_variable += f'[{self.variable_advanced_and_modified_color}]Variable non documentée mais modifiée[/{self.variable_advanced_and_modified_color}]' # header_variable += f'[{self.variable_advanced_and_modified_color}]Variable non documentée mais modifiée[/{self.variable_advanced_and_modified_color}]'
header_variable += f'[{self.variable_advanced_color}]{_("Undocumented variable")}[/{self.variable_advanced_color}]\n' header_variable += f'[{self.variable_advanced_color}]{_("Undocumented variable")}[/{self.variable_advanced_color}]\n'
header_variable += f'[{self.variable_advanced_and_modified_color}]{_("Undocumented but modified variable")}[/{self.variable_advanced_and_modified_color}]' header_variable += f'[{self.variable_advanced_and_modified_color}]{_("Undocumented but modified variable")}[/{self.variable_advanced_and_modified_color}]'
if not self.read_write: if not self.read_write:
#header_variable += f'\n[{self.variable_hidden_color}]Variable non modifiable[/{self.variable_hidden_color}]' # header_variable += f'\n[{self.variable_hidden_color}]Variable non modifiable[/{self.variable_hidden_color}]'
header_variable += f'\n[{self.variable_hidden_color}]{_("Unmodifiable variable")}[/{self.variable_hidden_color}]' header_variable += f'\n[{self.variable_hidden_color}]{_("Unmodifiable variable")}[/{self.variable_hidden_color}]'
#header_value = f'[{self.value_unmodified_color}]Valeur par défaut[/{self.value_unmodified_color}]\n' # header_value = f'[{self.value_unmodified_color}]Valeur par défaut[/{self.value_unmodified_color}]\n'
#header_value += 'Valeur modifiée\n' # header_value += 'Valeur modifiée\n'
#header_value += f'([{self.value_default_color}]Valeur par défaut originale[/{self.value_default_color}])' # header_value += f'([{self.value_default_color}]Valeur par défaut originale[/{self.value_default_color}])'
header_value = f'[{self.value_unmodified_color}]{_("Default value")}[/{self.value_unmodified_color}]\n' header_value = f'[{self.value_unmodified_color}]{_("Default value")}[/{self.value_unmodified_color}]\n'
header_value += _('Modified value') + '\n' header_value += _("Modified value") + "\n"
header_value += f'([{self.value_default_color}]{_("Original default value")}[/{self.value_default_color}])' header_value += f'([{self.value_default_color}]{_("Original default value")}[/{self.value_default_color}])'
header = Table.grid(padding=1, collapse_padding=True) header = Table.grid(padding=1, collapse_padding=True)
header.pad_edge = False header.pad_edge = False
header.add_row(header_variable, header_value) header.add_row(header_variable, header_value)
self.out.append(Panel.fit(header, title=_("Caption"))) self.out.append(Panel.fit(header, title=_("Caption")))
def errors(self, def errors(
errors, self,
) -> None: errors,
tree = Tree(":stop_sign: ERRORS", ) -> None:
guide_style="bold bright_red", tree = Tree(
) ":stop_sign: ERRORS",
guide_style="bold bright_red",
)
for error in errors: for error in errors:
tree.add(error) tree.add(error)
self.out.append(tree) self.out.append(tree)
def warnings(self, def warnings(
warnings: list, self,
) -> None: warnings: list,
) -> None:
tree = Tree(":warning: WARNINGS") tree = Tree(":warning: WARNINGS")
for warning in warnings: for warning in warnings:
tree.add(warning) tree.add(warning)
self.out.append(tree) self.out.append(tree)
def root(self) -> None: def root(self) -> None:
self.output = OutputFamily(_("Variables:"), self.output = OutputFamily(
None, _("Variables:"),
self, None,
no_icon=True, self,
) no_icon=True,
)
return self.output return self.output
def end(self): def end(self):
@ -100,130 +105,130 @@ class Formater:
class OutputFamily: class OutputFamily:
def __init__(self, def __init__(
family, self, family, parent, root, *, is_leader: bool = False, no_icon: bool = False
parent, ) -> None:
root,
*,
is_leader: bool=False,
no_icon: bool=False
) -> None:
if parent is None: if parent is None:
tree = Tree tree = Tree
else: else:
tree = parent.add tree = parent.add
if is_leader: if is_leader:
self.tree = tree(f":notebook: {family} :", self.tree = tree(
guide_style="bold bright_blue", f":notebook: {family} :",
) guide_style="bold bright_blue",
)
elif no_icon: elif no_icon:
self.tree = tree(f"{family}", self.tree = tree(
guide_style="bold bright_blue", f"{family}",
) guide_style="bold bright_blue",
)
else: else:
self.tree = tree(f":open_file_folder: {family}", self.tree = tree(
guide_style="bold bright_blue", f":open_file_folder: {family}",
) guide_style="bold bright_blue",
)
self.root = root self.root = root
#
# def parse_option(self, #
# option, # def parse_option(self,
# value, # option,
# variables, # value,
# ): # variables,
# if '.' in line: # ):
# # it's a dict # if '.' in line:
# family, variable = line.split('.', 1) # # it's a dict
# current_path = parent_path # family, variable = line.split('.', 1)
# if current_path: # current_path = parent_path
# current_path += '.' # if current_path:
# current_path += family # current_path += '.'
# if for_doc: # current_path += family
# if 'hidden' in self.conf.option(current_path).property.get() or family_hidden: # if for_doc:
# family_hidden = True # if 'hidden' in self.conf.option(current_path).property.get() or family_hidden:
# family = f'[orange1]{family}[/orange1]' # family_hidden = True
# elif 'advanced' in self.conf.option(current_path).property.get(): # family = f'[orange1]{family}[/orange1]'
# family = f'[bright_blue]{family}[/bright_blue]' # elif 'advanced' in self.conf.option(current_path).property.get():
# if '.' not in variable and self.conf.option(full_path.rsplit('.', 1)[0]).isleadership(): # family = f'[bright_blue]{family}[/bright_blue]'
# dico.setdefault(family, []) # if '.' not in variable and self.conf.option(full_path.rsplit('.', 1)[0]).isleadership():
# leadership = True # dico.setdefault(family, [])
# else: # leadership = True
# dico.setdefault(family, {}) # else:
# leadership = False # dico.setdefault(family, {})
# self.parse_option(full_path, # leadership = False
# variable, # self.parse_option(full_path,
# value, # variable,
# ) # value,
# elif leadership: # )
# # it's a leadership # elif leadership:
# for idx, val in enumerate(value): # # it's a leadership
# dic = {k.rsplit('.', 1)[-1]: v for k, v in val.items()} # for idx, val in enumerate(value):
# if for_doc: # dic = {k.rsplit('.', 1)[-1]: v for k, v in val.items()}
# leader = True # if for_doc:
# for k, v in val.items(): # leader = True
# if leader: # for k, v in val.items():
# is_default = self.conf.option(k).owner.isdefault() # if leader:
# properties = self.conf.option(k).property.get() # is_default = self.conf.option(k).owner.isdefault()
# else: # properties = self.conf.option(k).property.get()
# is_default = self.conf.option(k, idx).owner.isdefault() # else:
# properties = self.conf.option(k, idx).property.get() # is_default = self.conf.option(k, idx).owner.isdefault()
# if self.conf.option(k).type() == _('password') and not self.args.show_secrets: # properties = self.conf.option(k, idx).property.get()
# v = "*" * 10 # if self.conf.option(k).type() == _('password') and not self.args.show_secrets:
# subpath = k.rsplit('.', 1)[-1] # v = "*" * 10
# if 'hidden' in properties or family_hidden: # subpath = k.rsplit('.', 1)[-1]
# subpath = f'[orange1]{subpath}[/orange1]' # if 'hidden' in properties or family_hidden:
# elif 'advanced' in properties: # subpath = f'[orange1]{subpath}[/orange1]'
# if isdefault: # elif 'advanced' in properties:
# subpath = f'[bright_blue]{subpath}[/bright_blue]' # if isdefault:
# else: # subpath = f'[bright_blue]{subpath}[/bright_blue]'
# subpath = f'[red1]{subpath}[/red1]' # else:
# if is_default: # subpath = f'[red1]{subpath}[/red1]'
# v = '[gold1]' + str(v) + '[/gold1]' # if is_default:
# dico.append(f'{subpath}: {v}') # v = '[gold1]' + str(v) + '[/gold1]'
# leader = False # dico.append(f'{subpath}: {v}')
# else: # leader = False
# dico.append(dic) # else:
# else: # dico.append(dic)
# # it's a variable # else:
# self.parse_variable(option, value) # # it's a variable
# # self.parse_variable(option, value)
def add_family(self, #
option, def add_family(
) -> None: self,
option,
) -> None:
properties = option.property.get() properties = option.property.get()
if 'hidden' in properties: if "hidden" in properties:
color = self.root.variable_hidden_color color = self.root.variable_hidden_color
elif 'advanced' in properties: elif "advanced" in properties:
color = self.root.variable_advanced_color color = self.root.variable_advanced_color
else: else:
color = None color = None
return OutputFamily(self.colorize(None, return OutputFamily(
option.name(), self.colorize(
color, None,
None, option.name(),
), color,
self.tree, None,
self.root, ),
) self.tree,
self.root,
)
def add_variable(self, def add_variable(
option, self, option, value: Any = undefined, leader_index: Optional[int] = None
value: Any=undefined, ):
leader_index: Optional[int]=None
):
properties = option.property.get() properties = option.property.get()
variable_color = None variable_color = None
if option.owner.isdefault(): if option.owner.isdefault():
if 'hidden' in properties: if "hidden" in properties:
variable_color = self.root.variable_hidden_color variable_color = self.root.variable_hidden_color
elif 'advanced' in properties: elif "advanced" in properties:
variable_color = self.root.variable_advanced_color variable_color = self.root.variable_advanced_color
color = self.root.value_unmodified_color color = self.root.value_unmodified_color
default_value = None default_value = None
else: else:
if 'hidden' in properties: if "hidden" in properties:
variable_color = self.root.variable_hidden_color variable_color = self.root.variable_hidden_color
elif 'advanced' in properties: elif "advanced" in properties:
variable_color = self.root.variable_advanced_and_modified_color variable_color = self.root.variable_advanced_and_modified_color
color = None color = None
default_value = option.value.default() default_value = option.value.default()
@ -231,31 +236,35 @@ class OutputFamily:
default_value = default_value[leader_index] default_value = default_value[leader_index]
if value is undefined: if value is undefined:
value = option.value.get() value = option.value.get()
key = self.colorize(None, key = self.colorize(
option.name(), None,
variable_color, option.name(),
None, variable_color,
) None,
value = self.colorize(option, )
value, value = self.colorize(
color, option,
default_value, value,
) color,
default_value,
)
if isinstance(value, list): if isinstance(value, list):
subtree = self.tree.add(f":notebook: {key} :", subtree = self.tree.add(
guide_style="bold bright_blue", f":notebook: {key} :",
) guide_style="bold bright_blue",
)
for val in value: for val in value:
subtree.add(str(val)) subtree.add(str(val))
else: else:
self.tree.add(f":notebook: {key}: {value}") self.tree.add(f":notebook: {key}: {value}")
def colorize(self, def colorize(
option, self,
value, option,
color: str, value,
default_value, color: str,
) -> str: default_value,
) -> str:
if isinstance(value, list): if isinstance(value, list):
if default_value is None: if default_value is None:
default_value = [] default_value = []
@ -267,38 +276,43 @@ class OutputFamily:
if idx < len_value: if idx < len_value:
val = value[idx] val = value[idx]
else: else:
val = '' val = ""
if idx < len_default_value: if idx < len_default_value:
if val: if val:
val += ' ' val += " "
default = default_value[idx] default = default_value[idx]
else: else:
default = None default = None
ret.append(self.colorize(option, ret.append(
val, self.colorize(
color, option,
default, val,
)) color,
default,
)
)
return ret return ret
if option and value is not None: if option and value is not None:
value = self.convert_value(option, value = self.convert_value(
value, option,
) value,
)
else: else:
value = str(value) value = str(value)
if color is not None: if color is not None:
ret = f'[{color}]{value}[/{color}]' ret = f"[{color}]{value}[/{color}]"
else: else:
ret = value ret = value
if default_value and 'force_store_value' not in option.property.get(): if default_value and "force_store_value" not in option.property.get():
default_value_color = self.root.value_default_color default_value_color = self.root.value_default_color
ret += f' ([{default_value_color}]{default_value}[/{default_value_color}])' ret += f" ([{default_value_color}]{default_value}[/{default_value_color}])"
return ret return ret
def convert_value(self, def convert_value(
option, self,
value, option,
): value,
if not self.root.show_secrets and option.type() == 'password': ):
if not self.root.show_secrets and option.type() == "password":
return "*" * 10 return "*" * 10
return str(value) return str(value)