WIP: Expand the developer documentation #27
4 changed files with 41 additions and 22 deletions
|
@ -83,11 +83,4 @@ class NotFoundError(Exception):
|
|||
## ---- specific exceptions ----
|
||||
|
||||
class VariableCalculationDependencyError(Exception):
|
||||
"""When an attribute is set, and
|
||||
the target of this attribute doesn't exists.
|
||||
"""
|
||||
def __init__(self, msg, errno, xmlfiles):
|
||||
if xmlfiles:
|
||||
msg = _(f"{msg} in {display_xmlfiles(xmlfiles)}")
|
||||
super().__init__(msg)
|
||||
self.errno = errno
|
||||
pass
|
||||
|
|
|
@ -293,6 +293,9 @@ class JinjaCalculation(Calculation):
|
|||
"__internal_jinja": jinja_path,
|
||||
"__internal_type": return_type,
|
||||
"__internal_multi": multi,
|
||||
"__internal_files": self.xmlfiles,
|
||||
"__internal_attribute": self.attribute_name,
|
||||
"__internal_variable": self.path,
|
||||
},
|
||||
}
|
||||
if self.default_values:
|
||||
|
@ -461,6 +464,8 @@ class _VariableCalculation(Calculation):
|
|||
calc_variable_is_multi = True
|
||||
else:
|
||||
calc_variable_is_multi = True
|
||||
elif suffix and '{{ suffix }}' in suffix:
|
||||
calc_variable_is_multi = True
|
||||
if needs_multi:
|
||||
if calc_variable_is_multi:
|
||||
if self.inside_list:
|
||||
|
@ -473,8 +478,12 @@ class _VariableCalculation(Calculation):
|
|||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", it\'s a list'
|
||||
raise DictConsistencyError(msg, 23, self.xmlfiles)
|
||||
elif calc_variable_is_multi:
|
||||
if variable.multi or variable.path.rsplit('.', 1)[0] != self.path.rsplit('.', 1)[0]:
|
||||
# it's not a follower or not in same leadership
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is a multi'
|
||||
raise DictConsistencyError(msg, 21, self.xmlfiles)
|
||||
else:
|
||||
params[None][0]['index'] = {'index': {'type': 'index'}}
|
||||
return params
|
||||
|
||||
|
||||
|
@ -486,13 +495,12 @@ class VariableCalculation(_VariableCalculation):
|
|||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
if self.attribute_name != "default" and self.optional is True:
|
||||
if self.attribute_name != "default" and self.optional:
|
||||
msg = f'"{self.attribute_name}" variable shall not have an "optional" attribute for variable "{self.variable}"'
|
||||
raise DictConsistencyError(msg, 33, self.xmlfiles)
|
||||
variable, suffix = self.get_variable(objectspace)
|
||||
if not variable and self.optional:
|
||||
msg = f'the dependent variable was not found "{self.optional}" for attribute "{self.attribute_name}" in variable "{self.path}"'
|
||||
raise VariableCalculationDependencyError(msg, 90, self.xmlfiles)
|
||||
raise VariableCalculationDependencyError()
|
||||
params = self.get_params(objectspace,
|
||||
variable,
|
||||
suffix,
|
||||
|
@ -728,6 +736,7 @@ class Variable(BaseModel):
|
|||
path: str
|
||||
namespace: Optional[str]
|
||||
version: str
|
||||
path_prefix: Optional[str]
|
||||
xmlfiles: List[str] = []
|
||||
|
||||
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
||||
|
@ -740,6 +749,7 @@ class SymLink(BaseModel):
|
|||
opt: Variable
|
||||
namespace: Optional[str]
|
||||
version: str
|
||||
path_prefix: Optional[str]
|
||||
xmlfiles: List[str] = []
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
|
|
@ -36,7 +36,8 @@ from importlib.util import spec_from_loader as _spec_from_loader, module_from_sp
|
|||
from jinja2 import StrictUndefined, DictLoader
|
||||
from jinja2.sandbox import SandboxedEnvironment
|
||||
from rougail.object_model import CONVERT_OPTION
|
||||
from tiramisu.error import ValueWarning
|
||||
from rougail.error import display_xmlfiles
|
||||
from tiramisu.error import ValueWarning, ConfigError
|
||||
from .utils import normalize_family
|
||||
|
||||
|
||||
|
@ -66,7 +67,7 @@ def rougail_calc_value(*args, __default_value=None, **kwargs):
|
|||
return values
|
||||
|
||||
|
||||
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, __default_value=None, **kwargs):
|
||||
def jinja_to_function(__internal_variable, __internal_attribute, __internal_jinja, __internal_type, __internal_multi, __internal_files, __default_value=None, **kwargs):
|
||||
global ENV, CONVERT_OPTION
|
||||
kw = {}
|
||||
for key, value in kwargs.items():
|
||||
|
@ -77,15 +78,23 @@ def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, __def
|
|||
c_kw = c_kw.setdefault(subkey, {})
|
||||
c_kw[var] = value
|
||||
else:
|
||||
if key in kw:
|
||||
raise ConfigError(f'internal error, multi key for "{key}" in jinja_to_function')
|
||||
kw[key] = value
|
||||
try:
|
||||
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
|
||||
except Exception as err:
|
||||
raise ConfigError(f'cannot calculating "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}') from err
|
||||
convert = CONVERT_OPTION[__internal_type].get('func', str)
|
||||
if __internal_multi:
|
||||
values = [convert(val) for val in values.split()]
|
||||
values = [convert(val) for val in values.split('\n') if val != ""]
|
||||
if not values and __default_value is not None:
|
||||
return __default_value
|
||||
return values
|
||||
try:
|
||||
values = convert(values)
|
||||
except Exception as err:
|
||||
raise ConfigError(f'cannot converting "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}') from err
|
||||
values = values if values != '' and values != 'None' else None
|
||||
if values is None and __default_value is not None:
|
||||
return __default_value
|
||||
|
|
|
@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
from typing import List, Union
|
||||
from unicodedata import normalize, combining
|
||||
import re
|
||||
from itertools import chain
|
||||
|
||||
from importlib.machinery import SourceFileLoader
|
||||
from importlib.util import spec_from_loader, module_from_spec
|
||||
|
@ -116,10 +117,10 @@ def get_jinja_variable_to_param(
|
|||
for g in parsed_content.find_all(Getattr):
|
||||
variables.add(recurse_getattr(g))
|
||||
except TemplateSyntaxError as err:
|
||||
msg = _(f'error in jinja "{jinja_text}": {err}')
|
||||
raise Exception(msg) from err
|
||||
msg = _(f'error in jinja "{jinja_text}" for the variable "{ current_path }": {err}')
|
||||
raise DictConsistencyError(msg, 39, xmlfiles) from err
|
||||
variables = list(variables)
|
||||
variables.sort()
|
||||
variables.sort(reverse=True)
|
||||
founded_variables = {}
|
||||
unknown_variables = []
|
||||
for variable_path in variables:
|
||||
|
@ -133,8 +134,14 @@ def get_jinja_variable_to_param(
|
|||
)
|
||||
if variable and variable.path in objectspace.variables:
|
||||
founded_variables[variable_path] = (suffix, variable)
|
||||
else:
|
||||
sub_family = variable_path + '.'
|
||||
for founded_variable in chain(founded_variables, unknown_variables):
|
||||
if founded_variable.startswith(sub_family):
|
||||
break
|
||||
else:
|
||||
unknown_variables.append(variable_path)
|
||||
|
||||
for variable_path in unknown_variables:
|
||||
for v in founded_variables:
|
||||
if get_common_path(v, variable_path) == v:
|
||||
|
|
Loading…
Reference in a new issue