2019-11-23 08:17:35 +01:00
|
|
|
"""
|
2021-01-30 08:15:26 +01:00
|
|
|
Config file for Rougail
|
2019-11-23 08:17:35 +01:00
|
|
|
|
2021-01-30 08:15:26 +01:00
|
|
|
Created by:
|
|
|
|
|
EOLE (http://eole.orion.education.fr)
|
|
|
|
|
Copyright (C) 2005-2018
|
|
|
|
|
|
|
|
|
|
Forked by:
|
|
|
|
|
Cadoles (http://www.cadoles.com)
|
|
|
|
|
Copyright (C) 2019-2021
|
|
|
|
|
|
2022-11-02 23:00:42 +01:00
|
|
|
Silique (https://www.silique.fr)
|
2024-01-28 19:03:09 +01:00
|
|
|
Copyright (C) 2022-2024
|
2022-11-02 23:00:42 +01:00
|
|
|
|
2021-01-30 08:15:26 +01:00
|
|
|
distribued with GPL-2 or later license
|
|
|
|
|
|
|
|
|
|
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 2 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 General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
2019-11-23 08:17:35 +01:00
|
|
|
"""
|
2024-07-06 15:26:01 +02:00
|
|
|
from pathlib import Path
|
|
|
|
|
from tiramisu import Config
|
|
|
|
|
from ruamel.yaml import YAML
|
|
|
|
|
from .utils import _, load_modules, normalize_family
|
|
|
|
|
from .convert import RougailConvert
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RENAMED = {'dictionaries_dir': 'main_dictionaries',
|
|
|
|
|
'variable_namespace': 'main_namespace',
|
|
|
|
|
'functions_file': 'functions_files',
|
|
|
|
|
}
|
|
|
|
|
NOT_IN_TIRAMISU = {'custom_types': {},
|
|
|
|
|
}
|
|
|
|
|
SUBMODULES = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_sub_modules():
|
|
|
|
|
global SUBMODULES
|
|
|
|
|
if SUBMODULES is None:
|
|
|
|
|
SUBMODULES = {}
|
|
|
|
|
for submodule in Path(__file__).parent.iterdir():
|
|
|
|
|
if submodule.name.startswith('_') or not submodule.is_dir():
|
|
|
|
|
continue
|
|
|
|
|
config_file = submodule / 'config.py'
|
|
|
|
|
if config_file.is_file():
|
|
|
|
|
SUBMODULES[submodule.name] = load_modules('rougail.' + submodule.name + '.config', str(config_file))
|
|
|
|
|
return SUBMODULES
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_level(module):
|
|
|
|
|
return module['level']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _RougailConfig:
|
|
|
|
|
def __init__(self,
|
|
|
|
|
backward_compatibility: bool,
|
|
|
|
|
root,
|
|
|
|
|
):
|
|
|
|
|
self.backward_compatibility = backward_compatibility
|
|
|
|
|
self.root = root
|
|
|
|
|
self.config = Config(
|
|
|
|
|
self.root,
|
|
|
|
|
)
|
|
|
|
|
self.config.property.read_only()
|
|
|
|
|
for variable, default_value in NOT_IN_TIRAMISU.items():
|
|
|
|
|
if not isinstance(default_value, str):
|
|
|
|
|
default_value = default_value.copy()
|
|
|
|
|
setattr(self, variable, default_value)
|
|
|
|
|
|
|
|
|
|
def copy(self):
|
|
|
|
|
rougailconfig = _RougailConfig(self.backward_compatibility, self.root)
|
|
|
|
|
rougailconfig.config.value.importation(self.config.value.exportation())
|
|
|
|
|
rougailconfig.config.property.importation(self.config.property.exportation())
|
|
|
|
|
rougailconfig.config.property.read_only()
|
|
|
|
|
for variable in NOT_IN_TIRAMISU:
|
|
|
|
|
value = getattr(self, variable)
|
|
|
|
|
if not isinstance(value, str):
|
|
|
|
|
value = value.copy()
|
|
|
|
|
setattr(rougailconfig, variable, value)
|
|
|
|
|
return rougailconfig
|
|
|
|
|
|
|
|
|
|
def __setitem__(self,
|
|
|
|
|
key,
|
|
|
|
|
value,
|
|
|
|
|
) -> None:
|
|
|
|
|
if key in NOT_IN_TIRAMISU:
|
|
|
|
|
setattr(self, key, value)
|
|
|
|
|
else:
|
|
|
|
|
self.config.property.read_write()
|
|
|
|
|
if key == 'export_with_import':
|
|
|
|
|
key = 'not_export_with_import'
|
|
|
|
|
key = RENAMED.get(key, key)
|
|
|
|
|
option = self.config.option(key)
|
|
|
|
|
if option.isoptiondescription() and option.isleadership():
|
|
|
|
|
leader = list(value)
|
|
|
|
|
option.leader().value.set(leader)
|
|
|
|
|
follower = option.followers()[0]
|
|
|
|
|
for idx, val in enumerate(value.values()):
|
|
|
|
|
self.config.option(follower.path(), idx).value.set(val)
|
|
|
|
|
elif key == 'not_export_with_import':
|
|
|
|
|
option.value.set(not value)
|
|
|
|
|
else:
|
|
|
|
|
option.value.set(value)
|
|
|
|
|
self.config.property.read_only()
|
|
|
|
|
|
|
|
|
|
def __getitem__(self,
|
|
|
|
|
key,
|
|
|
|
|
) -> None:
|
|
|
|
|
if key in NOT_IN_TIRAMISU:
|
|
|
|
|
return getattr(self, key)
|
|
|
|
|
if key == 'export_with_import':
|
|
|
|
|
key = 'not_export_with_import'
|
|
|
|
|
option = self.config.option(key)
|
|
|
|
|
if option.isoptiondescription() and option.isleadership():
|
|
|
|
|
return self.get_leadership(option)
|
|
|
|
|
ret = self.config.option(key).value.get()
|
|
|
|
|
if key == 'not_export_with_import':
|
|
|
|
|
return not ret
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def get_leadership(self,
|
|
|
|
|
option
|
|
|
|
|
) -> dict:
|
2024-08-25 12:23:06 +02:00
|
|
|
leader = None
|
|
|
|
|
followers = []
|
|
|
|
|
for opt, value in option.value.get().items():
|
|
|
|
|
if opt.issymlinkoption():
|
|
|
|
|
continue
|
|
|
|
|
if leader is None:
|
|
|
|
|
leader = value
|
|
|
|
|
else:
|
|
|
|
|
followers.append(value)
|
2024-07-06 15:26:01 +02:00
|
|
|
return dict(zip(leader, followers))
|
|
|
|
|
|
2024-08-25 12:23:06 +02:00
|
|
|
def parse(self, config) -> str:
|
|
|
|
|
for option in config:
|
|
|
|
|
if option.isoptiondescription():
|
|
|
|
|
yield from self.parse(option)
|
|
|
|
|
elif not option.issymlinkoption():
|
|
|
|
|
yield f'{option.path()}: {option.value.get()}'
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
self.config.property.read_write()
|
|
|
|
|
try:
|
|
|
|
|
values = "\n".join(self.parse(self.config))
|
|
|
|
|
except Exception as err:
|
|
|
|
|
values = str(err)
|
|
|
|
|
self.config.property.read_only()
|
|
|
|
|
return values
|
|
|
|
|
|
2024-07-06 15:26:01 +02:00
|
|
|
|
|
|
|
|
class FakeRougailConvert(RougailConvert):
|
2024-08-08 09:04:49 +02:00
|
|
|
def __init__(self,
|
|
|
|
|
add_extra_options: bool,
|
|
|
|
|
) -> None:
|
|
|
|
|
self.add_extra_options = add_extra_options
|
|
|
|
|
super().__init__({})
|
|
|
|
|
|
2024-07-06 15:26:01 +02:00
|
|
|
def load_config(self,
|
|
|
|
|
rougailconfig: 'RougailConfig',
|
|
|
|
|
) -> None:
|
|
|
|
|
self.main_namespace = None
|
|
|
|
|
self.suffix = ''
|
|
|
|
|
self.custom_types = {}
|
|
|
|
|
self.functions_files = []
|
|
|
|
|
self.modes_level = []
|
|
|
|
|
self.extra_annotators = []
|
|
|
|
|
self.base_option_name = "baseoption"
|
|
|
|
|
self.export_with_import = True
|
|
|
|
|
self.internal_functions = []
|
|
|
|
|
self.plugins = ['structural_commandline']
|
2024-08-08 09:04:49 +02:00
|
|
|
self.add_extra_options = self.add_extra_options
|
2024-07-06 15:26:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_rougail_config(*,
|
2024-08-08 09:04:49 +02:00
|
|
|
backward_compatibility: bool=True,
|
|
|
|
|
add_extra_options: bool=True,
|
2024-07-06 15:26:01 +02:00
|
|
|
) -> _RougailConfig:
|
|
|
|
|
if backward_compatibility:
|
|
|
|
|
main_namespace_default = 'rougail'
|
|
|
|
|
else:
|
|
|
|
|
main_namespace_default = 'null'
|
|
|
|
|
rougail_options = """default_dictionary_format_version:
|
|
|
|
|
description: Dictionary format version by default, if not specified in dictionary file
|
|
|
|
|
alternative_name: v
|
|
|
|
|
choices:
|
|
|
|
|
- '1.0'
|
|
|
|
|
- '1.1'
|
|
|
|
|
mandatory: false
|
|
|
|
|
main_dictionaries:
|
|
|
|
|
description: 'Directories where dictionary files are placed'
|
|
|
|
|
type: unix_filename
|
|
|
|
|
alternative_name: m
|
|
|
|
|
params:
|
|
|
|
|
allow_relative: True
|
|
|
|
|
test_existence: True
|
|
|
|
|
types:
|
|
|
|
|
- directory
|
|
|
|
|
multi: true
|
|
|
|
|
main_namespace:
|
|
|
|
|
description: Main namespace name
|
|
|
|
|
default: MAIN_MAMESPACE_DEFAULT
|
2024-08-08 09:04:49 +02:00
|
|
|
alternative_name: s
|
2024-07-06 15:26:01 +02:00
|
|
|
mandatory: false
|
|
|
|
|
extra_dictionaries:
|
|
|
|
|
description: Extra namespaces
|
|
|
|
|
type: leadership
|
|
|
|
|
disabled:
|
2024-09-02 15:47:33 +02:00
|
|
|
variable: main_namespace
|
|
|
|
|
when: null
|
2024-07-06 15:26:01 +02:00
|
|
|
names:
|
|
|
|
|
description: 'Extra namespace name'
|
2024-09-02 15:47:33 +02:00
|
|
|
alternative_name: xn
|
2024-07-06 15:26:01 +02:00
|
|
|
multi: true
|
|
|
|
|
mandatory: false
|
|
|
|
|
directories:
|
|
|
|
|
description: Directories where extra dictionary files are placed
|
2024-09-02 15:47:33 +02:00
|
|
|
alternative_name: xd
|
2024-07-06 15:26:01 +02:00
|
|
|
type: unix_filename
|
|
|
|
|
params:
|
|
|
|
|
allow_relative: true
|
|
|
|
|
test_existence: true
|
|
|
|
|
types:
|
|
|
|
|
- directory
|
|
|
|
|
multi: true
|
|
|
|
|
functions_files:
|
|
|
|
|
description: File with functions
|
2024-09-02 15:47:33 +02:00
|
|
|
alternative_name: c
|
2024-07-06 15:26:01 +02:00
|
|
|
type: unix_filename
|
|
|
|
|
params:
|
|
|
|
|
allow_relative: true
|
|
|
|
|
test_existence: true
|
|
|
|
|
types:
|
|
|
|
|
- file
|
|
|
|
|
multi: true
|
|
|
|
|
mandatory: false
|
|
|
|
|
modes_level:
|
|
|
|
|
description: All modes level available
|
|
|
|
|
default:
|
|
|
|
|
- basic
|
|
|
|
|
- standard
|
|
|
|
|
- advanced
|
|
|
|
|
commandline: false
|
|
|
|
|
default_family_mode:
|
|
|
|
|
description: Default mode for a family
|
|
|
|
|
default:
|
|
|
|
|
type: jinja
|
|
|
|
|
jinja: |
|
|
|
|
|
{{ modes_level[0] }}
|
|
|
|
|
validators:
|
|
|
|
|
- type: jinja
|
|
|
|
|
jinja: |
|
|
|
|
|
{% if default_family_mode not in modes_level %}
|
|
|
|
|
not in modes_level ({modes_level})
|
|
|
|
|
{% endif %}
|
|
|
|
|
commandline: false
|
|
|
|
|
default_variable_mode:
|
|
|
|
|
description: Default mode for a variable
|
|
|
|
|
default:
|
|
|
|
|
type: jinja
|
|
|
|
|
jinja: |
|
|
|
|
|
{{ modes_level[1] }}
|
|
|
|
|
validators:
|
|
|
|
|
- type: jinja
|
|
|
|
|
jinja: |
|
|
|
|
|
{% if default_variable_mode not in modes_level %}
|
|
|
|
|
not in modes_level ({modes_level})
|
|
|
|
|
{% endif %}
|
|
|
|
|
commandline: false
|
|
|
|
|
base_option_name:
|
|
|
|
|
description: Option name for the base option
|
|
|
|
|
default: baseoption
|
|
|
|
|
commandline: false
|
|
|
|
|
not_export_with_import:
|
|
|
|
|
description: In cache file, do not importation of Tiramisu and other dependencies
|
|
|
|
|
default: false
|
|
|
|
|
commandline: false
|
|
|
|
|
tiramisu_cache:
|
|
|
|
|
description: Tiramisu cache filename
|
|
|
|
|
alternative_name: t
|
|
|
|
|
type: unix_filename
|
|
|
|
|
mandatory: false
|
|
|
|
|
params:
|
|
|
|
|
allow_relative: true
|
|
|
|
|
internal_functions:
|
|
|
|
|
description: Name of internal functions that we can use as a function
|
|
|
|
|
multi: true
|
|
|
|
|
mandatory: false
|
|
|
|
|
commandline: false
|
|
|
|
|
extra_annotators:
|
|
|
|
|
description: Name of extra annotators
|
|
|
|
|
multi: true
|
|
|
|
|
mandatory: false
|
|
|
|
|
commandline: false
|
|
|
|
|
suffix:
|
|
|
|
|
description: Suffix add to generated option name
|
|
|
|
|
default: ''
|
|
|
|
|
mandatory: false
|
|
|
|
|
commandline: false
|
|
|
|
|
""".replace('MAIN_MAMESPACE_DEFAULT', main_namespace_default)
|
2024-08-08 09:04:49 +02:00
|
|
|
processes = {'structural': [],
|
|
|
|
|
'output': [],
|
2024-07-06 15:26:01 +02:00
|
|
|
'user data': [],
|
|
|
|
|
}
|
|
|
|
|
for module in get_sub_modules().values():
|
|
|
|
|
data = module.get_rougail_config()
|
|
|
|
|
processes[data['process']].append(data)
|
|
|
|
|
# reorder
|
|
|
|
|
for process in processes:
|
|
|
|
|
processes[process] = list(sorted(processes[process], key=get_level))
|
|
|
|
|
rougail_process = 'step: # Load and exporter steps'
|
|
|
|
|
for process in processes:
|
|
|
|
|
if processes[process]:
|
|
|
|
|
objects = processes[process]
|
|
|
|
|
rougail_process += """
|
|
|
|
|
{NAME}:
|
|
|
|
|
description: Select for {NAME}
|
|
|
|
|
alternative_name: {NAME[0]}
|
|
|
|
|
choices:
|
|
|
|
|
""".format(NAME=normalize_family(process),
|
|
|
|
|
)
|
|
|
|
|
for obj in objects:
|
|
|
|
|
rougail_process += f" - {obj['name']}\n"
|
2024-08-08 09:04:49 +02:00
|
|
|
if process == 'structural':
|
|
|
|
|
rougail_process += " commandline: false"
|
|
|
|
|
elif process == 'user data':
|
|
|
|
|
rougail_process += """ multi: true
|
2024-07-06 15:26:01 +02:00
|
|
|
mandatory: false
|
|
|
|
|
"""
|
|
|
|
|
hidden_outputs = [process['name'] for process in processes['output'] if not process.get('allow_user_data', True)]
|
|
|
|
|
if hidden_outputs:
|
2024-08-08 09:04:49 +02:00
|
|
|
rougail_process += """ hidden:
|
2024-07-06 15:26:01 +02:00
|
|
|
type: jinja
|
|
|
|
|
jinja: |
|
|
|
|
|
"""
|
|
|
|
|
for hidden_output in hidden_outputs:
|
|
|
|
|
rougail_process += """ {% if _.output == 'NAME' %}
|
|
|
|
|
Cannot load user data for NAME output
|
|
|
|
|
{% endif %}
|
|
|
|
|
""".replace('NAME', hidden_output)
|
|
|
|
|
else:
|
|
|
|
|
rougail_process += ' default: {DEFAULT}'.format(DEFAULT=objects[0]['name'])
|
|
|
|
|
else:
|
|
|
|
|
rougail_process += """
|
|
|
|
|
{NAME}:
|
|
|
|
|
description: Select for {NAME}
|
|
|
|
|
hidden: true
|
2024-08-05 18:09:13 +02:00
|
|
|
mandatory: false
|
|
|
|
|
multi: true
|
2024-07-06 15:26:01 +02:00
|
|
|
""".format(NAME=normalize_family(process),
|
|
|
|
|
)
|
|
|
|
|
rougail_options += rougail_process
|
2024-08-08 09:04:49 +02:00
|
|
|
convert = FakeRougailConvert(add_extra_options)
|
2024-07-06 15:26:01 +02:00
|
|
|
convert._init()
|
|
|
|
|
convert.namespace = None
|
|
|
|
|
convert.parse_root_file(
|
|
|
|
|
'rougail.config',
|
|
|
|
|
'',
|
|
|
|
|
'1.1',
|
|
|
|
|
YAML().load(rougail_options),
|
|
|
|
|
)
|
|
|
|
|
for process in processes:
|
|
|
|
|
for obj in processes[process]:
|
|
|
|
|
if not 'options' in obj:
|
|
|
|
|
continue
|
|
|
|
|
convert.parse_root_file(
|
|
|
|
|
f'rougail.config.{obj["name"]}',
|
|
|
|
|
'',
|
|
|
|
|
'1.1',
|
|
|
|
|
YAML().load(obj['options']),
|
|
|
|
|
)
|
|
|
|
|
|
2024-08-05 16:24:26 +02:00
|
|
|
tiram_obj = convert.save(None)
|
2024-07-06 15:26:01 +02:00
|
|
|
optiondescription = {}
|
|
|
|
|
exec(tiram_obj, {}, optiondescription) # pylint: disable=W0122
|
|
|
|
|
return _RougailConfig(backward_compatibility, optiondescription["option_0"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RougailConfig = get_rougail_config()
|