diff --git a/pyproject.toml b/pyproject.toml
index 152bfa6..d92cbd6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,12 +5,11 @@ requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail.output_exporter"
version = "0.0.0"
-authors = [
- {name = "Emmanuel Garette", email = "gnunux@gnunux.info"},
-]
-description = "Rougail output exporter"
+authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md"
+description = "Rougail output exporter"
requires-python = ">=3.8"
+license = {file = "LICENSE"}
classifiers = [
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
@@ -39,3 +38,4 @@ tag_format = "$version"
version_scheme = "pep440"
version_provider = "pep621"
update_changelog_on_bump = true
+changelog_merge_prerelease = true
diff --git a/src/rougail/output_exporter/__init__.py b/src/rougail/output_exporter/__init__.py
index 9930f6c..18fe583 100644
--- a/src/rougail/output_exporter/__init__.py
+++ b/src/rougail/output_exporter/__init__.py
@@ -23,22 +23,26 @@ from .i18n import _
class RougailOutputExporter:
- def __init__(self,
- config: 'Config',
- rougailconfig: "RougailConfig"=None,
- user_data_errors: Optional[list]=None,
- user_data_warnings: Optional[list]=None,
- ) -> None:
+ def __init__(
+ self,
+ config: "Config",
+ rougailconfig: "RougailConfig" = None,
+ user_data_errors: Optional[list] = None,
+ user_data_warnings: Optional[list] = None,
+ ) -> None:
if rougailconfig is None:
from rougail import RougailConfig
+
rougailconfig = RougailConfig
outputs = OutPuts().get()
- output = rougailconfig['exporter.output_format']
+ output = rougailconfig["exporter.output_format"]
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.config = config
- self.read_write = self.rougailconfig['exporter.read_write']
+ self.read_write = self.rougailconfig["exporter.read_write"]
self.errors = []
self.warnings = []
if user_data_errors is None:
@@ -51,31 +55,37 @@ class RougailOutputExporter:
self.root = self.formater.root()
def mandatory(self):
- if not self.rougailconfig['exporter.mandatory']:
+ if not self.rougailconfig["exporter.mandatory"]:
return
title = False
options_with_error = []
try:
mandatories = self.config.value.mandatory()
except (ConfigError, PropertiesOptionError) as err:
- self.errors.append(f'Error in config: {err}')
+ self.errors.append(f"Error in config: {err}")
return
for option in mandatories:
try:
option.value.get()
if not title:
- #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("Les variables suivantes sont obligatoires mais n'ont pas de valeur :")
+ self.errors.append(
+ _("The following variables are mandatory but have no value:")
+ )
title = True
- self.errors.append(f' - {option.description()}')
+ self.errors.append(f" - {option.description()}")
except PropertiesOptionError:
options_with_error.append(option)
if not title:
for idx, option in enumerate(options_with_error):
if not idx:
- #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(f' - {option.description()}')
+ # 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(f" - {option.description()}")
def exporter(self) -> bool:
self.config.property.read_write()
@@ -93,9 +103,10 @@ class RougailOutputExporter:
if warnings:
self.formater.warnings(warnings)
self.formater.header()
- self.parse_options(self.config,
- self.root,
- )
+ self.parse_options(
+ self.config,
+ self.root,
+ )
self.formater.end()
return True
@@ -106,36 +117,41 @@ class RougailOutputExporter:
self.exporter()
return self.print()
- def parse_options(self,
- conf,
- parent,
- ):
+ def parse_options(
+ self,
+ conf,
+ parent,
+ ):
for option in conf:
if option.isoptiondescription():
family = parent.add_family(option)
if option.isleadership():
- self.parse_leadership(option,
- family,
- )
+ self.parse_leadership(
+ option,
+ family,
+ )
else:
- self.parse_options(option,
- family,
- )
+ self.parse_options(
+ option,
+ family,
+ )
else:
parent.add_variable(option)
- def parse_leadership(self,
- conf,
- parent,
- ):
+ def parse_leadership(
+ self,
+ conf,
+ parent,
+ ):
leader, *followers = list(conf)
leader_values = leader.value.get()
for idx, leader_value in enumerate(leader_values):
leader_obj = parent.add_family(leader)
- leader_obj.add_variable(leader,
- value=leader_value,
- leader_index=idx,
- )
+ leader_obj.add_variable(
+ leader,
+ value=leader_value,
+ leader_index=idx,
+ )
for follower in followers:
if follower.index() != idx:
continue
@@ -145,4 +161,4 @@ class RougailOutputExporter:
RougailOutput = RougailOutputExporter
-__all__ = ('RougailOutputExporter',)
+__all__ = ("RougailOutputExporter",)
diff --git a/src/rougail/output_exporter/config.py b/src/rougail/output_exporter/config.py
index dce6327..68d3e60 100644
--- a/src/rougail/output_exporter/config.py
+++ b/src/rougail/output_exporter/config.py
@@ -17,6 +17,7 @@ details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
"""
+
from pathlib import Path
from rougail.utils import load_modules
@@ -25,18 +26,20 @@ OUTPUTS = None
def get_outputs() -> None:
- module_name = 'rougail.output_exporter.output'
+ module_name = "rougail.output_exporter.output"
outputs = {}
- for path in (Path(__file__).parent / 'output').iterdir():
+ for path in (Path(__file__).parent / "output").iterdir():
name = path.name
if not name.endswith(".py") or name.endswith("__.py"):
continue
- module = load_modules(module_name + '.' + name, str(path))
+ module = load_modules(module_name + "." + name, str(path))
if "Formater" not in dir(module):
continue
level = module.Formater.level
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
return {outputs[level].name: outputs[level] for level in sorted(outputs)}
@@ -55,9 +58,10 @@ class OutPuts: # pylint: disable=R0903
return OUTPUTS
-def get_rougail_config(*,
- backward_compatibility=True,
- ) -> dict:
+def get_rougail_config(
+ *,
+ backward_compatibility=True,
+) -> dict:
outputs = tuple(OutPuts().get())
options = """
exporter:
@@ -88,14 +92,17 @@ exporter:
alternative_name: eo
default: DEFAULT
choices:
-""".replace('DEFAULT', outputs[0])
+""".replace(
+ "DEFAULT", outputs[0]
+ )
for output in outputs:
options += f" - {output}\n"
- return {'name': 'exporter',
- 'process': 'output',
- 'options': options,
- 'level': 40,
- }
+ return {
+ "name": "exporter",
+ "process": "output",
+ "options": options,
+ "level": 40,
+ }
-__all__ = ("OutPuts", 'get_rougail_config')
+__all__ = ("OutPuts", "get_rougail_config")
diff --git a/src/rougail/output_exporter/i18n.py b/src/rougail/output_exporter/i18n.py
index 0c6b2f4..635691a 100644
--- a/src/rougail/output_exporter/i18n.py
+++ b/src/rougail/output_exporter/i18n.py
@@ -2,23 +2,23 @@
Silique (https://www.silique.fr)
Copyright (C) 2024
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU 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 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.
-Mtools 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 General Public License for more details.
+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 General Public License
-along with Mtools. If not, see .
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
"""
from gettext import translation
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
diff --git a/src/rougail/output_exporter/output/console.py b/src/rougail/output_exporter/output/console.py
index 1ec6528..2a054f4 100644
--- a/src/rougail/output_exporter/output/console.py
+++ b/src/rougail/output_exporter/output/console.py
@@ -28,67 +28,72 @@ from ...i18n import _
class Formater:
- name = 'console'
+ name = "console"
level = 10
- variable_hidden_color = 'orange1'
- variable_advanced_color = 'bright_blue'
- variable_advanced_and_modified_color = 'red1'
- value_unmodified_color = 'gold1'
- value_default_color = 'green'
+ variable_hidden_color = "orange1"
+ variable_advanced_color = "bright_blue"
+ variable_advanced_and_modified_color = "red1"
+ value_unmodified_color = "gold1"
+ value_default_color = "green"
- def __init__(self,
- rougailconfig: 'RougailConfig',
- ) -> None:
+ def __init__(
+ self,
+ rougailconfig: "RougailConfig",
+ ) -> None:
self.console = Console(force_terminal=True)
self.rougailconfig = rougailconfig
- self.read_write = self.rougailconfig['exporter.read_write']
- self.show_secrets = self.rougailconfig['exporter.show_secrets']
+ self.read_write = self.rougailconfig["exporter.read_write"]
+ self.show_secrets = self.rougailconfig["exporter.show_secrets"]
self.out = []
def header(self):
- 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_and_modified_color}]Variable non documentée mais modifiée[/{self.variable_advanced_and_modified_color}]'
+ 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_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_and_modified_color}]{_("Undocumented but modified variable")}[/{self.variable_advanced_and_modified_color}]'
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_value = f'[{self.value_unmodified_color}]Valeur par défaut[/{self.value_unmodified_color}]\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_unmodified_color}]Valeur par défaut[/{self.value_unmodified_color}]\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_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 = Table.grid(padding=1, collapse_padding=True)
header.pad_edge = False
header.add_row(header_variable, header_value)
self.out.append(Panel.fit(header, title=_("Caption")))
- def errors(self,
- errors,
- ) -> None:
- tree = Tree(":stop_sign: ERRORS",
- guide_style="bold bright_red",
- )
+ def errors(
+ self,
+ errors,
+ ) -> None:
+ tree = Tree(
+ ":stop_sign: ERRORS",
+ guide_style="bold bright_red",
+ )
for error in errors:
tree.add(error)
self.out.append(tree)
- def warnings(self,
- warnings: list,
- ) -> None:
+ def warnings(
+ self,
+ warnings: list,
+ ) -> None:
tree = Tree(":warning: WARNINGS")
for warning in warnings:
tree.add(warning)
self.out.append(tree)
def root(self) -> None:
- self.output = OutputFamily(_("Variables:"),
- None,
- self,
- no_icon=True,
- )
+ self.output = OutputFamily(
+ _("Variables:"),
+ None,
+ self,
+ no_icon=True,
+ )
return self.output
def end(self):
@@ -100,130 +105,130 @@ class Formater:
class OutputFamily:
- def __init__(self,
- family,
- parent,
- root,
- *,
- is_leader: bool=False,
- no_icon: bool=False
- ) -> None:
+ def __init__(
+ self, family, parent, root, *, is_leader: bool = False, no_icon: bool = False
+ ) -> None:
if parent is None:
tree = Tree
else:
tree = parent.add
if is_leader:
- self.tree = tree(f":notebook: {family} :",
- guide_style="bold bright_blue",
- )
+ self.tree = tree(
+ f":notebook: {family} :",
+ guide_style="bold bright_blue",
+ )
elif no_icon:
- self.tree = tree(f"{family}",
- guide_style="bold bright_blue",
- )
+ self.tree = tree(
+ f"{family}",
+ guide_style="bold bright_blue",
+ )
else:
- self.tree = tree(f":open_file_folder: {family}",
- guide_style="bold bright_blue",
- )
+ self.tree = tree(
+ f":open_file_folder: {family}",
+ guide_style="bold bright_blue",
+ )
self.root = root
-#
-# def parse_option(self,
-# option,
-# value,
-# variables,
-# ):
-# if '.' in line:
-# # it's a dict
-# family, variable = line.split('.', 1)
-# current_path = parent_path
-# if current_path:
-# current_path += '.'
-# current_path += family
-# if for_doc:
-# if 'hidden' in self.conf.option(current_path).property.get() or family_hidden:
-# family_hidden = True
-# family = f'[orange1]{family}[/orange1]'
-# elif 'advanced' in self.conf.option(current_path).property.get():
-# family = f'[bright_blue]{family}[/bright_blue]'
-# if '.' not in variable and self.conf.option(full_path.rsplit('.', 1)[0]).isleadership():
-# dico.setdefault(family, [])
-# leadership = True
-# else:
-# dico.setdefault(family, {})
-# leadership = False
-# self.parse_option(full_path,
-# variable,
-# value,
-# )
-# elif leadership:
-# # it's a leadership
-# for idx, val in enumerate(value):
-# dic = {k.rsplit('.', 1)[-1]: v for k, v in val.items()}
-# if for_doc:
-# leader = True
-# for k, v in val.items():
-# if leader:
-# is_default = self.conf.option(k).owner.isdefault()
-# properties = self.conf.option(k).property.get()
-# else:
-# is_default = self.conf.option(k, idx).owner.isdefault()
-# properties = self.conf.option(k, idx).property.get()
-# if self.conf.option(k).type() == _('password') and not self.args.show_secrets:
-# v = "*" * 10
-# subpath = k.rsplit('.', 1)[-1]
-# if 'hidden' in properties or family_hidden:
-# subpath = f'[orange1]{subpath}[/orange1]'
-# elif 'advanced' in properties:
-# if isdefault:
-# subpath = f'[bright_blue]{subpath}[/bright_blue]'
-# else:
-# subpath = f'[red1]{subpath}[/red1]'
-# if is_default:
-# v = '[gold1]' + str(v) + '[/gold1]'
-# dico.append(f'{subpath}: {v}')
-# leader = False
-# else:
-# dico.append(dic)
-# else:
-# # it's a variable
-# self.parse_variable(option, value)
-#
- def add_family(self,
- option,
- ) -> None:
+
+ #
+ # def parse_option(self,
+ # option,
+ # value,
+ # variables,
+ # ):
+ # if '.' in line:
+ # # it's a dict
+ # family, variable = line.split('.', 1)
+ # current_path = parent_path
+ # if current_path:
+ # current_path += '.'
+ # current_path += family
+ # if for_doc:
+ # if 'hidden' in self.conf.option(current_path).property.get() or family_hidden:
+ # family_hidden = True
+ # family = f'[orange1]{family}[/orange1]'
+ # elif 'advanced' in self.conf.option(current_path).property.get():
+ # family = f'[bright_blue]{family}[/bright_blue]'
+ # if '.' not in variable and self.conf.option(full_path.rsplit('.', 1)[0]).isleadership():
+ # dico.setdefault(family, [])
+ # leadership = True
+ # else:
+ # dico.setdefault(family, {})
+ # leadership = False
+ # self.parse_option(full_path,
+ # variable,
+ # value,
+ # )
+ # elif leadership:
+ # # it's a leadership
+ # for idx, val in enumerate(value):
+ # dic = {k.rsplit('.', 1)[-1]: v for k, v in val.items()}
+ # if for_doc:
+ # leader = True
+ # for k, v in val.items():
+ # if leader:
+ # is_default = self.conf.option(k).owner.isdefault()
+ # properties = self.conf.option(k).property.get()
+ # else:
+ # is_default = self.conf.option(k, idx).owner.isdefault()
+ # properties = self.conf.option(k, idx).property.get()
+ # if self.conf.option(k).type() == _('password') and not self.args.show_secrets:
+ # v = "*" * 10
+ # subpath = k.rsplit('.', 1)[-1]
+ # if 'hidden' in properties or family_hidden:
+ # subpath = f'[orange1]{subpath}[/orange1]'
+ # elif 'advanced' in properties:
+ # if isdefault:
+ # subpath = f'[bright_blue]{subpath}[/bright_blue]'
+ # else:
+ # subpath = f'[red1]{subpath}[/red1]'
+ # if is_default:
+ # v = '[gold1]' + str(v) + '[/gold1]'
+ # dico.append(f'{subpath}: {v}')
+ # leader = False
+ # else:
+ # dico.append(dic)
+ # else:
+ # # it's a variable
+ # self.parse_variable(option, value)
+ #
+ def add_family(
+ self,
+ option,
+ ) -> None:
properties = option.property.get()
- if 'hidden' in properties:
+ if "hidden" in properties:
color = self.root.variable_hidden_color
- elif 'advanced' in properties:
+ elif "advanced" in properties:
color = self.root.variable_advanced_color
else:
color = None
- return OutputFamily(self.colorize(None,
- option.name(),
- color,
- None,
- ),
- self.tree,
- self.root,
- )
+ return OutputFamily(
+ self.colorize(
+ None,
+ option.name(),
+ color,
+ None,
+ ),
+ self.tree,
+ self.root,
+ )
- def add_variable(self,
- option,
- value: Any=undefined,
- leader_index: Optional[int]=None
- ):
+ def add_variable(
+ self, option, value: Any = undefined, leader_index: Optional[int] = None
+ ):
properties = option.property.get()
variable_color = None
if option.owner.isdefault():
- if 'hidden' in properties:
+ if "hidden" in properties:
variable_color = self.root.variable_hidden_color
- elif 'advanced' in properties:
+ elif "advanced" in properties:
variable_color = self.root.variable_advanced_color
color = self.root.value_unmodified_color
default_value = None
else:
- if 'hidden' in properties:
+ if "hidden" in properties:
variable_color = self.root.variable_hidden_color
- elif 'advanced' in properties:
+ elif "advanced" in properties:
variable_color = self.root.variable_advanced_and_modified_color
color = None
default_value = option.value.default()
@@ -231,31 +236,35 @@ class OutputFamily:
default_value = default_value[leader_index]
if value is undefined:
value = option.value.get()
- key = self.colorize(None,
- option.name(),
- variable_color,
- None,
- )
- value = self.colorize(option,
- value,
- color,
- default_value,
- )
+ key = self.colorize(
+ None,
+ option.name(),
+ variable_color,
+ None,
+ )
+ value = self.colorize(
+ option,
+ value,
+ color,
+ default_value,
+ )
if isinstance(value, list):
- subtree = self.tree.add(f":notebook: {key} :",
- guide_style="bold bright_blue",
- )
+ subtree = self.tree.add(
+ f":notebook: {key} :",
+ guide_style="bold bright_blue",
+ )
for val in value:
subtree.add(str(val))
else:
self.tree.add(f":notebook: {key}: {value}")
- def colorize(self,
- option,
- value,
- color: str,
- default_value,
- ) -> str:
+ def colorize(
+ self,
+ option,
+ value,
+ color: str,
+ default_value,
+ ) -> str:
if isinstance(value, list):
if default_value is None:
default_value = []
@@ -267,38 +276,43 @@ class OutputFamily:
if idx < len_value:
val = value[idx]
else:
- val = ''
+ val = ""
if idx < len_default_value:
if val:
- val += ' '
+ val += " "
default = default_value[idx]
else:
default = None
- ret.append(self.colorize(option,
- val,
- color,
- default,
- ))
+ ret.append(
+ self.colorize(
+ option,
+ val,
+ color,
+ default,
+ )
+ )
return ret
if option and value is not None:
- value = self.convert_value(option,
- value,
- )
+ value = self.convert_value(
+ option,
+ value,
+ )
else:
value = str(value)
if color is not None:
- ret = f'[{color}]{value}[/{color}]'
+ ret = f"[{color}]{value}[/{color}]"
else:
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
- ret += f' ([{default_value_color}]{default_value}[/{default_value_color}])'
+ ret += f" ([{default_value_color}]{default_value}[/{default_value_color}])"
return ret
- def convert_value(self,
- option,
- value,
- ):
- if not self.root.show_secrets and option.type() == 'password':
+ def convert_value(
+ self,
+ option,
+ value,
+ ):
+ if not self.root.show_secrets and option.type() == "password":
return "*" * 10
return str(value)