Added main Datavars module and its functionality is almost implemented.

packages
Иванов Денис 4 years ago
parent 632b88b79f
commit 2e5946ed6e

@ -159,6 +159,7 @@ class ParametersProcessor:
def check_template_parameter(self, parameter_name, parameter_value, def check_template_parameter(self, parameter_name, parameter_value,
template_type, lineno): template_type, lineno):
'''Метод, проверяющий указанный параметр.'''
self.lineno = lineno self.lineno = lineno
self.template_type = template_type self.template_type = template_type
@ -191,6 +192,7 @@ class ParametersProcessor:
{parameter_name: checked_value}) {parameter_name: checked_value})
def check_postparse_parameters(self): def check_postparse_parameters(self):
'''Метод, запускающий проверку параметров после их разбора.'''
for parameter, parameter_checker in\ for parameter, parameter_checker in\
self.postparse_checkers_list.items(): self.postparse_checkers_list.items():
if parameter not in self._parameters_container: if parameter not in self._parameters_container:
@ -200,6 +202,7 @@ class ParametersProcessor:
parameter_checker(parameter_value) parameter_checker(parameter_value)
def check_template_parameters(self, parameters, template_type, lineno): def check_template_parameters(self, parameters, template_type, lineno):
'''Метод, запускающий проверку указанных параметров.'''
self.template_type = template_type self.template_type = template_type
self.lineno = lineno self.lineno = lineno
@ -230,6 +233,8 @@ class ParametersProcessor:
self._parameters_container.set_parameter( self._parameters_container.set_parameter(
parameter_name=checked_value) parameter_name=checked_value)
# Методы для проверки параметров во время разбора шаблона.
def check_package_parameter(self, parameter_value): def check_package_parameter(self, parameter_value):
try: try:
atom_object = self.package_atom_parser.parse_package_parameter( atom_object = self.package_atom_parser.parse_package_parameter(
@ -774,6 +779,8 @@ class CalculateExtension(Extension):
'''Метод для разбора тега save, сохраняющего значение указанной '''Метод для разбора тега save, сохраняющего значение указанной
переменной datavars.''' переменной datavars.'''
lineno = next(self.stream).lineno lineno = next(self.stream).lineno
# Целового файла больше не будет.
target_file = nodes.Const('', lineno=lineno) target_file = nodes.Const('', lineno=lineno)
if self.stream.skip_if('dot'): if self.stream.skip_if('dot'):

@ -1,30 +1,31 @@
import os import os
import re import re
import calculate.utils.fs as fs from calculate.utils.files import read_file_lines
class ProfileWalker: class ProfileWalker:
""" '''Объект обходящий все директории профиля через parent файлы.'''
Объект обходящий все директории профиля через parent файлы
"""
def __init__(self, filename, repositories): def __init__(self, filename, repositories):
self.repositories = repositories self.repositories = repositories
self.filename = filename self.filename = filename
self.reReppath = re.compile("^({0})+:".format( self.re_reppath = re.compile("^({0})+:".format(
"|".join(self.repositories.keys()))) "|".join(self.repositories.keys())))
def interpolate(self, path): def interpolate(self, path):
def subfunc(m): def subfunc(m):
return "{0}/profiles/".format(self.repositories.get(m.group(1))) return "{0}/profiles/".format(self.repositories.get(m.group(1)))
return self.reReppath.sub(subfunc, path) return self.re_reppath.sub(subfunc, path)
def find(self, directory): def find(self, directory):
parent = os.path.join(directory, "parent") '''Метод для поиска по профилю всех файлов с именем, указанным в
for line in (x for x in fs.readFileLines(parent) if x.strip()): self.filename.'''
parentdir = os.path.normpath( parent_file_path = os.path.join(directory, "parent")
os.path.join(directory, self.interpolate(line))) for line in (parent_line for parent_line in
if fs.exists(parentdir): read_file_lines(parent_file_path) if parent_line.strip()):
yield from self.find(parentdir) parent_directory = os.path.normpath(
os.path.join(directory, self.interpolate(line)))
if os.path.exists(parent_directory):
yield from self.find(parent_directory)
findfile = os.path.normpath(os.path.join(directory, self.filename)) findfile = os.path.normpath(os.path.join(directory, self.filename))
if fs.exists(findfile): if os.path.exists(findfile):
yield findfile yield findfile

@ -1,6 +1,6 @@
import ast import ast
import dis import dis
from typing import List, Union, Any from typing import List, Any
from contextlib import contextmanager from contextlib import contextmanager
from inspect import signature, getsource from inspect import signature, getsource
from types import FunctionType, LambdaType from types import FunctionType, LambdaType
@ -36,9 +36,14 @@ class VariableType:
name = 'undefined' name = 'undefined'
@classmethod @classmethod
def process_value(self, value, variable): def process_value(cls, value, variable):
return value return value
@classmethod
def readonly(cls, variable_object) -> None:
variable_object.variable_type = cls
variable_object.readonly = True
class IniType(VariableType): class IniType(VariableType):
'''Класс, соответствующий типу переменных созданных в calculate.ini файлах. '''Класс, соответствующий типу переменных созданных в calculate.ini файлах.
@ -46,7 +51,7 @@ class IniType(VariableType):
name = 'ini' name = 'ini'
@classmethod @classmethod
def process_value(self, value, variable): def process_value(cls, value, variable):
return value return value
@ -55,7 +60,7 @@ class StringType(VariableType):
name = 'string' name = 'string'
@classmethod @classmethod
def process_value(self, value, variable) -> str: def process_value(cls, value, variable) -> str:
if isinstance(value, str): if isinstance(value, str):
return value return value
else: else:
@ -73,7 +78,7 @@ class IntegerType(VariableType):
name = 'integer' name = 'integer'
@classmethod @classmethod
def process_value(self, value, variable) -> int: def process_value(cls, value, variable) -> int:
if isinstance(value, int): if isinstance(value, int):
return value return value
else: else:
@ -91,7 +96,7 @@ class FloatType(VariableType):
name = 'float' name = 'float'
@classmethod @classmethod
def process_value(self, value, variable) -> float: def process_value(cls, value, variable) -> float:
if isinstance(value, float): if isinstance(value, float):
return value return value
else: else:
@ -111,13 +116,13 @@ class BooleanType(VariableType):
false_values = {'False', 'false'} false_values = {'False', 'false'}
@classmethod @classmethod
def process_value(self, value, variable) -> bool: def process_value(cls, value, variable) -> bool:
if isinstance(value, bool): if isinstance(value, bool):
return value return value
elif isinstance(value, str): elif isinstance(value, str):
if value in self.true_values: if value in cls.true_values:
return True return True
if value in self.false_values: if value in cls.false_values:
return False return False
try: try:
return bool(value) return bool(value)
@ -132,7 +137,7 @@ class ListType(VariableType):
name = 'list' name = 'list'
@classmethod @classmethod
def process_value(self, value, variable) -> list: def process_value(cls, value, variable) -> list:
# TODO нормально все сделать. # TODO нормально все сделать.
if isinstance(value, list): if isinstance(value, list):
return value return value
@ -181,6 +186,7 @@ class Hash:
'''Класс реализующий контейнер для хранения хэша в переменной '''Класс реализующий контейнер для хранения хэша в переменной
соответствующего типа.''' соответствующего типа.'''
def __init__(self, values: dict, master_variable, parent=None): def __init__(self, values: dict, master_variable, parent=None):
self.fixed = master_variable.fixed
self._values = dict() self._values = dict()
for key, value in values.items(): for key, value in values.items():
self._values.update({key: HashValue(key, value, master_variable, self._values.update({key: HashValue(key, value, master_variable,
@ -189,11 +195,27 @@ class Hash:
self.row_index = None self.row_index = None
def get_hash(self) -> dict: def get_hash(self) -> dict:
'''Метод для получения словаря из значений хэша.'''
dict_value = {} dict_value = {}
for key in self._values.keys(): for key in self._values.keys():
dict_value.update({key: self._values[key].get_value()}) dict_value.update({key: self._values[key].get_value()})
return dict_value return dict_value
def update_hash(self, values: dict) -> None:
'''Метод для обновления значения хэша.'''
print('UPDATE HASH')
for key, value in values.items():
if key in self._values:
self._values[key].value = value
elif self.fixed:
raise VariableError("key '{}' is unavailable for fixed"
" hash, available keys: '{}'".
format(key, ', '.join(self._fields)))
else:
self._values[key] = HashValue(key, value, self.master_variable,
self)
return self
def __getattr__(self, key: str): def __getattr__(self, key: str):
'''Метод возвращает ноду пространства имен или значение переменной.''' '''Метод возвращает ноду пространства имен или значение переменной.'''
if key in self._values: if key in self._values:
@ -226,12 +248,21 @@ class HashType(VariableType):
name = 'hash' name = 'hash'
@classmethod @classmethod
def process_value(self, value, variable) -> Hash: def process_value(cls, values, variable) -> Hash:
if not isinstance(value, dict): if not isinstance(values, dict):
raise VariableTypeError("can not set value with type '{_type}' to" raise VariableTypeError("can not set value with type '{_type}' to"
" hash variable: value must be 'dict' type" " hash variable: value must be 'dict' type"
.format(_type=type(value))) .format(_type=type(values)))
return Hash(value, variable) if variable.value is not None:
updated_hash = variable.value.update_hash(values)
else:
updated_hash = Hash(values, variable)
return updated_hash
@classmethod
def fixed(cls, variable_object) -> None:
variable_object.variable_type = cls
variable_object.fixed = True
class Table: class Table:
@ -487,8 +518,8 @@ class VariableNode:
# динамическом связывании. # динамическом связывании.
self._subscriptions = set() self._subscriptions = set()
# Если значение переменной None -- значит она обнулена.
self.value = None self.value = None
self._invalidated = True
# Источник значения переменной, может быть значением, а может быть # Источник значения переменной, может быть значением, а может быть
# зависимостью. # зависимостью.
@ -501,6 +532,10 @@ class VariableNode:
self.set_by_user = False self.set_by_user = False
self._readonly = False self._readonly = False
# Флаг имеющий значение только для переменных типа HashType.
# Предназначен для включения проверки соответствия полей хэша при
# установке значения.
self._fixed = False
def update_value(self) -> None: def update_value(self) -> None:
'''Метод для обновления значения переменной с помощью указанного '''Метод для обновления значения переменной с помощью указанного
@ -537,6 +572,25 @@ class VariableNode:
value = self._source value = self._source
self.value = self.variable_type.process_value(value, self) self.value = self.variable_type.process_value(value, self)
self._invalidated = False
def set_variable_type(self, variable_type, readonly=None, fixed=None):
'''Метод для установки типа переменной.'''
if readonly is not None and isinstance(readonly, bool):
self._readonly = readonly
elif fixed is not None and isinstance(fixed, bool):
self._fixed = fixed
if self.variable_type is VariableType:
if isinstance(variable_type, type):
if issubclass(variable_type, VariableType):
self.variable_type = variable_type
else:
raise VariableError('variable type object must be'
' VariableType or its class method,'
' not {}'.format(type(variable_type)))
elif callable(variable_type):
variable_type(self)
def set(self, value): def set(self, value):
self._invalidate() self._invalidate()
@ -550,7 +604,8 @@ class VariableNode:
@source.setter @source.setter
def source(self, source) -> None: def source(self, source) -> None:
if self._readonly: if self._readonly:
raise VariableError("can not change the variable '{}': read only") raise VariableError("can not change the variable '{}': read only".
format(self.get_fullname()))
# Если источники не совпадают или текущее значение переменной было # Если источники не совпадают или текущее значение переменной было
# установлено пользователем, то инвалидируем переменную и меняем # установлено пользователем, то инвалидируем переменную и меняем
@ -572,12 +627,22 @@ class VariableNode:
# self.update_value() # self.update_value()
self._readonly = value self._readonly = value
@property
def fixed(self) -> bool:
return self._fixed
@fixed.setter
def fixed(self, value) -> bool:
self._fixed = value
def _invalidate(self) -> None: def _invalidate(self) -> None:
'''Метод для инвалидации данной переменной и всех зависящих от нее '''Метод для инвалидации данной переменной и всех зависящих от нее
переменных.''' переменных.'''
# print('{} is invalidated'.format(self.get_fullname())) # print('{} is invalidated'.format(self.get_fullname()))
if self.value is not None and not self.set_by_user: if not self._invalidated and not self.set_by_user:
self.value = None if self.variable_type is not HashType:
self.value = None
self._invalidated = True
for subscriber in self.subscribers: for subscriber in self.subscribers:
subscriber._invalidate() subscriber._invalidate()
@ -593,7 +658,7 @@ class VariableNode:
def get_value(self) -> Any: def get_value(self) -> Any:
'''Метод для получения значения переменной.''' '''Метод для получения значения переменной.'''
if self.value is None and not self.set_by_user: if self._invalidated and not self.set_by_user:
self.update_value() self.update_value()
return self.value return self.value
@ -641,8 +706,8 @@ class NamespaceNode:
def clear(self): def clear(self):
'''Метод для очистки пространства имен. Очищает и пространства имен '''Метод для очистки пространства имен. Очищает и пространства имен
и переменные. Предназначен только для использования в calculate.ini.''' и переменные. Предназначен только для использования в calculate.ini.'''
for namespace in self.namespaces: for namespace_name in self.namespaces.keys():
namespace.clear() self.namespaces[namespace_name].clear()
self.variables.clear() self.variables.clear()
self.namespaces.clear() self.namespaces.clear()
@ -653,7 +718,7 @@ class NamespaceNode:
else: else:
return self.name return self.name
def __getattr__(self, name: str) -> None: def __getattr__(self, name: str):
'''Метод возвращает ноду пространства имен или значение переменной.''' '''Метод возвращает ноду пространства имен или значение переменной.'''
if name in self.namespaces: if name in self.namespaces:
return self.namespaces[name] return self.namespaces[name]
@ -747,14 +812,13 @@ class VariableAPI:
self.errors = [] self.errors = []
def __call__(self, name: str, source=None, type=VariableType, def __call__(self, name: str, source=None, type=VariableType,
readonly=False, force=False): readonly=False, fixed=False, force=False):
'''Метод для создания переменных внутри with Namespace('name').''' '''Метод для создания переменных внутри with Namespace('name').'''
if name not in self.current_namespace.variables: if name not in self.current_namespace.variables:
print('CREATE VARIABLE: {}'.format('{}.{}'.format( print('CREATE VARIABLE: {}'.format('{}.{}'.format(
self.current_namespace.get_fullname(), self.current_namespace.get_fullname(),
name))) name)))
variable = VariableNode(name, self.current_namespace, variable = VariableNode(name, self.current_namespace)
variable_type=type)
else: else:
print('MODIFY VARIABLE: {}'.format(name)) print('MODIFY VARIABLE: {}'.format(name))
variable = self.current_namespace[name] variable = self.current_namespace[name]
@ -770,7 +834,12 @@ class VariableAPI:
else: else:
variable.source = source variable.source = source
variable.readonly = readonly if readonly:
variable.set_variable_type(type, readonly=True)
elif fixed:
variable.set_variable_type(type, fixed=True)
else:
variable.set_variable_type(type)
return variable return variable
@ -798,15 +867,18 @@ class NamespaceAPI:
можно получить доступ к переменным.''' можно получить доступ к переменным.'''
return self._datavars return self._datavars
def set_root(self, datavars_root: NamespaceNode): def set_datavars(self, datavars):
'''Метод для установки корневого пространства имен, которое пока что '''Метод для установки корневого пространства имен, которое пока что
будет использоваться для предоставления доступа к переменным.''' будет использоваться для предоставления доступа к переменным.'''
self._datavars = datavars_root self._datavars = datavars
self._variables_fabric.current_namespace = self._datavars self._variables_fabric.current_namespace = self._datavars
def reset(self): def reset(self):
'''Метод для сброса корневого пространства имен.''' '''Метод для сброса корневого пространства имен.'''
self._datavars = NamespaceNode('<root>') if isinstance(self._datavars, NamespaceNode):
self._datavars = NamespaceNode('<root>')
else:
self._datavars.reset()
self.current_namespace = self._datavars self.current_namespace = self._datavars
self._variables_fabric.current_namespace = self._datavars self._variables_fabric.current_namespace = self._datavars

@ -4,11 +4,12 @@ import os
import importlib import importlib
import importlib.util import importlib.util
import site import site
from calculate.vars.datavars import Variable, HashVariable, TableVariable from calculate.variables.old_vars.datavars import Variable, HashVariable,\
from calculate.vars.alt_datavars import NamespaceNode, VariableNode,\ TableVariable
ListType, IntegerType,\ from calculate.variables.datavars import NamespaceNode, VariableNode,\
FloatType, IniType, TableType,\ ListType, IntegerType,\
Namespace FloatType, IniType, TableType,\
Namespace, VariableError
from calculate.utils.gentoo import ProfileWalker from calculate.utils.gentoo import ProfileWalker
from calculate.utils.files import list_directory, read_file, FilesError from calculate.utils.files import list_directory, read_file, FilesError
from pyparsing import Literal, Word, ZeroOrMore, Group, Optional, restOfLine,\ from pyparsing import Literal, Word, ZeroOrMore, Group, Optional, restOfLine,\
@ -182,17 +183,24 @@ class NamespaceIniFiller:
def start_section(self, sections: str) -> None: def start_section(self, sections: str) -> None:
'''Метод для получения доступа и создания пространств имен.''' '''Метод для получения доступа и создания пространств имен.'''
print('SECTIONS: {}'.format(sections))
if self.restricted: if self.restricted:
self.modify_only = sections[0] not in self.available_sections self.modify_only = sections[0] not in self.available_sections
self.current_namespace = self.namespace self.current_namespace = self.namespace
for section in sections: for section in sections:
if section not in self.current_namespace.namespaces: print('START SECTION: {}'.format(section))
if not self.modify_only: if isinstance(self.current_namespace, Datavars):
self.current_namespace.add_namespace( if section not in self.current_namespace:
raise VariableError("variables package '{}' is not found".
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)) NamespaceNode(section))
else: else:
self.current_namespace = None self.current_namespace = None
return return
self.current_namespace = self.current_namespace.namespaces[section] self.current_namespace = self.current_namespace.namespaces[section]
def clear_section(self, sections: list) -> None: def clear_section(self, sections: list) -> None:
@ -202,18 +210,22 @@ class NamespaceIniFiller:
current_namespace = self.namespace current_namespace = self.namespace
for section in sections: for section in sections:
if section in current_namespace.namespaces: if (isinstance(current_namespace, Datavars) and
current_namespace = current_namespace.namespaces[section] section in current_namespace):
elif (section in current_namespace.variables and current_namespace = current_namespace[section]
current_namespace.variables[section].variable_type elif isinstance(current_namespace, NamespaceNode):
is TableType): if section in current_namespace.namespaces:
table_variable = current_namespace.variables[section] current_namespace = current_namespace[section]
table_to_clear = table_variable.get_value() elif (section in current_namespace.variables and
table_to_clear.clear() current_namespace.variables[section].variable_type
table_variable.source = table_to_clear is TableType):
return table_variable = current_namespace.variables[section]
else: table_to_clear = table_variable.get_value()
return table_to_clear.clear()
table_variable.source = table_to_clear
return
else:
return
if not self.modify_only: if not self.modify_only:
current_namespace.clear() current_namespace.clear()
@ -249,6 +261,8 @@ class NamespaceIniFiller:
table_variable.source = table table_variable.source = table
def define_key(self, key: str, value: str, optype) -> None: 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: if self.current_namespace is None:
return return
@ -345,17 +359,35 @@ class NamespaceIniFiller:
class VariableLoader: class VariableLoader:
basename = "calculate.ini" '''Класс загрузчика переменных из python-файлов и из ini-файлов.'''
ini_basename = "calculate.ini"
def load_variables(self, directory_path) -> NamespaceNode:
root = Namespace.datavars def __init__(self, datavars, variables_path, repository_map=None):
package = '.'.join(directory_path.split('/')) self.datavars = datavars
self._fill_from_package(root, directory_path, package) self.ini_filler = NamespaceIniFiller()
return root
self.variables_path = variables_path
self.variables_package = '.'.join(variables_path.split('/'))
self.repository_map = repository_map
def load_variables_package(self, package_name: str) -> None:
'''Метод для загрузки пакетов с переменными.'''
directory_path = os.path.join(self.variables_path, package_name)
package = '{}.{}'.format(self.variables_package, package_name)
package_namespace = NamespaceNode(package_name)
self.datavars.root.add_namespace(package_namespace)
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))
profile_path = self.datavars.os.gentoo.profile.path
self._fill_from_ini(profile_path)
def _fill_from_package(self, current_namespace: NamespaceNode, def _fill_from_package(self, current_namespace: NamespaceNode,
directory_path: str, package: str) -> None: directory_path: str, package: str) -> None:
print('FILL -> {}'.format(current_namespace)) '''Метод для зaполнения переменных из python-файла.'''
file_nodes = [] file_nodes = []
directory_nodes = [] directory_nodes = []
# Просматриваем директорию # Просматриваем директорию
@ -385,21 +417,31 @@ class VariableLoader:
'{}.{}'.format(package, '{}.{}'.format(package,
directory_node.name)) directory_node.name))
def _fill_from_ini(self, datavars, profile_path): def _fill_from_ini(self, profile_path):
ini_filler = NamespaceIniFiller() '''Метод для зaполнения переменных из ini-файла.'''
profile_walker = ProfileWalker(self.basename, print('PROCESSING INI FROM PROFILE')
self.get_repository_map(datavars)) profile_walker = ProfileWalker(self.ini_basename,
self.repository_map)
for file_path in profile_walker.find(profile_path): for file_path in profile_walker.find(profile_path):
try: try:
print('PROCESS FILE: {}'.format(file_path))
ini_file_text = read_file(file_path) ini_file_text = read_file(file_path)
ini_filler.fill(datavars, ini_file_text) self.ini_filler.fill(self.datavars, ini_file_text)
except FilesError: except FilesError:
# TODO продумать обработку ошибок.
pass pass
def get_repository_map(self, datavars): def _get_repository_map(self, datavars):
return {repo['name']: repo['path'] return {repo['name']: repo['path']
for repo in datavars.os.gentoo.repositories} for repo in datavars.os.gentoo.repositories}
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)
@contextmanager @contextmanager
def test(self, file_name, namespace): def test(self, file_name, namespace):
print('IMPORT: {}.{}'.format(namespace.get_fullname(), file_name)) print('IMPORT: {}.{}'.format(namespace.get_fullname(), file_name))
@ -410,6 +452,80 @@ class VariableLoader:
file_name)) file_name))
class Datavars:
'''Класс для хранения переменных и управления ими.'''
def __init__(self, variables_path='calculate/vars', repository_map=None):
self._variables_path = variables_path
self._available_packages = self._get_available_packages()
self.root = NamespaceNode('<root>')
self._loader = VariableLoader(self, self._variables_path,
repository_map=repository_map)
Namespace.reset()
Namespace.set_datavars(self)
self._loader.load_from_profile()
def reset(self):
'''Метод для сброса модуля переменных.'''
self.root.clear()
self.root = NamespaceNode('<root>')
self._available_packages.clear()
self._available_packages = self._get_available_packages()
Namespace.set_datavars(self)
def _get_available_packages(self) -> dict:
'''Метод для получения словаря с имеющимися пакетами переменных
и путями к ним.'''
available_packages = dict()
for file_name in os.listdir(self._variables_path):
if file_name.startswith('__'):
continue
file_path = os.path.join(self._variables_path, file_name)
if os.path.isdir(file_path):
available_packages.update({file_name: file_path})
return available_packages
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 not in self._available_packages:
raise VariableError("variables package '{}' is not found".
format(package_name))
else:
self._loader.load_variables_package(package_name)
return self.root[package_name]
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 not in self._available_packages:
raise VariableError("variables package '{}' is not found".
format(package_name))
else:
self._loader.load_variables_package(package_name)
return self.root[package_name]
def __contains__(self, package_name):
if package_name in self.root.namespaces:
return True
elif package_name not in self._available_packages:
return False
else:
self._loader.load_variables_package(package_name)
return True
@property
def namespaces(self):
return self.root.namespaces
class OldVariableLoader: class OldVariableLoader:
'''Класс, используемый для загрузки переменных из python модуля.''' '''Класс, используемый для загрузки переменных из python модуля.'''
re_upper = re.compile("(.)([A-Z])") re_upper = re.compile("(.)([A-Z])")

@ -0,0 +1,5 @@
from calculate.vars.datavars import Variable, ReadonlyVariable
class Chroot(Variable):
properties = [ReadonlyVariable]
value = "/"

@ -0,0 +1,88 @@
from calculate.vars.datavars import Variable, ChoiceVariable, HashVariable, TableVariable, Namespace
from calculate.utils.files import stderr_devnull
import calculate.utils.fs as fs
import os
"""
gentoo
make_profile
profile.path
profile.name
repositories[*].name
repositories[*].path
config
"""
class MakeProfile(Variable):
"""
Путь до файла, указывающего на активный профиль
"""
value = '/etc/portage/make.profile'
class Profile(Namespace):
"""
Параметры текущего профиля
"""
class Path(Variable):
"""
Абсолютный путь до профиля
"""
def get(self):
make_profile = self.vars.parent.make_profile.getValue(self)
make_profile_dir = os.path.dirname(make_profile)
profileLink = fs.readlink(make_profile)
if profileLink:
profileLink = os.path.normpath(
os.path.join(make_profile_dir,profileLink))
return profileLink
else:
return ""
class Name(Variable):
"""
Название профиля
"""
def get(self):
profile_path = self.vars.path.getValue(self)
if not profile_path:
return ""
repositories = self.vars.parent.repositories
for rep in repositories:
reppath = rep.path.getValue(self)
repname = rep.name.getValue(self)
removepart = os.path.normpath(os.path.join(reppath,"profiles"))
if profile_path.startswith(removepart):
return "%s:%s"%(
repname,
profile_path[len(removepart)+1:])
return profile_path
class Repositories(TableVariable):
"""
Информация о репозиториях
name: имя репозитория
path: полный путь до репозитория
"""
class Data(TableVariable.Data):
def get(self):
config = self.vars.config.getValue(self)
return [
{
'name': name,
'path': path
}
for path, name in config.repositories.location_map.items()
]
hash_vars = ["name", "path"]
class Config(Variable):
"""
Объект текущей конфигурации Portage
"""
def get(self):
from portage.package.ebuild.config import config
chroot_path = self.vars.root.main.chroot.getValue(self)
if chroot_path == '/':
with stderr_devnull():
return config()

@ -4,8 +4,9 @@ import os
import importlib import importlib
import importlib.util import importlib.util
import site import site
from calculate.vars.datavars import Variable, Namespace, HashVariable,\ from calculate.variables.old_vars.datavars import Variable, Namespace,\
TableVariable, IniCreated, DefaultValue HashVariable, TableVariable,\
IniCreated, DefaultValue
from calculate.utils.gentoo import ProfileWalker from calculate.utils.gentoo import ProfileWalker
from calculate.utils.fs import readFile from calculate.utils.fs import readFile
from calculate.utils.files import list_directory from calculate.utils.files import list_directory

@ -1,5 +1,7 @@
from calculate.vars.datavars import Variable, ReadonlyVariable from calculate.variables.datavars import Variable, StringType
'''
main:
chroot -> string
'''
class Chroot(Variable): Variable('chroot', type=StringType.readonly, source='/')
properties = [ReadonlyVariable]
value = "/"

@ -1,88 +1,79 @@
from calculate.vars.datavars import Variable, ChoiceVariable, HashVariable, TableVariable, Namespace
from calculate.utils.files import stderr_devnull
import calculate.utils.fs as fs
import os import os
from calculate.utils.files import stderr_devnull
from calculate.utils.files import read_link, FilesError
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
'''
# Путь до файла, указывающего на активный профиль
Variable('make_profile', type=StringType, source='/etc/portage/make.profile')
# Параметры текущего профиля.
with Namespace('profile'):
def get_profile_link(make_profile):
make_profile_dir = os.path.dirname(make_profile.value)
try:
profile_link = read_link(make_profile)
except FilesError:
return ""
if profile_link:
profile_link = os.path.normpath(
os.path.join(make_profile_dir, profile_link))
return profile_link
else:
return ""
# Абсолютный путь до профиля
Variable('path', type=StringType,
source=Dependence('..make_profile', depend=get_profile_link))
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_link))
def get_repository_table(config):
return [{'name': name,
'path': path}
for path, name in config.value.repositories.location_map.items()]
"""
gentoo
make_profile
profile.path
profile.name
repositories[*].name
repositories[*].path
config
"""
class MakeProfile(Variable): # Информация о репозиториях
""" # name: имя репозитория
Путь до файла, указывающего на активный профиль # path: полный путь до репозитория
""" Variable('repositories', type=TableType,
value = '/etc/portage/make.profile' source=Dependence('.config', depend=get_repository_table))
class Profile(Namespace):
"""
Параметры текущего профиля
"""
class Path(Variable):
"""
Абсолютный путь до профиля
"""
def get(self):
make_profile = self.vars.parent.make_profile.getValue(self)
make_profile_dir = os.path.dirname(make_profile)
profileLink = fs.readlink(make_profile)
if profileLink:
profileLink = os.path.normpath(
os.path.join(make_profile_dir,profileLink))
return profileLink
else:
return ""
class Name(Variable):
"""
Название профиля
"""
def get(self):
profile_path = self.vars.path.getValue(self)
if not profile_path:
return ""
repositories = self.vars.parent.repositories
for rep in repositories:
reppath = rep.path.getValue(self)
repname = rep.name.getValue(self)
removepart = os.path.normpath(os.path.join(reppath,"profiles"))
if profile_path.startswith(removepart):
return "%s:%s"%(
repname,
profile_path[len(removepart)+1:])
return profile_path
class Repositories(TableVariable): def get_config_object(chroot_path):
""" from portage.package.ebuild.config import config
Информация о репозиториях if chroot_path.value == '/':
with stderr_devnull():
return config()
name: имя репозитория
path: полный путь до репозитория
"""
class Data(TableVariable.Data):
def get(self):
config = self.vars.config.getValue(self)
return [
{
'name': name,
'path': path
}
for path, name in config.repositories.location_map.items()
]
hash_vars = ["name", "path"]
class Config(Variable): # Объект текущей конфигурации Portage
""" Variable('config', source=Dependence('main.chroot', depend=get_config_object))
Объект текущей конфигурации Portage
"""
def get(self):
from portage.package.ebuild.config import config
chroot_path = self.vars.root.main.chroot.getValue(self)
if chroot_path == '/':
with stderr_devnull():
return config()

@ -0,0 +1,13 @@
from calculate.variables.datavars import Variable, ListType, HashType
'''
system:
env_order -> list
env_path -> hash
'''
# Список мест, где есть calculate.ini файлы.
Variable('env_order', type=ListType.readonly,
source=['grp', 'system', 'etc', 'local', 'remote'])
# Отображение множества мест, где есть calculate.ini файлы, на пути к ним.
Variable('env_path', type=HashType, source=dict())

@ -24,8 +24,8 @@ markers =
files_utils: marker for running tests for calculate.utils.files module. files_utils: marker for running tests for calculate.utils.files module.
package_utils: marker for running tests for calculate.utils.contents module. package_utils: marker for running tests for calculate.utils.contents module.
vars: marker for running tests for datavars old_vars: marker for running tests for datavars
alt_vars: marker for testing alternative version of the datavars module. vars: marker for testing alternative version of the datavars module.
gentoo: marker for running tests for utils.gentoo gentoo: marker for running tests for utils.gentoo
calculateini: marker for running tests for utils.calculateini calculateini: marker for running tests for utils.calculateini
template_engine: marker for running tests for TemplateEngine. template_engine: marker for running tests for TemplateEngine.

@ -1,16 +1,22 @@
import pytest import pytest
import os import os
from calculate.vars.datavars import Namespace, Variable, CyclicVariableError,\ from calculate.variables.old_vars.datavars import Namespace, Variable,\
VariableError, ReadonlyVariable,\ CyclicVariableError,\
ChoiceVariable, IntegerVariable,\ VariableError,\
StringVariable, DefaultValue,\ ReadonlyVariable,\
TableVariable, HashVariable,\ ChoiceVariable,\
VariableNotFoundError IntegerVariable,\
from calculate.vars.vars_loader import NamespaceIniFiller, VariableLoader,\ StringVariable,\
ProfileFiller, NamespaceIniFillerStrict DefaultValue,\
TableVariable, HashVariable,\
VariableNotFoundError
@pytest.mark.vars from calculate.variables.old_vars.vars_loader import NamespaceIniFiller,\
VariableLoader,\
ProfileFiller,\
NamespaceIniFillerStrict
@pytest.mark.old_vars
class TestNamespace: class TestNamespace:
def test_init_empty_namespace(self): def test_init_empty_namespace(self):
ns = Namespace() ns = Namespace()

@ -1,9 +1,8 @@
import pytest import pytest
from calculate.vars.vars_loader import CalculateIniParser, Define from calculate.variables.loader import CalculateIniParser, Define
@pytest.mark.vars @pytest.mark.vars
@pytest.mark.calculateini
class TestCalculateIni: class TestCalculateIni:
def test_empty_calculate_ini(self): def test_empty_calculate_ini(self):
pass pass
@ -17,8 +16,7 @@ class TestCalculateIni:
"varval1 = value1\n") "varval1 = value1\n")
parsed_lines = [{'start_section': (['section'],)}, parsed_lines = [{'start_section': (['section'],)},
{'define_key': (['section'], 'varval1', {'define_key': ('varval1', 'value1', Define.assign)},
'value1', Define.assign)},
] ]
parse_result = list(ini_parser.parse(input_text)) parse_result = list(ini_parser.parse(input_text))
@ -35,12 +33,9 @@ class TestCalculateIni:
"varval3 -= value3\n") "varval3 -= value3\n")
parsed_lines = [{'start_section': (['section'],)}, parsed_lines = [{'start_section': (['section'],)},
{'define_key': (['section'], 'varval1', {'define_key': ('varval1', 'value1', Define.assign)},
'value1', Define.assign)}, {'define_key': ('varval2', 'value2', Define.append)},
{'define_key': (['section'], 'varval2', {'define_key': ('varval3', 'value3', Define.remove)},
'value2', Define.append)},
{'define_key': (['section'], 'varval3',
'value3', Define.remove)},
] ]
parse_result = list(ini_parser.parse(input_text)) parse_result = list(ini_parser.parse(input_text))
@ -60,16 +55,12 @@ class TestCalculateIni:
"varval1 = value1\n") "varval1 = value1\n")
parsed_lines = [{'start_section': (['section', 'sub'],)}, parsed_lines = [{'start_section': (['section', 'sub'],)},
{'define_key': (['section', 'sub'], {'define_key': ('varval1', 'value1', Define.assign)},
'varval1', 'value1', Define.assign)}, {'define_key': ('varval2', 'value2', Define.assign)},
{'define_key': (['section', 'sub'],
'varval2', 'value2', Define.assign)},
{'start_section': (['section', 'sub2'],)}, {'start_section': (['section', 'sub2'],)},
{'define_key': (['section', 'sub2'], {'define_key': ('varval1', 'value1', Define.assign)},
'varval1', 'value1', Define.assign)},
{'start_section': (['section2'],)}, {'start_section': (['section2'],)},
{'define_key': (['section2'], 'varval1', {'define_key': ('varval1', 'value1', Define.assign)}]
'value1', Define.assign)}]
parse_result = list(ini_parser.parse(input_text)) parse_result = list(ini_parser.parse(input_text))
for parsed_line, result_line in zip(parsed_lines, parse_result): for parsed_line, result_line in zip(parsed_lines, parse_result):
@ -92,10 +83,8 @@ class TestCalculateIni:
"[section][][sub][]\n") "[section][][sub][]\n")
parsed_lines = [{'start_section': (['section', 'sub2'],)}, parsed_lines = [{'start_section': (['section', 'sub2'],)},
{'define_key': (['section', 'sub2'], {'define_key': ('varval1', 'value1', Define.assign)},
'varval1', 'value1', Define.assign)}, {'define_key': ('varval4', 'value4', Define.assign)},
{'define_key': (['section', 'sub2'],
'varval4', 'value4', Define.assign)},
{'clear_section': (['section'],)} {'clear_section': (['section'],)}
] ]

@ -1,15 +1,22 @@
import os
import shutil
import pytest import pytest
from calculate.vars.alt_datavars import NamespaceNode, VariableNode,\ from calculate.variables.datavars import NamespaceNode, VariableNode,\
Namespace, Variable, Dependence,\ Namespace, Variable, Dependence,\
CyclicVariableError, HashType,\ CyclicVariableError, HashType,\
StringType, IntegerType, VariableType,\ StringType, IntegerType,\
VariableError, TableType, BooleanType,\ VariableType, VariableError,\
VariableTypeError, FloatType, ListType TableType, BooleanType,\
from calculate.vars.alt_vars_loader import NamespaceIniFiller, VariableLoader VariableTypeError, FloatType,\
ListType
from calculate.variables.loader import NamespaceIniFiller, Datavars
from calculate.utils.files import stderr_devnull from calculate.utils.files import stderr_devnull
@pytest.mark.alt_vars TESTFILES_PATH = os.path.join(os.getcwd(), 'tests/variables/testfiles')
@pytest.mark.vars
class TestNamespace: class TestNamespace:
# Сначала тестируем классы и методы необходимые для построения дерева # Сначала тестируем классы и методы необходимые для построения дерева
# переменных и пространств имен. # переменных и пространств имен.
@ -364,7 +371,7 @@ class TestNamespace:
Namespace.reset() Namespace.reset()
with Namespace('namespace_1'): with Namespace('namespace_1'):
Variable('var_1', source='value_1', type=StringType, readonly=True) Variable('var_1', source='value_1', type=StringType.readonly)
with Namespace('namespace_1'): with Namespace('namespace_1'):
with pytest.raises(VariableError): with pytest.raises(VariableError):
@ -520,6 +527,47 @@ class TestNamespace:
assert datavars.namespace_1.var_4.key_2 == 'other_value' assert datavars.namespace_1.var_4.key_2 == 'other_value'
assert datavars.namespace_1.var_4.key_3 == 'another_value' assert datavars.namespace_1.var_4.key_3 == 'another_value'
def test_if_hash_variable_is_created_as_not_fixed_and_then_changed_using_dictionary_with_a_new_key__the_hash_adds_a_new_key_to_the_first_hash(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', type=HashType, source={'key_1': 'value_1',
'key_2': 'value_2'})
assert datavars.namespace_1.var_1.key_1 == 'value_1'
assert datavars.namespace_1.var_1.key_2 == 'value_2'
with Namespace('namespace_1'):
Variable('var_1', source={'key_1': 'another_value',
'key_2': 'other_value',
'key_3': 'new_value'})
assert datavars.namespace_1.var_1.key_1 == 'another_value'
assert datavars.namespace_1.var_1.key_2 == 'other_value'
assert datavars.namespace_1.var_1.key_3 == 'new_value'
def test_if_hash_variable_is_created_as_fixed_and_then_changed_using_dictionary_with_a_new_key__the_hash_raises_the_VariableError_exception(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', type=HashType.fixed, source={'key_1': 'value_1',
'key_2': 'value_2'})
assert datavars.namespace_1.var_1.key_1 == 'value_1'
assert datavars.namespace_1.var_1.key_2 == 'value_2'
with Namespace('namespace_1'):
Variable('var_1', source={'key_1': 'another_value',
'key_2': 'other_value',
'key_3': 'new_value'})
assert datavars.namespace_1['var_1'].fixed
with pytest.raises(VariableError):
datavars.namespace_1.var_1.key_1
def test_if_variable_is_created_with_dependence_and_one_of_arguments_of_a_depend_function_is_whole_hash__the_variable_will_set_this_argument_as_dictionary_of_the_whole_hash_in_a_depend_function(self): def test_if_variable_is_created_with_dependence_and_one_of_arguments_of_a_depend_function_is_whole_hash__the_variable_will_set_this_argument_as_dictionary_of_the_whole_hash_in_a_depend_function(self):
Namespace.reset() Namespace.reset()
datavars = Namespace.datavars datavars = Namespace.datavars
@ -568,7 +616,7 @@ class TestNamespace:
datavars = Namespace.datavars datavars = Namespace.datavars
with Namespace('main'): with Namespace('main'):
Variable('chroot', source='/', type=StringType, readonly=True) Variable('chroot', source='/', type=StringType.readonly)
with Namespace('os'): with Namespace('os'):
def source_function(chroot_path): def source_function(chroot_path):
@ -901,22 +949,33 @@ value = another_value
{'name': 'common_name', 'value': 'another_value'}, {'name': 'common_name', 'value': 'another_value'},
{'name': 'name_3', 'value': 'value_3'}] {'name': 'name_3', 'value': 'value_3'}]
def test_loader(self): def test_if_a_Datavars_object_is_created_with_path_to_the_variables_without_any_Dependencies_and_then_used_to_get_access_to_the_some_variables_from__the_datavars_object_dynamically_loads_variables_and_retruns_necessary_variables(self):
Namespace.reset() datavars = Datavars(
loader = VariableLoader() variables_path='tests/variables/testfiles/variables_0',
datavars = loader.load_variables('tests/vars/testfiles/variables_0') repository_map={})
assert datavars.os.ns.var_1 == 'value_1' assert datavars.os.ns.var_1 == 'value_1'
assert datavars.os.ns.var_2 == 2 assert datavars.os.ns.var_2 == 2
assert 'main' not in datavars.root
assert datavars.main.strange_variable == 'weird_value' assert datavars.main.strange_variable == 'weird_value'
assert datavars.main.plain_variable is True assert datavars.main.plain_variable is True
assert 'main' in datavars.root
def test_loader_2(self): def test_if_a_Datavars_object_is_created_with_path_to_the_variables_with_some_Dependencies_and_then_used_to_get_access_to_the_some_variables_from__the_datavars_object_dynamically_loads_variables_and_retruns_necessary_variables(self):
Namespace.reset() datavars = Datavars(
loader = VariableLoader() variables_path='tests/variables/testfiles/variables_1',
datavars = loader.load_variables('tests/vars/testfiles/variables_1') repository_map={})
assert datavars.main.chroot == '/' assert datavars.main.chroot == '/'
assert 'os' not in datavars.root
assert datavars.os.calculate == 'test1 test2'
assert 'os' in datavars.root
assert datavars.level.level_2.vargetter == '/ test'
assert 'main' in datavars.root
assert datavars.level.simple == "simple value" assert datavars.level.simple == "simple value"
assert datavars.level.use_local_simple == "Using simple value" assert datavars.level.use_local_simple == "Using simple value"
assert datavars.level.use_full_simple == "Using simple value" assert datavars.level.use_full_simple == "Using simple value"
@ -927,3 +986,52 @@ value = another_value
{"dev": "/dev/sdb", {"dev": "/dev/sdb",
"type": "flash", "type": "flash",
"name": "Transcend 64GB"}] "name": "Transcend 64GB"}]
def test_if_a_Datavars_object_is_created_with_path_to_the_variables_with_Dependencies_and_then_the_variables_are_changed_using_calculate_ini_files_and_the_datavars_object_used_to_get_access_to_the_some_variables_from__the_datavars_object_dynamically_loads_variables_and_retruns_necessary_variables(self):
datavars = Datavars(
variables_path='tests/variables/testfiles/variables_4',
repository_map={})
assert datavars.main.chroot == '/'
assert 'os' not in datavars.root
assert datavars.level.level_2.vargetter == '/ test'
assert 'main' in datavars.root
assert datavars.level.simple == "simple value"
datavars._loader.fill_from_custom_ini(os.path.join(TESTFILES_PATH,
'calculate_0.ini'))
assert 'os' in datavars.root
assert datavars.level.simple == 'weird value'
assert datavars.main.chroot == '/any/other/path'
assert datavars.level.level_2.vargetter == '/any/other/path test'
def test_to_make_testfiles(self):
shutil.copytree(os.path.join(TESTFILES_PATH, 'gentoo.backup'),
os.path.join(TESTFILES_PATH, 'gentoo'),
symlinks=True)
def test_ini_loader(self):
repository_map = {'distros': os.path.join(TESTFILES_PATH,
"gentoo/repos/distros"),
'calculate': os.path.join(TESTFILES_PATH,
"gentoo/repos/calculate"),
'gentoo': os.path.join(TESTFILES_PATH,
"gentoo/portage")}
datavars = Datavars(
variables_path=os.path.join(TESTFILES_PATH, 'variables_2'),
repository_map=repository_map)
def test_get_repository_map(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 False
def test_for_removing_testfile(self):
shutil.rmtree(os.path.join(TESTFILES_PATH, 'gentoo'))

@ -0,0 +1,9 @@
[main]
chroot = /any/other/path
[level]
simple = weird value
[os][linux]
fullname = full_name
shortname = SN

@ -0,0 +1,21 @@
[os][linux]
ver = 20
shortname = CLD
fullname = Calculate Linux Desktop
subname = KDE
[os][hashvar]
value1 = 20
value2 = 30
[os][tablevar][0]
dev = /dev/sda1
mount = swap
[os][tablevar][1]
dev = /dev/sda2
mount = /
[os][tablevar][2]
dev = /dev/sda5
mount = /var/calculate

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

@ -0,0 +1,6 @@
from calculate.variables.datavars import Namespace, Variable, StringType,\
IntegerType, BooleanType
Variable('strange_variable', source='weird_value', type=StringType)
Variable('plain_variable', source=True, type=BooleanType)

@ -1,5 +1,5 @@
from calculate.vars.alt_datavars import Namespace, Variable, StringType,\ from calculate.variables.datavars import Namespace, Variable, StringType,\
IntegerType IntegerType
with Namespace('ns'): with Namespace('ns'):
Variable('var_1', source='value_1', type=StringType) Variable('var_1', source='value_1', type=StringType)

@ -1,6 +1,6 @@
from calculate.vars.alt_datavars import Namespace, Variable, Dependence,\ from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType,\ StringType, HashType, TableType,\
ListType, FloatType ListType, FloatType
Variable('simple', type=StringType, source='simple value') Variable('simple', type=StringType, source='simple value')

@ -1,4 +1,4 @@
from calculate.vars.alt_datavars import Variable, StringType, Dependence from calculate.variables.datavars import Variable, StringType, Dependence
Variable('vargetter', type=StringType, Variable('vargetter', type=StringType,

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

@ -1,4 +1,4 @@
from calculate.vars.alt_datavars import Namespace, Variable, Dependence,\ from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType StringType, HashType, TableType
with Namespace('linux'): with Namespace('linux'):
@ -27,8 +27,10 @@ Variable('hashvar', source={'value1': 'test1',
'value2': 'test2'}, type=HashType) 'value2': 'test2'}, type=HashType)
Variable('calculate', type=StringType, Variable('calculate', type=StringType,
source=lambda hashvar: "{} {}".format(hashvar.value['value1'], source=Dependence('.hashvar',
hashvar.value['value2'])) depend=lambda hashvar: "{} {}".format(
hashvar.value['value1'],
hashvar.value['value2'])))
Variable('tablevar', type=TableType, source=[{"dev": "/dev/sdb1", Variable('tablevar', type=TableType, source=[{"dev": "/dev/sdb1",
"mount": "/"}, "mount": "/"},

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

@ -0,0 +1,38 @@
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)
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,4 @@
from calculate.variables.datavars import Variable, StringType
Variable('chroot', type=StringType, source='/')

@ -0,0 +1,38 @@
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)
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,62 @@
from calculate.variables.datavars import Namespace, Variable, Dependence,\
StringType, HashType, TableType,\
ListType, FloatType
Variable('simple', type=StringType, source='simple value')
Variable('use_local_simple', type=StringType,
source=Dependence('.simple',
depend=lambda simple: 'Using {}'.format(
simple.value)))
Variable('use_full_simple', type=StringType,
source=Dependence('level.simple',
depend=lambda simple: 'Using {}'.format(
simple.value)))
Variable('disks', type=ListType,
source=["/dev/sda1", "/dev/sda2", "/dev/sda3"])
Variable('version', type=FloatType, source='1.0')
Variable('my_shortname', type=StringType, source='CLD')
Variable('linux', type=HashType,
source=Dependence('.version', '.my_shortname',
depend=lambda version, my_shortname:
{'version': version.value,
'shortname': my_shortname.value}))
Variable('shortname_test', type=StringType,
source=Dependence('.linux.shortname',
depend=lambda shortname: '{} test'.format(
shortname.value)))
Variable('device_list', type=ListType,
source=["/dev/sda", "/dev/sdb"])
def get_device_table(device_list):
map_data = {'/dev/sda': ["hdd", "Samsung SSD"],
'/dev/sdb': ["flash", "Transcend 64GB"],
'/dev/sdc': ["usbhdd", "WD 1TB"]}
default_value = ["hdd", "Unknown"]
print('device_list = {}'.format(device_list.value))
return [{"dev": device,
"type": map_data.get(device, default_value)[0],
"name": map_data.get(device, default_value)[1]}
for device in device_list.value]
Variable('device', type=TableType, source=Dependence('.device_list',
depend=get_device_table))
Variable('device_child', type=StringType,
source=Dependence('.device',
depend=lambda device: device.value[0]['type']))
with Namespace('level_3'):
Variable('my_var_1', type=StringType, source='testing')
Variable('my_var_2', type=StringType, source='testing_2')

@ -0,0 +1,7 @@
from calculate.variables.datavars import Variable, StringType, Dependence
Variable('vargetter', type=StringType,
source=Dependence('main.chroot',
depend=lambda chroot:
'{} test'.format(chroot.value)))

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

@ -0,0 +1,38 @@
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)
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"}])

@ -1,6 +0,0 @@
from calculate.vars.alt_datavars import Namespace, Variable, StringType,\
IntegerType, BooleanType
Variable('strange_variable', source='weird_value', type=StringType)
Variable('plain_variable', source=True, type=BooleanType)

@ -1,5 +0,0 @@
from calculate.vars.alt_datavars import Variable, StringType
Variable('chroot', type=StringType, source='/', readonly=True)
print('chroot really created')
Loading…
Cancel
Save