From 841adf07d96da27037ca8002ca6a32778468a57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=81?= Date: Thu, 29 Oct 2020 15:10:13 +0300 Subject: [PATCH] Now namespaces can be set in env parameter using dots. fixed #15 --- calculate/templates/template_engine.py | 50 +++++++++++++++-------- calculate/templates/template_processor.py | 1 + tests/scripts/test_scripts.py | 1 - tests/templates/test_template_engine.py | 21 ++++++---- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/calculate/templates/template_engine.py b/calculate/templates/template_engine.py index b873313..52c9f56 100644 --- a/calculate/templates/template_engine.py +++ b/calculate/templates/template_engine.py @@ -91,6 +91,9 @@ class Variables(MutableMapping): def __contains__(self, name: str) -> bool: return name in self.__attrs + def __hash__(self): + return hash(id(self)) + class ParametersProcessor: '''Класс для проверки и разбора параметров шаблона.''' @@ -456,11 +459,18 @@ class ParametersProcessor: for env_value in parameter_value.split(','): env_value = env_value.strip() - if env_value not in self.datavars_module: - raise ConditionFailed( - "Modules from 'env' parameter do not exist.", self.lineno) - else: - env_set.add(env_value) + + name_parts = env_value.split('.') + namespace = self.datavars_module + for name in name_parts: + if name not in namespace: + raise ConditionFailed( + (f"Namespace '{env_value}' from 'env' parameter" + " does not exist."), + self.lineno) + namespace = namespace[name] + env_set.add(namespace) + CalculateContext._env_set.add(namespace) # Если шаблон файла -- не добавляем env в контейнер, # а только используем для рендеринга шаблона. @@ -777,6 +787,7 @@ class ParametersProcessor: def resolve_or_missing(context, key, missing=missing, env={}): '''Переопределение функции из для поиска значений переменных из jinja2. Ищет переменные в datavars.''' + print('looking for:', key) datavars = context.parent['__datavars__'] if key in context.vars: @@ -788,9 +799,10 @@ def resolve_or_missing(context, key, missing=missing, env={}): if key in datavars: return datavars[key] - for name in env: - if name in datavars and key in datavars[name]: - return datavars[name][key] + for namespace in env: + print(namespace) + if key in namespace: + return namespace[key] return missing @@ -1079,13 +1091,15 @@ class CalculateExtension(Extension): return nodes.Output([nodes.Const('')], lineno=lineno) def _is_variable_name(self, token): + '''Метод для проверки токена на предмет того, что он является частью + имени переменной.''' if not token.type == 'name': return False if (token.value in self._datavars.available_packages or token.value in self.environment.globals): return True - for env in self.environment.context_class._env_set: - if token.value in self._datavars[env]: + for namespace in self.environment.context_class._env_set: + if token.value in namespace: return True return False @@ -1393,17 +1407,17 @@ class CalculateExtension(Extension): parameter_name_node = nodes.Const(parameter_name, lineno=lineno) if self.stream.skip_if('assign'): - parameter_value = self.stream.current.value + # parameter_value = self.stream.current.value parameter_rvalue = self.parser.parse_expression(with_condexpr=True) - if parameter_name == 'env': - # если параметр env -- обновляем множество значений env - # контекста вo время парсинга. - env_names = parameter_value.split(',') - for name in env_names: - self.environment.context_class._env_set.add(name.strip()) + # if parameter_name == 'env': + # # если параметр env -- обновляем множество значений env + # # контекста вo время парсинга. + # env_names = parameter_value.split(',') + # for name in env_names: + # self.environment.context_class._env_set.add(name.strip()) else: parameter_rvalue = nodes.Const(True, lineno=lineno) - parameter_value = True + # parameter_value = True return (parameter_name_node, parameter_rvalue) diff --git a/calculate/templates/template_processor.py b/calculate/templates/template_processor.py index e299fad..0ab69c5 100644 --- a/calculate/templates/template_processor.py +++ b/calculate/templates/template_processor.py @@ -1769,6 +1769,7 @@ class DirectoryProcessor: self.output = output_module self.datavars_module = datavars_module + self._namespace = namespace # Корневая директория. if 'cl_chroot_path' in datavars_module.main: diff --git a/tests/scripts/test_scripts.py b/tests/scripts/test_scripts.py index 2be0199..15edd81 100644 --- a/tests/scripts/test_scripts.py +++ b/tests/scripts/test_scripts.py @@ -1895,7 +1895,6 @@ class TestTasks(): def test_run_templates_using_script_and_namespace_is_set(self): datavars = Datavars(variables_path=os.path.join(TESTFILES_PATH, 'variables')) - Script('test_script', ).tasks(RunTemplate(id="templates_1", action='action_2', diff --git a/tests/templates/test_template_engine.py b/tests/templates/test_template_engine.py index 425d712..8f6d137 100644 --- a/tests/templates/test_template_engine.py +++ b/tests/templates/test_template_engine.py @@ -49,7 +49,8 @@ class TestTemplateEngine(): output_parameters.autoupdate) def test_if_an_input_template_contains_env_parameter_in_which_module_name_is_assigned__the_variables_from_this_module_can_be_used_in_template_without_determining_of_their_module(self): - input_template = '''{% calculate name = vars.var_1, env = 'other_vars', path = var_3 %}''' + input_template = '''{% calculate name = vars.var_1, + env = 'other_vars', path = var_3 %}''' datavars_module = Variables({'vars': Variables({'var_1': 'filename', 'var_2': '/etc/path'}), @@ -62,7 +63,7 @@ class TestTemplateEngine(): output_parameters = template_engine.parameters assert (output_parameters.name == 'filename' and output_parameters.path == '/etc/other_path' and - output_parameters.env == {'other_vars'}) + output_parameters.env == {datavars_module['other_vars']}) def test_if_an_input_template_contains_condition_and_it_is_True__the_template_engine_object_will_be_initialized_without_any_exceptions(self): input_template = '''{% calculate vars.var_1 < vars.var_2 or (not (var_3 == 'required status') and vars.var_4), env = 'vars' %}''' @@ -114,23 +115,25 @@ class TestTemplateEngine(): output_parameters = template_engine.parameters assert (output_parameters.name == 'filename' and output_parameters.path == '/etc/other_path' and - output_parameters.env == {'other_vars', 'vars'}) + output_parameters.env == {datavars_module['other_vars'], + datavars_module['vars']}) def test_if_an_input_template_contains_variables_in_its_text__the_rendered_text_will_contain_values_of_this_variables(self): input_template = '''{% calculate name = 'filename', force, - env = 'vars_1' -%} + env = 'vars.vars_1' -%} parameter_1 = {{ vars_2.var_3 }} parameter_2 = {{ vars_2.var_4 }} parameter_3 = {{ var_1 }}''' output_text = '''parameter_1 = value_1 parameter_2 = value_2 parameter_3 = 12''' - datavars_module = Variables({'vars_1': - Variables({'var_1': 12, - 'var_2': 1.2}), - 'vars_2': + datavars_module = Variables({'vars_2': Variables({'var_3': 'value_1', - 'var_4': 'value_2'})}) + 'var_4': 'value_2'}), + 'vars': + Variables({'vars_1': + Variables({'var_1': 12, + 'var_2': 1.2})})}) template_engine = TemplateEngine(appends_set=APPENDS_SET, datavars_module=datavars_module) template_engine.process_template_from_string(input_template, DIR)