WIP: Expand the developer documentation #27
4 changed files with 41 additions and 22 deletions
|
@ -83,11 +83,4 @@ class NotFoundError(Exception):
|
||||||
## ---- specific exceptions ----
|
## ---- specific exceptions ----
|
||||||
|
|
||||||
class VariableCalculationDependencyError(Exception):
|
class VariableCalculationDependencyError(Exception):
|
||||||
"""When an attribute is set, and
|
pass
|
||||||
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
|
|
||||||
|
|
|
@ -293,6 +293,9 @@ class JinjaCalculation(Calculation):
|
||||||
"__internal_jinja": jinja_path,
|
"__internal_jinja": jinja_path,
|
||||||
"__internal_type": return_type,
|
"__internal_type": return_type,
|
||||||
"__internal_multi": multi,
|
"__internal_multi": multi,
|
||||||
|
"__internal_files": self.xmlfiles,
|
||||||
|
"__internal_attribute": self.attribute_name,
|
||||||
|
"__internal_variable": self.path,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if self.default_values:
|
if self.default_values:
|
||||||
|
@ -461,6 +464,8 @@ class _VariableCalculation(Calculation):
|
||||||
calc_variable_is_multi = True
|
calc_variable_is_multi = True
|
||||||
else:
|
else:
|
||||||
calc_variable_is_multi = True
|
calc_variable_is_multi = True
|
||||||
|
elif suffix and '{{ suffix }}' in suffix:
|
||||||
|
calc_variable_is_multi = True
|
||||||
if needs_multi:
|
if needs_multi:
|
||||||
if calc_variable_is_multi:
|
if calc_variable_is_multi:
|
||||||
if self.inside_list:
|
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'
|
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", it\'s a list'
|
||||||
raise DictConsistencyError(msg, 23, self.xmlfiles)
|
raise DictConsistencyError(msg, 23, self.xmlfiles)
|
||||||
elif calc_variable_is_multi:
|
elif calc_variable_is_multi:
|
||||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is a multi'
|
if variable.multi or variable.path.rsplit('.', 1)[0] != self.path.rsplit('.', 1)[0]:
|
||||||
raise DictConsistencyError(msg, 21, self.xmlfiles)
|
# 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
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
@ -486,13 +495,12 @@ class VariableCalculation(_VariableCalculation):
|
||||||
self,
|
self,
|
||||||
objectspace,
|
objectspace,
|
||||||
) -> dict:
|
) -> 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}"'
|
msg = f'"{self.attribute_name}" variable shall not have an "optional" attribute for variable "{self.variable}"'
|
||||||
raise DictConsistencyError(msg, 33, self.xmlfiles)
|
raise DictConsistencyError(msg, 33, self.xmlfiles)
|
||||||
variable, suffix = self.get_variable(objectspace)
|
variable, suffix = self.get_variable(objectspace)
|
||||||
if not variable and self.optional:
|
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()
|
||||||
raise VariableCalculationDependencyError(msg, 90, self.xmlfiles)
|
|
||||||
params = self.get_params(objectspace,
|
params = self.get_params(objectspace,
|
||||||
variable,
|
variable,
|
||||||
suffix,
|
suffix,
|
||||||
|
@ -728,6 +736,7 @@ class Variable(BaseModel):
|
||||||
path: str
|
path: str
|
||||||
namespace: Optional[str]
|
namespace: Optional[str]
|
||||||
version: str
|
version: str
|
||||||
|
path_prefix: Optional[str]
|
||||||
xmlfiles: List[str] = []
|
xmlfiles: List[str] = []
|
||||||
|
|
||||||
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
||||||
|
@ -740,6 +749,7 @@ class SymLink(BaseModel):
|
||||||
opt: Variable
|
opt: Variable
|
||||||
namespace: Optional[str]
|
namespace: Optional[str]
|
||||||
version: str
|
version: str
|
||||||
|
path_prefix: Optional[str]
|
||||||
xmlfiles: List[str] = []
|
xmlfiles: List[str] = []
|
||||||
|
|
||||||
model_config = ConfigDict(extra="forbid")
|
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 import StrictUndefined, DictLoader
|
||||||
from jinja2.sandbox import SandboxedEnvironment
|
from jinja2.sandbox import SandboxedEnvironment
|
||||||
from rougail.object_model import CONVERT_OPTION
|
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
|
from .utils import normalize_family
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ def rougail_calc_value(*args, __default_value=None, **kwargs):
|
||||||
return values
|
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
|
global ENV, CONVERT_OPTION
|
||||||
kw = {}
|
kw = {}
|
||||||
for key, value in kwargs.items():
|
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 = c_kw.setdefault(subkey, {})
|
||||||
c_kw[var] = value
|
c_kw[var] = value
|
||||||
else:
|
else:
|
||||||
|
if key in kw:
|
||||||
|
raise ConfigError(f'internal error, multi key for "{key}" in jinja_to_function')
|
||||||
kw[key] = value
|
kw[key] = value
|
||||||
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
|
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)
|
convert = CONVERT_OPTION[__internal_type].get('func', str)
|
||||||
if __internal_multi:
|
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:
|
if not values and __default_value is not None:
|
||||||
return __default_value
|
return __default_value
|
||||||
return values
|
return values
|
||||||
values = convert(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
|
values = values if values != '' and values != 'None' else None
|
||||||
if values is None and __default_value is not None:
|
if values is None and __default_value is not None:
|
||||||
return __default_value
|
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 typing import List, Union
|
||||||
from unicodedata import normalize, combining
|
from unicodedata import normalize, combining
|
||||||
import re
|
import re
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
from importlib.machinery import SourceFileLoader
|
from importlib.machinery import SourceFileLoader
|
||||||
from importlib.util import spec_from_loader, module_from_spec
|
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):
|
for g in parsed_content.find_all(Getattr):
|
||||||
variables.add(recurse_getattr(g))
|
variables.add(recurse_getattr(g))
|
||||||
except TemplateSyntaxError as err:
|
except TemplateSyntaxError as err:
|
||||||
msg = _(f'error in jinja "{jinja_text}": {err}')
|
msg = _(f'error in jinja "{jinja_text}" for the variable "{ current_path }": {err}')
|
||||||
raise Exception(msg) from err
|
raise DictConsistencyError(msg, 39, xmlfiles) from err
|
||||||
variables = list(variables)
|
variables = list(variables)
|
||||||
variables.sort()
|
variables.sort(reverse=True)
|
||||||
founded_variables = {}
|
founded_variables = {}
|
||||||
unknown_variables = []
|
unknown_variables = []
|
||||||
for variable_path in variables:
|
for variable_path in variables:
|
||||||
|
@ -134,7 +135,13 @@ def get_jinja_variable_to_param(
|
||||||
if variable and variable.path in objectspace.variables:
|
if variable and variable.path in objectspace.variables:
|
||||||
founded_variables[variable_path] = (suffix, variable)
|
founded_variables[variable_path] = (suffix, variable)
|
||||||
else:
|
else:
|
||||||
unknown_variables.append(variable_path)
|
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 variable_path in unknown_variables:
|
||||||
for v in founded_variables:
|
for v in founded_variables:
|
||||||
if get_common_path(v, variable_path) == v:
|
if get_common_path(v, variable_path) == v:
|
||||||
|
|
Loading…
Reference in a new issue