'handler' and 'notify' parameters are added.

handlers
Иванов Денис 4 years ago
parent 3276a63859
commit 6561bb2c00

@ -54,11 +54,19 @@ class Variables(MutableMapping):
def __getattribute__(self, name):
if name == '_Variables__attrs':
return super().__getattribute__(name)
if name == 'available_packages':
return super().__getattribute__(name)
try:
return self.__attrs[name]
except KeyError:
raise AttributeError(name)
@property
def available_packages(self):
packages = set(self.__attrs.keys())
packages.update({'custom'})
return packages
def __getitem__(self, name):
return self.__attrs[name]
@ -84,7 +92,8 @@ class ParametersProcessor:
'autoupdate', 'env', 'force', 'source', 'format',
'unbound', 'mirror', 'run', 'exec', 'env',
'package', 'merge', 'postmerge', 'action',
'rebuild', 'restart', 'stop', 'start'}
'rebuild', 'restart', 'stop', 'start', 'handler',
'notify'}
inheritable_parameters = {'chmod', 'chown', 'autoupdate', 'env',
'package', 'action'}
@ -135,7 +144,10 @@ class ParametersProcessor:
'source': self.check_source_parameter,
'force': self.check_force_parameter,
'env': self.check_env_parameter,
'merge': self.check_merge_parameter
'merge': self.check_merge_parameter,
'format': self.check_format_parameter,
'handler': self.check_handler_parameter,
'notify': self.check_notify_parameter
})
# Если добавляемый параметр должен быть проверен после того, как
@ -297,13 +309,6 @@ class ParametersProcessor:
raise IncorrectParameter(
"'restart' parameter value is not correct")
def check_format_parameter(self, parameter_value):
if parameter_value in self.available_formats:
return parameter_value
else:
raise IncorrectParameter(
"'format' parameter value is not available")
def check_stop_parameter(self, parameter_value):
if not parameter_value and isinstance(parameter_value, bool):
raise IncorrectParameter("'stop' parameter value is empty")
@ -426,7 +431,35 @@ class ParametersProcessor:
return parameter_value
else:
raise IncorrectParameter(
"'autoupdate' parameter value is not bool")
"'autoupdate' parameter value is not bool.")
def check_format_parameter(self, parameter_value):
if self.template_type == DIR:
raise IncorrectParameter("'format' parameter is redundant for"
" directory templates.")
if isinstance(parameter_value, str):
if parameter_value not in self.available_formats:
raise IncorrectParameter(f"'{parameter_value}' value of the"
" 'format' parameter is not"
" available.")
return parameter_value
raise IncorrectParameter("'format' parameter must be string value not"
f" {type(parameter_value)}.")
def check_handler_parameter(self, parameter_value):
if isinstance(parameter_value, str):
return parameter_value
raise IncorrectParameter("'handler' parameter must be string"
f" value not {type(parameter_value)}.")
def check_notify_parameter(self, parameter_value):
if isinstance(parameter_value, list):
return parameter_value
elif isinstance(parameter_value, str):
return [parameter.strip() for parameter in
parameter_value.split(',')]
raise IncorrectParameter("'notify' parameter must be string or list"
f" value not {type(parameter_value)}.")
# Методы для проверки параметров после разбора всего шаблона.
@ -879,7 +912,7 @@ class CalculateExtension(Extension):
check_template_node)
check_template.render(__datavars__=self._datavars)
elif (self.stream.current.type == 'name'
elif (self._is_variable_name(self.stream.current)
or self.stream.current.type == 'lparen'
or self.stream.current.type == 'integer'):
# разбираем условие. Если условие False -- кидаем исключение.
@ -887,9 +920,16 @@ class CalculateExtension(Extension):
if not condition_result:
raise ConditionFailed('Condition is failed',
lineno=self.stream.current.lineno)
elif self.stream.current.type == 'name':
raise TemplateSyntaxError(
f"Unknown identifier '{self.stream.current.value}'"
" in calculate tag.",
lineno=self.stream.current.lineno)
else:
raise TemplateSyntaxError('Name is expected in calculate tag.',
lineno=self.stream.current.lineno)
raise TemplateSyntaxError(
f"Can not parse token '{self.stream.current.value}'"
" in caluculate tag.",
lineno=self.stream.current.lineno)
expect_comma_flag = True
# dictionary_node = nodes.Dict(pairs_list)
@ -901,6 +941,17 @@ class CalculateExtension(Extension):
return nodes.Output([nodes.Const('')], lineno=lineno)
def _is_variable_name(self, token):
if not token.type == 'name':
return False
if (token.value in self._datavars.available_packages or
token.value in self.environment.globals):
return True
for env in self.environment.context_class._env_set:
if token.value in self._datavars[env]:
return True
return False
def check_parameter(self, parameter_name, parameter_value, context):
self.parameters_processor.check_template_parameter(
parameter_name,
@ -913,6 +964,7 @@ class CalculateExtension(Extension):
'''Метод для разбора условий из тега calculate.'''
# лучший способ -- парсим в AST дерево, после чего компилируем и
# выполняем его.
print('GET CONDITION')
self.condition_result = False
try:
@ -929,9 +981,11 @@ class CalculateExtension(Extension):
template = self.environment.from_string(condition_template)
template.render(__datavars__=self._datavars)
except Exception:
except Exception as error:
print('Error during running condition:', str(error))
return False
print('condition result:', self.condition_result)
return self.condition_result
# собираем исходный код условия из токенов.
@ -1210,7 +1264,7 @@ class CalculateExtension(Extension):
# контекста вo время парсинга.
env_names = parameter_value.split(',')
for name in env_names:
CalculateContext._env_set.add(name.strip())
self.environment.context_class._env_set.add(name.strip())
else:
parameter_rvalue = nodes.Const(True, lineno=lineno)
parameter_value = True

@ -213,9 +213,10 @@ class TemplateWrapper:
if self.parameters.format:
self.format_class = ParametersProcessor.\
available_formats[self.parameters.format]
else:
elif self.template_type is FILE:
# TODO Здесь будет детектор форматов. Когда-нибудь.
pass
raise TemplateExecutorError("'format' parameter is not set"
" file template.")
# Если по этому пути что-то есть -- проверяем конфликты.
if os.path.exists(target_file_path):
@ -1687,6 +1688,9 @@ class DirectoryProcessor:
# Словарь для хранения деревьев директорий для различных пакетов.
self.packages_file_trees = {}
# Список обработчиков.
self.handlers = OrderedDict()
def _get_cl_ignore_files(self) -> list:
'''Метод для получения из соответствующей переменной списка паттернов
для обнаружения игнорируемых в ходе обработки шаблонов файлов.'''
@ -1941,7 +1945,7 @@ class DirectoryProcessor:
# Если в данный момент обходим дерево -- берем список файлов и
# директорий из него.
if not self.fill_trees and directory_tree:
template_directories, template_file =\
template_directories, template_files =\
self._get_files_and_dirs_from_tree(template_files,
template_directories,
directory_tree)
@ -2229,6 +2233,10 @@ class DirectoryProcessor:
template_path))
return False
if parameters.handler:
self.handlers.update({parameters.handler: template_path})
return False
if self.for_package:
if not parameters.package:
if self.for_package is not NonePackage:

@ -749,13 +749,20 @@ class Datavars:
def _load_package(self, package_name):
'''Метод для загрузки переменных содержащихся в указанном пакете.'''
self.output.set_info("Loading datavars package '{}'".format(package_name))
self.output.set_info("Loading datavars package '{}'".format(
package_name))
try:
self._loader.load_variables_package(package_name)
except Exception as error:
raise VariableError("Can not load datavars package: {}".
format(error))
@property
def available_packages(self):
packages = set(self._available_packages)
packages.update({'custom'})
return packages
def __getattr__(self, package_name: str):
'''Метод возвращает ноду пространства имен, соответствующего искомому
пакету.'''

@ -894,6 +894,30 @@ class TestDirectoryProcessor:
'etc/dir_35/file_0'))
assert '/etc/dir_35/file_0' in test_package
def test_handlers_basic(self):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
'templates_35')
directory_processor = DirectoryProcessor(
'install',
datavars_module=datavars,
package='test-category/test-package'
)
directory_processor.process_template_directories()
test_package = Package(test_package_name, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_37'))
assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_37/file_0'))
assert '/etc/dir_37/file_0' in test_package
assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_38'))
assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_38/file_0'))
assert '/etc/dir_38/file_0' in other_package
def test_view_tree(self):
list_path = join_paths(CHROOT_PATH, '/etc')
show_tree(list_path)

@ -0,0 +1 @@
{% calculate append = 'skip', path = '/etc', action = 'install' %}

@ -0,0 +1 @@
{% calculate append = 'join', package = 'test-category/test-package' %}

@ -0,0 +1,5 @@
{% calculate append = 'join', format = 'bind', notify = 'handler_0' %}
options {
parameter-1 {{ variables.variable_1 }};
parameter-2 {{ variables.variable_2 }};
};

@ -0,0 +1 @@
{% calculate append = 'join', package = 'test-category/other-package' %}

@ -0,0 +1,5 @@
{% calculate append = 'join', format = 'bind' %}
options {
parameter-1 {{ variables.variable_1 }};
parameter-2 {{ variables.variable_2 }};
};

@ -0,0 +1,3 @@
{% calculate handler = 'handler_0', merge = 'test-category/other-package',
run = '/usr/bin/python' %}
print('This handler is needed for merging test-category.')
Loading…
Cancel
Save