updates
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Classes for managing templates and their runtime and compile time
|
||||
options.
|
||||
"""
|
||||
|
||||
import os
|
||||
import typing
|
||||
import typing as t
|
||||
@@ -20,10 +21,10 @@ from .defaults import BLOCK_END_STRING
|
||||
from .defaults import BLOCK_START_STRING
|
||||
from .defaults import COMMENT_END_STRING
|
||||
from .defaults import COMMENT_START_STRING
|
||||
from .defaults import DEFAULT_FILTERS
|
||||
from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined]
|
||||
from .defaults import DEFAULT_NAMESPACE
|
||||
from .defaults import DEFAULT_POLICIES
|
||||
from .defaults import DEFAULT_TESTS
|
||||
from .defaults import DEFAULT_TESTS # type: ignore[attr-defined]
|
||||
from .defaults import KEEP_TRAILING_NEWLINE
|
||||
from .defaults import LINE_COMMENT_PREFIX
|
||||
from .defaults import LINE_STATEMENT_PREFIX
|
||||
@@ -55,6 +56,7 @@ from .utils import missing
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
import typing_extensions as te
|
||||
|
||||
from .bccache import BytecodeCache
|
||||
from .ext import Extension
|
||||
from .loaders import BaseLoader
|
||||
@@ -79,7 +81,7 @@ def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_b
|
||||
|
||||
def create_cache(
|
||||
size: int,
|
||||
) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]:
|
||||
) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]:
|
||||
"""Return the cache class for the given size."""
|
||||
if size == 0:
|
||||
return None
|
||||
@@ -91,13 +93,13 @@ def create_cache(
|
||||
|
||||
|
||||
def copy_cache(
|
||||
cache: t.Optional[t.MutableMapping],
|
||||
) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]:
|
||||
cache: t.Optional[t.MutableMapping[t.Any, t.Any]],
|
||||
) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]:
|
||||
"""Create an empty copy of the given cache."""
|
||||
if cache is None:
|
||||
return None
|
||||
|
||||
if type(cache) is dict:
|
||||
if type(cache) is dict: # noqa E721
|
||||
return {}
|
||||
|
||||
return LRUCache(cache.capacity) # type: ignore
|
||||
@@ -121,7 +123,7 @@ def load_extensions(
|
||||
return result
|
||||
|
||||
|
||||
def _environment_config_check(environment: "Environment") -> "Environment":
|
||||
def _environment_config_check(environment: _env_bound) -> _env_bound:
|
||||
"""Perform a sanity check on the environment."""
|
||||
assert issubclass(
|
||||
environment.undefined, Undefined
|
||||
@@ -404,8 +406,8 @@ class Environment:
|
||||
cache_size: int = missing,
|
||||
auto_reload: bool = missing,
|
||||
bytecode_cache: t.Optional["BytecodeCache"] = missing,
|
||||
enable_async: bool = False,
|
||||
) -> "Environment":
|
||||
enable_async: bool = missing,
|
||||
) -> "te.Self":
|
||||
"""Create a new overlay environment that shares all the data with the
|
||||
current environment except for cache and the overridden attributes.
|
||||
Extensions cannot be removed for an overlayed environment. An overlayed
|
||||
@@ -417,8 +419,11 @@ class Environment:
|
||||
copied over so modifications on the original environment may not shine
|
||||
through.
|
||||
|
||||
.. versionchanged:: 3.1.5
|
||||
``enable_async`` is applied correctly.
|
||||
|
||||
.. versionchanged:: 3.1.2
|
||||
Added the ``newline_sequence``,, ``keep_trailing_newline``,
|
||||
Added the ``newline_sequence``, ``keep_trailing_newline``,
|
||||
and ``enable_async`` parameters to match ``__init__``.
|
||||
"""
|
||||
args = dict(locals())
|
||||
@@ -670,7 +675,7 @@ class Environment:
|
||||
stream = ext.filter_stream(stream) # type: ignore
|
||||
|
||||
if not isinstance(stream, TokenStream):
|
||||
stream = TokenStream(stream, name, filename) # type: ignore
|
||||
stream = TokenStream(stream, name, filename)
|
||||
|
||||
return stream
|
||||
|
||||
@@ -701,18 +706,17 @@ class Environment:
|
||||
|
||||
.. versionadded:: 2.5
|
||||
"""
|
||||
return compile(source, filename, "exec") # type: ignore
|
||||
return compile(source, filename, "exec")
|
||||
|
||||
@typing.overload
|
||||
def compile( # type: ignore
|
||||
def compile(
|
||||
self,
|
||||
source: t.Union[str, nodes.Template],
|
||||
name: t.Optional[str] = None,
|
||||
filename: t.Optional[str] = None,
|
||||
raw: "te.Literal[False]" = False,
|
||||
defer_init: bool = False,
|
||||
) -> CodeType:
|
||||
...
|
||||
) -> CodeType: ...
|
||||
|
||||
@typing.overload
|
||||
def compile(
|
||||
@@ -722,8 +726,7 @@ class Environment:
|
||||
filename: t.Optional[str] = None,
|
||||
raw: "te.Literal[True]" = ...,
|
||||
defer_init: bool = False,
|
||||
) -> str:
|
||||
...
|
||||
) -> str: ...
|
||||
|
||||
@internalcode
|
||||
def compile(
|
||||
@@ -814,7 +817,7 @@ class Environment:
|
||||
|
||||
def compile_templates(
|
||||
self,
|
||||
target: t.Union[str, os.PathLike],
|
||||
target: t.Union[str, "os.PathLike[str]"],
|
||||
extensions: t.Optional[t.Collection[str]] = None,
|
||||
filter_func: t.Optional[t.Callable[[str], bool]] = None,
|
||||
zip: t.Optional[str] = "deflated",
|
||||
@@ -858,7 +861,10 @@ class Environment:
|
||||
f.write(data.encode("utf8"))
|
||||
|
||||
if zip is not None:
|
||||
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
|
||||
from zipfile import ZIP_DEFLATED
|
||||
from zipfile import ZIP_STORED
|
||||
from zipfile import ZipFile
|
||||
from zipfile import ZipInfo
|
||||
|
||||
zip_file = ZipFile(
|
||||
target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip]
|
||||
@@ -920,7 +926,7 @@ class Environment:
|
||||
)
|
||||
|
||||
def filter_func(x: str) -> bool:
|
||||
return "." in x and x.rsplit(".", 1)[1] in extensions # type: ignore
|
||||
return "." in x and x.rsplit(".", 1)[1] in extensions
|
||||
|
||||
if filter_func is not None:
|
||||
names = [name for name in names if filter_func(name)]
|
||||
@@ -1245,7 +1251,7 @@ class Template:
|
||||
namespace: t.MutableMapping[str, t.Any],
|
||||
globals: t.MutableMapping[str, t.Any],
|
||||
) -> "Template":
|
||||
t: "Template" = object.__new__(cls)
|
||||
t: Template = object.__new__(cls)
|
||||
t.environment = environment
|
||||
t.globals = globals
|
||||
t.name = namespace["name"]
|
||||
@@ -1253,7 +1259,7 @@ class Template:
|
||||
t.blocks = namespace["blocks"]
|
||||
|
||||
# render function and module
|
||||
t.root_render_func = namespace["root"] # type: ignore
|
||||
t.root_render_func = namespace["root"]
|
||||
t._module = None
|
||||
|
||||
# debug and loader helpers
|
||||
@@ -1279,19 +1285,7 @@ class Template:
|
||||
if self.environment.is_async:
|
||||
import asyncio
|
||||
|
||||
close = False
|
||||
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
close = True
|
||||
|
||||
try:
|
||||
return loop.run_until_complete(self.render_async(*args, **kwargs))
|
||||
finally:
|
||||
if close:
|
||||
loop.close()
|
||||
return asyncio.run(self.render_async(*args, **kwargs))
|
||||
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
@@ -1349,13 +1343,13 @@ class Template:
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
try:
|
||||
yield from self.root_render_func(ctx) # type: ignore
|
||||
yield from self.root_render_func(ctx)
|
||||
except Exception:
|
||||
yield self.environment.handle_exception()
|
||||
|
||||
async def generate_async(
|
||||
self, *args: t.Any, **kwargs: t.Any
|
||||
) -> t.AsyncIterator[str]:
|
||||
) -> t.AsyncGenerator[str, object]:
|
||||
"""An async version of :meth:`generate`. Works very similarly but
|
||||
returns an async iterator instead.
|
||||
"""
|
||||
@@ -1367,8 +1361,14 @@ class Template:
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
try:
|
||||
async for event in self.root_render_func(ctx): # type: ignore
|
||||
yield event
|
||||
agen = self.root_render_func(ctx)
|
||||
try:
|
||||
async for event in agen: # type: ignore
|
||||
yield event
|
||||
finally:
|
||||
# we can't use async with aclosing(...) because that's only
|
||||
# in 3.10+
|
||||
await agen.aclose() # type: ignore
|
||||
except Exception:
|
||||
yield self.environment.handle_exception()
|
||||
|
||||
@@ -1417,7 +1417,9 @@ class Template:
|
||||
"""
|
||||
ctx = self.new_context(vars, shared, locals)
|
||||
return TemplateModule(
|
||||
self, ctx, [x async for x in self.root_render_func(ctx)] # type: ignore
|
||||
self,
|
||||
ctx,
|
||||
[x async for x in self.root_render_func(ctx)], # type: ignore
|
||||
)
|
||||
|
||||
@internalcode
|
||||
@@ -1532,7 +1534,7 @@ class TemplateModule:
|
||||
" API you are using."
|
||||
)
|
||||
|
||||
body_stream = list(template.root_render_func(context)) # type: ignore
|
||||
body_stream = list(template.root_render_func(context))
|
||||
|
||||
self._body_stream = body_stream
|
||||
self.__dict__.update(context.get_exported())
|
||||
@@ -1564,7 +1566,7 @@ class TemplateExpression:
|
||||
|
||||
def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]:
|
||||
context = self._template.new_context(dict(*args, **kwargs))
|
||||
consume(self._template.root_render_func(context)) # type: ignore
|
||||
consume(self._template.root_render_func(context))
|
||||
rv = context.vars["result"]
|
||||
if self._undefined_to_none and isinstance(rv, Undefined):
|
||||
rv = None
|
||||
@@ -1588,7 +1590,7 @@ class TemplateStream:
|
||||
|
||||
def dump(
|
||||
self,
|
||||
fp: t.Union[str, t.IO],
|
||||
fp: t.Union[str, t.IO[bytes]],
|
||||
encoding: t.Optional[str] = None,
|
||||
errors: t.Optional[str] = "strict",
|
||||
) -> None:
|
||||
@@ -1606,22 +1608,25 @@ class TemplateStream:
|
||||
if encoding is None:
|
||||
encoding = "utf-8"
|
||||
|
||||
fp = open(fp, "wb")
|
||||
real_fp: t.IO[bytes] = open(fp, "wb")
|
||||
close = True
|
||||
else:
|
||||
real_fp = fp
|
||||
|
||||
try:
|
||||
if encoding is not None:
|
||||
iterable = (x.encode(encoding, errors) for x in self) # type: ignore
|
||||
else:
|
||||
iterable = self # type: ignore
|
||||
|
||||
if hasattr(fp, "writelines"):
|
||||
fp.writelines(iterable)
|
||||
if hasattr(real_fp, "writelines"):
|
||||
real_fp.writelines(iterable)
|
||||
else:
|
||||
for item in iterable:
|
||||
fp.write(item)
|
||||
real_fp.write(item)
|
||||
finally:
|
||||
if close:
|
||||
fp.close()
|
||||
real_fp.close()
|
||||
|
||||
def disable_buffering(self) -> None:
|
||||
"""Disable the output buffering."""
|
||||
|
||||
Reference in New Issue
Block a user