|
|
@@ -1,12 +1,15 @@ |
|
|
|
# vim: fileencoding=utf-8 |
|
|
|
# |
|
|
|
from jinja2.ext import Extension |
|
|
|
from jinja2.lexer import Token |
|
|
|
from jinja2.parser import Parser |
|
|
|
from jinja2 import ( |
|
|
|
Environment, |
|
|
|
FileSystemLoader, |
|
|
|
TemplateSyntaxError, |
|
|
|
nodes, |
|
|
|
contextfunction |
|
|
|
contextfunction, |
|
|
|
Template, |
|
|
|
) |
|
|
|
from jinja2.utils import missing |
|
|
|
from jinja2.runtime import Context, Undefined |
|
|
@@ -22,7 +25,10 @@ from typing import ( |
|
|
|
Union, |
|
|
|
Any, |
|
|
|
List, |
|
|
|
Tuple |
|
|
|
Tuple, |
|
|
|
NoReturn, |
|
|
|
Optional, |
|
|
|
Iterator, |
|
|
|
) |
|
|
|
from ..utils.package import ( |
|
|
|
PackageAtomName, |
|
|
@@ -39,6 +45,7 @@ from ..utils.files import ( |
|
|
|
FilesError |
|
|
|
) |
|
|
|
from calculate.variables.datavars import ( |
|
|
|
VariableNotFoundError, |
|
|
|
HashType, |
|
|
|
NamespaceNode, |
|
|
|
VariableNode, |
|
|
@@ -55,7 +62,6 @@ import calculate.templates.template_filters as template_filters |
|
|
|
# Типы шаблона: директория или файл. |
|
|
|
DIR, FILE, LINK = range(3) |
|
|
|
|
|
|
|
|
|
|
|
# Словарь, в котором можно регистрировать фильтры. |
|
|
|
CALCULATE_FILTERS = {"cut": template_filters.cut} |
|
|
|
|
|
|
@@ -79,19 +85,23 @@ class ConditionFailed(TemplateSyntaxError): |
|
|
|
class Variables(MutableMapping): |
|
|
|
'''Класс-заглушка вместо модуля переменных для тестов.''' |
|
|
|
def __init__(self, *args, **kwargs): |
|
|
|
self.__attrs = dict(*args, **kwargs) |
|
|
|
self.__attrs: dict = dict(*args, **kwargs) |
|
|
|
self.__iter: Union[Iterator, None] = None |
|
|
|
|
|
|
|
def __next__(self): |
|
|
|
iterator = iter(self.__attrs) |
|
|
|
return next(iterator) |
|
|
|
def __next__(self) -> Any: |
|
|
|
if self._iter is None: |
|
|
|
self._iter = iter(self.__attrs) |
|
|
|
return next(self._iter) |
|
|
|
|
|
|
|
def __getattribute__(self, name: str): |
|
|
|
def __getattribute__(self, name: str) -> Any: |
|
|
|
if name == '_Variables__attrs': |
|
|
|
return super().__getattribute__(name) |
|
|
|
if name == 'available_packages': |
|
|
|
return super().__getattribute__(name) |
|
|
|
if name == '_variables': |
|
|
|
return self.__attrs |
|
|
|
if name == '_iter': |
|
|
|
return self._iter |
|
|
|
try: |
|
|
|
return self.__attrs[name] |
|
|
|
except KeyError: |
|
|
@@ -103,16 +113,16 @@ class Variables(MutableMapping): |
|
|
|
packages.update({'custom'}) |
|
|
|
return packages |
|
|
|
|
|
|
|
def __getitem__(self, name: str): |
|
|
|
def __getitem__(self, name: str) -> Any: |
|
|
|
return self.__attrs[name] |
|
|
|
|
|
|
|
def __setitem__(self, name: str, value) -> None: |
|
|
|
def __setitem__(self, name: str, value: Any) -> NoReturn: |
|
|
|
self.__attrs[name] = value |
|
|
|
|
|
|
|
def __delitem__(self, name: str) -> None: |
|
|
|
def __delitem__(self, name: str) -> NoReturn: |
|
|
|
del self.__attrs[name] |
|
|
|
|
|
|
|
def __iter__(self): |
|
|
|
def __iter__(self) -> Iterator: |
|
|
|
return iter(self.__attrs) |
|
|
|
|
|
|
|
def __len__(self) -> int: |
|
|
@@ -124,7 +134,7 @@ class Variables(MutableMapping): |
|
|
|
def __contains__(self, name: str) -> bool: |
|
|
|
return name in self.__attrs |
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
def __hash__(self) -> int: |
|
|
|
return hash(id(self)) |
|
|
|
|
|
|
|
|
|
|
@@ -135,7 +145,8 @@ class ParametersProcessor: |
|
|
|
'format', 'unbound', 'mirror', 'run', 'exec', |
|
|
|
'env', 'package', 'merge', 'postmerge', |
|
|
|
'action', 'rebuild', 'restart', 'stop', |
|
|
|
'start', 'handler', 'notify', 'group'} |
|
|
|
'start', 'handler', 'notify', 'group', |
|
|
|
'convert', 'stretch'} |
|
|
|
|
|
|
|
inheritable_parameters: set = {'chmod', 'chown', 'autoupdate', 'env', |
|
|
|
'package', 'action', 'handler', 'group'} |
|
|
@@ -158,21 +169,24 @@ class ParametersProcessor: |
|
|
|
r'([r-][w-][Xx-])([r-][w-][Xx-])([r-][w-][Xx-])') |
|
|
|
|
|
|
|
def __init__(self, |
|
|
|
parameters_container: Union["ParametersContainer", |
|
|
|
None] = None, |
|
|
|
parameters_container: Optional["ParametersContainer"] = None, |
|
|
|
chroot_path: str = '/', |
|
|
|
datavars_module: Union[Datavars, Variables] = Variables(), |
|
|
|
for_package: Union[Package, None] = None): |
|
|
|
datavars_module: Union[Datavars, |
|
|
|
NamespaceNode, |
|
|
|
Variables] = Variables(), |
|
|
|
for_package: Optional[Package] = None): |
|
|
|
self.chroot_path: str = chroot_path |
|
|
|
|
|
|
|
self.template_type: int = DIR |
|
|
|
|
|
|
|
self.datavars_module: Union[Datavars, Variables] = datavars_module |
|
|
|
self.datavars_module: Union[Datavars, |
|
|
|
NamespaceNode, |
|
|
|
Variables] = datavars_module |
|
|
|
|
|
|
|
self._parameters_container: ParametersContainer = parameters_container |
|
|
|
|
|
|
|
self.package_atom_parser: PackageAtomParser =\ |
|
|
|
PackageAtomParser(chroot_path=chroot_path) |
|
|
|
self.package_atom_parser: PackageAtomParser = PackageAtomParser( |
|
|
|
chroot_path=chroot_path) |
|
|
|
|
|
|
|
self._groups: dict = {} |
|
|
|
try: |
|
|
@@ -212,7 +226,9 @@ class ParametersProcessor: |
|
|
|
'merge': self.check_merge_parameter, |
|
|
|
'format': self.check_format_parameter, |
|
|
|
'handler': self.check_handler_parameter, |
|
|
|
'notify': self.check_notify_parameter |
|
|
|
'notify': self.check_notify_parameter, |
|
|
|
'convert': self.check_convert_parameter, |
|
|
|
'stretch': self.check_stretch_parameter, |
|
|
|
}) |
|
|
|
|
|
|
|
# Если добавляемый параметр должен быть проверен после того, как |
|
|
@@ -225,7 +241,9 @@ class ParametersProcessor: |
|
|
|
'autoupdate': self.check_postparse_autoupdate, |
|
|
|
'run': self.check_postparse_run, |
|
|
|
'exec': self.check_postparse_exec, |
|
|
|
'handler': self.check_postparse_handler |
|
|
|
'handler': self.check_postparse_handler, |
|
|
|
'convert': self.check_postparse_convert, |
|
|
|
'stretch': self.check_postparse_stretch, |
|
|
|
}) |
|
|
|
|
|
|
|
# Если параметр является наследуемым только при некоторых условиях -- |
|
|
@@ -234,7 +252,7 @@ class ParametersProcessor: |
|
|
|
|
|
|
|
def set_parameters_container(self, |
|
|
|
parameters_container: "ParametersContainer" |
|
|
|
) -> None: |
|
|
|
) -> NoReturn: |
|
|
|
'''Метод для установки текущего контейнера параметров.''' |
|
|
|
self._parameters_container = parameters_container |
|
|
|
self._added_parameters = set() |
|
|
@@ -244,7 +262,7 @@ class ParametersProcessor: |
|
|
|
return self._for_package |
|
|
|
|
|
|
|
@for_package.setter |
|
|
|
def for_package(self, package: Package): |
|
|
|
def for_package(self, package: Package) -> NoReturn: |
|
|
|
self._for_package = package |
|
|
|
|
|
|
|
def __getattr__(self, parameter_name: str) -> Any: |
|
|
@@ -258,7 +276,7 @@ class ParametersProcessor: |
|
|
|
|
|
|
|
def check_template_parameter(self, parameter_name: str, |
|
|
|
parameter_value: Any, |
|
|
|
template_type: int, lineno: int) -> None: |
|
|
|
template_type: int, lineno: int) -> NoReturn: |
|
|
|
'''Метод, проверяющий указанный параметр.''' |
|
|
|
self.lineno = lineno |
|
|
|
self.template_type = template_type |
|
|
@@ -293,7 +311,7 @@ class ParametersProcessor: |
|
|
|
self._parameters_container.set_parameter({parameter_name: |
|
|
|
checked_value}) |
|
|
|
|
|
|
|
def check_postparse_parameters(self) -> None: |
|
|
|
def check_postparse_parameters(self) -> NoReturn: |
|
|
|
'''Метод, запускающий проверку параметров после их разбора.''' |
|
|
|
for parameter, parameter_checker in\ |
|
|
|
self.postparse_checkers_list.items(): |
|
|
@@ -306,7 +324,7 @@ class ParametersProcessor: |
|
|
|
result) |
|
|
|
|
|
|
|
def check_template_parameters(self, parameters: dict, |
|
|
|
template_type: int, lineno: int) -> None: |
|
|
|
template_type: int, lineno: int) -> NoReturn: |
|
|
|
'''Метод, запускающий проверку указанных параметров.''' |
|
|
|
self.template_type = template_type |
|
|
|
self.lineno = lineno |
|
|
@@ -339,7 +357,6 @@ class ParametersProcessor: |
|
|
|
parameter_name=checked_value) |
|
|
|
|
|
|
|
# Методы для проверки параметров во время разбора шаблона. |
|
|
|
|
|
|
|
def check_package_parameter(self, parameter_value: Any) -> str: |
|
|
|
if not isinstance(parameter_value, str): |
|
|
|
raise IncorrectParameter("'package' parameter must have value of" |
|
|
@@ -402,17 +419,17 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter( |
|
|
|
"'restart' parameter value is not correct") |
|
|
|
|
|
|
|
def check_stop_parameter(self, parameter_value: Any): |
|
|
|
def check_stop_parameter(self, parameter_value: Any) -> str: |
|
|
|
if not parameter_value and isinstance(parameter_value, bool): |
|
|
|
raise IncorrectParameter("'stop' parameter value is empty") |
|
|
|
return parameter_value |
|
|
|
|
|
|
|
def check_start_parameter(self, parameter_value: Any): |
|
|
|
def check_start_parameter(self, parameter_value: Any) -> str: |
|
|
|
if not parameter_value and isinstance(parameter_value, bool): |
|
|
|
raise IncorrectParameter("'start' parameter value is empty") |
|
|
|
return parameter_value |
|
|
|
|
|
|
|
def check_run_parameter(self, parameter_value: Any): |
|
|
|
def check_run_parameter(self, parameter_value: Any) -> str: |
|
|
|
if self.template_type == DIR: |
|
|
|
raise IncorrectParameter("'run' parameter is not available in" |
|
|
|
" directory templates") |
|
|
@@ -425,7 +442,7 @@ class ParametersProcessor: |
|
|
|
" found") |
|
|
|
return interpreter_path |
|
|
|
|
|
|
|
def check_exec_parameter(self, parameter_value: Any): |
|
|
|
def check_exec_parameter(self, parameter_value: Any) -> str: |
|
|
|
if self.template_type == DIR: |
|
|
|
raise IncorrectParameter("'exec' parameter is not available in" |
|
|
|
" directory templates") |
|
|
@@ -438,7 +455,7 @@ class ParametersProcessor: |
|
|
|
" found") |
|
|
|
return interpreter_path |
|
|
|
|
|
|
|
def check_chown_parameter(self, parameter_value: Any): |
|
|
|
def check_chown_parameter(self, parameter_value: Any) -> dict: |
|
|
|
if not parameter_value or isinstance(parameter_value, bool): |
|
|
|
raise IncorrectParameter("'chown' parameter value is empty.") |
|
|
|
parameter_value = self.get_chown_values(parameter_value) |
|
|
@@ -478,7 +495,8 @@ class ParametersProcessor: |
|
|
|
x_mask = x_mask + "0" |
|
|
|
return (int(chmod, 2), int(x_mask, 2)) |
|
|
|
|
|
|
|
def check_source_parameter(self, parameter_value: Any): |
|
|
|
def check_source_parameter(self, parameter_value: Any |
|
|
|
) -> Union[str, Tuple[bool, str]]: |
|
|
|
if not parameter_value or isinstance(parameter_value, bool): |
|
|
|
raise IncorrectParameter("'source' parameter value is empty") |
|
|
|
|
|
|
@@ -510,7 +528,7 @@ class ParametersProcessor: |
|
|
|
|
|
|
|
return os.path.normpath(real_path) |
|
|
|
|
|
|
|
def check_env_parameter(self, parameter_value: Any): |
|
|
|
def check_env_parameter(self, parameter_value: Any) -> Union[None, set]: |
|
|
|
env_set = set() |
|
|
|
|
|
|
|
for env_value in parameter_value.split(','): |
|
|
@@ -538,20 +556,20 @@ class ParametersProcessor: |
|
|
|
|
|
|
|
return env_set |
|
|
|
|
|
|
|
def check_force_parameter(self, parameter_value: Any): |
|
|
|
def check_force_parameter(self, parameter_value: Any) -> bool: |
|
|
|
if isinstance(parameter_value, bool): |
|
|
|
return parameter_value |
|
|
|
else: |
|
|
|
raise IncorrectParameter("'force' parameter value is not bool") |
|
|
|
|
|
|
|
def check_autoupdate_parameter(self, parameter_value: Any): |
|
|
|
def check_autoupdate_parameter(self, parameter_value: Any) -> bool: |
|
|
|
if isinstance(parameter_value, bool): |
|
|
|
return parameter_value |
|
|
|
else: |
|
|
|
raise IncorrectParameter( |
|
|
|
"'autoupdate' parameter value is not bool.") |
|
|
|
|
|
|
|
def check_format_parameter(self, parameter_value: Any): |
|
|
|
def check_format_parameter(self, parameter_value: Any) -> str: |
|
|
|
if self.template_type == DIR: |
|
|
|
raise IncorrectParameter("'format' parameter is redundant for" |
|
|
|
" directory templates.") |
|
|
@@ -564,13 +582,13 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'format' parameter must be string value not" |
|
|
|
f" {type(parameter_value)}.") |
|
|
|
|
|
|
|
def check_handler_parameter(self, parameter_value: Any): |
|
|
|
def check_handler_parameter(self, parameter_value: Any) -> str: |
|
|
|
if not isinstance(parameter_value, str): |
|
|
|
raise IncorrectParameter("'handler' parameter must be string" |
|
|
|
f" value not {type(parameter_value)}.") |
|
|
|
return parameter_value |
|
|
|
|
|
|
|
def check_notify_parameter(self, parameter_value: Any): |
|
|
|
def check_notify_parameter(self, parameter_value: Any) -> List[str]: |
|
|
|
if isinstance(parameter_value, list): |
|
|
|
return parameter_value |
|
|
|
elif isinstance(parameter_value, str): |
|
|
@@ -579,9 +597,33 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'notify' parameter must be string or list" |
|
|
|
f" value not {type(parameter_value)}.") |
|
|
|
|
|
|
|
# Методы для проверки параметров после разбора всего шаблона. |
|
|
|
def check_convert_parameter(self, parameter_value: Any) -> str: |
|
|
|
if not isinstance(parameter_value, str): |
|
|
|
raise IncorrectParameter("'convert' parameter value must be string" |
|
|
|
f" not '{type(parameter_value)}'.") |
|
|
|
parameter_value = parameter_value.strip().upper() |
|
|
|
|
|
|
|
try: |
|
|
|
available_image_formats =\ |
|
|
|
self.datavars_module.main.cl_image_formats |
|
|
|
except VariableNotFoundError: |
|
|
|
# TODO возможно стоит кидать ошибку. |
|
|
|
available_image_formats = ["JPEG", "PNG", "GIF", "JPG"] |
|
|
|
if parameter_value not in available_image_formats: |
|
|
|
raise IncorrectParameter(f"'{parameter_value}' image format is " |
|
|
|
"not available. Available image formats: " |
|
|
|
f"'{', '.join(available_image_formats)}.'" |
|
|
|
) |
|
|
|
return parameter_value |
|
|
|
|
|
|
|
def check_stretch_parameter(self, parameter_value: Any) -> bool: |
|
|
|
if not isinstance(parameter_value, bool): |
|
|
|
raise IncorrectParameter("'stretch' parameter value should be bool" |
|
|
|
f" value not '{type(parameter_value)}'") |
|
|
|
return parameter_value |
|
|
|
|
|
|
|
def check_postparse_append(self, parameter_value): |
|
|
|
# Методы для проверки параметров после разбора всего шаблона. |
|
|
|
def check_postparse_append(self, parameter_value: str) -> NoReturn: |
|
|
|
if parameter_value == 'link': |
|
|
|
if 'source' not in self._parameters_container: |
|
|
|
raise IncorrectParameter("append = 'link' without source " |
|
|
@@ -595,7 +637,7 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'append' parameter is not 'compatible' " |
|
|
|
"with the 'exec' parameter") |
|
|
|
|
|
|
|
def check_postparse_run(self, parameter_value): |
|
|
|
def check_postparse_run(self, parameter_value: str) -> NoReturn: |
|
|
|
if self._parameters_container.append: |
|
|
|
raise IncorrectParameter("'run' parameter is not 'compatible' " |
|
|
|
"with the 'append' parameter") |
|
|
@@ -604,7 +646,7 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'run' parameter is not 'compatible' " |
|
|
|
"with the 'exec' parameter") |
|
|
|
|
|
|
|
def check_postparse_exec(self, parameter_value): |
|
|
|
def check_postparse_exec(self, parameter_value: str) -> NoReturn: |
|
|
|
if self._parameters_container.append: |
|
|
|
raise IncorrectParameter("'exec' parameter is not 'compatible' " |
|
|
|
"with the 'append' parameter") |
|
|
@@ -613,13 +655,16 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'exec' parameter is not 'compatible' " |
|
|
|
"with the 'run' parameter") |
|
|
|
|
|
|
|
def check_postparse_source(self, parameter_value): |
|
|
|
def check_postparse_source(self, |
|
|
|
parameter_value: Union[str, Tuple[bool, str]] |
|
|
|
) -> NoReturn: |
|
|
|
# Если файл по пути source не существует, но присутствует параметр |
|
|
|
# mirror -- пропускаем шаблон для того, чтобы целевой файл мог быть |
|
|
|
# удален в исполнительном модуле. |
|
|
|
if isinstance(parameter_value, tuple): |
|
|
|
if (self._parameters_container.append == "link" and |
|
|
|
self._parameters_container.force): |
|
|
|
if ((self._parameters_container.append == "link" and |
|
|
|
self._parameters_container.force) |
|
|
|
or self._parameters_container.format == "backgrounds"): |
|
|
|
self._parameters_container['source'] = parameter_value[1] |
|
|
|
elif not self._parameters_container.mirror: |
|
|
|
raise IncorrectParameter( |
|
|
@@ -632,12 +677,12 @@ class ParametersProcessor: |
|
|
|
"append = 'link' for directory template") |
|
|
|
) |
|
|
|
|
|
|
|
def check_postparse_autoupdate(self, parameter_value): |
|
|
|
def check_postparse_autoupdate(self, parameter_value: bool) -> NoReturn: |
|
|
|
if self._parameters_container.unbound: |
|
|
|
raise IncorrectParameter("'unbound' parameter is incompatible" |
|
|
|
" with 'autoupdate' parameter") |
|
|
|
|
|
|
|
def check_postparse_handler(self, parameter_value): |
|
|
|
def check_postparse_handler(self, parameter_value: bool) -> NoReturn: |
|
|
|
if self._parameters_container.merge: |
|
|
|
raise IncorrectParameter("'merge' parameter is not available" |
|
|
|
" in handler templates") |
|
|
@@ -646,7 +691,7 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'package' parameter is not available" |
|
|
|
" in handler templates") |
|
|
|
|
|
|
|
def check_postparse_package(self, parameter_value): |
|
|
|
def check_postparse_package(self, parameter_value: str) -> NoReturn: |
|
|
|
groups = [] |
|
|
|
package_atom = PackageAtomParser.parse_atom_name(parameter_value) |
|
|
|
|
|
|
@@ -679,7 +724,8 @@ class ParametersProcessor: |
|
|
|
" does not match the template condition", |
|
|
|
self.lineno if hasattr(self, 'lineno') else 0) |
|
|
|
|
|
|
|
def _check_package_group(self, package: dict, group_packages: list): |
|
|
|
def _check_package_group(self, package: dict, group_packages: list |
|
|
|
) -> bool: |
|
|
|
'''Метод для проверки соответствия описания пакета, заданного словарем, |
|
|
|
какому-либо описанию пакета, заданного в переменных groups.''' |
|
|
|
for group_package in group_packages: |
|
|
@@ -699,16 +745,28 @@ class ParametersProcessor: |
|
|
|
return True |
|
|
|
return False |
|
|
|
|
|
|
|
def check_postparse_convert(self, parameter_value: str) -> NoReturn: |
|
|
|
template_format = self._parameters_container.format |
|
|
|
if not template_format or template_format != "backgrounds": |
|
|
|
raise IncorrectParameter("'convert' parameter available for" |
|
|
|
" 'backgrounds' format only.") |
|
|
|
|
|
|
|
def check_postparse_stretch(self, parameter_value: str) -> NoReturn: |
|
|
|
template_format = self._parameters_container.format |
|
|
|
if not template_format or template_format != "backgrounds": |
|
|
|
raise IncorrectParameter("'stretch' parameter available for" |
|
|
|
" 'backgrounds' format only.") |
|
|
|
|
|
|
|
# Методы для проверки того, являются ли параметры наследуемыми. |
|
|
|
|
|
|
|
def is_chmod_inheritable(self, parameter_value): |
|
|
|
def is_chmod_inheritable(self, parameter_value: str) -> bool: |
|
|
|
chmod_regex = re.compile(r'\d+') |
|
|
|
|
|
|
|
if chmod_regex.search(parameter_value): |
|
|
|
return False |
|
|
|
return True |
|
|
|
|
|
|
|
def get_chown_values(self, chown: str): |
|
|
|
def get_chown_values(self, chown: str) -> dict: |
|
|
|
"""Получить значения uid и gid из параметра chown.""" |
|
|
|
if chown and ':' in chown: |
|
|
|
user_name, group_name = chown.split(':') |
|
|
@@ -746,7 +804,7 @@ class ParametersProcessor: |
|
|
|
raise IncorrectParameter("'chown' value '{0}' is not correct". |
|
|
|
format(chown)) |
|
|
|
|
|
|
|
def get_uid_from_passwd(self, user_name: str): |
|
|
|
def get_uid_from_passwd(self, user_name: str) -> int: |
|
|
|
"""Функция для получения uid из chroot passwd файла.""" |
|
|
|
passwd_file_path = os.path.join(self.chroot_path, 'etc/passwd') |
|
|
|
passwd_dictionary = dict() |
|
|
@@ -771,7 +829,7 @@ class ParametersProcessor: |
|
|
|
raise FilesError("passwd file was not found in {}". |
|
|
|
format(passwd_file_path)) |
|
|
|
|
|
|
|
def get_gid_from_group(self, group_name: str): |
|
|
|
def get_gid_from_group(self, group_name: str) -> int: |
|
|
|
"""Функция для получения gid из chroot group файла.""" |
|
|
|
group_file_path = os.path.join(self.chroot_path, 'etc/group') |
|
|
|
group_dictionary = dict() |
|
|
@@ -797,7 +855,7 @@ class ParametersProcessor: |
|
|
|
format(group_file_path)) |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def _inspect_formats_package(cls): |
|
|
|
def _inspect_formats_package(cls) -> NoReturn: |
|
|
|
'''Метод для определения множества доступных форматов и |
|
|
|
предоставляемых ими параметров.''' |
|
|
|
if cls.format_is_inspected: |
|
|
@@ -845,9 +903,13 @@ class ParametersProcessor: |
|
|
|
cls.formats_inspected = True |
|
|
|
|
|
|
|
|
|
|
|
def resolve_or_missing(context, key, missing=missing, env={}): |
|
|
|
def resolve_or_missing(context: "CalculateContext", |
|
|
|
key: str, missing=missing, |
|
|
|
env: Optional[set] = None) -> Any: |
|
|
|
'''Переопределение функции из для поиска значений переменных из jinja2. |
|
|
|
Ищет переменные в datavars.''' |
|
|
|
if env is None: |
|
|
|
env = {} |
|
|
|
datavars = context.parent['__datavars__'] |
|
|
|
|
|
|
|
if key in context.vars: |
|
|
@@ -871,7 +933,7 @@ class CalculateContext(Context): |
|
|
|
сохранять их.''' |
|
|
|
_env_set = set() |
|
|
|
|
|
|
|
def resolve(self, key): |
|
|
|
def resolve(self, key: str) -> Any: |
|
|
|
if self._legacy_resolve_mode: |
|
|
|
rv = resolve_or_missing(self, key, |
|
|
|
env=self._env_set) |
|
|
@@ -881,7 +943,7 @@ class CalculateContext(Context): |
|
|
|
return self.environment.undefined(name=key) |
|
|
|
return rv |
|
|
|
|
|
|
|
def resolve_or_missing(self, key): |
|
|
|
def resolve_or_missing(self, key: str) -> Any: |
|
|
|
if self._legacy_resolve_mode: |
|
|
|
rv = self.resolve(key) |
|
|
|
if isinstance(rv, Undefined): |
|
|
@@ -894,56 +956,56 @@ class CalculateContext(Context): |
|
|
|
class ParametersContainer(MutableMapping): |
|
|
|
'''Класс для хранения параметров, взятых из шаблона, и передачи |
|
|
|
их шаблонизатору.''' |
|
|
|
def __init__(self, parameters_dictionary=None): |
|
|
|
def __init__(self, parameters_dictionary: Optional[dict] = None): |
|
|
|
# Слой ненаследуемых параметров. |
|
|
|
self.__parameters = {} |
|
|
|
self.__parameters: dict = {} |
|
|
|
|
|
|
|
# Слой наследуемых параметров. |
|
|
|
if parameters_dictionary is not None: |
|
|
|
self.__inheritable = parameters_dictionary |
|
|
|
self.__inheritable: dict = parameters_dictionary |
|
|
|
else: |
|
|
|
self.__inheritable = {} |
|
|
|
self.__inheritable: dict = {} |
|
|
|
|
|
|
|
def set_parameter(self, item_to_add: dict): |
|
|
|
def set_parameter(self, item_to_add: dict) -> NoReturn: |
|
|
|
self.__parameters.update(item_to_add) |
|
|
|
|
|
|
|
def set_inheritable(self, item_to_add: dict): |
|
|
|
def set_inheritable(self, item_to_add: dict) -> NoReturn: |
|
|
|
self.__inheritable.update(item_to_add) |
|
|
|
|
|
|
|
def get_inheritables(self): |
|
|
|
def get_inheritables(self) -> "ParametersContainer": |
|
|
|
return ParametersContainer(copy.deepcopy(self.__inheritable)) |
|
|
|
|
|
|
|
def remove_not_inheritable(self): |
|
|
|
def remove_not_inheritable(self) -> NoReturn: |
|
|
|
self.__parameters.clear() |
|
|
|
|
|
|
|
def print_parameters_for_debug(self): |
|
|
|
def print_parameters_for_debug(self) -> NoReturn: |
|
|
|
print('Parameters:') |
|
|
|
pprint(self.__parameters) |
|
|
|
|
|
|
|
print('Inherited:') |
|
|
|
pprint(self.__inheritable) |
|
|
|
|
|
|
|
def is_inherited(self, parameter_name): |
|
|
|
def is_inherited(self, parameter_name: str) -> bool: |
|
|
|
return (parameter_name not in self.__parameters |
|
|
|
and parameter_name in self.__inheritable) |
|
|
|
|
|
|
|
def remove_parameter(self, parameter_name): |
|
|
|
def remove_parameter(self, parameter_name: str) -> NoReturn: |
|
|
|
if parameter_name in self.__parameters: |
|
|
|
self.__parameters.pop(parameter_name) |
|
|
|
elif parameter_name in self.__inheritable: |
|
|
|
self.__inheritable.pop(parameter_name) |
|
|
|
|
|
|
|
def change_parameter(self, parameter, value): |
|
|
|
def change_parameter(self, parameter: str, value: Any) -> NoReturn: |
|
|
|
if parameter in self.__parameters: |
|
|
|
self.__parameters.update({parameter: value}) |
|
|
|
elif parameter in self.__inheritable: |
|
|
|
self.__inheritable.update({parameter: value}) |
|
|
|
|
|
|
|
def _clear_container(self): |
|
|
|
def _clear_container(self) -> NoReturn: |
|
|
|
self.__parameters.clear() |
|
|
|
self.__inheritable.clear() |
|
|
|
|
|
|
|
def __getattr__(self, parameter_name): |
|
|
|
def __getattr__(self, parameter_name: str) -> Any: |
|
|
|
if (parameter_name not in |
|
|
|
ParametersProcessor.available_parameters): |
|
|
|
raise IncorrectParameter("Unknown parameter: '{}'". |
|
|
@@ -956,7 +1018,7 @@ class ParametersContainer(MutableMapping): |
|
|
|
else: |
|
|
|
return False |
|
|
|
|
|
|
|
def __getitem__(self, name): |
|
|
|
def __getitem__(self, name: str) -> Any: |
|
|
|
if name in self.__parameters: |
|
|
|
return self.__parameters[name] |
|
|
|
elif name in self.__inheritable: |
|
|
@@ -964,31 +1026,31 @@ class ParametersContainer(MutableMapping): |
|
|
|
else: |
|
|
|
return False |
|
|
|
|
|
|
|
def __setitem__(self, name, value): |
|
|
|
def __setitem__(self, name: str, value: Any) -> NoReturn: |
|
|
|
self.__parameters[name] = value |
|
|
|
|
|
|
|
def __delitem__(self, name): |
|
|
|
def __delitem__(self, name: str) -> NoReturn: |
|
|
|
if name in self.__parameters: |
|
|
|
del self.__parameters[name] |
|
|
|
|
|
|
|
if name in self.__inheritable: |
|
|
|
del self.__inheritable[name] |
|
|
|
|
|
|
|
def __iter__(self): |
|
|
|
def __iter__(self) -> Iterator[str]: |
|
|
|
return iter(set(self.__parameters).union(self.__inheritable)) |
|
|
|
|
|
|
|
def __len__(self): |
|
|
|
def __len__(self) -> int: |
|
|
|
return len(set(self.__parameters).union(self.__inheritable)) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
return '<ParametersContainer: parameters={0}, inheritables={1}>'.\ |
|
|
|
format(self.__parameters, self.__inheritable) |
|
|
|
|
|
|
|
def __contains__(self, name): |
|
|
|
def __contains__(self, name: str) -> bool: |
|
|
|
return name in self.__parameters or name in self.__inheritable |
|
|
|
|
|
|
|
@property |
|
|
|
def parameters(self): |
|
|
|
def parameters(self) -> dict: |
|
|
|
return self.__parameters |
|
|
|
|
|
|
|
|
|
|
@@ -999,10 +1061,14 @@ class CalculateExtension(Extension): |
|
|
|
# Виды операций в теге save. |
|
|
|
ASSIGN, APPEND, REMOVE = range(3) |
|
|
|
|
|
|
|
def __init__(self, environment, parameters_processor: ParametersProcessor, |
|
|
|
datavars_module=Variables(), chroot_path="/"): |
|
|
|
def __init__(self, environment: Environment, |
|
|
|
parameters_processor: ParametersProcessor, |
|
|
|
datavars_module: Union[Datavars, |
|
|
|
NamespaceNode, |
|
|
|
Variables] = Variables(), |
|
|
|
chroot_path: str = "/"): |
|
|
|
super().__init__(environment) |
|
|
|
self.environment = environment |
|
|
|
self.environment: Environment = environment |
|
|
|
self.package_atom_parser = PackageAtomParser(chroot_path=chroot_path) |
|
|
|
|
|
|
|
self.environment.globals.update({'pkg': self.pkg}) |
|
|
@@ -1011,11 +1077,11 @@ class CalculateExtension(Extension): |
|
|
|
|
|
|
|
self._datavars = datavars_module |
|
|
|
self.parameters_processor = parameters_processor |
|
|
|
self.template_type = DIR |
|
|
|
self.template_type: int = DIR |
|
|
|
|
|
|
|
# Флаг, указывающий, что тег calculate уже был разобран. Нужен для |
|
|
|
# того, чтобы проверять единственность тега calculate. |
|
|
|
self.calculate_parsed = False |
|
|
|
self.calculate_parsed: bool = False |
|
|
|
|
|
|
|
self.tags = {'calculate', 'save', 'set_var'} |
|
|
|
self.CONDITION_TOKENS_TYPES = {'eq', 'ne', 'lt', 'gt', 'lteq', 'gteq'} |
|
|
@@ -1031,24 +1097,25 @@ class CalculateExtension(Extension): |
|
|
|
self.parse_methods = {'calculate': self.parse_calculate, |
|
|
|
'save': self.parse_save} |
|
|
|
|
|
|
|
def __call__(self, env): |
|
|
|
def __call__(self, env: Environment) -> "CalculateExtension": |
|
|
|
# Необходимо для обеспечения возможности передать готовый объект |
|
|
|
# расширения, а не его класс. |
|
|
|
return self |
|
|
|
|
|
|
|
def parse(self, parser): |
|
|
|
def parse(self, parser: Parser) -> List[nodes.Output]: |
|
|
|
self.parser = parser |
|
|
|
self.stream = parser.stream |
|
|
|
tag_token = self.stream.current.value |
|
|
|
return [self.parse_methods[tag_token]()] |
|
|
|
|
|
|
|
def parse_save(self): |
|
|
|
def parse_save(self) -> nodes.Output: |
|
|
|
'''Метод для разбора тега save, сохраняющего значение указанной |
|
|
|
переменной datavars.''' |
|
|
|
lineno = next(self.stream).lineno |
|
|
|
|
|
|
|
target_file = nodes.Const('', lineno=lineno) |
|
|
|
|
|
|
|
# Получаем имя целевого файла. |
|
|
|
if self.stream.skip_if('dot'): |
|
|
|
target_file_name = self.stream.expect('name').value |
|
|
|
if target_file_name in self.TARGET_FILES_SET: |
|
|
@@ -1084,7 +1151,7 @@ class CalculateExtension(Extension): |
|
|
|
raise TemplateSyntaxError("'=' is expected in 'save' tag", |
|
|
|
lineno=lineno) |
|
|
|
|
|
|
|
def parse_calculate(self): |
|
|
|
def parse_calculate(self) -> nodes.Output: |
|
|
|
'''Метод для разбора тега calculate, содержащего значения параметров и |
|
|
|
условия выполнения шаблона.''' |
|
|
|
lineno = next(self.stream).lineno |
|
|
@@ -1155,7 +1222,7 @@ class CalculateExtension(Extension): |
|
|
|
self.calculate_parsed = True |
|
|
|
return nodes.Output([nodes.Const('')], lineno=lineno) |
|
|
|
|
|
|
|
def _is_variable_name(self, token): |
|
|
|
def _is_variable_name(self, token: Token) -> bool: |
|
|
|
'''Метод для проверки токена на предмет того, что он является частью |
|
|
|
имени переменной.''' |
|
|
|
if not token.type == 'name': |
|
|
@@ -1168,7 +1235,8 @@ class CalculateExtension(Extension): |
|
|
|
return True |
|
|
|
return False |
|
|
|
|
|
|
|
def check_parameter(self, parameter_name, parameter_value, context): |
|
|
|
def check_parameter(self, parameter_name: str, parameter_value: Any, |
|
|
|
context: CalculateContext) -> str: |
|
|
|
self.parameters_processor.check_template_parameter( |
|
|
|
parameter_name, |
|
|
|
parameter_value, |
|
|
@@ -1176,7 +1244,7 @@ class CalculateExtension(Extension): |
|
|
|
self.stream.current.lineno) |
|
|
|
return '' |
|
|
|
|
|
|
|
def parse_condition(self): |
|
|
|
def parse_condition(self) -> Template: |
|
|
|
try: |
|
|
|
condition_node = self.parser.parse_expression(with_condexpr=True) |
|
|
|
condition_node = self.call_method( |
|
|
@@ -1196,7 +1264,7 @@ class CalculateExtension(Extension): |
|
|
|
.format(str(error)), |
|
|
|
lineno=self.stream.current.lineno) |
|
|
|
|
|
|
|
def check_conditions(self, conditions: list): |
|
|
|
def check_conditions(self, conditions: List[Template]) -> NoReturn: |
|
|
|
for condition in conditions: |
|
|
|
self.condition_result = False |
|
|
|
try: |
|
|
@@ -1210,7 +1278,7 @@ class CalculateExtension(Extension): |
|
|
|
lineno=self.stream.current.lineno) |
|
|
|
|
|
|
|
# DEPRECATED |
|
|
|
def get_condition_result(self): |
|
|
|
def get_condition_result(self) -> bool: |
|
|
|
'''Метод для разбора условий из тега calculate.''' |
|
|
|
self.condition_result = False |
|
|
|
|
|
|
@@ -1233,13 +1301,14 @@ class CalculateExtension(Extension): |
|
|
|
|
|
|
|
return self.condition_result |
|
|
|
|
|
|
|
def set_condition_result(self, condition_result): |
|
|
|
def set_condition_result(self, condition_result: Any) -> str: |
|
|
|
'''Метод для сохранения результата вычисления условия.''' |
|
|
|
self.condition_result = condition_result |
|
|
|
return '' |
|
|
|
|
|
|
|
def _make_save_node(self, variable_name_node, target_file_node, optype, |
|
|
|
lineno): |
|
|
|
def _make_save_node(self, variable_name_node: nodes.List, |
|
|
|
target_file_node: nodes.Const, optype: int, |
|
|
|
lineno: int) -> nodes.Output: |
|
|
|
'''Метод для создания ноды, сохраняющей переменные.''' |
|
|
|
right_value = self.parser.parse_expression(with_condexpr=True) |
|
|
|
optype_node = nodes.Const(optype, lineno=lineno) |
|
|
@@ -1252,8 +1321,9 @@ class CalculateExtension(Extension): |
|
|
|
lineno=lineno) |
|
|
|
return nodes.Output([save_variable_node], lineno=lineno) |
|
|
|
|
|
|
|
def save_variable(self, variable, right_value, target_file, |
|
|
|
optype, context): |
|
|
|
def save_variable(self, variable: List[str], right_value: Any, |
|
|
|
target_file: str, optype: int, |
|
|
|
context: CalculateContext) -> str: |
|
|
|
'''Метод для сохранения значений переменных указанных в теге save.''' |
|
|
|
datavars = context.parent['__datavars__'] |
|
|
|
if variable[0] not in datavars: |
|
|
@@ -1272,7 +1342,7 @@ class CalculateExtension(Extension): |
|
|
|
# Теперь меняем знaчение переменной. |
|
|
|
if isinstance(value_container, NamespaceNode): |
|
|
|
self._modify_variables(variable, value_container, right_value, |
|
|
|
optype, target=target_file, |
|
|
|
optype, target_file=target_file, |
|
|
|
modify_only=modify_only) |
|
|
|
elif isinstance(value_container, VariableNode): |
|
|
|
hash_value = value_container.get_value().get_hash() |
|
|
@@ -1296,7 +1366,7 @@ class CalculateExtension(Extension): |
|
|
|
def _find_value_container(self, variable: List[str], |
|
|
|
vars_package: NamespaceNode, |
|
|
|
modify_only: bool = True |
|
|
|
) -> Union[NamespaceNode]: |
|
|
|
) -> Union[NamespaceNode, VariableNode]: |
|
|
|
'''Метод для поиска контейнера, путь к которому указан в аргументе. |
|
|
|
Этим контейнером может быть пространство имен или хэш.''' |
|
|
|
current_container = vars_package |
|
|
@@ -1329,8 +1399,10 @@ class CalculateExtension(Extension): |
|
|
|
current_container.get_fullname())) |
|
|
|
return current_container |
|
|
|
|
|
|
|
def _modify_variables(self, variable, namespace, new_value, optype, |
|
|
|
target='', modify_only=True): |
|
|
|
def _modify_variables(self, variable: List[str], namespace: NamespaceNode, |
|
|
|
new_value: Any, optype: int, |
|
|
|
target_file: Optional[str] = None, |
|
|
|
modify_only: bool = True) -> NoReturn: |
|
|
|
'''Метод для модификации значения переменной.''' |
|
|
|
variable_name = variable[-1] |
|
|
|
|
|
|
@@ -1353,18 +1425,20 @@ class CalculateExtension(Extension): |
|
|
|
raise SaveError("can not create variable '{}' in not 'custom'" |
|
|
|
" namespace".format('.'.join(variable))) |
|
|
|
|
|
|
|
if target: |
|
|
|
if target_file: |
|
|
|
if namespace._variables[variable_name].variable_type is HashType: |
|
|
|
for key, value in new_value.items(): |
|
|
|
self._save_to_target(variable, key, value, target) |
|
|
|
self._save_to_target(variable, key, value, target_file) |
|
|
|
else: |
|
|
|
self._save_to_target(variable[:-1], variable_name, |
|
|
|
new_value, target) |
|
|
|
new_value, target_file) |
|
|
|
|
|
|
|
def _modify_hash(self, variable, hash_variable, new_value, optype, |
|
|
|
target=''): |
|
|
|
# DEPRECATED |
|
|
|
def _modify_hash(self, variable_name: List[str], |
|
|
|
hash_variable: VariableNode, new_value, optype, |
|
|
|
target_file: Optional[str] = None) -> NoReturn: |
|
|
|
'''Метод для модификации значения в переменной-хэше.''' |
|
|
|
value_name = variable[-1] |
|
|
|
value_name = variable_name[-1] |
|
|
|
hash_value = hash_variable.get_value().get_hash() |
|
|
|
|
|
|
|
if value_name in hash_value: |
|
|
@@ -1376,22 +1450,25 @@ class CalculateExtension(Extension): |
|
|
|
hash_value.update({value_name: new_value}) |
|
|
|
hash_variable.set(hash_value) |
|
|
|
|
|
|
|
if target: |
|
|
|
self._save_to_target(variable[:-1], value_name, |
|
|
|
new_value, target) |
|
|
|
if target_file: |
|
|
|
self._save_to_target(variable_name[:-1], value_name, |
|
|
|
new_value, target_file) |
|
|
|
|
|
|
|
def _save_to_target(self, namespace_name, variable_name, value, target): |
|
|
|
def _save_to_target(self, namespace_name: List[str], |
|
|
|
variable_name: str, value: Any, target_file: str |
|
|
|
) -> NoReturn: |
|
|
|
'''Метод для добавления переменной в список переменных, значение |
|
|
|
которых было установлено через тег save и при этом должно быть |
|
|
|
сохранено в указанном файле: save.target_file.''' |
|
|
|
namespace_name = tuple(namespace_name) |
|
|
|
target_file_dict = self._datavars.variables_to_save[target] |
|
|
|
target_file_dict = self._datavars.variables_to_save[target_file] |
|
|
|
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): |
|
|
|
def _append_variable_value(self, variable: VariableNode, |
|
|
|
value: Any) -> Any: |
|
|
|
'''Метод описывающий операцию += в теге save.''' |
|
|
|
variable_value = variable.get_value() |
|
|
|
if (variable.variable_type is IntegerType or |
|
|
@@ -1429,7 +1506,8 @@ class CalculateExtension(Extension): |
|
|
|
# значение. |
|
|
|
return variable_value |
|
|
|
|
|
|
|
def _remove_variable_value(self, variable, value): |
|
|
|
def _remove_variable_value(self, variable: VariableNode, value: Any |
|
|
|
) -> Any: |
|
|
|
'''Метод описывающий операцию -= в теге save.''' |
|
|
|
variable_value = variable.get_value() |
|
|
|
|
|
|
@@ -1469,7 +1547,7 @@ class CalculateExtension(Extension): |
|
|
|
# значение. |
|
|
|
return variable_value |
|
|
|
|
|
|
|
def _get_parameter(self): |
|
|
|
def _get_parameter(self) -> Tuple[nodes.Const, nodes.Node]: |
|
|
|
'''Метод для разбора параметров, содержащихся в теге calculate.''' |
|
|
|
lineno = self.stream.current.lineno |
|
|
|
|
|
|
@@ -1491,13 +1569,14 @@ class CalculateExtension(Extension): |
|
|
|
|
|
|
|
return (parameter_name_node, parameter_rvalue) |
|
|
|
|
|
|
|
def save_parameters(cls, parameters_dictionary, context): |
|
|
|
def save_parameters(cls, parameters_dictionary: dict, |
|
|
|
context: CalculateContext) -> str: |
|
|
|
'''Метод для сохранения значений параметров.''' |
|
|
|
context.parent['__parameters__'].set_parameter(parameters_dictionary) |
|
|
|
return '' |
|
|
|
|
|
|
|
@contextfunction |
|
|
|
def pkg(self, context, *args) -> Version: |
|
|
|
def pkg(self, context: CalculateContext, *args: dict) -> Version: |
|
|
|
'''Метод, реализующий функцию pkg() шаблонов. Функция предназначена для |
|
|
|
получения версии пакета, к которому уже привязан шаблон, если |
|
|
|
аргументов нет, или версию пакета в аргументе функции. Если аргументов |
|
|
@@ -1518,7 +1597,7 @@ class CalculateExtension(Extension): |
|
|
|
return Version() |
|
|
|
return package.version |
|
|
|
|
|
|
|
def get_full_filepath(self, fname): |
|
|
|
def get_full_filepath(self, fname: str) -> str: |
|
|
|
# TODO: добавить получение домашней директории пользователя |
|
|
|
# if fname[0] == "~": |
|
|
|
# # Получаем директорию пользователя |
|
|
@@ -1531,10 +1610,9 @@ class CalculateExtension(Extension): |
|
|
|
return fname |
|
|
|
|
|
|
|
@contextfunction |
|
|
|
def grep(self, context, fname, regpattern) -> str: |
|
|
|
''' |
|
|
|
Метод реализующий функцию grep |
|
|
|
''' |
|
|
|
def grep(self, context: CalculateContext, fname: str, |
|
|
|
regpattern: str) -> str: |
|
|
|
'''Метод реализующий функцию grep.''' |
|
|
|
fname = self.get_full_filepath(fname) |
|
|
|
try: |
|
|
|
reg = re.compile(regpattern, re.MULTILINE) |
|
|
@@ -1554,10 +1632,8 @@ class CalculateExtension(Extension): |
|
|
|
return "" |
|
|
|
|
|
|
|
@contextfunction |
|
|
|
def exists(self, context, fname) -> str: |
|
|
|
''' |
|
|
|
Метод реализующий функцию exists |
|
|
|
''' |
|
|
|
def exists(self, context: CalculateContext, fname: str) -> str: |
|
|
|
'''Метод реализующий функцию exists.''' |
|
|
|
fname = self.get_full_filepath(fname) |
|
|
|
|
|
|
|
try: |
|
|
@@ -1627,19 +1703,20 @@ class TemplateEngine: |
|
|
|
self.environment.context_class = CalculateContext |
|
|
|
|
|
|
|
@property |
|
|
|
def for_package(self): |
|
|
|
def for_package(self) -> Package: |
|
|
|
return self.parameters_processor.for_package |
|
|
|
|
|
|
|
@for_package.setter |
|
|
|
def for_package(self, package): |
|
|
|
def for_package(self, package: Package) -> NoReturn: |
|
|
|
self.parameters_processor.for_package = package |
|
|
|
|
|
|
|
def change_directory(self, directory_path): |
|
|
|
def change_directory(self, directory_path: str) -> NoReturn: |
|
|
|
'''Метод для смены директории в загрузчике.''' |
|
|
|
self.environment.loader = FileSystemLoader(directory_path) |
|
|
|
|
|
|
|
def process_template(self, template_path, template_type, |
|
|
|
parameters=None): |
|
|
|
def process_template(self, template_path: str, template_type: str, |
|
|
|
parameters: Optional[ParametersContainer] = None |
|
|
|
) -> NoReturn: |
|
|
|
'''Метод для обработки файла шаблона, расположенного по указанному |
|
|
|
пути.''' |
|
|
|
if parameters is not None: |
|
|
@@ -1666,8 +1743,10 @@ class TemplateEngine: |
|
|
|
Version=Version |
|
|
|
) |
|
|
|
|
|
|
|
def process_template_from_string(self, string, template_type, |
|
|
|
parameters=None): |
|
|
|
def process_template_from_string( |
|
|
|
self, string: str, template_type: int, |
|
|
|
parameters: Optional[ParametersContainer] = None |
|
|
|
) -> NoReturn: |
|
|
|
'''Метод для обработки текста шаблона.''' |
|
|
|
if parameters is not None: |
|
|
|
self._parameters_object = parameters |
|
|
@@ -1694,10 +1773,10 @@ class TemplateEngine: |
|
|
|
) |
|
|
|
|
|
|
|
@property |
|
|
|
def parameters(self): |
|
|
|
def parameters(self) -> ParametersContainer: |
|
|
|
return self._parameters_object |
|
|
|
|
|
|
|
@property |
|
|
|
def template_text(self): |
|
|
|
def template_text(self) -> str: |
|
|
|
text, self._template_text = self._template_text, '' |
|
|
|
return text |