168 lines
6.5 KiB
Python
168 lines
6.5 KiB
Python
"""Annotate check
|
|
|
|
Created by:
|
|
EOLE (http://eole.orion.education.fr)
|
|
Copyright (C) 2005-2018
|
|
|
|
Forked by:
|
|
Cadoles (http://www.cadoles.com)
|
|
Copyright (C) 2019-2021
|
|
|
|
Silique (https://www.silique.fr)
|
|
Copyright (C) 2022-2023
|
|
|
|
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
|
|
"""
|
|
from typing import List, Any
|
|
from copy import copy
|
|
|
|
from rougail.annotator.target import TargetAnnotator
|
|
from rougail.annotator.param import ParamAnnotator
|
|
#from rougail.annotator.fill import get_jinja_variable_to_param
|
|
|
|
from rougail.i18n import _
|
|
from rougail.error import DictConsistencyError, display_xmlfiles
|
|
|
|
INTERNAL_FUNCTIONS = ['valid_in_network', 'valid_differ', 'valid_entier']
|
|
|
|
class Annotator(TargetAnnotator, ParamAnnotator):
|
|
"""Annotate check
|
|
"""
|
|
level = 40
|
|
def __init__(self,
|
|
objectspace,
|
|
*args,
|
|
):
|
|
return
|
|
self.objectspace = objectspace
|
|
self.only_variable = True
|
|
self.target_is_uniq = False
|
|
self.allow_function = True
|
|
self.functions = copy(functions)
|
|
self.functions.extend(INTERNAL_FUNCTIONS)
|
|
self.functions.extend(self.objectspace.rougailconfig['internal_functions'])
|
|
for path_prefix, constraints in self.get_constraints():
|
|
if not hasattr(constraints, 'check'):
|
|
continue
|
|
self.convert_target(constraints.check, path_prefix)
|
|
self.convert_param(constraints.check, path_prefix)
|
|
self.check_check(constraints)
|
|
self.convert_check_jinja(constraints, path_prefix)
|
|
self.check_change_warning(constraints)
|
|
self.convert_valid_entier(constraints)
|
|
self.convert_check(constraints)
|
|
del constraints.check
|
|
|
|
def check_check(self,
|
|
constraints,
|
|
): # pylint: disable=R0912
|
|
"""valid and manage <check>
|
|
"""
|
|
remove_indexes = []
|
|
for check_idx, check in enumerate(constraints.check):
|
|
if check.type == 'function' and not check.name in self.functions and not self.objectspace.just_doc:
|
|
msg = _(f'cannot find check function "{check.name}"')
|
|
raise DictConsistencyError(msg, 1, check.xmlfiles)
|
|
if hasattr(check, 'param') and check.param == []:
|
|
remove_indexes.append(check_idx)
|
|
remove_indexes.sort(reverse=True)
|
|
for idx in remove_indexes:
|
|
del constraints.check[idx]
|
|
|
|
def convert_valid_entier(self,
|
|
constraints,
|
|
) -> None:
|
|
"""valid and manage <check>
|
|
"""
|
|
remove_indexes = []
|
|
for check_idx, check in enumerate(constraints.check):
|
|
if not check.name == 'valid_entier':
|
|
continue
|
|
remove_indexes.append(check_idx)
|
|
if not hasattr(check, 'param'):
|
|
msg = _(f'{check.name} must have, at least, 1 param')
|
|
raise DictConsistencyError(msg, 17, check.xmlfiles)
|
|
for param in check.param:
|
|
if param.type != 'number':
|
|
msg = _(f'param in "valid_entier" must be an "integer", not "{param.type}"')
|
|
raise DictConsistencyError(msg, 18, check.xmlfiles)
|
|
if not hasattr(param, 'name'):
|
|
continue
|
|
for target in check.target:
|
|
if param.name == 'mini':
|
|
target.name.min_number = int(param.text)
|
|
elif param.name == 'maxi':
|
|
target.name.max_number = int(param.text)
|
|
else:
|
|
msg = _(f'unknown parameter "{param.name}" in check "valid_entier"')
|
|
raise DictConsistencyError(msg, 19, check.xmlfiles)
|
|
remove_indexes.sort(reverse=True)
|
|
for idx in remove_indexes:
|
|
del constraints.check[idx]
|
|
|
|
def convert_check_jinja(self,
|
|
constraints,
|
|
path_prefix,
|
|
) -> None:
|
|
"""convert jinja <check> to a function
|
|
"""
|
|
for check in constraints.check:
|
|
if check.type != 'jinja':
|
|
continue
|
|
if len(check.target) > 1:
|
|
msg = _(f'a check with type jinja cannot have more than one target')
|
|
raise DictConsistencyError(msg, 92, check.xmlfiles)
|
|
if not hasattr(check, 'param'):
|
|
check.param = []
|
|
jinja_text = check.name
|
|
check.name = 'valid_with_jinja'
|
|
new_param = self.objectspace.param(check.xmlfiles)
|
|
new_param.name = '__internal_jinja'
|
|
new_param.text = jinja_text
|
|
new_param.type = 'jinja'
|
|
check.param.append(new_param)
|
|
if path_prefix:
|
|
path = check.target[0].name.path.split('.', 1)[-1]
|
|
else:
|
|
path = check.target[0].name.path
|
|
get_jinja_variable_to_param(jinja_text,
|
|
self.objectspace,
|
|
check,
|
|
path_prefix,
|
|
check.target[0].name.name,
|
|
path,
|
|
)
|
|
|
|
def check_change_warning(self,
|
|
constraints,
|
|
):
|
|
"""convert level to "warnings_only"
|
|
"""
|
|
for check in constraints.check:
|
|
check.warnings_only = check.level == 'warning'
|
|
check.level = None
|
|
|
|
def convert_check(self,
|
|
constraints,
|
|
) -> None:
|
|
"""valid and manage <check>
|
|
"""
|
|
for check in constraints.check:
|
|
for target in check.target:
|
|
if not hasattr(target.name, 'validators'):
|
|
target.name.validators = []
|
|
target.name.validators.append(check)
|