diff --git a/calculate/templates/template_engine.py b/calculate/templates/template_engine.py index e26f47c..eaecb37 100644 --- a/calculate/templates/template_engine.py +++ b/calculate/templates/template_engine.py @@ -18,7 +18,9 @@ from ..utils.package import PackageAtomParser, PackageAtomError, NOTEXIST,\ from ..utils.files import join_paths, check_directory_link, check_command,\ FilesError from calculate.variables.datavars import HashType, NamespaceNode,\ - VariableNode, IniType + VariableNode, IniType, IntegerType,\ + FloatType, ListType,\ + VariableNotFoundError # Типы шаблона: директория или файл. @@ -755,6 +757,9 @@ class CalculateExtension(Extension): parameters_processor = None + # Виды операций в теге save. + ASSIGN, APPEND, REMOVE = range(3) + def __init__(self, environment, datavars_module=Variables()): super().__init__(environment) self.environment = environment @@ -767,7 +772,12 @@ class CalculateExtension(Extension): self.tags = {'calculate', 'save', 'set_var'} self.CONDITION_TOKENS_TYPES = {'eq', 'ne', 'lt', 'gt', 'lteq', 'gteq'} self.LITERAL_TOKENS_TYPES = {'string', 'integer', 'float'} - self.TARGET_FILES_SET = {'grp', 'system', 'etc', 'local', 'remote'} + + if hasattr(self._datavars, 'variables_to_save'): + self.TARGET_FILES_SET =\ + set(self._datavars.variables_to_save.keys()) + else: + self.TARGET_FILES_SET = set() self.parse_methods = {'calculate': self.parse_calculate, 'save': self.parse_save} @@ -794,9 +804,9 @@ class CalculateExtension(Extension): if target_file_name in self.TARGET_FILES_SET: target_file = nodes.Const(target_file_name) else: - TemplateSyntaxError("Unknown target file '{}'". - format(target_file_name), - lineno=lineno) + raise TemplateSyntaxError("Unknown target file '{}'". + format(target_file_name), + lineno=lineno) # получаем список из имени переменной. module_name = self.stream.expect('name').value @@ -807,17 +817,22 @@ class CalculateExtension(Extension): variable_name = nodes.List(variable_name, lineno=lineno) if self.stream.skip_if('assign'): - right_value = self.parser.parse_expression(with_condexpr=True) - save_variable_node = self.call_method('save_variable', - [variable_name, - right_value, - target_file, - nodes.ContextReference()], - lineno=lineno) - return nodes.Output([save_variable_node], lineno=lineno) - else: - TemplateSyntaxError("'=' is expected in 'save' tag.", - lineno=lineno) + return self._make_save_node(variable_name, + target_file, + self.ASSIGN, + lineno) + elif self.stream.skip_if('add') and self.stream.skip_if('assign'): + return self._make_save_node(variable_name, + target_file, + self.APPEND, + lineno) + elif self.stream.skip_if('sub') and self.stream.skip_if('assign'): + return self._make_save_node(variable_name, + target_file, + self.REMOVE, + lineno) + raise TemplateSyntaxError("'=' is expected in 'save' tag", + lineno=lineno) def parse_calculate(self): '''Метод для разбора тега calculate, содержащего значения параметров и @@ -940,18 +955,34 @@ class CalculateExtension(Extension): # return condition_result def set_condition_result(self, condition_result): + '''Метод для сохранения результата вычисления условия.''' self.condition_result = condition_result return '' - def save_variable(self, variable, right_value, target_file, context): + def _make_save_node(self, variable_name_node, target_file_node, optype, + lineno): + '''Метод для создания ноды, сохраняющей переменные.''' + right_value = self.parser.parse_expression(with_condexpr=True) + optype_node = nodes.Const(optype, lineno=lineno) + save_variable_node = self.call_method('save_variable', + [variable_name_node, + right_value, + target_file_node, + optype_node, + nodes.ContextReference()], + lineno=lineno) + return nodes.Output([save_variable_node], lineno=lineno) + + def save_variable(self, variable, right_value, target_file, + optype, context): '''Метод для сохранения значений переменных указанных в теге save.''' datavars = context.parent['__datavars__'] - print('DATAVARS: {}'.format(datavars)) - print('VARIABLE NAME: {}'.format(variable)) - print('RIGHT VALUE: {}'.format(right_value)) + optypes = {self.ASSIGN: '=', self.APPEND: '+=', self.REMOVE: '-='} + print('SAVE VARIABLE: {} {} {}'.format('.'.join(variable), + optypes[optype], + right_value)) print('TARGET FILE: {}'.format(target_file)) if variable[0] not in datavars: - # TODO продумать получше ошибку. raise SaveError("can not save variable '{}'. The variable's" " package '{}' is not found".format( '.'.join(variable), @@ -961,6 +992,9 @@ class CalculateExtension(Extension): current_container = datavars[variable[0]] variable_path = variable[1:] variable_name = variable_path.pop() + + # Ищем пространство имен или в хэш, в котором должна быть переменная + # или значение. for section in variable_path: if section in current_container.namespaces: current_container = current_container.namespaces[section] @@ -985,23 +1019,136 @@ class CalculateExtension(Extension): section, current_container.get_fullname())) + # Теперь меняем знaчение переменной. if isinstance(current_container, NamespaceNode): if variable_name in current_container.variables: - current_container[variable_name].set(right_value) + variable_node = current_container[variable_name] + if optype == self.ASSIGN: + variable_node.set(right_value) + elif optype == self.APPEND: + new_value = self._append_variable_value(variable_node, + right_value) + variable_node.set(new_value) + elif optype == self.REMOVE: + new_value = self._remove_variable_value(variable_node, + right_value) + variable_node.set(new_value) + + if target_file: + self.save_to_target(variable[:-1], variable_name, + new_value, target_file) elif not modify_only: VariableNode(variable_name, current_container, variable_type=IniType, source=str(right_value)) + + if target_file: + self.save_to_target(variable[:-1], variable_name, + right_value, target_file) else: raise SaveError("can not create variable '{}' in the not" " 'custom' namespace". format('.'.join(variable))) elif isinstance(current_container, VariableNode): hash_value = current_container.get_value().get_hash() - hash_value.update({variable_name: right_value}) + if variable_name in hash_value: + if optype == self.ASSIGN: + new_value = right_value + elif optype == self.APPEND: + new_value = new_value + right_value + elif optype == self.REMOVE: + new_value = new_value - right_value + else: + new_value = right_value + + hash_value.update({variable_name: new_value}) current_container.set(hash_value) + if target_file: + self.save_to_target(variable[:-1], variable_name, + new_value, target_file) print('VARIABLE IS SAVED') return '' + def save_to_target(self, namespace_name, variable_name, value, target): + namespace_name = tuple(namespace_name) + target_file_dict = self._datavars.variables_to_save[target] + if namespace_name not in target_file_dict: + target_file_dict.update({namespace_name: dict()}) + target_file_dict[namespace_name].update( + {variable_name: ('=', str(value))}) + + def _append_variable_value(self, variable, value): + '''Метод описывающий операцию += в теге save.''' + variable_value = variable.get_value() + if (variable.variable_type is IntegerType or + variable.variable_type is FloatType): + variable_value += value + return variable_value + elif variable.variable_type is ListType: + if isinstance(value, str): + value = value.split(',') + if isinstance(value, list): + for item in value: + if item not in variable_value: + variable_value.append(item) + else: + variable_value.append(value) + return variable_value + elif variable.variable_type is IniType: + if not isinstance(variable_value, str): + variable_value = str(variable_value) + variable_value = variable_value.split(',') + + if not isinstance(value, list): + if isinstance(value, str): + value = value.split(',') + else: + value = str(value).split(',') + + for item in value: + if item not in variable_value: + variable_value.append(item) + return ','.join(variable_value) + # Пока что во всех остальных случаях будем просто возвращать исходное + # значение. + return variable_value + + def _remove_variable_value(self, variable, value): + '''Метод описывающий операцию -= в теге save.''' + variable_value = variable.get_value() + if (variable.variable_type is IntegerType or + variable.variable_type is FloatType): + variable_value -= value + return variable_value + elif variable.variable_type is ListType: + if isinstance(value, str): + value = value.split(',') + if isinstance(value, list): + for item in value: + if item in variable_value: + variable_value.remove(item) + elif value in variable_value: + variable_value.remove(value) + return variable_value + elif variable.variable_type is IniType: + if not isinstance(variable_value, list): + if not isinstance(variable_value, str): + variable_value = str(variable_value) + variable_value = variable_value.split(',') + + if not isinstance(value, list): + if isinstance(value, str): + value = value.split(',') + else: + value = str(value).split(',') + + for item in value: + if item in variable_value: + variable_value.remove(item) + return ','.join(variable_value) + # Пока что во всех остальных случаях будем просто возвращать исходное + # значение. + return variable_value + def get_parameter(self): '''Метод для разбра параметров, содержащихся в теге calculate.''' lineno = self.stream.current.lineno diff --git a/calculate/variables/datavars.py b/calculate/variables/datavars.py index d5238c1..552f0ff 100644 --- a/calculate/variables/datavars.py +++ b/calculate/variables/datavars.py @@ -205,7 +205,6 @@ class Hash: '''Метод для обновления значения хэша.''' for key, value in values.items(): if key in self._values: - print('[*] UPDATE KEY: {} to {}'.format(key, value)) self._values[key].value = value elif self.fixed: raise VariableError("key '{}' is unavailable for fixed" @@ -650,7 +649,6 @@ class VariableNode: переменных.''' # print('{} is invalidated'.format(self.get_fullname())) if not self._invalidated and not self.set_by_user: - print('INVALIDATING: {}'.format(self.get_fullname())) if self.variable_type is not HashType: self.value = None self._invalidated = True @@ -684,8 +682,9 @@ class VariableNode: if key in self.get_value(): return self.value[key] else: - raise VariableError("value '{}' is not found in hash variable" - " '{}'".format(key, self.get_fullname())) + raise VariableNotFoundError("value '{}' is not found in hash" + " variable '{}'".format( + key, self.get_fullname())) else: raise VariableError("'{}' variable type is not subscriptable.". format(self.variable_type.name)) @@ -739,8 +738,8 @@ class NamespaceNode: return variable.get_value().get_table() return variable.get_value() else: - raise VariableError("'{variable_name}' is not found in the" - " namespace '{namespace_name}'".format( + raise VariableNotFoundError("'{variable_name}' is not found in the" + " namespace '{namespace_name}'".format( variable_name=name, namespace_name=self.name)) @@ -751,8 +750,8 @@ class NamespaceNode: elif name in self.variables: return self.variables[name] else: - raise VariableError("'{variable_name}' is not found in the" - " namespace '{namespace_name}'".format( + raise VariableNotFoundError("'{variable_name}' is not found in the" + " namespace '{namespace_name}'".format( variable_name=name, namespace_name=self.name)) diff --git a/calculate/variables/ini_template b/calculate/variables/ini_template new file mode 100644 index 0000000..e69de29 diff --git a/calculate/variables/loader.py b/calculate/variables/loader.py index 83fa6b0..2adf818 100644 --- a/calculate/variables/loader.py +++ b/calculate/variables/loader.py @@ -1,10 +1,12 @@ import os import importlib import importlib.util +from pprint import pprint from calculate.variables.datavars import NamespaceNode, VariableNode,\ ListType, IntegerType,\ FloatType, IniType, TableType,\ - Namespace, VariableError, HashType + Namespace, VariableError, HashType,\ + VariableNotFoundError from calculate.utils.gentoo import ProfileWalker from calculate.utils.files import read_file, FilesError from pyparsing import Literal, Word, ZeroOrMore, Group, Optional, restOfLine,\ @@ -180,12 +182,10 @@ class NamespaceIniFiller: def start_section(self, sections: str) -> None: '''Метод для получения доступа и создания пространств имен.''' - print('SECTIONS: {}'.format(sections)) if self.restricted: self.modify_only = sections[0] not in self.available_sections self.current_namespace = self.namespace for section in sections: - print('START SECTION: {}'.format(section)) if isinstance(self.current_namespace, Datavars): if section not in self.current_namespace: raise VariableError("variables package '{}' is not found". @@ -266,8 +266,6 @@ class NamespaceIniFiller: table_variable.source = table def define_key(self, key: str, value: str, optype) -> None: - print('DEFINE KEY: {} -> {} TO {}'.format(key, value, - self.current_namespace)) if self.current_namespace is None: return @@ -477,13 +475,13 @@ class VariableLoader: for file_node in file_nodes: file_name = file_node.name[:-3] Namespace.set_current_namespace(current_namespace) - with self.test(file_name, current_namespace): - # importlib.import_module('{}.{}'.format(package, file_name)) - spec = importlib.util.spec_from_file_location( - '{}.{}'.format(package, file_name), - file_node.path) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) + # with self.test(file_name, current_namespace): + # importlib.import_module('{}.{}'.format(package, file_name)) + spec = importlib.util.spec_from_file_location( + '{}.{}'.format(package, file_name), + file_node.path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) # Обходим остальные директории. for directory_node in directory_nodes: @@ -513,7 +511,6 @@ class VariableLoader: def fill_from_custom_ini(self, file_path: str): '''Метод для заполнения переменных из конкретного указанного файла.''' - print('LOAD FROM INI: {}'.format(file_path)) if os.path.exists(file_path): ini_file_text = read_file(file_path) self.ini_filler.fill(self.datavars, ini_file_text) @@ -528,6 +525,12 @@ class VariableLoader: file_name)) +class CalculateIniSaver: + '''Класс для сохранения значений пользовательских переменных.''' + def __init__(self): + self.ini_parser = CalculateIniParser() + + class Datavars: '''Класс для хранения переменных и управления ими.''' def __init__(self, variables_path='calculate/vars', repository_map=None): @@ -543,6 +546,13 @@ class Datavars: self._loader.load_from_profile() self._loader.load_user_variables() + try: + self.variables_to_save = {target: dict() for target in + self.system.env_order if target in + self.system.env_path} + except VariableNotFoundError: + self.variables_to_save = dict() + def reset(self): '''Метод для сброса модуля переменных.''' self.root.clear() @@ -573,8 +583,8 @@ class Datavars: self.root.add_namespace(custom_namespace) return self.root[package_name] elif package_name not in self._available_packages: - raise VariableError("variables package '{}' is not found". - format(package_name)) + raise VariableNotFoundError("variables package '{}' is not found". + format(package_name)) else: self._loader.load_variables_package(package_name) return self.root[package_name] @@ -589,8 +599,8 @@ class Datavars: self.root.add_namespace(custom_namespace) return self.root[package_name] elif package_name not in self._available_packages: - raise VariableError("variables package '{}' is not found". - format(package_name)) + raise VariableNotFoundError("variables package '{}' is not found". + format(package_name)) else: self._loader.load_variables_package(package_name) return self.root[package_name] @@ -612,3 +622,56 @@ class Datavars: @property def namespaces(self): return self.root.namespaces + + def save_variables(self): + '''Метод для сохранения в calculate.ini файлах ''' + ini_parser = self._loader.ini_filler.ini_parser + target_paths = self.system.env_path + + operations = {Define.assign: '=', + Define.append: '+=', + Define.remove: '-='} + + for target in self.variables_to_save: + if self.variables_to_save[target]: + dict_to_save = self.variables_to_save[target] + + # Распарсим файл в словарь. + current_namespace = None + ini_dictionary = dict() + ini_file_text = read_file(target_paths[target].value) + + for parsed_line in ini_parser.parse(ini_file_text): + line_type = next(iter(parsed_line)) + print('line_type: {}'.format(line_type)) + line_content = parsed_line[line_type] + print('line_content: {}'.format(line_content)) + + if (line_type == 'start_section' or + line_type == 'start_table'): + current_namespace = tuple(line_content[0]) + if current_namespace not in ini_dictionary: + ini_dictionary[current_namespace] = dict() + + elif (line_type == 'clear_section' or + line_type == 'clear_table'): + current_namespace = (*line_content[0], '') + ini_dictionary[current_namespace] = dict() + elif line_type == 'define_key': + namespace = ini_dictionary[current_namespace] + namespace.update({line_content[0]: + (operations[line_content[2]], + line_content[1])}) + + for namespace in dict_to_save: + if namespace in ini_dictionary: + ini_dictionary[namespace].update( + dict_to_save[namespace]) + else: + ini_dictionary[namespace] = dict_to_save[namespace] + + print('INI DICTIONARY FOR {}:'.format(target)) + pprint(ini_dictionary) + + def _get_text(self, ini_dictionary): + pass diff --git a/tests/templates/test_template_engine.py b/tests/templates/test_template_engine.py index 8924db8..2794bc8 100644 --- a/tests/templates/test_template_engine.py +++ b/tests/templates/test_template_engine.py @@ -132,24 +132,6 @@ class TestTemplateEngine(): text = template_engine.template_text assert text == output_text - def test_if_value_of_variable_is_set_using_save_tag__the_new_value_of_variable_can_be_used_in_template(self): - input_template = '''{% calculate name = 'filename', force -%} - {% save vars_1.var_3 = 13 -%} - parameter = {{ vars_1.var_3 - 1 + vars_1.var_2 * 2 }} - {% save.session vars_1.var_4 = True -%} - bool parameter = {{ vars_1.var_4 }}''' - output_text = '''parameter = 14.4 - bool parameter = True''' - datavars_module = 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, FILE) - - text = template_engine.template_text - assert text == output_text - def test_if_an_input_template_contains_pkg_function_with_existing_package_as_its_argument__it_works_correctly_and_pkg_function_returns_version_value(self): input_template = '''{% calculate name = 'filename', force -%} {% if pkg('test-category/test-package') < 2.7 -%} diff --git a/tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS b/tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS index 4e5e59a..aad0da2 100644 --- a/tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS +++ b/tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS @@ -6,6 +6,6 @@ obj /etc/dir/deleted.json 11e3a79fe51cce828d973dba8702adaa 1591356795 dir /etc/dir/subdir obj /etc/dir/subdir/config.json 506649cf099878124deda2c2452c3693 1591605050 obj /etc/dir/subdir/file 84bcceb2c8e6de79849ea5f3304f2411 1591343236 -obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1597740848 +obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1591196541 dir /etc/dir/dir_1 -obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1597740848 +obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1591617024 diff --git a/tests/variables/test_variables.py b/tests/variables/test_variables.py index 3dc9079..d016a28 100644 --- a/tests/variables/test_variables.py +++ b/tests/variables/test_variables.py @@ -1,6 +1,7 @@ import os import shutil import pytest +from pprint import pprint from calculate.variables.datavars import NamespaceNode, VariableNode,\ Namespace, Variable, Dependence,\ CyclicVariableError, HashType,\ @@ -1196,7 +1197,7 @@ value = another_value assert datavars.os.calculate == 'new1 new2' - def test_using_datavars_in_the_template(self): + def test_if_Datavars_object_is_set_as_the_datavars_for_the_TemplateEngine_object__variables_from_the_Datavars_object_can_be_inserted_in_the_processed_template(self): datavars = Datavars( variables_path=os.path.join(TESTFILES_PATH, 'variables_7')) template_engine = TemplateEngine(appends_set=APPENDS_SET, @@ -1216,7 +1217,7 @@ os.calculate = new1 new2''' text = template_engine.template_text assert text == output_text - def test_save_variable(self): + def test_if_Datavars_object_is_set_as_the_datavars_for_the_TemplateEngine_object_and_save_tag_is_used_for_saving_some_variables_and_target_file_is_not_set_for_the_save_tag__variables_from_the_Datavars_object_can_be_inserted_in_the_processed_template(self): datavars = Datavars( variables_path=os.path.join(TESTFILES_PATH, 'variables_7')) template_engine = TemplateEngine(appends_set=APPENDS_SET, @@ -1240,11 +1241,70 @@ os.calculate = new1 new2''' input_template_2 = '''{% calculate name = 'filename', force -%} {% save os.hashvar.value1 = 'new1' %}''' template_engine.process_template_from_string(input_template_2, FILE) - print('calculate is invalidated: {}'.format()) assert datavars.os.hashvar.value1 == 'new1' assert datavars.os.hashvar.value2 == 'weird2' assert datavars.os.calculate == 'new1 weird2' + + def test_if_Datavars_object_is_set_as_the_datavars_for_the_TemplateEngine_object_and_save_tag_is_used_for_appending_and_removing_some_variable_s_values_and_target_file_is_not_set_for_the_save_tag__variables_from_the_Datavars_object_can_be_inserted_in_the_processed_template(self): + datavars = Datavars( + variables_path=os.path.join(TESTFILES_PATH, 'variables_8')) + template_engine = TemplateEngine(appends_set=APPENDS_SET, + chroot_path=TESTFILES_PATH, + datavars_module=datavars) + + input_template_1 = '''{% calculate name = 'filename', force -%} +{% save custom.ns.var_1 += 12 -%} +{% save os.linux.test_1 += 10 -%} +{% save os.linux.test_2 += 12 -%} +{% save os.linux.test_3 += 'd' -%} +{% save os.linux.test_4 += [4, 5] -%} +{% save custom.ns.var_2 += 'val4,val5' -%} +''' + + template_engine.process_template_from_string(input_template_1, FILE) + + assert datavars.custom.ns.var_1 == '1,12' + assert datavars.os.linux.test_1 == 22 + assert datavars.os.linux.test_2 == 13.2 + assert datavars.os.linux.test_3 == ['a', 'b', 'c', 'd'] + assert datavars.os.linux.test_4 == [1, 2, 3, 4, 5] + assert datavars.custom.ns.var_2 == 'val1,val2,val3,val4,val5' + + input_template_2 = '''{% calculate name = 'filename', force -%} +{% save custom.ns.var_1 -= 1 -%} +{% save os.linux.test_1 -= 11 -%} +{% save os.linux.test_2 -= 2.1 -%} +{% save os.linux.test_3 -= 'a' -%} +{% save os.linux.test_4 -= [1, 3] -%} +{% save custom.ns.var_2 -= 'val1,val4' -%} +''' + + template_engine.process_template_from_string(input_template_2, FILE) + + assert datavars.custom.ns.var_1 == '12' + assert datavars.os.linux.test_1 == 11 + assert datavars.os.linux.test_2 == 11.1 + assert datavars.os.linux.test_3 == ['b', 'c', 'd'] + assert datavars.os.linux.test_4 == [2, 4, 5] + assert datavars.custom.ns.var_2 == 'val2,val3,val5' + + def test_save_variables_to_target_files(self): + datavars = Datavars( + variables_path=os.path.join(TESTFILES_PATH, 'variables_9')) + template_engine = TemplateEngine(appends_set=APPENDS_SET, + chroot_path=TESTFILES_PATH, + datavars_module=datavars) + + input_template_1 = '''{% calculate name = 'filename', force -%} +{% save.local custom.ns.var_3 = 'value' -%} +{% save.local custom.ns.var_2 += 'val4' -%} +''' + + template_engine.process_template_from_string(input_template_1, FILE) + print('VARIABLES TO SAVE:') + pprint(datavars.variables_to_save) + datavars.save_variables() assert False def test_for_removing_testfiles(self): diff --git a/tests/variables/testfiles/ini_vars.backup/calculate_2.ini b/tests/variables/testfiles/ini_vars.backup/calculate_2.ini new file mode 100644 index 0000000..8ce36e8 --- /dev/null +++ b/tests/variables/testfiles/ini_vars.backup/calculate_2.ini @@ -0,0 +1,3 @@ +[custom][ns] +var_1 = 1 +var_2 = val1,val2,val3 diff --git a/tests/variables/testfiles/ini_vars.backup/calculate_3.ini b/tests/variables/testfiles/ini_vars.backup/calculate_3.ini new file mode 100644 index 0000000..8413a25 --- /dev/null +++ b/tests/variables/testfiles/ini_vars.backup/calculate_3.ini @@ -0,0 +1,6 @@ +[custom][ns] +var_3 = /the/true/path/to/eternity/in/the/abyss +var_4 = 12 + +[os][linux] +test = new value diff --git a/tests/variables/testfiles/ini_vars.backup/calculate_4.ini b/tests/variables/testfiles/ini_vars.backup/calculate_4.ini new file mode 100644 index 0000000..8ce36e8 --- /dev/null +++ b/tests/variables/testfiles/ini_vars.backup/calculate_4.ini @@ -0,0 +1,3 @@ +[custom][ns] +var_1 = 1 +var_2 = val1,val2,val3 diff --git a/tests/variables/testfiles/ini_vars.backup/calculate_5.ini b/tests/variables/testfiles/ini_vars.backup/calculate_5.ini new file mode 100644 index 0000000..8ce36e8 --- /dev/null +++ b/tests/variables/testfiles/ini_vars.backup/calculate_5.ini @@ -0,0 +1,3 @@ +[custom][ns] +var_1 = 1 +var_2 = val1,val2,val3 diff --git a/tests/variables/testfiles/variables_8/main/__init__.py b/tests/variables/testfiles/variables_8/main/__init__.py new file mode 100644 index 0000000..43d6a38 --- /dev/null +++ b/tests/variables/testfiles/variables_8/main/__init__.py @@ -0,0 +1,4 @@ +from calculate.variables.datavars import Variable, StringType + + +Variable('chroot', type=StringType.readonly, source='/') diff --git a/tests/variables/testfiles/variables_8/os/__init__.py b/tests/variables/testfiles/variables_8/os/__init__.py new file mode 100644 index 0000000..86cc29c --- /dev/null +++ b/tests/variables/testfiles/variables_8/os/__init__.py @@ -0,0 +1,45 @@ +from calculate.variables.datavars import Namespace, Variable, Dependence,\ + StringType, HashType, TableType,\ + ListType, IntegerType, FloatType + +with Namespace('linux'): + Variable('shortname', source='', type=StringType) + + Variable('ver', source='', type=StringType) + + Variable('fullname', source='', type=StringType) + + Variable('subname', source='', type=StringType) + + Variable('arch', source='', type=StringType) + + Variable('test_1', source=12, type=IntegerType) + + Variable('test_2', source=1.2, type=FloatType) + + Variable('test_3', type=ListType, source=['a', 'b', 'c']) + + Variable('test_4', type=ListType, source=[1, 2, 3]) + + def get_title(subname, fullname, ver): + if subname.value: + return '{} {} {}'.format(fullname.value, subname.value, ver.value) + else: + return '{} {}'.format(fullname.value, ver.value) + Variable('title', type=StringType, + source=Dependence('.subname', '.fullname', '.ver', + depend=get_title)) + +Variable('hashvar', source={'value1': 'test1', + 'value2': 'test2'}, type=HashType) + +Variable('calculate', type=StringType, + source=Dependence('.hashvar', + depend=lambda hashvar: "{} {}".format( + hashvar.value['value1'], + hashvar.value['value2']))) + +Variable('tablevar', type=TableType, source=[{"dev": "/dev/sdb1", + "mount": "/"}, + {"dev": "/dev/sdb2", + "mount": "/var/calculate"}]) diff --git a/tests/variables/testfiles/variables_8/os/gentoo/__init__.py b/tests/variables/testfiles/variables_8/os/gentoo/__init__.py new file mode 100644 index 0000000..d704c66 --- /dev/null +++ b/tests/variables/testfiles/variables_8/os/gentoo/__init__.py @@ -0,0 +1,57 @@ +import os +from calculate.variables.datavars import Variable, Namespace, Dependence,\ + StringType, TableType +''' +gentoo: + make_profile -> string + profile: + path -> string + name -> string + repositories[*]{name, path} -> table + config -> undefined +''' + +TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles') + +# Путь до файла, указывающего на активный профиль +Variable('make_profile', type=StringType, source='/etc/portage/make.profile') + +# Параметры текущего профиля. +with Namespace('profile'): + # Абсолютный путь до профиля + Variable('path', type=StringType, + source=os.path.join(TESTFILES_PATH, + "gentoo/repos/distros/profiles/CLD/amd64")) + + def get_profile_name(path, repositories): + profile_path = path.value + if not profile_path: + return "" + + for repository in repositories.value: + repository_path = repository['path'] + repository_name = repository['name'] + remove_part = os.path.normpath(os.path.join(repository_path, + "profiles")) + if profile_path.startswith(remove_part): + return "{}:{}".format(repository_name, + profile_path[len(remove_part) + 1:]) + return profile_path + # Название профиля + Variable('name', type=StringType, + source=Dependence('.path', '..repositories', + depend=get_profile_name)) + +# Информация о репозиториях +# name: имя репозитория +# path: полный путь до репозитория +Variable('repositories', type=TableType, + source=[{'name': 'distros', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/repos/distros")}, + {'name': 'calculate', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/repos/calculate")}, + {'name': 'gentoo', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/portage")}]) diff --git a/tests/variables/testfiles/variables_8/system/__init__.py b/tests/variables/testfiles/variables_8/system/__init__.py new file mode 100644 index 0000000..458f97c --- /dev/null +++ b/tests/variables/testfiles/variables_8/system/__init__.py @@ -0,0 +1,21 @@ +import os +from calculate.variables.datavars import Variable, ListType, HashType +''' +system: + env_order -> list + env_path -> hash +''' + + +TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles') + + +# Список мест, где есть calculate.ini файлы. +Variable('env_order', type=ListType, source=['system', 'local']) + +# Отображение множества мест, где есть calculate.ini файлы, на пути к ним. +Variable('env_path', type=HashType, + source={'system': os.path.join(TESTFILES_PATH, + 'ini_vars/calculate_2.ini'), + 'local': os.path.join(TESTFILES_PATH, + 'ini_vars/calculate_3.ini')}) diff --git a/tests/variables/testfiles/variables_9/main/__init__.py b/tests/variables/testfiles/variables_9/main/__init__.py new file mode 100644 index 0000000..43d6a38 --- /dev/null +++ b/tests/variables/testfiles/variables_9/main/__init__.py @@ -0,0 +1,4 @@ +from calculate.variables.datavars import Variable, StringType + + +Variable('chroot', type=StringType.readonly, source='/') diff --git a/tests/variables/testfiles/variables_9/os/__init__.py b/tests/variables/testfiles/variables_9/os/__init__.py new file mode 100644 index 0000000..901f95a --- /dev/null +++ b/tests/variables/testfiles/variables_9/os/__init__.py @@ -0,0 +1,41 @@ +from calculate.variables.datavars import Namespace, Variable, Dependence,\ + StringType, HashType, TableType,\ + ListType, IntegerType, FloatType + +with Namespace('linux'): + Variable('shortname', source='', type=StringType) + + Variable('ver', source='', type=StringType) + + Variable('fullname', source='', type=StringType) + + Variable('subname', source='', type=StringType) + + Variable('arch', source='', type=StringType) + + Variable('test_1', source=12, type=IntegerType) + + Variable('test_2', source=1.2, type=FloatType) + + def get_title(subname, fullname, ver): + if subname.value: + return '{} {} {}'.format(fullname.value, subname.value, ver.value) + else: + return '{} {}'.format(fullname.value, ver.value) + Variable('title', type=StringType, + source=Dependence('.subname', '.fullname', '.ver', + depend=get_title)) + +Variable('hashvar', source={'value1': 'test1', + 'value2': 'test2'}, type=HashType) + +Variable('calculate', type=StringType, + source=Dependence('.hashvar', + depend=lambda hashvar: "{} {}".format( + hashvar.value['value1'], + hashvar.value['value2']))) + +Variable('tablevar', type=TableType, source=[{"dev": "/dev/sdb1", + "mount": "/"}, + {"dev": "/dev/sdb2", + "mount": "/var/calculate"}]) diff --git a/tests/variables/testfiles/variables_9/os/gentoo/__init__.py b/tests/variables/testfiles/variables_9/os/gentoo/__init__.py new file mode 100644 index 0000000..d704c66 --- /dev/null +++ b/tests/variables/testfiles/variables_9/os/gentoo/__init__.py @@ -0,0 +1,57 @@ +import os +from calculate.variables.datavars import Variable, Namespace, Dependence,\ + StringType, TableType +''' +gentoo: + make_profile -> string + profile: + path -> string + name -> string + repositories[*]{name, path} -> table + config -> undefined +''' + +TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles') + +# Путь до файла, указывающего на активный профиль +Variable('make_profile', type=StringType, source='/etc/portage/make.profile') + +# Параметры текущего профиля. +with Namespace('profile'): + # Абсолютный путь до профиля + Variable('path', type=StringType, + source=os.path.join(TESTFILES_PATH, + "gentoo/repos/distros/profiles/CLD/amd64")) + + def get_profile_name(path, repositories): + profile_path = path.value + if not profile_path: + return "" + + for repository in repositories.value: + repository_path = repository['path'] + repository_name = repository['name'] + remove_part = os.path.normpath(os.path.join(repository_path, + "profiles")) + if profile_path.startswith(remove_part): + return "{}:{}".format(repository_name, + profile_path[len(remove_part) + 1:]) + return profile_path + # Название профиля + Variable('name', type=StringType, + source=Dependence('.path', '..repositories', + depend=get_profile_name)) + +# Информация о репозиториях +# name: имя репозитория +# path: полный путь до репозитория +Variable('repositories', type=TableType, + source=[{'name': 'distros', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/repos/distros")}, + {'name': 'calculate', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/repos/calculate")}, + {'name': 'gentoo', + 'path': os.path.join(TESTFILES_PATH, + "gentoo/portage")}]) diff --git a/tests/variables/testfiles/variables_9/system/__init__.py b/tests/variables/testfiles/variables_9/system/__init__.py new file mode 100644 index 0000000..d18e36b --- /dev/null +++ b/tests/variables/testfiles/variables_9/system/__init__.py @@ -0,0 +1,21 @@ +import os +from calculate.variables.datavars import Variable, ListType, HashType +''' +system: + env_order -> list + env_path -> hash +''' + + +TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles') + + +# Список мест, где есть calculate.ini файлы. +Variable('env_order', type=ListType, source=['system', 'local']) + +# Отображение множества мест, где есть calculate.ini файлы, на пути к ним. +Variable('env_path', type=HashType, + source={'system': os.path.join(TESTFILES_PATH, + 'ini_vars/calculate_4.ini'), + 'local': os.path.join(TESTFILES_PATH, + 'ini_vars/calculate_5.ini')})