diff --git a/src/rougail/annotator/__init__.py b/src/rougail/annotator/__init__.py index 6c1ee0c6..ba1bfec7 100644 --- a/src/rougail/annotator/__init__.py +++ b/src/rougail/annotator/__init__.py @@ -24,34 +24,44 @@ 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 """ -from .group import GroupAnnotator -from .service import ServiceAnnotator -from .variable import VariableAnnotator, CONVERT_OPTION -from .check import CheckAnnotator -from .value import ValueAnnotator -from .condition import ConditionAnnotator -from .fill import FillAnnotator -from .family import FamilyAnnotator -from .property import PropertyAnnotator +from .variable import CONVERT_OPTION +import importlib.resources +from ..utils import load_modules + + +ANNOTATORS = None + + +def get_level(module): + return module.level + + +def get_annotators(annotators, module_name): + annotators[module_name] = [] + for pathobj in importlib.resources.files(module_name).iterdir(): + path = str(pathobj) + if not path.endswith('__') and not path.endswith('__.py'): + module = load_modules(path) + if 'Annotator' in dir(module): + annotators[module_name].append(module.Annotator) + class SpaceAnnotator: # pylint: disable=R0903 """Transformations applied on a object instance """ def __init__(self, objectspace, eosfunc_file): - self.objectspace = objectspace - GroupAnnotator(objectspace) - ServiceAnnotator(objectspace) - VariableAnnotator(objectspace) - CheckAnnotator(objectspace, - eosfunc_file, - ) - ConditionAnnotator(objectspace) - FillAnnotator(objectspace, - eosfunc_file, - ) - ValueAnnotator(objectspace) - FamilyAnnotator(objectspace) - PropertyAnnotator(objectspace) + global ANNOTATORS + if ANNOTATORS is None: + ANNOTATORS = {} + get_annotators(ANNOTATORS, 'rougail.annotator') + for extra_annotator in objectspace.rougailconfig['extra_annotators']: + get_annotators(ANNOTATORS, extra_annotator) + annotators = ANNOTATORS['rougail.annotator'].copy() + for extra_annotator in objectspace.rougailconfig['extra_annotators']: + annotators.extend(ANNOTATORS[extra_annotator]) + annotators = sorted(annotators, key=get_level) + for annotator in annotators: + annotator(objectspace, eosfunc_file) __all__ = ('SpaceAnnotator', 'CONVERT_OPTION') diff --git a/src/rougail/annotator/check.py b/src/rougail/annotator/check.py index f2e1bdde..f006831c 100644 --- a/src/rougail/annotator/check.py +++ b/src/rougail/annotator/check.py @@ -26,21 +26,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ from typing import List, Any -from .target import TargetAnnotator -from .param import ParamAnnotator +from rougail.annotator.target import TargetAnnotator +from rougail.annotator.param import ParamAnnotator -from ..utils import load_modules -from ..i18n import _ -from ..error import DictConsistencyError, display_xmlfiles +from rougail.utils import load_modules +from rougail.i18n import _ +from rougail.error import DictConsistencyError, display_xmlfiles INTERNAL_FUNCTIONS = ['valid_enum', 'valid_in_network', 'valid_differ', 'valid_entier'] -class CheckAnnotator(TargetAnnotator, ParamAnnotator): +class Annotator(TargetAnnotator, ParamAnnotator): """Annotate check """ + level = 40 def __init__(self, objectspace, eosfunc_file, + *args, ): if not hasattr(objectspace.space, 'constraints') or \ not hasattr(objectspace.space.constraints, 'check'): diff --git a/src/rougail/annotator/condition.py b/src/rougail/annotator/condition.py index f8f6f8fc..b31d8183 100644 --- a/src/rougail/annotator/condition.py +++ b/src/rougail/annotator/condition.py @@ -27,19 +27,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from typing import List -from ..i18n import _ -from ..error import DictConsistencyError +from rougail.i18n import _ +from rougail.error import DictConsistencyError -from .target import TargetAnnotator -from .param import ParamAnnotator -from .variable import Walk +from rougail.annotator.target import TargetAnnotator +from rougail.annotator.param import ParamAnnotator +from rougail.annotator.variable import Walk -class ConditionAnnotator(TargetAnnotator, ParamAnnotator, Walk): +class Annotator(TargetAnnotator, ParamAnnotator, Walk): """Annotate condition """ + level = 50 def __init__(self, objectspace, + *args, ): self.objectspace = objectspace self.force_service_value = {} diff --git a/src/rougail/annotator/family.py b/src/rougail/annotator/family.py index 45f4e1b9..3006b7b9 100644 --- a/src/rougail/annotator/family.py +++ b/src/rougail/annotator/family.py @@ -24,9 +24,9 @@ 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 """ -from ..i18n import _ -from ..error import DictConsistencyError -from .variable import Walk +from rougail.i18n import _ +from rougail.error import DictConsistencyError +from rougail.annotator.variable import Walk class Mode: # pylint: disable=R0903 @@ -43,11 +43,13 @@ class Mode: # pylint: disable=R0903 return other.level < self.level -class FamilyAnnotator(Walk): +class Annotator(Walk): """Annotate family """ + level = 80 def __init__(self, objectspace, + *args, ): self.objectspace = objectspace if not hasattr(self.objectspace.space, 'variables'): @@ -74,6 +76,7 @@ class FamilyAnnotator(Walk): def remove_empty_families(self) -> None: """Remove all families without any variable """ + #FIXME pas sous family for families in self.objectspace.space.variables.values(): removed_families = [] for family_name, family in families.variable.items(): diff --git a/src/rougail/annotator/fill.py b/src/rougail/annotator/fill.py index 6d002767..47aed614 100644 --- a/src/rougail/annotator/fill.py +++ b/src/rougail/annotator/fill.py @@ -24,28 +24,30 @@ 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 """ -from ..utils import load_modules -from ..i18n import _ -from ..error import DictConsistencyError +from rougail.utils import load_modules +from rougail.i18n import _ +from rougail.error import DictConsistencyError -from .target import TargetAnnotator -from .param import ParamAnnotator +from rougail.annotator.target import TargetAnnotator +from rougail.annotator.param import ParamAnnotator CALC_MULTI = ('calc_value', 'calc_list', 'get_range', 'calc_val_first_value', 'unbound_filename') -class FillAnnotator(TargetAnnotator, ParamAnnotator): +class Annotator(TargetAnnotator, ParamAnnotator): """Fill annotator """ + level = 60 def __init__(self, objectspace, eosfunc_file, + *args, ): - self.objectspace = objectspace if not hasattr(objectspace.space, 'constraints') or \ - not hasattr(self.objectspace.space.constraints, 'fill'): + not hasattr(objectspace.space.constraints, 'fill'): return + self.objectspace = objectspace self.functions = dir(load_modules(eosfunc_file)) self.functions.extend(self.objectspace.rougailconfig['internal_functions']) self.target_is_uniq = True @@ -68,12 +70,11 @@ class FillAnnotator(TargetAnnotator, ParamAnnotator): """valid and manage """ for fill in self.objectspace.space.constraints.fill: + # test if the function exists + if fill.name not in self.functions: + msg = _(f'cannot find fill function "{fill.name}"') + raise DictConsistencyError(msg, 25, fill.xmlfiles) for target in fill.target: - # test if the function exists - if fill.name not in self.functions: - msg = _(f'cannot find fill function "{fill.name}"') - raise DictConsistencyError(msg, 25, fill.xmlfiles) - # create an object value value = self.objectspace.value(fill.xmlfiles) value.type = 'calculation' @@ -87,7 +88,6 @@ class FillAnnotator(TargetAnnotator, ParamAnnotator): target.name.default = value else: target.name.value = [value] - # manage params if hasattr(fill, 'param') and fill.param: value.param = fill.param diff --git a/src/rougail/annotator/group.py b/src/rougail/annotator/group.py index 00b1f25e..884dce32 100644 --- a/src/rougail/annotator/group.py +++ b/src/rougail/annotator/group.py @@ -24,16 +24,18 @@ 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 """ -from ..i18n import _ -from ..error import DictConsistencyError -from ..utils import normalize_family +from rougail.i18n import _ +from rougail.error import DictConsistencyError +from rougail.utils import normalize_family -class GroupAnnotator: +class Annotator: """Annotate group """ + level = 10 def __init__(self, objectspace, + *args, ): self.objectspace = objectspace if not hasattr(self.objectspace.space, 'constraints') or \ diff --git a/src/rougail/annotator/param.py b/src/rougail/annotator/param.py index f93c0fc5..f261505a 100644 --- a/src/rougail/annotator/param.py +++ b/src/rougail/annotator/param.py @@ -29,10 +29,10 @@ try: except ModuleNotFoundError: import tiramisu -from .variable import CONVERT_OPTION +from rougail.annotator.variable import CONVERT_OPTION -from ..i18n import _ -from ..error import DictConsistencyError +from rougail.i18n import _ +from rougail.error import DictConsistencyError class ParamAnnotator: diff --git a/src/rougail/annotator/property.py b/src/rougail/annotator/property.py index 12a3ee2d..24feadc9 100644 --- a/src/rougail/annotator/property.py +++ b/src/rougail/annotator/property.py @@ -24,19 +24,23 @@ 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 """ -from ..i18n import _ -from ..error import DictConsistencyError -from .variable import Walk +from rougail.i18n import _ +from rougail.error import DictConsistencyError +from rougail.annotator.variable import Walk PROPERTIES = ('hidden', 'frozen', 'force_default_on_freeze', 'force_store_value', 'disabled', 'mandatory') -class PropertyAnnotator(Walk): +class Annotator(Walk): """Annotate properties """ - def __init__(self, objectspace): + level = 90 + def __init__(self, + objectspace, + *args + ) -> None: self.objectspace = objectspace if hasattr(self.objectspace.space, 'services'): self.convert_services() diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py index 7b8a3d34..de14cf9b 100644 --- a/src/rougail/annotator/service.py +++ b/src/rougail/annotator/service.py @@ -27,9 +27,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from os.path import basename from typing import Tuple -from ..i18n import _ -from ..utils import normalize_family -from ..error import DictConsistencyError +from rougail.i18n import _ +from rougail.utils import normalize_family +from rougail.error import DictConsistencyError # a object's attribute has some annotations # that shall not be present in the exported (flatened) XML ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespace', @@ -39,7 +39,7 @@ ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespac ALLOW_ATTRIBUT_NOT_MANAGE = ['file'] -class ServiceAnnotator: +class Annotator: """Manage service's object for example:: @@ -49,7 +49,11 @@ class ServiceAnnotator: """ - def __init__(self, objectspace): + level = 20 + def __init__(self, + objectspace, + *args, + ) -> None: self.objectspace = objectspace self.uniq_overrides = [] if 'network_type' not in self.objectspace.types: diff --git a/src/rougail/annotator/target.py b/src/rougail/annotator/target.py index b3ed69dc..0639d61d 100644 --- a/src/rougail/annotator/target.py +++ b/src/rougail/annotator/target.py @@ -24,8 +24,8 @@ 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 """ -from ..i18n import _ -from ..error import DictConsistencyError +from rougail.i18n import _ +from rougail.error import DictConsistencyError class TargetAnnotator: diff --git a/src/rougail/annotator/value.py b/src/rougail/annotator/value.py index 7496f47c..3697fd29 100644 --- a/src/rougail/annotator/value.py +++ b/src/rougail/annotator/value.py @@ -24,16 +24,18 @@ 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 """ -from .variable import Walk +from rougail.annotator.variable import Walk -from ..i18n import _ -from ..error import DictConsistencyError +from rougail.i18n import _ +from rougail.error import DictConsistencyError -class ValueAnnotator(Walk): # pylint: disable=R0903 +class Annotator(Walk): # pylint: disable=R0903 """Annotate value """ + level = 70 def __init__(self, objectspace, + *args, ) -> None: if not hasattr(objectspace.space, 'variables'): return diff --git a/src/rougail/annotator/variable.py b/src/rougail/annotator/variable.py index b6c7cbd3..e52783fb 100644 --- a/src/rougail/annotator/variable.py +++ b/src/rougail/annotator/variable.py @@ -25,9 +25,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -from ..i18n import _ -from ..error import DictConsistencyError -from ..objspace import convert_boolean +from rougail.i18n import _ +from rougail.error import DictConsistencyError +from rougail.objspace import convert_boolean CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), @@ -111,11 +111,13 @@ class Walk: yield from self._get_families(fam) -class VariableAnnotator(Walk): # pylint: disable=R0903 +class Annotator(Walk): # pylint: disable=R0903 """Annotate variable """ + level = 30 def __init__(self, objectspace, + *args, ): if not hasattr(objectspace.space, 'variables'): return diff --git a/src/rougail/config.py b/src/rougail/config.py index 7e0abd2f..23721373 100644 --- a/src/rougail/config.py +++ b/src/rougail/config.py @@ -43,6 +43,7 @@ RougailConfig = {'dictionaries_dir': [join(ROUGAILROOT, 'dictionaries')], 'variable_namespace': 'rougail', 'auto_freeze_variable': 'server_deployed', 'internal_functions': [], + 'extra_annotators': [], 'modes_level': ['basic', 'normal', 'expert'], 'default_family_mode': 'basic', 'default_variable_mode': 'normal', diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 5c7a7713..8612f48d 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -83,7 +83,7 @@ - + @@ -102,7 +102,7 @@ - +