Tested the template engine using Datavars object and save tag in the templates too.

packages
Denis Ivanov 4 years ago
parent 2e5946ed6e
commit 1116c28e36

@ -17,6 +17,8 @@ from ..utils.package import PackageAtomParser, PackageAtomError, NOTEXIST,\
Version
from ..utils.files import join_paths, check_directory_link, check_command,\
FilesError
from calculate.variables.datavars import HashType, NamespaceNode,\
VariableNode, IniType
# Типы шаблона: директория или файл.
@ -31,6 +33,10 @@ class DefaultParameterError(Exception):
pass
class SaveError(Exception):
pass
class ConditionFailed(TemplateSyntaxError):
pass
@ -937,24 +943,63 @@ class CalculateExtension(Extension):
self.condition_result = condition_result
return ''
def save_variable(self, variable_name, right_value, target_file, context):
def save_variable(self, variable, right_value, target_file, context):
'''Метод для сохранения значений переменных указанных в теге save.'''
# временная реализация.
datavars = context.parent['__datavars__']
module_name = variable_name[0]
namespaces = variable_name[1:-1]
variable_name = variable_name[-1]
if module_name in datavars:
variables_module = datavars[module_name]
for namespace in namespaces:
if namespace not in variables_module:
variables_module[namespace] = Variables()
variables_module = variables_module[namespace]
variables_module[variable_name] = right_value
else:
AttributeError("Unknown variables module '{}'".
format(module_name))
print('DATAVARS: {}'.format(datavars))
print('VARIABLE NAME: {}'.format(variable))
print('RIGHT VALUE: {}'.format(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),
variable[0]))
modify_only = (variable[0] != 'custom')
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]
elif (section in current_container.variables and current_container.
variables[section].variable_type is HashType):
current_container = current_container.variables[section]
if section != variable_path[-1]:
# Если обнаружен хэш, но в пути к переменной кроме ключа
# хэша есть что-то еще -- значит путь к переменной
# ошибочен.
raise SaveError("can not save variable '{}'. Other"
" variable '{}' on the path".format(
'.'.join(variable),
current_container.get_fullname()))
elif not modify_only:
new_namespace = NamespaceNode(section)
current_container.add_namespace(new_namespace)
else:
raise SaveError("can not save variable '{}'. Namespace '{}'"
" is not found in '{}'".format(
'.'.join(variable),
section,
current_container.get_fullname()))
if isinstance(current_container, NamespaceNode):
if variable_name in current_container.variables:
current_container[variable_name].set(right_value)
elif not modify_only:
VariableNode(variable_name, current_container,
variable_type=IniType, source=str(right_value))
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})
current_container.set(hash_value)
print('VARIABLE IS SAVED')
return ''
def get_parameter(self):

@ -203,9 +203,9 @@ class Hash:
def update_hash(self, values: dict) -> None:
'''Метод для обновления значения хэша.'''
print('UPDATE 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"
@ -338,7 +338,6 @@ class TableType(VariableType):
@classmethod
def process_value(self, value: List[dict], variable) -> Table:
print('PROCESS TABLE')
if not isinstance(value, list) and not isinstance(value, Table):
raise VariableTypeError("can not set value with type '{_type}' to"
" hash variable: value must be 'dict' type"
@ -540,7 +539,6 @@ class VariableNode:
def update_value(self) -> None:
'''Метод для обновления значения переменной с помощью указанного
источника ее значения.'''
print('updating {}'.format(self.get_fullname()))
if self.calculating:
raise CyclicVariableError(self.name)
@ -549,7 +547,6 @@ class VariableNode:
format(self.get_fullname()))
if isinstance(self._source, DependenceSource):
print('NAMESPACE: {}'.format(self.namespace))
self._source.get_args(self.namespace)
with self._start_calculate():
try:
@ -593,10 +590,23 @@ class VariableNode:
variable_type(self)
def set(self, value):
'''Метод для установки временного пользовательского значения
переменной.'''
# Сбрасываем флаги, чтобы провести инвалидацию.
self._invalidated = False
self.set_by_user = False
self._invalidate()
self.set_by_user = True
self.value = self.variable_type.process_value(value, self)
def reset(self):
'''Метод для сброса пользовательского значения.'''
if self.set_by_user:
self._invalidated = False
self.set_by_user = False
self._invalidate()
@property
def source(self):
return self._source
@ -640,6 +650,7 @@ 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
@ -815,12 +826,8 @@ class VariableAPI:
readonly=False, fixed=False, force=False):
'''Метод для создания переменных внутри with Namespace('name').'''
if name not in self.current_namespace.variables:
print('CREATE VARIABLE: {}'.format('{}.{}'.format(
self.current_namespace.get_fullname(),
name)))
variable = VariableNode(name, self.current_namespace)
else:
print('MODIFY VARIABLE: {}'.format(name))
variable = self.current_namespace[name]
if isinstance(source, DependenceSource):

@ -1,17 +1,12 @@
import re
import sys
import os
import importlib
import importlib.util
import site
from calculate.variables.old_vars.datavars import Variable, HashVariable,\
TableVariable
from calculate.variables.datavars import NamespaceNode, VariableNode,\
ListType, IntegerType,\
FloatType, IniType, TableType,\
Namespace, VariableError
Namespace, VariableError, HashType
from calculate.utils.gentoo import ProfileWalker
from calculate.utils.files import list_directory, read_file, FilesError
from calculate.utils.files import read_file, FilesError
from pyparsing import Literal, Word, ZeroOrMore, Group, Optional, restOfLine,\
empty, printables, OneOrMore, lineno, line, col, SkipTo,\
LineEnd, Combine, nums
@ -167,6 +162,8 @@ class NamespaceIniFiller:
clear_table=None,
define_key=None,
error=None, **kwargs):
'''Метод вызывающий обработку токенов, выдаваемых парсером в
зависимости от их типа.'''
if start_section is not None:
self.start_section(*start_section)
elif clear_section is not None:
@ -195,12 +192,20 @@ class NamespaceIniFiller:
format(section))
elif isinstance(self.current_namespace, NamespaceNode):
if section not in self.current_namespace.namespaces:
if not self.modify_only:
self.current_namespace.add_namespace(
NamespaceNode(section))
else:
self.current_namespace = None
if (section in self.current_namespace.variables and
self.current_namespace[section].variable_type
is HashType):
# Если секция является хэшем, используем ее.
self.current_namespace = self.current_namespace.\
variables[section]
return
else:
if not self.modify_only:
self.current_namespace.add_namespace(
NamespaceNode(section))
else:
self.current_namespace = None
return
self.current_namespace = self.current_namespace.namespaces[section]
def clear_section(self, sections: list) -> None:
@ -266,21 +271,25 @@ class NamespaceIniFiller:
if self.current_namespace is None:
return
if optype == Define.assign:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.change_value(key, value)
elif optype == Define.append:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.append_value(key, value)
elif optype == Define.remove:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.remove_value(key, value)
if (isinstance(self.current_namespace, VariableNode) and
self.current_namespace.variable_type is HashType):
self.update_hash(key, value, optype)
else:
if optype == Define.assign:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.change_value(key, value)
elif optype == Define.append:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.append_value(key, value)
elif optype == Define.remove:
if key not in self.current_namespace:
self.define_variable(key, value)
else:
self.remove_value(key, value)
def change_value(self, key: str, value: str) -> None:
'''Метод для изменения значения переменной.'''
@ -353,6 +362,40 @@ class NamespaceIniFiller:
variable.source = variable_value
def update_hash(self, key: str, value: str, optype):
'''Метод для изменения переменных хэшей через calculate.ini.'''
hash_to_update = self.current_namespace.get_value().get_hash()
if key not in hash_to_update:
# Если ключ отсутствует в хэше, то проверяем, является ли он
# фиксированным.
if self.current_namespace.fixed:
raise VariableError("key '{}' is unavailable for fixed"
" hash, available keys: '{}'".
format(key,
', '.join(self.current_namespace.
get_value()._fields)))
else:
hash_to_update.update({key: value})
elif optype == Define.assign:
hash_to_update.update({key: value})
elif optype == Define.append:
current_value = hash_to_update[key]
hash_to_update[key] = current_value + value
elif optype == Define.remove:
current_value = hash_to_update[key]
if (isinstance(current_value, int) or
isinstance(current_value, float)):
hash_to_update[key] = current_value - value
elif isinstance(current_value, str):
value_list = [item.strip() for item in value.split(',')]
current_value = [item.strip() for item in
current_value.split(',')]
for value_to_remove in value_list:
if value_to_remove in current_value:
current_value.remove(value_to_remove)
hash_to_update[key] = ','.join(current_value)
self.current_namespace.source = hash_to_update
def set_error(self, line, lineno, col):
'''Метод для добавления ошибки в лог.'''
self.error(lineno, "Syntax error: {}".format(line))
@ -379,11 +422,44 @@ class VariableLoader:
self._fill_from_package(package_namespace, directory_path, package)
def load_from_profile(self):
if self.repository_map != {}:
self.repository_map = (self.repository_map or
self._get_repository_map(self.datavars))
'''Метод для загрузки переменных из calculate.ini профиля.'''
# Проверяем наличие таблицы репозиториев в переменных.
if self.repository_map == {}:
return
if self.repository_map is None:
repositories_variable_path = ['os', 'gentoo', 'repositories']
current_namespace = self.datavars
for section in repositories_variable_path:
if section in current_namespace:
current_namespace = current_namespace[section]
else:
# TODO детальнее продумать действия при отсутствии нужной
# переменной.
return
self.repository_map = self._get_repository_map(self.datavars)
# Проверяем наличие пути к профилю в переменных.
if ('profile' in self.datavars.os.gentoo and
'path' in self.datavars.os.gentoo.profile):
profile_path = self.datavars.os.gentoo.profile.path
self._fill_from_ini(profile_path)
else:
# TODO детальнее продумать действия при отсутствии нужной
# переменной.
return
self._fill_from_ini(profile_path)
def load_user_variables(self):
'''Метод для загрузки переменных из calculate.ini указанных в
переменных env_order и env_path.'''
if ('system' in self.datavars and 'env_order' in self.datavars.system
and 'env_path' in self.datavars.system):
env_order = self.datavars.system.env_order
env_path = self.datavars.system.env_path
for ini_file in env_order:
if ini_file in env_path:
self.fill_from_custom_ini(env_path[ini_file].value)
def _fill_from_package(self, current_namespace: NamespaceNode,
directory_path: str, package: str) -> None:
@ -419,12 +495,10 @@ class VariableLoader:
def _fill_from_ini(self, profile_path):
'''Метод для зaполнения переменных из ini-файла.'''
print('PROCESSING INI FROM PROFILE')
profile_walker = ProfileWalker(self.ini_basename,
self.repository_map)
for file_path in profile_walker.find(profile_path):
try:
print('PROCESS FILE: {}'.format(file_path))
ini_file_text = read_file(file_path)
self.ini_filler.fill(self.datavars, ini_file_text)
except FilesError:
@ -432,6 +506,8 @@ class VariableLoader:
pass
def _get_repository_map(self, datavars):
'''Метод для получения из переменной словаря с репозиториями и путями
к ним.'''
return {repo['name']: repo['path']
for repo in datavars.os.gentoo.repositories}
@ -465,6 +541,7 @@ class Datavars:
Namespace.set_datavars(self)
self._loader.load_from_profile()
self._loader.load_user_variables()
def reset(self):
'''Метод для сброса модуля переменных.'''
@ -489,9 +566,12 @@ class Datavars:
def __getattr__(self, package_name: str):
'''Метод возвращает ноду пространства имен, соответствующего искомому
пакету.'''
print('getattr: {}'.format(package_name))
if package_name in self.root.namespaces:
return self.root[package_name]
elif package_name == 'custom':
custom_namespace = NamespaceNode('custom')
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))
@ -502,9 +582,12 @@ class Datavars:
def __getitem__(self, package_name: str) -> None:
'''Метод возвращает ноду пространства имен, соответствующего искомому
пакету.'''
print('getitem: {}'.format(package_name))
if package_name in self.root:
return self.root[package_name]
elif package_name == 'custom':
custom_namespace = NamespaceNode('custom')
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))
@ -515,7 +598,12 @@ class Datavars:
def __contains__(self, package_name):
if package_name in self.root.namespaces:
return True
elif package_name not in self._available_packages:
elif package_name == 'custom':
custom_namespace = NamespaceNode('custom')
self.root.add_namespace(custom_namespace)
return True
elif (package_name not in self._available_packages
and package_name != 'custom'):
return False
else:
self._loader.load_variables_package(package_name)
@ -524,80 +612,3 @@ class Datavars:
@property
def namespaces(self):
return self.root.namespaces
class OldVariableLoader:
'''Класс, используемый для загрузки переменных из python модуля.'''
re_upper = re.compile("(.)([A-Z])")
def _get_varlike_attrs(self, obj):
'''Метод для получения списка аттрибутов похожих на переменные.'''
for attrname in (x for x in dir(obj) if x[:1].isupper()):
yield self.re_upper.sub(r"\1_\2", attrname).lower(), \
getattr(obj, attrname)
def fill(self, namespace, dirpath, package):
'''Загрузить в namespace переменные из указанных модулей.'''
for fullfn in list_directory(dirpath, fullpath=True):
dn, fn = os.path.split(fullfn)
if os.path.isdir(fullfn):
newns = namespace.add_namespace(Namespace(fn))
self.fill(newns, fullfn, "{}.{}".format(package, fn))
elif fn.endswith(".py"):
module = self._load_module_source(package, fn, fullfn)
for varname, cls in self._get_varlike_attrs(module):
if Variable.is_implementation(cls):
namespace.add_variable(cls(varname))
elif HashVariable.is_implementation(cls) or \
TableVariable.is_implementation(cls) or \
Namespace.is_implementation(cls):
_newns = namespace.add_namespace(cls(varname,
namespace))
for _varname, _cls in self._get_varlike_attrs(cls):
if Variable.is_implementation(_cls):
_newns.add_variable(_cls(_varname))
@classmethod
def default(cls):
site_dirs = [os.path.normpath(x) for x in site.getsitepackages()]
for site_dir in site_dirs:
calculate_dir = os.path.join(site_dir, "calculate/vars")
if os.path.exists(calculate_dir):
return (calculate_dir, "calculate.vars")
def _load_module_source(self, package, name, path):
if name.startswith('calculate.vars.'):
full_name = name
else:
full_name = '.'.join([package, name])
if full_name in sys.modules:
return sys.modules[full_name]
spec = importlib.util.spec_from_file_location(full_name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[full_name] = module
return module
class OldProfileFiller:
"""
Заполнитель значений переменных из файлов calculate.ini в профилях
"""
basename = "calculate.ini"
def get_repository_map(self, datavars):
return {repo['name']: repo['path']
for repo in datavars.os.gentoo.repositories}
def fill(self, datavars, profile_path):
ini_filler = NamespaceIniFiller()
profile_walker = ProfileWalker(self.basename,
self.get_repository_map(datavars))
for file_path in profile_walker.find(profile_path):
try:
ini_file_text = read_file(file_path)
ini_filler.fill(datavars, ini_file_text)
except FilesError:
pass

@ -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 1591196541
obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1597740848
dir /etc/dir/dir_1
obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1591617024
obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1597740848

@ -9,12 +9,19 @@ from calculate.variables.datavars import NamespaceNode, VariableNode,\
TableType, BooleanType,\
VariableTypeError, FloatType,\
ListType
from calculate.templates.template_engine import TemplateEngine, FILE
from calculate.templates.template_processor import TemplateExecutor
from calculate.variables.loader import NamespaceIniFiller, Datavars
from calculate.utils.files import stderr_devnull
TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles')
APPENDS_SET = TemplateExecutor(cl_config_path=os.path.join(
TESTFILES_PATH,
'var/lib/calculate/config')
).available_appends
@pytest.mark.vars
class TestNamespace:
@ -608,33 +615,37 @@ class TestNamespace:
assert datavars.namespace_1.var_2 == 'value_2'
def test_if_variable_of_TableType_is_created_using_dependence_that_creates_table__the_created_variable_has_generated_table_as_its_value(self):
from portage.package.ebuild.config import config
value = [{'name': name, 'path': path}
for path, name in
config().repositories.location_map.items()]
Namespace.reset()
datavars = Namespace.datavars
with Namespace('main'):
Variable('chroot', source='/', type=StringType.readonly)
with Namespace('os'):
def source_function(chroot_path):
if chroot_path.value == '/':
with stderr_devnull():
return config()
Variable('config', source=Dependence('main.chroot',
depend=source_function),
type=VariableType)
def config_source(config):
return [{'name': name, 'path': path}
for path, name in
config.value.repositories.location_map.items()]
Variable('repositories', type=TableType,
source=Dependence('.config', depend=config_source))
assert datavars.os.repositories == value
try:
from portage.package.ebuild.config import config
value = [{'name': name, 'path': path}
for path, name in
config().repositories.location_map.items()]
Namespace.reset()
datavars = Namespace.datavars
with Namespace('main'):
Variable('chroot', source='/', type=StringType.readonly)
with Namespace('os'):
def source_function(chroot_path):
if chroot_path.value == '/':
with stderr_devnull():
return config()
Variable('config', source=Dependence('main.chroot',
depend=source_function),
type=VariableType)
def config_source(config):
return [{'name': name, 'path': path}
for path, name in
config.value.repositories.location_map.items()]
Variable('repositories', type=TableType,
source=Dependence('.config', depend=config_source))
assert datavars.os.repositories == value
except ImportError:
# Если тестируем на другой системе модуль portage будет не найден.
assert True
# Тестируем теперь заполнитель переменных из calculate.ini
def test_if_calculate_ini_file_is_used_just_to_create_some_variables__the_namespace_filler_will_create_them(self):
@ -787,6 +798,61 @@ var_2 = value_2
assert 'var_1' not in datavars.custom.test.variables
assert 'var_2' not in datavars.custom.test.variables
def test_if_calculate_ini_file_is_used_for_changing_of_an_unfixed_hash_variable_created_using_the_variables_api_and_for_adding_of_the_new_key_in_it__the_NamespaceIniFiller_object_changes_hash_value_and_adds_a_new_key(self):
Namespace.reset()
datavars = Namespace.datavars
namespace_filler = NamespaceIniFiller()
with Namespace('os'):
Variable('var_1', type=HashType, source={'key_1': 'value_1',
'key_2': 'value_2'})
first_ini_text = """
[os][var_1]
key_1 = new_value
key_3 = value_3
"""
namespace_filler.fill(datavars, first_ini_text)
print('NEW HASH VALUE: {}'.format(datavars.os.var_1.get_hash()))
assert datavars.os.var_1.get_hash() == {'key_1': 'new_value',
'key_2': 'value_2',
'key_3': 'value_3'}
def test_if_calculate_ini_file_is_used_just_for_changing_of_an_fixed_hash_variable_created_using_the_variables_api__the_NamespaceIniFiller_object_changes_hash_value(self):
Namespace.reset()
datavars = Namespace.datavars
namespace_filler = NamespaceIniFiller()
with Namespace('os'):
Variable('var_1', type=HashType.fixed, source={'key_1': 'value_1',
'key_2': 'value_2'})
first_ini_text = """
[os][var_1]
key_1 = new_value
key_2 = weird_value
"""
namespace_filler.fill(datavars, first_ini_text)
print('NEW HASH VALUE: {}'.format(datavars.os.var_1.get_hash()))
assert datavars.os.var_1.get_hash() == {'key_1': 'new_value',
'key_2': 'weird_value'}
def test_if_calculate_ini_file_is_used_just_for_adding_a_new_key_to_an_fixed_hash_variable_created_using_the_variables_api__the_NamespaceIniFiller_object_raises_the_VariableError_exception(self):
Namespace.reset()
datavars = Namespace.datavars
namespace_filler = NamespaceIniFiller()
with Namespace('os'):
Variable('var_1', type=HashType.fixed, source={'key_1': 'value_1',
'key_2': 'value_2'})
first_ini_text = """
[os][var_1]
key_3 = weird_value
"""
with pytest.raises(VariableError):
namespace_filler.fill(datavars, first_ini_text)
def test_if_calculate_ini_file_is_used_for_creation_of_the_table_variable_in_the_custom_namespace__the_NamespaceIniFiller_object_creates_table_in_the_custom_namespace(self):
Namespace.reset()
datavars = Namespace.datavars
@ -1001,7 +1067,7 @@ value = another_value
assert datavars.level.simple == "simple value"
datavars._loader.fill_from_custom_ini(os.path.join(TESTFILES_PATH,
'calculate_0.ini'))
'calculate.ini'))
assert 'os' in datavars.root
assert datavars.level.simple == 'weird value'
@ -1012,8 +1078,10 @@ value = another_value
shutil.copytree(os.path.join(TESTFILES_PATH, 'gentoo.backup'),
os.path.join(TESTFILES_PATH, 'gentoo'),
symlinks=True)
shutil.copytree(os.path.join(TESTFILES_PATH, 'ini_vars.backup'),
os.path.join(TESTFILES_PATH, 'ini_vars'))
def test_ini_loader(self):
def test_test_if_Datavars_object_is_created_with_a_specific_variables_path_and_repository_map_is_set_and_profile_path_is_set_in_the_variables__the_Datavars_object_finds_all_variables_packages_and_ini_files_from_a_profile_using_the_profile_path_variable_and_the_repository_map(self):
repository_map = {'distros': os.path.join(TESTFILES_PATH,
"gentoo/repos/distros"),
'calculate': os.path.join(TESTFILES_PATH,
@ -1025,13 +1093,160 @@ value = another_value
variables_path=os.path.join(TESTFILES_PATH, 'variables_2'),
repository_map=repository_map)
def test_get_repository_map(self):
assert datavars.os.linux.shortname == 'CLD'
assert datavars.os.linux.fullname == 'Calculate Linux Desktop'
assert datavars.os.linux.ver == '20'
assert datavars.os.linux.subname == 'KDE'
assert datavars.os.linux.arch == 'amd64'
assert datavars.os.hashvar.value1 == '20'
assert datavars.os.hashvar.value2 == '30'
assert datavars.os.tablevar == [
{'dev': '/dev/sda1', 'mount': 'swap'},
{'dev': '/dev/sda2', 'mount': '/'},
{'dev': '/dev/sda5', 'mount': '/var/calculate'}]
def test_test_if_Datavars_object_is_created_with_a_specific_variables_path_and_the_repository_map_and_the_current_profile_path_is_set_in_the_variables__the_Datavars_object_finds_all_variables_packages_and_ini_files_from_a_profile_using_the_profile_path_variable_and_the_repositories_variable(self):
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_3'))
print('LOADING IS DONE')
print('hashvar.value1 = {}'.format(datavars.os.hashvar.value1))
print('hashvar.value2 = {}'.format(datavars.os.hashvar.value2))
assert datavars.os.linux.shortname == 'CLD'
assert datavars.os.linux.fullname == 'Calculate Linux Desktop'
assert datavars.os.linux.ver == '20'
assert datavars.os.linux.subname == 'KDE'
assert datavars.os.linux.arch == 'amd64'
assert datavars.os.hashvar.value1 == '20'
assert datavars.os.hashvar.value2 == '30'
assert datavars.os.tablevar == [
{'dev': '/dev/sda1', 'mount': 'swap'},
{'dev': '/dev/sda2', 'mount': '/'},
{'dev': '/dev/sda5', 'mount': '/var/calculate'}]
def test_test_if_Datavars_object_is_created_with_a_specific_variables_path_and_the_repository_map_the_current_profile_path_and_some_ini_files_paths_is_set_in_the_variables__the_Datavars_object_finds_all_variables_packages_and_ini_files_from_a_profile_using_the_profile_path_variable_and_the_repositories_variable_and_loads_variables_from_ini_files_from_the_env_order_and_the_env_path_variables(self):
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_5'))
assert datavars.system.env_order == ['system', 'local']
assert datavars.system.env_path.get_hash() == {
'system':
os.path.join(
TESTFILES_PATH,
'ini_vars/calculate_0.ini'),
'local':
os.path.join(
TESTFILES_PATH,
'ini_vars/calculate_1.ini')}
assert datavars.custom.ns.var_1 == '1'
assert datavars.custom.ns.var_2 == 'weird value'
assert datavars.custom.ns.var_3 ==\
'/the/true/path/to/eternity/in/the/abyss'
assert datavars.custom.ns.var_4 == '12'
assert datavars.os.linux.test == 'new value'
assert datavars.os.linux.test_var == 'test = new value'
assert datavars.os.hashvar.value1 == 'new1'
assert datavars.os.hashvar.value2 == 'new2'
assert datavars.os.calculate == 'new1 new2'
def test_if_Datavars_object_is_created_and_all_variables_are_loaded__the_set_method_can_be_used_for_changing_just_variable_s_values_and_save_their_sources_and_the_reset_method_can_return_values_from_source(self):
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_6'))
datavars.os.linux['test'].set('other value')
datavars.os['hashvar'].set({'value1': 'other1',
'value2': 'other2'})
assert datavars.os.linux['test'].set_by_user
assert datavars.os['hashvar'].set_by_user
assert datavars.os.linux.test == 'other value'
assert datavars.os.hashvar.value1 == 'other1'
assert datavars.os.hashvar.value2 == 'other2'
assert datavars.os.linux.test_var == 'test = other value'
assert datavars.os.calculate == 'other1 other2'
datavars.os['calculate'].set('special value')
assert datavars.os.calculate == 'special value'
datavars.os['hashvar'].set({'value1': 'weird1',
'value2': 'weird2'})
assert datavars.os.hashvar.value1 == 'weird1'
assert datavars.os.hashvar.value2 == 'weird2'
# При изменении зависимости эта переменная не инвалидируется, потому
# что была задана пользователем. Поэтому ее значение установленное set
# сохраняется.
assert datavars.os.calculate == 'special value'
# Если сбросить значения будут пересчитаны, используя установленный
# источник значения.
datavars.os['calculate'].reset()
assert datavars.os.calculate == 'weird1 weird2'
datavars.os.linux['test'].reset()
assert datavars.os.linux.test == 'new value'
datavars.os['hashvar'].reset()
assert datavars.os.hashvar.value1 == 'new1'
assert datavars.os.hashvar.value2 == 'new2'
assert datavars.os.calculate == 'new1 new2'
def test_using_datavars_in_the_template(self):
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_7'))
template_engine = TemplateEngine(appends_set=APPENDS_SET,
chroot_path=TESTFILES_PATH,
datavars_module=datavars)
input_template = '''{% calculate name = 'filename', force -%}
os.linux.test = {{ os.linux.test }}
os.hashvar.value1 = {{ os.hashvar.value1 }}
os.hashvar.value2 = {{ os.hashvar.value2 }}
os.calculate = {{ os.calculate }}'''
output_text = '''os.linux.test = new value
os.hashvar.value1 = new1
os.hashvar.value2 = new2
os.calculate = new1 new2'''
template_engine.process_template_from_string(input_template, FILE)
text = template_engine.template_text
assert text == output_text
def test_save_variable(self):
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_7'))
template_engine = TemplateEngine(appends_set=APPENDS_SET,
chroot_path=TESTFILES_PATH,
datavars_module=datavars)
input_template_1 = '''{% calculate name = 'filename', force -%}
{% save custom.ns.value = 12 -%}
{% save os.linux.test = 'new value' %}
{% save os.hashvar = {'value1': 'weird1', 'value2': 'weird2'} %}'''
template_engine.process_template_from_string(input_template_1, FILE)
assert datavars.custom.ns.value == '12'
assert datavars.os.linux.test == 'new value'
assert datavars.os.linux.test_var == 'test = new value'
assert datavars.os.hashvar.value1 == 'weird1'
assert datavars.os.hashvar.value2 == 'weird2'
assert datavars.os.calculate == 'weird1 weird2'
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'
assert False
def test_for_removing_testfile(self):
def test_for_removing_testfiles(self):
shutil.rmtree(os.path.join(TESTFILES_PATH, 'gentoo'))
shutil.rmtree(os.path.join(TESTFILES_PATH, 'ini_vars'))

@ -1,3 +0,0 @@
[os][linux]
shortname = Calculate
test = test

@ -0,0 +1,7 @@
[custom][ns]
var_1 = 1
var_2 = weird value
[os][hashvar]
value1 = new1
value2 = new2

@ -0,0 +1,6 @@
[custom][ns]
var_3 = /the/true/path/to/eternity/in/the/abyss
var_4 = 12
[os][linux]
test = new value

@ -0,0 +1,4 @@
from calculate.variables.datavars import Variable, StringType
Variable('chroot', type=StringType.readonly, source='/')

@ -0,0 +1,43 @@
from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType
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', source='', type=StringType)
Variable('test_var', type=StringType,
source=Dependence('.test',
depend=lambda test: 'test = {}'.
format(test.value)))
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"}])

@ -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")}])

@ -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_0.ini'),
'local': os.path.join(TESTFILES_PATH,
'ini_vars/calculate_1.ini')})

@ -0,0 +1,4 @@
from calculate.variables.datavars import Variable, StringType
Variable('chroot', type=StringType.readonly, source='/')

@ -0,0 +1,43 @@
from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType
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', source='', type=StringType)
Variable('test_var', type=StringType,
source=Dependence('.test',
depend=lambda test: 'test = {}'.
format(test.value)))
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"}])

@ -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")}])

@ -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_0.ini'),
'local': os.path.join(TESTFILES_PATH,
'ini_vars/calculate_1.ini')})

@ -0,0 +1,4 @@
from calculate.variables.datavars import Variable, StringType
Variable('chroot', type=StringType.readonly, source='/')

@ -0,0 +1,43 @@
from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType
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', source='', type=StringType)
Variable('test_var', type=StringType,
source=Dependence('.test',
depend=lambda test: 'test = {}'.
format(test.value)))
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"}])

@ -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")}])

@ -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_0.ini'),
'local': os.path.join(TESTFILES_PATH,
'ini_vars/calculate_1.ini')})
Loading…
Cancel
Save