template: add support for async rendering
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
fc5e34096a
commit
3bd5f7edbd
|
@ -25,8 +25,12 @@ class TemplateFactory:
|
|||
self.server = config.get_server()
|
||||
secrets: Secrets = self.server.load_component(config, 'secrets')
|
||||
self.jenv = jinja2.Environment('{%', '%}', '{', '}')
|
||||
self.async_env = jinja2.Environment('{%', '%}', '{', '}',
|
||||
enable_async=True)
|
||||
self.jenv.add_extension("jinja2.ext.do")
|
||||
self.jenv.filters['fromjson'] = json.loads
|
||||
self.async_env.add_extension("jinja2.ext.do")
|
||||
self.async_env.filters['fromjson'] = json.loads
|
||||
self.add_environment_global('raise_error', self._raise_error)
|
||||
self.add_environment_global('secrets', secrets)
|
||||
|
||||
|
@ -35,35 +39,49 @@ class TemplateFactory:
|
|||
raise self.server.error(
|
||||
f"Jinja 2 environment already contains global {name}")
|
||||
self.jenv.globals[name] = value
|
||||
self.async_env.globals[name] = value
|
||||
|
||||
def _raise_error(self, err_msg: str, err_code: int = 400) -> None:
|
||||
raise self.server.error(err_msg, err_code)
|
||||
|
||||
def create_template(self, source: str) -> JinjaTemplate:
|
||||
return JinjaTemplate(source, self.server, self.jenv)
|
||||
def create_template(self,
|
||||
source: str,
|
||||
is_async: bool = False
|
||||
) -> JinjaTemplate:
|
||||
env = self.async_env if is_async else self.jenv
|
||||
try:
|
||||
template = env.from_string(source)
|
||||
except Exception:
|
||||
logging.exception(f"Error creating template from source:\n{source}")
|
||||
raise
|
||||
return JinjaTemplate(source, self.server, template, is_async)
|
||||
|
||||
|
||||
class JinjaTemplate:
|
||||
def __init__(self,
|
||||
source: str,
|
||||
server: Server,
|
||||
env: jinja2.Environment
|
||||
template: jinja2.Template,
|
||||
is_async: bool
|
||||
) -> None:
|
||||
self.server = server
|
||||
self.orig_source = source.strip()
|
||||
try:
|
||||
self.template = env.from_string(self.orig_source)
|
||||
except Exception:
|
||||
logging.exception(f"Error creating template from source:\n{source}")
|
||||
raise
|
||||
|
||||
def render(self, context: Dict[str, Any] = {}) -> str:
|
||||
try:
|
||||
return self.template.render(context).strip()
|
||||
except Exception as e:
|
||||
raise self.server.error("Error rendering template") from e
|
||||
self.orig_source = source
|
||||
self.template = template
|
||||
self.is_async = is_async
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.orig_source
|
||||
|
||||
def render(self, context: Dict[str, Any] = {}) -> str:
|
||||
if self.is_async:
|
||||
raise self.server.error(
|
||||
"Cannot render async templates with the render() method"
|
||||
", use render_async()")
|
||||
return self.template.render(context).strip()
|
||||
|
||||
async def render_async(self, context: Dict[str, Any] = {}) -> str:
|
||||
ret = await self.template.render_async(context)
|
||||
return ret.strip()
|
||||
|
||||
def load_component(config: ConfigHelper) -> TemplateFactory:
|
||||
return TemplateFactory(config)
|
||||
|
|
|
@ -333,6 +333,7 @@ class ConfigHelper:
|
|||
def gettemplate(self,
|
||||
option: str,
|
||||
default: Union[SentinelClass, _T] = SENTINEL,
|
||||
is_async: bool = False,
|
||||
deprecate: bool = False
|
||||
) -> Union[JinjaTemplate, _T]:
|
||||
try:
|
||||
|
@ -345,7 +346,7 @@ class ConfigHelper:
|
|||
|
||||
def gettemplate_wrapper(sec: str, opt: str) -> JinjaTemplate:
|
||||
val = self.config.get(sec, opt)
|
||||
return template.create_template(val)
|
||||
return template.create_template(val.strip(), is_async)
|
||||
|
||||
return self._get_option(gettemplate_wrapper, option, default,
|
||||
deprecate=deprecate)
|
||||
|
@ -353,13 +354,14 @@ class ConfigHelper:
|
|||
def load_template(self,
|
||||
option: str,
|
||||
default: Union[SentinelClass, str] = SENTINEL,
|
||||
is_async: bool = False,
|
||||
deprecate: bool = False
|
||||
) -> JinjaTemplate:
|
||||
val = self.gettemplate(option, default, deprecate)
|
||||
val = self.gettemplate(option, default, is_async, deprecate)
|
||||
if isinstance(val, str):
|
||||
template: TemplateFactory
|
||||
template = self.server.lookup_component('template')
|
||||
return template.create_template(val)
|
||||
return template.create_template(val.strip(), is_async)
|
||||
return val
|
||||
|
||||
def read_supplemental_config(self, file_name: str) -> ConfigHelper:
|
||||
|
|
Loading…
Reference in New Issue