From 63e679036b2fdaf0d6bf0ce5b68aec2ef4053bed Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 19 Mar 2021 10:14:08 +0100 Subject: [PATCH] add valid_enum with function and rename domain type to domainname --- src/rougail/annotator/check.py | 17 ++++++++++++++++- src/rougail/annotator/param.py | 10 ++++++++++ src/rougail/annotator/variable.py | 2 +- src/rougail/data/rougail.dtd | 4 ++-- src/rougail/tiramisureflector.py | 18 +++++++++++------- tests/eosfunc/test.py | 5 +++++ 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/rougail/annotator/check.py b/src/rougail/annotator/check.py index fda7f8f3..f2e1bdde 100644 --- a/src/rougail/annotator/check.py +++ b/src/rougail/annotator/check.py @@ -52,6 +52,7 @@ class CheckAnnotator(TargetAnnotator, ParamAnnotator): self.functions.extend(INTERNAL_FUNCTIONS) self.functions.extend(self.objectspace.rougailconfig['internal_functions']) self.target_is_uniq = False + self.allow_function = True self.convert_target(self.objectspace.space.constraints.check) self.convert_param(self.objectspace.space.constraints.check) self.check_check() @@ -132,11 +133,23 @@ class CheckAnnotator(TargetAnnotator, ParamAnnotator): has_variable = False values = [] has_nil = False + is_function = False for param in check.param: if has_variable: msg = _(f'only one "variable" parameter is allowed for valid_enum ' f'of variable "{variable.name}"') raise DictConsistencyError(msg, 5, param.xmlfiles) + if param.type == 'function': + is_function = True + choice = self.objectspace.choice(variable.xmlfiles) + choice.name = param.text + choice.type = 'function' + choice.param = [] + variable.values.append(choice) + continue + if is_function: + variable.values[0].param.append(param) + continue param_type = variable.ori_type if param.type == 'variable': has_variable = True @@ -148,7 +161,7 @@ class CheckAnnotator(TargetAnnotator, ParamAnnotator): msg = _(f'only multi "variable" parameter is allowed for valid_enum ' f'of variable "{variable.name}"') raise DictConsistencyError(msg, 6, param.xmlfiles) - param_type = 'calculation' + param_type = 'variable' elif param.type == 'nil': has_nil = True values.append(param.text) @@ -156,6 +169,8 @@ class CheckAnnotator(TargetAnnotator, ParamAnnotator): choice.name = param.text choice.type = param_type variable.values.append(choice) + if is_function: + return None if 'mandatory' not in vars(variable): variable.mandatory = not has_nil elif variable.mandatory is False: diff --git a/src/rougail/annotator/param.py b/src/rougail/annotator/param.py index 1b874bfe..1fc6090c 100644 --- a/src/rougail/annotator/param.py +++ b/src/rougail/annotator/param.py @@ -82,6 +82,16 @@ class ParamAnnotator: if err.errno != 42 or not param.optional: raise err param_to_delete.append(param_idx) + elif param.type == 'function': + if not self.allow_function: + msg = _(f'cannot use "function" type') + raise DictConsistencyError(msg, 74, param.xmlfiles) + if not param.text in self.functions: + msg = _(f'cannot find function "{param.text}"') + raise DictConsistencyError(msg, 67, param.xmlfiles) + if param_idx != 0: + msg = _(f'function "{param.text}" must only set has first parameter') + raise DictConsistencyError(msg, 75, param.xmlfiles) elif variable_type: self._convert_with_variable_type(variable_type, param) continue diff --git a/src/rougail/annotator/variable.py b/src/rougail/annotator/variable.py index 1949b441..1cecf742 100644 --- a/src/rougail/annotator/variable.py +++ b/src/rougail/annotator/variable.py @@ -50,7 +50,7 @@ CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int), 'broadcast': dict(opttype="BroadcastOption"), 'netbios': dict(opttype="DomainnameOption", initkwargs={'type': 'netbios', 'warnings_only': True}), - 'domain': dict(opttype="DomainnameOption", initkwargs={'type': 'domainname', + 'domainname': dict(opttype="DomainnameOption", initkwargs={'type': 'domainname', 'allow_ip': False}), 'hostname': dict(opttype="DomainnameOption", initkwargs={'type': 'hostname', 'allow_ip': False}), diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd index 499fd53b..a3da5858 100644 --- a/src/rougail/data/rougail.dtd +++ b/src/rougail/data/rougail.dtd @@ -86,7 +86,7 @@ - + @@ -121,7 +121,7 @@ - + diff --git a/src/rougail/tiramisureflector.py b/src/rougail/tiramisureflector.py index 470e2477..318e6dd3 100644 --- a/src/rougail/tiramisureflector.py +++ b/src/rougail/tiramisureflector.py @@ -296,9 +296,11 @@ class Variable(Common): keys['opt'] = self.elt.opt.reflector_object.get() if hasattr(self.elt, 'values'): values = self.elt.values - if values[0].type == 'calculation': + if values[0].type == 'variable': value = values[0].name.reflector_object.get() keys['values'] = f"Calculation(func.calc_value, Params((ParamOption({value}))))" + elif values[0].type == 'function': + keys['values'] = self.calculation_value(self.elt.values[0], []) else: keys['values'] = str(tuple([val.name for val in values])) if hasattr(self.elt, 'multi') and self.elt.multi: @@ -309,11 +311,11 @@ class Variable(Common): if isinstance(value, str): value = self.convert_str(value) elif isinstance(value, self.objectspace.value): - value = self.calculation_value(value, []) + value = self.calculation_value(value, [], calc_multi=value.calc_multi) keys[key] = value if hasattr(self.elt, 'validators'): keys['validators'] = '[' + ', '.join([self.calculation_value(val, - ['ParamSelfOption()']) for val in self.elt.validators]) + ']' + ['ParamSelfOption(whole=False)']) for val in self.elt.validators]) + ']' for key in ['min_number', 'max_number']: if hasattr(self.elt, key): keys[key] = getattr(self.elt, key) @@ -325,6 +327,7 @@ class Variable(Common): def calculation_value(self, child, args, + calc_multi=False, ) -> str: """Generate calculated value """ @@ -336,11 +339,9 @@ class Variable(Common): for param in child.param: value = self.populate_param(param) if not hasattr(param, 'name'): -# args.append(str(value)) new_args.append(str(value)) else: kwargs.append(f"'{param.name}': " + value) -# ret = f'Calculation(func.{function}, Params((' + ', '.join(args) + ')' if function == 'valid_network_netmask': new_args.extend(args) else: @@ -352,7 +353,10 @@ class Variable(Common): ret += ')' if hasattr(child, 'warnings_only'): ret += f', warnings_only={child.warnings_only}' - return ret + ')' + ret = ret + ')' + if calc_multi: + ret = '[' + ret + ']' + return ret class Family(Common): @@ -383,5 +387,5 @@ class Family(Common): ) -> None: if hasattr(self.elt, 'suffixes'): dyn = self.elt.suffixes.reflector_object.get() - keys['suffixes'] = f"Calculation(func.calc_value, Params((ParamOption({dyn}))))" + keys['suffixes'] = f"Calculation(func.calc_value, Params((ParamOption({dyn}, notraisepropertyerror=True))))" keys['children'] = '[' + ', '.join([child.get() for child in self.children]) + ']' diff --git a/tests/eosfunc/test.py b/tests/eosfunc/test.py index 13bd0452..5be27593 100644 --- a/tests/eosfunc/test.py +++ b/tests/eosfunc/test.py @@ -1,5 +1,10 @@ from tiramisu import valid_not_equal, valid_ip_netmask, calc_value, valid_in_network + +def trange(start, stop): + return list(range(start, stop)) + + def calc_val(*args, **kwargs): if len(args) > 0: return args[0]