|
|
|
@ -18,7 +18,9 @@ from ..utils.package import PackageAtomParser, PackageAtomError, NOTEXIST,\
|
|
|
|
|
from ..utils.files import join_paths, check_directory_link, check_command,\
|
|
|
|
|
FilesError
|
|
|
|
|
from calculate.variables.datavars import HashType, NamespaceNode,\
|
|
|
|
|
VariableNode, IniType
|
|
|
|
|
VariableNode, IniType, IntegerType,\
|
|
|
|
|
FloatType, ListType,\
|
|
|
|
|
VariableNotFoundError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Типы шаблона: директория или файл.
|
|
|
|
@ -755,6 +757,9 @@ class CalculateExtension(Extension):
|
|
|
|
|
|
|
|
|
|
parameters_processor = None
|
|
|
|
|
|
|
|
|
|
# Виды операций в теге save.
|
|
|
|
|
ASSIGN, APPEND, REMOVE = range(3)
|
|
|
|
|
|
|
|
|
|
def __init__(self, environment, datavars_module=Variables()):
|
|
|
|
|
super().__init__(environment)
|
|
|
|
|
self.environment = environment
|
|
|
|
@ -767,7 +772,12 @@ class CalculateExtension(Extension):
|
|
|
|
|
self.tags = {'calculate', 'save', 'set_var'}
|
|
|
|
|
self.CONDITION_TOKENS_TYPES = {'eq', 'ne', 'lt', 'gt', 'lteq', 'gteq'}
|
|
|
|
|
self.LITERAL_TOKENS_TYPES = {'string', 'integer', 'float'}
|
|
|
|
|
self.TARGET_FILES_SET = {'grp', 'system', 'etc', 'local', 'remote'}
|
|
|
|
|
|
|
|
|
|
if hasattr(self._datavars, 'variables_to_save'):
|
|
|
|
|
self.TARGET_FILES_SET =\
|
|
|
|
|
set(self._datavars.variables_to_save.keys())
|
|
|
|
|
else:
|
|
|
|
|
self.TARGET_FILES_SET = set()
|
|
|
|
|
|
|
|
|
|
self.parse_methods = {'calculate': self.parse_calculate,
|
|
|
|
|
'save': self.parse_save}
|
|
|
|
@ -794,9 +804,9 @@ class CalculateExtension(Extension):
|
|
|
|
|
if target_file_name in self.TARGET_FILES_SET:
|
|
|
|
|
target_file = nodes.Const(target_file_name)
|
|
|
|
|
else:
|
|
|
|
|
TemplateSyntaxError("Unknown target file '{}'".
|
|
|
|
|
format(target_file_name),
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
raise TemplateSyntaxError("Unknown target file '{}'".
|
|
|
|
|
format(target_file_name),
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
|
|
|
|
|
# получаем список из имени переменной.
|
|
|
|
|
module_name = self.stream.expect('name').value
|
|
|
|
@ -807,17 +817,22 @@ class CalculateExtension(Extension):
|
|
|
|
|
variable_name = nodes.List(variable_name, lineno=lineno)
|
|
|
|
|
|
|
|
|
|
if self.stream.skip_if('assign'):
|
|
|
|
|
right_value = self.parser.parse_expression(with_condexpr=True)
|
|
|
|
|
save_variable_node = self.call_method('save_variable',
|
|
|
|
|
[variable_name,
|
|
|
|
|
right_value,
|
|
|
|
|
target_file,
|
|
|
|
|
nodes.ContextReference()],
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
return nodes.Output([save_variable_node], lineno=lineno)
|
|
|
|
|
else:
|
|
|
|
|
TemplateSyntaxError("'=' is expected in 'save' tag.",
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
return self._make_save_node(variable_name,
|
|
|
|
|
target_file,
|
|
|
|
|
self.ASSIGN,
|
|
|
|
|
lineno)
|
|
|
|
|
elif self.stream.skip_if('add') and self.stream.skip_if('assign'):
|
|
|
|
|
return self._make_save_node(variable_name,
|
|
|
|
|
target_file,
|
|
|
|
|
self.APPEND,
|
|
|
|
|
lineno)
|
|
|
|
|
elif self.stream.skip_if('sub') and self.stream.skip_if('assign'):
|
|
|
|
|
return self._make_save_node(variable_name,
|
|
|
|
|
target_file,
|
|
|
|
|
self.REMOVE,
|
|
|
|
|
lineno)
|
|
|
|
|
raise TemplateSyntaxError("'=' is expected in 'save' tag",
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
|
|
|
|
|
def parse_calculate(self):
|
|
|
|
|
'''Метод для разбора тега calculate, содержащего значения параметров и
|
|
|
|
@ -940,18 +955,34 @@ class CalculateExtension(Extension):
|
|
|
|
|
# return condition_result
|
|
|
|
|
|
|
|
|
|
def set_condition_result(self, condition_result):
|
|
|
|
|
'''Метод для сохранения результата вычисления условия.'''
|
|
|
|
|
self.condition_result = condition_result
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
|
|
def save_variable(self, variable, right_value, target_file, context):
|
|
|
|
|
def _make_save_node(self, variable_name_node, target_file_node, optype,
|
|
|
|
|
lineno):
|
|
|
|
|
'''Метод для создания ноды, сохраняющей переменные.'''
|
|
|
|
|
right_value = self.parser.parse_expression(with_condexpr=True)
|
|
|
|
|
optype_node = nodes.Const(optype, lineno=lineno)
|
|
|
|
|
save_variable_node = self.call_method('save_variable',
|
|
|
|
|
[variable_name_node,
|
|
|
|
|
right_value,
|
|
|
|
|
target_file_node,
|
|
|
|
|
optype_node,
|
|
|
|
|
nodes.ContextReference()],
|
|
|
|
|
lineno=lineno)
|
|
|
|
|
return nodes.Output([save_variable_node], lineno=lineno)
|
|
|
|
|
|
|
|
|
|
def save_variable(self, variable, right_value, target_file,
|
|
|
|
|
optype, context):
|
|
|
|
|
'''Метод для сохранения значений переменных указанных в теге save.'''
|
|
|
|
|
datavars = context.parent['__datavars__']
|
|
|
|
|
print('DATAVARS: {}'.format(datavars))
|
|
|
|
|
print('VARIABLE NAME: {}'.format(variable))
|
|
|
|
|
print('RIGHT VALUE: {}'.format(right_value))
|
|
|
|
|
optypes = {self.ASSIGN: '=', self.APPEND: '+=', self.REMOVE: '-='}
|
|
|
|
|
print('SAVE VARIABLE: {} {} {}'.format('.'.join(variable),
|
|
|
|
|
optypes[optype],
|
|
|
|
|
right_value))
|
|
|
|
|
print('TARGET FILE: {}'.format(target_file))
|
|
|
|
|
if variable[0] not in datavars:
|
|
|
|
|
# TODO продумать получше ошибку.
|
|
|
|
|
raise SaveError("can not save variable '{}'. The variable's"
|
|
|
|
|
" package '{}' is not found".format(
|
|
|
|
|
'.'.join(variable),
|
|
|
|
@ -961,6 +992,9 @@ class CalculateExtension(Extension):
|
|
|
|
|
current_container = datavars[variable[0]]
|
|
|
|
|
variable_path = variable[1:]
|
|
|
|
|
variable_name = variable_path.pop()
|
|
|
|
|
|
|
|
|
|
# Ищем пространство имен или в хэш, в котором должна быть переменная
|
|
|
|
|
# или значение.
|
|
|
|
|
for section in variable_path:
|
|
|
|
|
if section in current_container.namespaces:
|
|
|
|
|
current_container = current_container.namespaces[section]
|
|
|
|
@ -985,23 +1019,136 @@ class CalculateExtension(Extension):
|
|
|
|
|
section,
|
|
|
|
|
current_container.get_fullname()))
|
|
|
|
|
|
|
|
|
|
# Теперь меняем знaчение переменной.
|
|
|
|
|
if isinstance(current_container, NamespaceNode):
|
|
|
|
|
if variable_name in current_container.variables:
|
|
|
|
|
current_container[variable_name].set(right_value)
|
|
|
|
|
variable_node = current_container[variable_name]
|
|
|
|
|
if optype == self.ASSIGN:
|
|
|
|
|
variable_node.set(right_value)
|
|
|
|
|
elif optype == self.APPEND:
|
|
|
|
|
new_value = self._append_variable_value(variable_node,
|
|
|
|
|
right_value)
|
|
|
|
|
variable_node.set(new_value)
|
|
|
|
|
elif optype == self.REMOVE:
|
|
|
|
|
new_value = self._remove_variable_value(variable_node,
|
|
|
|
|
right_value)
|
|
|
|
|
variable_node.set(new_value)
|
|
|
|
|
|
|
|
|
|
if target_file:
|
|
|
|
|
self.save_to_target(variable[:-1], variable_name,
|
|
|
|
|
new_value, target_file)
|
|
|
|
|
elif not modify_only:
|
|
|
|
|
VariableNode(variable_name, current_container,
|
|
|
|
|
variable_type=IniType, source=str(right_value))
|
|
|
|
|
|
|
|
|
|
if target_file:
|
|
|
|
|
self.save_to_target(variable[:-1], variable_name,
|
|
|
|
|
right_value, target_file)
|
|
|
|
|
else:
|
|
|
|
|
raise SaveError("can not create variable '{}' in the not"
|
|
|
|
|
" 'custom' namespace".
|
|
|
|
|
format('.'.join(variable)))
|
|
|
|
|
elif isinstance(current_container, VariableNode):
|
|
|
|
|
hash_value = current_container.get_value().get_hash()
|
|
|
|
|
hash_value.update({variable_name: right_value})
|
|
|
|
|
if variable_name in hash_value:
|
|
|
|
|
if optype == self.ASSIGN:
|
|
|
|
|
new_value = right_value
|
|
|
|
|
elif optype == self.APPEND:
|
|
|
|
|
new_value = new_value + right_value
|
|
|
|
|
elif optype == self.REMOVE:
|
|
|
|
|
new_value = new_value - right_value
|
|
|
|
|
else:
|
|
|
|
|
new_value = right_value
|
|
|
|
|
|
|
|
|
|
hash_value.update({variable_name: new_value})
|
|
|
|
|
current_container.set(hash_value)
|
|
|
|
|
if target_file:
|
|
|
|
|
self.save_to_target(variable[:-1], variable_name,
|
|
|
|
|
new_value, target_file)
|
|
|
|
|
print('VARIABLE IS SAVED')
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
|
|
def save_to_target(self, namespace_name, variable_name, value, target):
|
|
|
|
|
namespace_name = tuple(namespace_name)
|
|
|
|
|
target_file_dict = self._datavars.variables_to_save[target]
|
|
|
|
|
if namespace_name not in target_file_dict:
|
|
|
|
|
target_file_dict.update({namespace_name: dict()})
|
|
|
|
|
target_file_dict[namespace_name].update(
|
|
|
|
|
{variable_name: ('=', str(value))})
|
|
|
|
|
|
|
|
|
|
def _append_variable_value(self, variable, value):
|
|
|
|
|
'''Метод описывающий операцию += в теге save.'''
|
|
|
|
|
variable_value = variable.get_value()
|
|
|
|
|
if (variable.variable_type is IntegerType or
|
|
|
|
|
variable.variable_type is FloatType):
|
|
|
|
|
variable_value += value
|
|
|
|
|
return variable_value
|
|
|
|
|
elif variable.variable_type is ListType:
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
|
value = value.split(',')
|
|
|
|
|
if isinstance(value, list):
|
|
|
|
|
for item in value:
|
|
|
|
|
if item not in variable_value:
|
|
|
|
|
variable_value.append(item)
|
|
|
|
|
else:
|
|
|
|
|
variable_value.append(value)
|
|
|
|
|
return variable_value
|
|
|
|
|
elif variable.variable_type is IniType:
|
|
|
|
|
if not isinstance(variable_value, str):
|
|
|
|
|
variable_value = str(variable_value)
|
|
|
|
|
variable_value = variable_value.split(',')
|
|
|
|
|
|
|
|
|
|
if not isinstance(value, list):
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
|
value = value.split(',')
|
|
|
|
|
else:
|
|
|
|
|
value = str(value).split(',')
|
|
|
|
|
|
|
|
|
|
for item in value:
|
|
|
|
|
if item not in variable_value:
|
|
|
|
|
variable_value.append(item)
|
|
|
|
|
return ','.join(variable_value)
|
|
|
|
|
# Пока что во всех остальных случаях будем просто возвращать исходное
|
|
|
|
|
# значение.
|
|
|
|
|
return variable_value
|
|
|
|
|
|
|
|
|
|
def _remove_variable_value(self, variable, value):
|
|
|
|
|
'''Метод описывающий операцию -= в теге save.'''
|
|
|
|
|
variable_value = variable.get_value()
|
|
|
|
|
if (variable.variable_type is IntegerType or
|
|
|
|
|
variable.variable_type is FloatType):
|
|
|
|
|
variable_value -= value
|
|
|
|
|
return variable_value
|
|
|
|
|
elif variable.variable_type is ListType:
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
|
value = value.split(',')
|
|
|
|
|
if isinstance(value, list):
|
|
|
|
|
for item in value:
|
|
|
|
|
if item in variable_value:
|
|
|
|
|
variable_value.remove(item)
|
|
|
|
|
elif value in variable_value:
|
|
|
|
|
variable_value.remove(value)
|
|
|
|
|
return variable_value
|
|
|
|
|
elif variable.variable_type is IniType:
|
|
|
|
|
if not isinstance(variable_value, list):
|
|
|
|
|
if not isinstance(variable_value, str):
|
|
|
|
|
variable_value = str(variable_value)
|
|
|
|
|
variable_value = variable_value.split(',')
|
|
|
|
|
|
|
|
|
|
if not isinstance(value, list):
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
|
value = value.split(',')
|
|
|
|
|
else:
|
|
|
|
|
value = str(value).split(',')
|
|
|
|
|
|
|
|
|
|
for item in value:
|
|
|
|
|
if item in variable_value:
|
|
|
|
|
variable_value.remove(item)
|
|
|
|
|
return ','.join(variable_value)
|
|
|
|
|
# Пока что во всех остальных случаях будем просто возвращать исходное
|
|
|
|
|
# значение.
|
|
|
|
|
return variable_value
|
|
|
|
|
|
|
|
|
|
def get_parameter(self):
|
|
|
|
|
'''Метод для разбра параметров, содержащихся в теге calculate.'''
|
|
|
|
|
lineno = self.stream.current.lineno
|
|
|
|
|