mirror of
https://gitee.com/openharmony/third_party_jinja2
synced 2024-11-23 07:10:31 +00:00
Merge branch '3.0.x'
This commit is contained in:
commit
cdbda09e44
11
CHANGES.rst
11
CHANGES.rst
@ -6,11 +6,17 @@ Version 3.1.0
|
||||
Unreleased
|
||||
|
||||
|
||||
Version 3.0.1
|
||||
Version 3.0.2
|
||||
-------------
|
||||
|
||||
Unreleased
|
||||
|
||||
|
||||
Version 3.0.1
|
||||
-------------
|
||||
|
||||
Released 2021-05-18
|
||||
|
||||
- Update MarkupSafe dependency to >= 2.0. :pr:`1418`
|
||||
- Mark top-level names as exported so type checking understands
|
||||
imports in user projects. :issue:`1426`
|
||||
@ -19,6 +25,9 @@ Unreleased
|
||||
extensions shows more relevant context. :issue:`1429`
|
||||
- Fixed calling deprecated ``jinja2.Markup`` without an argument.
|
||||
Use ``markupsafe.Markup`` instead. :issue:`1438`
|
||||
- Calling sync ``render`` for an async template uses ``asyncio.run``
|
||||
on Python >= 3.7. This fixes a deprecation that Python 3.10
|
||||
introduces. :issue:`1443`
|
||||
|
||||
|
||||
Version 3.0.0
|
||||
|
@ -513,12 +513,12 @@ handle async and sync code in an asyncio event loop. This has the
|
||||
following implications:
|
||||
|
||||
- Template rendering requires an event loop to be available to the
|
||||
current thread. :func:`asyncio.get_event_loop` must return an event
|
||||
loop.
|
||||
current thread. :func:`asyncio.get_running_loop` must return an
|
||||
event loop.
|
||||
- The compiled code uses ``await`` for functions and attributes, and
|
||||
uses ``async for`` loops. In order to support using both async and
|
||||
sync functions in this context, a small wrapper is placed around
|
||||
all calls and access, which add overhead compared to purely async
|
||||
all calls and access, which adds overhead compared to purely async
|
||||
code.
|
||||
- Sync methods and filters become wrappers around their corresponding
|
||||
async implementations where needed. For example, ``render`` invokes
|
||||
|
@ -2,6 +2,7 @@
|
||||
options.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import typing
|
||||
import typing as t
|
||||
import weakref
|
||||
@ -1278,8 +1279,22 @@ class Template:
|
||||
if self.environment.is_async:
|
||||
import asyncio
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
return loop.run_until_complete(self.render_async(*args, **kwargs))
|
||||
close = False
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
loop = asyncio.get_event_loop()
|
||||
else:
|
||||
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()
|
||||
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
@ -1326,14 +1341,17 @@ class Template:
|
||||
if self.environment.is_async:
|
||||
import asyncio
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
async_gen = self.generate_async(*args, **kwargs)
|
||||
async def to_list() -> t.List[str]:
|
||||
return [x async for x in self.generate_async(*args, **kwargs)]
|
||||
|
||||
try:
|
||||
while True:
|
||||
yield loop.run_until_complete(async_gen.__anext__())
|
||||
except StopAsyncIteration:
|
||||
return
|
||||
if sys.version_info < (3, 7):
|
||||
loop = asyncio.get_event_loop()
|
||||
out = loop.run_until_complete(to_list())
|
||||
else:
|
||||
out = asyncio.run(to_list())
|
||||
|
||||
yield from out
|
||||
return
|
||||
|
||||
ctx = self.new_context(dict(*args, **kwargs))
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@ -27,8 +27,8 @@ def package_loader():
|
||||
@pytest.fixture
|
||||
def filesystem_loader():
|
||||
"""returns FileSystemLoader initialized to res/templates directory"""
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
return loaders.FileSystemLoader(here + "/res/templates")
|
||||
here = Path(__file__).parent.resolve()
|
||||
return loaders.FileSystemLoader(here / "res" / "templates")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -1,6 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@ -242,13 +242,12 @@ class TestStreaming:
|
||||
assert not stream.buffered
|
||||
|
||||
def test_dump_stream(self, env):
|
||||
tmp = tempfile.mkdtemp()
|
||||
tmp = Path(tempfile.mkdtemp())
|
||||
try:
|
||||
tmpl = env.from_string("\u2713")
|
||||
stream = tmpl.stream()
|
||||
stream.dump(os.path.join(tmp, "dump.txt"), "utf-8")
|
||||
with open(os.path.join(tmp, "dump.txt"), "rb") as f:
|
||||
assert f.read() == b"\xe2\x9c\x93"
|
||||
stream.dump(str(tmp / "dump.txt"), "utf-8")
|
||||
assert (tmp / "dump.txt").read_bytes() == b"\xe2\x9c\x93"
|
||||
finally:
|
||||
shutil.rmtree(tmp)
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
@ -13,9 +14,17 @@ from jinja2.exceptions import UndefinedError
|
||||
from jinja2.nativetypes import NativeEnvironment
|
||||
|
||||
|
||||
def run(coro):
|
||||
loop = asyncio.get_event_loop()
|
||||
return loop.run_until_complete(coro)
|
||||
if sys.version_info < (3, 7):
|
||||
|
||||
def run(coro):
|
||||
loop = asyncio.get_event_loop()
|
||||
return loop.run_until_complete(coro)
|
||||
|
||||
|
||||
else:
|
||||
|
||||
def run(coro):
|
||||
return asyncio.run(coro)
|
||||
|
||||
|
||||
def test_basic_async():
|
||||
|
@ -8,6 +8,7 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import weakref
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@ -32,8 +33,7 @@ class TestLoaders:
|
||||
pytest.raises(TemplateNotFound, env.get_template, "missing.html")
|
||||
|
||||
def test_filesystem_loader_overlapping_names(self, filesystem_loader):
|
||||
res = os.path.dirname(filesystem_loader.searchpath[0])
|
||||
t2_dir = os.path.join(res, "templates2")
|
||||
t2_dir = Path(filesystem_loader.searchpath[0]) / ".." / "templates2"
|
||||
# Make "foo" show up before "foo/test.html".
|
||||
filesystem_loader.searchpath.insert(0, t2_dir)
|
||||
e = Environment(loader=filesystem_loader)
|
||||
@ -118,9 +118,7 @@ class TestLoaders:
|
||||
|
||||
|
||||
class TestFileSystemLoader:
|
||||
searchpath = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "res", "templates"
|
||||
)
|
||||
searchpath = (Path(__file__) / ".." / "res" / "templates").resolve()
|
||||
|
||||
@staticmethod
|
||||
def _test_common(env):
|
||||
@ -131,24 +129,20 @@ class TestFileSystemLoader:
|
||||
pytest.raises(TemplateNotFound, env.get_template, "missing.html")
|
||||
|
||||
def test_searchpath_as_str(self):
|
||||
filesystem_loader = loaders.FileSystemLoader(self.searchpath)
|
||||
filesystem_loader = loaders.FileSystemLoader(str(self.searchpath))
|
||||
|
||||
env = Environment(loader=filesystem_loader)
|
||||
self._test_common(env)
|
||||
|
||||
def test_searchpath_as_pathlib(self):
|
||||
import pathlib
|
||||
|
||||
searchpath = pathlib.Path(self.searchpath)
|
||||
filesystem_loader = loaders.FileSystemLoader(searchpath)
|
||||
filesystem_loader = loaders.FileSystemLoader(self.searchpath)
|
||||
env = Environment(loader=filesystem_loader)
|
||||
self._test_common(env)
|
||||
|
||||
def test_searchpath_as_list_including_pathlib(self):
|
||||
import pathlib
|
||||
|
||||
searchpath = pathlib.Path(self.searchpath)
|
||||
filesystem_loader = loaders.FileSystemLoader(["/tmp/templates", searchpath])
|
||||
filesystem_loader = loaders.FileSystemLoader(
|
||||
["/tmp/templates", self.searchpath]
|
||||
)
|
||||
env = Environment(loader=filesystem_loader)
|
||||
self._test_common(env)
|
||||
|
||||
@ -160,7 +154,7 @@ class TestFileSystemLoader:
|
||||
tmpl2 = env.get_template("test.html")
|
||||
assert tmpl1 is tmpl2
|
||||
|
||||
os.utime(os.path.join(self.searchpath, "test.html"), (time.time(), time.time()))
|
||||
os.utime(self.searchpath / "test.html", (time.time(), time.time()))
|
||||
tmpl3 = env.get_template("test.html")
|
||||
assert tmpl1 is not tmpl3
|
||||
|
||||
@ -282,10 +276,7 @@ class TestModuleLoader:
|
||||
self.compile_down(prefix_loader)
|
||||
|
||||
mod_path = self.mod_env.loader.module.__path__[0]
|
||||
|
||||
import pathlib
|
||||
|
||||
mod_loader = loaders.ModuleLoader(pathlib.Path(mod_path))
|
||||
mod_loader = loaders.ModuleLoader(Path(mod_path))
|
||||
self.mod_env = Environment(loader=mod_loader)
|
||||
|
||||
self._test_common()
|
||||
@ -294,10 +285,7 @@ class TestModuleLoader:
|
||||
self.compile_down(prefix_loader)
|
||||
|
||||
mod_path = self.mod_env.loader.module.__path__[0]
|
||||
|
||||
import pathlib
|
||||
|
||||
mod_loader = loaders.ModuleLoader([pathlib.Path(mod_path), "/tmp/templates"])
|
||||
mod_loader = loaders.ModuleLoader([Path(mod_path), "/tmp/templates"])
|
||||
self.mod_env = Environment(loader=mod_loader)
|
||||
|
||||
self._test_common()
|
||||
@ -305,7 +293,7 @@ class TestModuleLoader:
|
||||
|
||||
@pytest.fixture()
|
||||
def package_dir_loader(monkeypatch):
|
||||
monkeypatch.syspath_prepend(os.path.dirname(__file__))
|
||||
monkeypatch.syspath_prepend(Path(__file__).parent)
|
||||
return PackageLoader("res")
|
||||
|
||||
|
||||
@ -327,9 +315,8 @@ def test_package_dir_list(package_dir_loader):
|
||||
|
||||
@pytest.fixture()
|
||||
def package_zip_loader(monkeypatch):
|
||||
monkeypatch.syspath_prepend(
|
||||
os.path.join(os.path.dirname(__file__), "res", "package.zip")
|
||||
)
|
||||
package_zip = (Path(__file__) / ".." / "res" / "package.zip").resolve()
|
||||
monkeypatch.syspath_prepend(package_zip)
|
||||
return PackageLoader("t_pack")
|
||||
|
||||
|
||||
|
@ -23,22 +23,17 @@ class TestLRUCache:
|
||||
d["c"] = 3
|
||||
d["a"]
|
||||
d["d"] = 4
|
||||
assert len(d) == 3
|
||||
assert "a" in d and "c" in d and "d" in d and "b" not in d
|
||||
assert d.keys() == ["d", "a", "c"]
|
||||
|
||||
def test_itervalues(self):
|
||||
def test_values(self):
|
||||
cache = LRUCache(3)
|
||||
cache["b"] = 1
|
||||
cache["a"] = 2
|
||||
values = [v for v in cache.values()]
|
||||
assert len(values) == 2
|
||||
assert 1 in values
|
||||
assert 2 in values
|
||||
assert cache.values() == [2, 1]
|
||||
|
||||
def test_itervalues_empty(self):
|
||||
def test_values_empty(self):
|
||||
cache = LRUCache(2)
|
||||
values = [v for v in cache.values()]
|
||||
assert len(values) == 0
|
||||
assert cache.values() == []
|
||||
|
||||
def test_pickleable(self):
|
||||
cache = LRUCache(2)
|
||||
@ -61,7 +56,7 @@ class TestLRUCache:
|
||||
assert copy._queue == cache._queue
|
||||
copy["c"] = 3
|
||||
assert copy._queue != cache._queue
|
||||
assert "a" not in copy and "b" in copy and "c" in copy
|
||||
assert copy.keys() == ["c", "b"]
|
||||
|
||||
def test_clear(self):
|
||||
d = LRUCache(3)
|
||||
|
Loading…
Reference in New Issue
Block a user