2019-06-01 08:35:03 -07:00
|
|
|
import logging
|
2011-09-01 12:35:04 -04:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
import pytest
|
2019-06-01 08:35:03 -07:00
|
|
|
import werkzeug.serving
|
|
|
|
|
from jinja2 import TemplateNotFound
|
2023-02-23 08:55:01 -08:00
|
|
|
from markupsafe import Markup
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2011-08-26 11:21:26 +01:00
|
|
|
import flask
|
2014-09-03 17:57:44 +02:00
|
|
|
|
2014-09-03 21:02:03 +02:00
|
|
|
|
2017-05-24 17:27:36 -07:00
|
|
|
def test_context_processing(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.context_processor
|
|
|
|
|
def context_processor():
|
2019-05-06 15:39:41 -04:00
|
|
|
return {"injected_value": 42}
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("context_template.html", value=23)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"<p>23|42"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_original_win(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template_string("{{ config }}", config=42)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"42"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2022-06-09 09:21:48 +01:00
|
|
|
def test_simple_stream(app, client):
|
|
|
|
|
@app.route("/")
|
|
|
|
|
def index():
|
|
|
|
|
return flask.stream_template_string("{{ config }}", config=42)
|
|
|
|
|
|
|
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"42"
|
|
|
|
|
|
|
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
def test_request_less_rendering(app, app_ctx):
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["WORLD_NAME"] = "Special World"
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.context_processor
|
|
|
|
|
def context_processor():
|
|
|
|
|
return dict(foo=42)
|
|
|
|
|
|
2019-06-01 09:22:20 -07:00
|
|
|
rv = flask.render_template_string("Hello {{ config.WORLD_NAME }} {{ foo }}")
|
2019-05-06 15:39:41 -04:00
|
|
|
assert rv == "Hello Special World 42"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_standard_context(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
|
|
|
|
flask.g.foo = 23
|
2019-05-06 15:39:41 -04:00
|
|
|
flask.session["test"] = "aha"
|
|
|
|
|
return flask.render_template_string(
|
|
|
|
|
"""
|
2014-09-03 20:50:54 +02:00
|
|
|
{{ request.args.foo }}
|
|
|
|
|
{{ g.foo }}
|
|
|
|
|
{{ config.DEBUG }}
|
|
|
|
|
{{ session.test }}
|
2019-05-06 15:39:41 -04:00
|
|
|
"""
|
|
|
|
|
)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/?foo=42")
|
|
|
|
|
assert rv.data.split() == [b"42", b"23", b"False", b"aha"]
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_escaping(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
text = "<p>Hello World!"
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template(
|
2023-02-23 08:55:01 -08:00
|
|
|
"escaping_template.html", text=text, html=Markup(text)
|
2019-05-06 15:39:41 -04:00
|
|
|
)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
lines = client.get("/").data.splitlines()
|
2014-09-03 20:50:54 +02:00
|
|
|
assert lines == [
|
2019-05-06 15:39:41 -04:00
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
2014-09-03 20:50:54 +02:00
|
|
|
]
|
|
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_no_escaping(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
text = "<p>Hello World!"
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2015-06-30 11:00:14 -07:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template(
|
2023-02-23 08:55:01 -08:00
|
|
|
"non_escaping_template.txt", text=text, html=Markup(text)
|
2019-05-06 15:39:41 -04:00
|
|
|
)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
lines = client.get("/").data.splitlines()
|
2015-06-30 11:00:14 -07:00
|
|
|
assert lines == [
|
2019-05-06 15:39:41 -04:00
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
|
|
|
|
b"<p>Hello World!",
|
2015-06-30 11:00:14 -07:00
|
|
|
]
|
|
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
def test_escaping_without_template_filename(app, client, req_ctx):
|
2019-05-06 15:39:41 -04:00
|
|
|
assert flask.render_template_string("{{ foo }}", foo="<test>") == "<test>"
|
|
|
|
|
assert flask.render_template("mail.txt", foo="<test>") == "<test> Mail"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_macros(app, req_ctx):
|
2019-05-06 15:39:41 -04:00
|
|
|
macro = flask.get_template_attribute("_macro.html", "hello")
|
|
|
|
|
assert macro("World") == "Hello World!"
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_template_filter(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.template_filter()
|
|
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "my_reverse" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["my_reverse"] == my_reverse
|
|
|
|
|
assert app.jinja_env.filters["my_reverse"]("abcd") == "dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2025-05-17 12:17:18 +08:00
|
|
|
@app.template_filter
|
|
|
|
|
def my_reverse_2(s):
|
|
|
|
|
return s[::-1]
|
|
|
|
|
|
|
|
|
|
assert "my_reverse_2" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_2"] == my_reverse_2
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_2"]("abcd") == "dcba"
|
|
|
|
|
|
|
|
|
|
@app.template_filter("my_reverse_custom_name_3")
|
|
|
|
|
def my_reverse_3(s):
|
|
|
|
|
return s[::-1]
|
|
|
|
|
|
|
|
|
|
assert "my_reverse_custom_name_3" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_custom_name_3"] == my_reverse_3
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_custom_name_3"]("abcd") == "dcba"
|
|
|
|
|
|
|
|
|
|
@app.template_filter(name="my_reverse_custom_name_4")
|
|
|
|
|
def my_reverse_4(s):
|
|
|
|
|
return s[::-1]
|
|
|
|
|
|
|
|
|
|
assert "my_reverse_custom_name_4" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_custom_name_4"] == my_reverse_4
|
|
|
|
|
assert app.jinja_env.filters["my_reverse_custom_name_4"]("abcd") == "dcba"
|
|
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_filter(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
app.add_template_filter(my_reverse)
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "my_reverse" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["my_reverse"] == my_reverse
|
|
|
|
|
assert app.jinja_env.filters["my_reverse"]("abcd") == "dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_filter_with_name(app):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.template_filter("strrev")
|
2014-09-03 20:50:54 +02:00
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "strrev" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["strrev"] == my_reverse
|
|
|
|
|
assert app.jinja_env.filters["strrev"]("abcd") == "dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_filter_with_name(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
app.add_template_filter(my_reverse, "strrev")
|
|
|
|
|
assert "strrev" in app.jinja_env.filters.keys()
|
|
|
|
|
assert app.jinja_env.filters["strrev"] == my_reverse
|
|
|
|
|
assert app.jinja_env.filters["strrev"]("abcd") == "dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_filter_with_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.template_filter()
|
|
|
|
|
def super_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_filter_with_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
def super_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
app.add_template_filter(super_reverse)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_filter_with_name_and_template(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.template_filter("super_reverse")
|
2014-09-03 20:50:54 +02:00
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_filter_with_name_and_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
def my_reverse(s):
|
|
|
|
|
return s[::-1]
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
app.add_template_filter(my_reverse, "super_reverse")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_test(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.template_test()
|
|
|
|
|
def boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "boolean" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["boolean"] == boolean
|
|
|
|
|
assert app.jinja_env.tests["boolean"](False)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2025-05-17 12:17:18 +08:00
|
|
|
@app.template_test
|
|
|
|
|
def boolean_2(value):
|
|
|
|
|
return isinstance(value, bool)
|
|
|
|
|
|
|
|
|
|
assert "boolean_2" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["boolean_2"] == boolean_2
|
|
|
|
|
assert app.jinja_env.tests["boolean_2"](False)
|
|
|
|
|
|
|
|
|
|
@app.template_test("my_boolean_custom_name")
|
|
|
|
|
def boolean_3(value):
|
|
|
|
|
return isinstance(value, bool)
|
|
|
|
|
|
|
|
|
|
assert "my_boolean_custom_name" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["my_boolean_custom_name"] == boolean_3
|
|
|
|
|
assert app.jinja_env.tests["my_boolean_custom_name"](False)
|
|
|
|
|
|
|
|
|
|
@app.template_test(name="my_boolean_custom_name_2")
|
|
|
|
|
def boolean_4(value):
|
|
|
|
|
return isinstance(value, bool)
|
|
|
|
|
|
|
|
|
|
assert "my_boolean_custom_name_2" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["my_boolean_custom_name_2"] == boolean_4
|
|
|
|
|
assert app.jinja_env.tests["my_boolean_custom_name_2"](False)
|
|
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_test(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
def boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
app.add_template_test(boolean)
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "boolean" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["boolean"] == boolean
|
|
|
|
|
assert app.jinja_env.tests["boolean"](False)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_test_with_name(app):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.template_test("boolean")
|
2014-09-03 20:50:54 +02:00
|
|
|
def is_boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "boolean" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["boolean"] == is_boolean
|
|
|
|
|
assert app.jinja_env.tests["boolean"](False)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_test_with_name(app):
|
2014-09-03 20:50:54 +02:00
|
|
|
def is_boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
app.add_template_test(is_boolean, "boolean")
|
|
|
|
|
assert "boolean" in app.jinja_env.tests.keys()
|
|
|
|
|
assert app.jinja_env.tests["boolean"] == is_boolean
|
|
|
|
|
assert app.jinja_env.tests["boolean"](False)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2017-05-24 17:27:36 -07:00
|
|
|
def test_template_test_with_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.template_test()
|
|
|
|
|
def boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_test_with_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
def boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
app.add_template_test(boolean)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_template_test_with_name_and_template(app, client):
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.template_test("boolean")
|
2014-09-03 20:50:54 +02:00
|
|
|
def is_boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_test_with_name_and_template(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
def is_boolean(value):
|
|
|
|
|
return isinstance(value, bool)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
app.add_template_test(is_boolean, "boolean")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_add_template_global(app, app_ctx):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.template_global()
|
|
|
|
|
def get_stuff():
|
|
|
|
|
return 42
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "get_stuff" in app.jinja_env.globals.keys()
|
|
|
|
|
assert app.jinja_env.globals["get_stuff"] == get_stuff
|
|
|
|
|
assert app.jinja_env.globals["get_stuff"](), 42
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = flask.render_template_string("{{ get_stuff() }}")
|
|
|
|
|
assert rv == "42"
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2025-05-17 12:17:18 +08:00
|
|
|
@app.template_global
|
|
|
|
|
def get_stuff_1():
|
|
|
|
|
return "get_stuff_1"
|
|
|
|
|
|
|
|
|
|
assert "get_stuff_1" in app.jinja_env.globals.keys()
|
|
|
|
|
assert app.jinja_env.globals["get_stuff_1"] == get_stuff_1
|
|
|
|
|
assert app.jinja_env.globals["get_stuff_1"](), "get_stuff_1"
|
|
|
|
|
|
|
|
|
|
rv = flask.render_template_string("{{ get_stuff_1() }}")
|
|
|
|
|
assert rv == "get_stuff_1"
|
|
|
|
|
|
|
|
|
|
@app.template_global("my_get_stuff_custom_name_2")
|
|
|
|
|
def get_stuff_2():
|
|
|
|
|
return "get_stuff_2"
|
|
|
|
|
|
|
|
|
|
assert "my_get_stuff_custom_name_2" in app.jinja_env.globals.keys()
|
|
|
|
|
assert app.jinja_env.globals["my_get_stuff_custom_name_2"] == get_stuff_2
|
|
|
|
|
assert app.jinja_env.globals["my_get_stuff_custom_name_2"](), "get_stuff_2"
|
|
|
|
|
|
|
|
|
|
rv = flask.render_template_string("{{ my_get_stuff_custom_name_2() }}")
|
|
|
|
|
assert rv == "get_stuff_2"
|
|
|
|
|
|
|
|
|
|
@app.template_global(name="my_get_stuff_custom_name_3")
|
|
|
|
|
def get_stuff_3():
|
|
|
|
|
return "get_stuff_3"
|
|
|
|
|
|
|
|
|
|
assert "my_get_stuff_custom_name_3" in app.jinja_env.globals.keys()
|
|
|
|
|
assert app.jinja_env.globals["my_get_stuff_custom_name_3"] == get_stuff_3
|
|
|
|
|
assert app.jinja_env.globals["my_get_stuff_custom_name_3"](), "get_stuff_3"
|
|
|
|
|
|
|
|
|
|
rv = flask.render_template_string("{{ my_get_stuff_custom_name_3() }}")
|
|
|
|
|
assert rv == "get_stuff_3"
|
|
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_custom_template_loader(client):
|
2014-09-03 20:50:54 +02:00
|
|
|
class MyFlask(flask.Flask):
|
|
|
|
|
def create_global_jinja_loader(self):
|
|
|
|
|
from jinja2 import DictLoader
|
2019-05-06 15:39:41 -04:00
|
|
|
|
|
|
|
|
return DictLoader({"index.html": "Hello Custom World!"})
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
app = MyFlask(__name__)
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
2019-05-06 15:39:41 -04:00
|
|
|
return flask.render_template("index.html")
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
c = app.test_client()
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = c.get("/")
|
|
|
|
|
assert rv.data == b"Hello Custom World!"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_iterable_loader(app, client):
|
2014-09-03 20:50:54 +02:00
|
|
|
@app.context_processor
|
|
|
|
|
def context_processor():
|
2019-05-06 15:39:41 -04:00
|
|
|
return {"whiskey": "Jameson"}
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
@app.route("/")
|
2014-09-03 20:50:54 +02:00
|
|
|
def index():
|
|
|
|
|
return flask.render_template(
|
2019-05-06 15:39:41 -04:00
|
|
|
[
|
|
|
|
|
"no_template.xml", # should skip this one
|
|
|
|
|
"simple_template.html", # should render this
|
|
|
|
|
"context_template.html",
|
|
|
|
|
],
|
|
|
|
|
value=23,
|
|
|
|
|
)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
rv = client.get("/")
|
|
|
|
|
assert rv.data == b"<h1>Jameson</h1>"
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
|
|
|
|
def test_templates_auto_reload(app):
|
2014-10-26 18:28:12 +03:00
|
|
|
# debug is False, config option is None
|
|
|
|
|
assert app.debug is False
|
2019-05-06 15:39:41 -04:00
|
|
|
assert app.config["TEMPLATES_AUTO_RELOAD"] is None
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.jinja_env.auto_reload is False
|
|
|
|
|
# debug is False, config option is False
|
2014-09-03 20:50:54 +02:00
|
|
|
app = flask.Flask(__name__)
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["TEMPLATES_AUTO_RELOAD"] = False
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.debug is False
|
|
|
|
|
assert app.jinja_env.auto_reload is False
|
|
|
|
|
# debug is False, config option is True
|
|
|
|
|
app = flask.Flask(__name__)
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.debug is False
|
|
|
|
|
assert app.jinja_env.auto_reload is True
|
|
|
|
|
# debug is True, config option is None
|
|
|
|
|
app = flask.Flask(__name__)
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["DEBUG"] = True
|
|
|
|
|
assert app.config["TEMPLATES_AUTO_RELOAD"] is None
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.jinja_env.auto_reload is True
|
|
|
|
|
# debug is True, config option is False
|
|
|
|
|
app = flask.Flask(__name__)
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["DEBUG"] = True
|
|
|
|
|
app.config["TEMPLATES_AUTO_RELOAD"] = False
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.jinja_env.auto_reload is False
|
|
|
|
|
# debug is True, config option is True
|
|
|
|
|
app = flask.Flask(__name__)
|
2019-05-06 15:39:41 -04:00
|
|
|
app.config["DEBUG"] = True
|
|
|
|
|
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
2014-10-26 18:28:12 +03:00
|
|
|
assert app.jinja_env.auto_reload is True
|
2014-09-03 20:50:54 +02:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
|
2017-06-14 12:31:56 -07:00
|
|
|
def test_templates_auto_reload_debug_run(app, monkeypatch):
|
2016-06-15 02:15:33 +01:00
|
|
|
def run_simple_mock(*args, **kwargs):
|
2016-06-15 02:25:48 +01:00
|
|
|
pass
|
2016-06-15 02:15:33 +01:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
|
2016-06-15 02:15:33 +01:00
|
|
|
|
2017-06-14 12:31:56 -07:00
|
|
|
app.run()
|
2019-05-31 14:53:26 -04:00
|
|
|
assert not app.jinja_env.auto_reload
|
2017-06-14 12:31:56 -07:00
|
|
|
|
2016-06-15 02:15:33 +01:00
|
|
|
app.run(debug=True)
|
2019-05-31 14:53:26 -04:00
|
|
|
assert app.jinja_env.auto_reload
|
2016-06-15 02:15:33 +01:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2017-07-28 14:55:52 -07:00
|
|
|
def test_template_loader_debugging(test_apps, monkeypatch):
|
2014-09-03 20:50:54 +02:00
|
|
|
from blueprintapp import app
|
|
|
|
|
|
|
|
|
|
called = []
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2014-09-03 20:50:54 +02:00
|
|
|
class _TestHandler(logging.Handler):
|
2019-05-31 14:53:26 -04:00
|
|
|
def handle(self, record):
|
2014-09-03 20:50:54 +02:00
|
|
|
called.append(True)
|
|
|
|
|
text = str(record.msg)
|
2020-04-04 11:39:03 -07:00
|
|
|
assert "1: trying loader of application 'blueprintapp'" in text
|
2019-05-06 15:39:41 -04:00
|
|
|
assert (
|
2020-04-04 11:39:03 -07:00
|
|
|
"2: trying loader of blueprint 'admin' (blueprintapp.apps.admin)"
|
2019-05-06 15:39:41 -04:00
|
|
|
) in text
|
|
|
|
|
assert (
|
2020-04-04 11:39:03 -07:00
|
|
|
"trying loader of blueprint 'frontend' (blueprintapp.apps.frontend)"
|
2019-05-06 15:39:41 -04:00
|
|
|
) in text
|
|
|
|
|
assert "Error: the template could not be found" in text
|
|
|
|
|
assert (
|
2020-04-04 11:39:03 -07:00
|
|
|
"looked up from an endpoint that belongs to the blueprint 'frontend'"
|
2019-05-06 15:39:41 -04:00
|
|
|
) in text
|
2019-11-15 12:27:44 +08:00
|
|
|
assert "See https://flask.palletsprojects.com/blueprints/#templates" in text
|
2014-09-03 20:50:54 +02:00
|
|
|
|
|
|
|
|
with app.test_client() as c:
|
2019-05-06 15:39:41 -04:00
|
|
|
monkeypatch.setitem(app.config, "EXPLAIN_TEMPLATE_LOADING", True)
|
2019-07-01 14:56:18 -07:00
|
|
|
monkeypatch.setattr(
|
|
|
|
|
logging.getLogger("blueprintapp"), "handlers", [_TestHandler()]
|
|
|
|
|
)
|
2017-07-28 14:55:52 -07:00
|
|
|
|
|
|
|
|
with pytest.raises(TemplateNotFound) as excinfo:
|
2019-05-06 15:39:41 -04:00
|
|
|
c.get("/missing")
|
2017-07-28 14:55:52 -07:00
|
|
|
|
2019-05-06 15:39:41 -04:00
|
|
|
assert "missing_template.html" in str(excinfo.value)
|
2014-09-03 20:50:54 +02:00
|
|
|
|
|
|
|
|
assert len(called) == 1
|
2015-04-06 14:55:01 +02:00
|
|
|
|
2017-05-23 15:18:39 -07:00
|
|
|
|
2015-04-06 14:55:01 +02:00
|
|
|
def test_custom_jinja_env():
|
|
|
|
|
class CustomEnvironment(flask.templating.Environment):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
class CustomFlask(flask.Flask):
|
2015-06-06 06:29:24 +02:00
|
|
|
jinja_environment = CustomEnvironment
|
2015-04-06 14:55:01 +02:00
|
|
|
|
|
|
|
|
app = CustomFlask(__name__)
|
|
|
|
|
assert isinstance(app.jinja_env, CustomEnvironment)
|
2026-01-24 16:26:46 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_template_string_caching(app, app_ctx):
|
|
|
|
|
"""Test that render_template_string caches compiled templates."""
|
|
|
|
|
source = "Hello {{ name }}!"
|
|
|
|
|
cache = app.jinja_env._string_template_cache
|
|
|
|
|
|
|
|
|
|
# Cache should be empty initially
|
|
|
|
|
assert len(cache) == 0
|
|
|
|
|
|
|
|
|
|
# First render should add to cache
|
|
|
|
|
result1 = flask.render_template_string(source, name="World")
|
|
|
|
|
assert result1 == "Hello World!"
|
|
|
|
|
assert len(cache) == 1
|
|
|
|
|
assert source in cache
|
|
|
|
|
|
|
|
|
|
# Second render should use cached template
|
|
|
|
|
cached_template = cache[source]
|
|
|
|
|
result2 = flask.render_template_string(source, name="Flask")
|
|
|
|
|
assert result2 == "Hello Flask!"
|
|
|
|
|
assert len(cache) == 1
|
|
|
|
|
assert cache[source] is cached_template # Same object
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_stream_template_string_caching(app, app_ctx):
|
|
|
|
|
"""Test that stream_template_string uses the same cache."""
|
|
|
|
|
source = "Hello {{ name }}!"
|
|
|
|
|
cache = app.jinja_env._string_template_cache
|
|
|
|
|
|
|
|
|
|
# Render with stream_template_string
|
|
|
|
|
result = "".join(flask.stream_template_string(source, name="World"))
|
|
|
|
|
assert result == "Hello World!"
|
|
|
|
|
assert source in cache
|
|
|
|
|
|
|
|
|
|
# Render same source with render_template_string should hit cache
|
|
|
|
|
cached_template = cache[source]
|
|
|
|
|
result2 = flask.render_template_string(source, name="Flask")
|
|
|
|
|
assert result2 == "Hello Flask!"
|
|
|
|
|
assert cache[source] is cached_template
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_template_string_cache_per_app(app_ctx):
|
|
|
|
|
"""Test that each app has its own template string cache."""
|
|
|
|
|
app1 = flask.Flask(__name__)
|
|
|
|
|
app2 = flask.Flask(__name__)
|
|
|
|
|
source = "Hello {{ name }}!"
|
|
|
|
|
|
|
|
|
|
with app1.app_context():
|
|
|
|
|
flask.render_template_string(source, name="App1")
|
|
|
|
|
|
|
|
|
|
with app2.app_context():
|
|
|
|
|
flask.render_template_string(source, name="App2")
|
|
|
|
|
|
|
|
|
|
# Each app should have its own cache with the template
|
|
|
|
|
assert source in app1.jinja_env._string_template_cache
|
|
|
|
|
assert source in app2.jinja_env._string_template_cache
|
|
|
|
|
# But they should be different template objects (different environments)
|
|
|
|
|
assert (
|
|
|
|
|
app1.jinja_env._string_template_cache[source]
|
|
|
|
|
is not app2.jinja_env._string_template_cache[source]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_template_string_cache_lru_eviction(app, app_ctx):
|
|
|
|
|
"""Test that the cache evicts least recently used templates."""
|
|
|
|
|
# Set a small cache size for testing
|
|
|
|
|
app.jinja_env.string_template_cache_size = 3
|
|
|
|
|
cache = app.jinja_env._string_template_cache
|
|
|
|
|
|
|
|
|
|
# Fill the cache
|
|
|
|
|
flask.render_template_string("{{ a }}", a=1)
|
|
|
|
|
flask.render_template_string("{{ b }}", b=2)
|
|
|
|
|
flask.render_template_string("{{ c }}", c=3)
|
|
|
|
|
assert len(cache) == 3
|
|
|
|
|
assert list(cache.keys()) == ["{{ a }}", "{{ b }}", "{{ c }}"]
|
|
|
|
|
|
|
|
|
|
# Access the first one to make it recently used
|
|
|
|
|
flask.render_template_string("{{ a }}", a=1)
|
|
|
|
|
assert list(cache.keys()) == ["{{ b }}", "{{ c }}", "{{ a }}"]
|
|
|
|
|
|
|
|
|
|
# Add a new template, should evict "{{ b }}" (least recently used)
|
|
|
|
|
flask.render_template_string("{{ d }}", d=4)
|
|
|
|
|
assert len(cache) == 3
|
|
|
|
|
assert "{{ b }}" not in cache
|
|
|
|
|
assert list(cache.keys()) == ["{{ c }}", "{{ a }}", "{{ d }}"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_template_string_cache_max_len(app, app_ctx):
|
|
|
|
|
"""Test that templates exceeding max length are not cached."""
|
|
|
|
|
# Set a small max length for testing
|
|
|
|
|
app.jinja_env.string_template_cache_max_len = 20
|
|
|
|
|
cache = app.jinja_env._string_template_cache
|
|
|
|
|
|
|
|
|
|
# Short template should be cached
|
|
|
|
|
short_source = "{{ x }}"
|
|
|
|
|
flask.render_template_string(short_source, x=1)
|
|
|
|
|
assert short_source in cache
|
|
|
|
|
|
|
|
|
|
# Long template should not be cached
|
|
|
|
|
long_source = "{{ x }}" + " " * 20 # exceeds max_len of 20
|
|
|
|
|
result = flask.render_template_string(long_source, x=2)
|
|
|
|
|
assert result == "2" + " " * 20
|
|
|
|
|
assert long_source not in cache
|