2014-09-02 11:26:52 +08:00
|
|
|
import pytest
|
2019-06-01 23:35:03 +08:00
|
|
|
from jinja2 import TemplateNotFound
|
|
|
|
from werkzeug.http import parse_cache_control_header
|
2014-09-02 11:26:52 +08:00
|
|
|
|
2011-08-26 18:21:26 +08:00
|
|
|
import flask
|
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_blueprint_specific_error_handling(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
frontend = flask.Blueprint("frontend", __name__)
|
|
|
|
backend = flask.Blueprint("backend", __name__)
|
|
|
|
sideend = flask.Blueprint("sideend", __name__)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@frontend.errorhandler(403)
|
|
|
|
def frontend_forbidden(e):
|
2019-05-07 03:39:41 +08:00
|
|
|
return "frontend says no", 403
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@frontend.route("/frontend-no")
|
2014-09-04 02:56:10 +08:00
|
|
|
def frontend_no():
|
|
|
|
flask.abort(403)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@backend.errorhandler(403)
|
|
|
|
def backend_forbidden(e):
|
2019-05-07 03:39:41 +08:00
|
|
|
return "backend says no", 403
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@backend.route("/backend-no")
|
2014-09-04 02:56:10 +08:00
|
|
|
def backend_no():
|
|
|
|
flask.abort(403)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@sideend.route("/what-is-a-sideend")
|
2014-09-04 02:56:10 +08:00
|
|
|
def sideend_no():
|
|
|
|
flask.abort(403)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
app.register_blueprint(frontend)
|
|
|
|
app.register_blueprint(backend)
|
|
|
|
app.register_blueprint(sideend)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.errorhandler(403)
|
|
|
|
def app_forbidden(e):
|
2019-05-07 03:39:41 +08:00
|
|
|
return "application itself says no", 403
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/frontend-no").data == b"frontend says no"
|
|
|
|
assert client.get("/backend-no").data == b"backend says no"
|
|
|
|
assert client.get("/what-is-a-sideend").data == b"application itself says no"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_blueprint_specific_user_error_handling(app, client):
|
2014-09-04 02:56:10 +08:00
|
|
|
class MyDecoratorException(Exception):
|
|
|
|
pass
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
class MyFunctionException(Exception):
|
|
|
|
pass
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
blue = flask.Blueprint("blue", __name__)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
@blue.errorhandler(MyDecoratorException)
|
|
|
|
def my_decorator_exception_handler(e):
|
|
|
|
assert isinstance(e, MyDecoratorException)
|
2019-05-07 03:39:41 +08:00
|
|
|
return "boom"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
def my_function_exception_handler(e):
|
|
|
|
assert isinstance(e, MyFunctionException)
|
2019-05-07 03:39:41 +08:00
|
|
|
return "bam"
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
blue.register_error_handler(MyFunctionException, my_function_exception_handler)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@blue.route("/decorator")
|
2014-09-04 02:56:10 +08:00
|
|
|
def blue_deco_test():
|
|
|
|
raise MyDecoratorException()
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@blue.route("/function")
|
2014-09-04 02:56:10 +08:00
|
|
|
def blue_func_test():
|
|
|
|
raise MyFunctionException()
|
|
|
|
|
|
|
|
app.register_blueprint(blue)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/decorator").data == b"boom"
|
|
|
|
assert client.get("/function").data == b"bam"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_blueprint_app_error_handling(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
errors = flask.Blueprint("errors", __name__)
|
2017-05-23 02:55:23 +08:00
|
|
|
|
|
|
|
@errors.app_errorhandler(403)
|
|
|
|
def forbidden_handler(e):
|
2019-05-07 03:39:41 +08:00
|
|
|
return "you shall not pass", 403
|
2017-05-23 02:55:23 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/forbidden")
|
2017-05-23 02:55:23 +08:00
|
|
|
def app_forbidden():
|
|
|
|
flask.abort(403)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
forbidden_bp = flask.Blueprint("forbidden_bp", __name__)
|
2017-05-23 02:55:23 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@forbidden_bp.route("/nope")
|
2017-05-23 02:55:23 +08:00
|
|
|
def bp_forbidden():
|
|
|
|
flask.abort(403)
|
|
|
|
|
|
|
|
app.register_blueprint(errors)
|
|
|
|
app.register_blueprint(forbidden_bp)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/forbidden").data == b"you shall not pass"
|
|
|
|
assert client.get("/nope").data == b"you shall not pass"
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("prefix", "rule", "url"),
|
|
|
|
(
|
|
|
|
("", "/", "/"),
|
|
|
|
("/", "", "/"),
|
|
|
|
("/", "/", "/"),
|
|
|
|
("/foo", "", "/foo"),
|
|
|
|
("/foo/", "", "/foo/"),
|
|
|
|
("", "/bar", "/bar"),
|
|
|
|
("/foo/", "/bar", "/foo/bar"),
|
|
|
|
("/foo/", "bar", "/foo/bar"),
|
|
|
|
("/foo", "/bar", "/foo/bar"),
|
|
|
|
("/foo/", "//bar", "/foo/bar"),
|
|
|
|
("/foo//", "/bar", "/foo/bar"),
|
|
|
|
),
|
|
|
|
)
|
2018-04-28 03:27:31 +08:00
|
|
|
def test_blueprint_prefix_slash(app, client, prefix, rule, url):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("test", __name__, url_prefix=prefix)
|
2018-04-28 03:27:31 +08:00
|
|
|
|
|
|
|
@bp.route(rule)
|
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return "", 204
|
2018-02-24 07:45:37 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
2018-04-28 03:27:31 +08:00
|
|
|
assert client.get(url).status_code == 204
|
2018-02-24 07:45:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_blueprint_url_defaults(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("test", __name__)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/foo", defaults={"baz": 42})
|
2014-09-04 02:56:10 +08:00
|
|
|
def foo(bar, baz):
|
2020-04-05 02:39:03 +08:00
|
|
|
return f"{bar}/{baz:d}"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/bar")
|
2014-09-04 02:56:10 +08:00
|
|
|
def bar(bar):
|
2020-04-04 09:33:40 +08:00
|
|
|
return str(bar)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/1", url_defaults={"bar": 23})
|
2021-05-21 04:08:28 +08:00
|
|
|
app.register_blueprint(bp, name="test2", url_prefix="/2", url_defaults={"bar": 19})
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/1/foo").data == b"23/42"
|
|
|
|
assert client.get("/2/foo").data == b"19/42"
|
|
|
|
assert client.get("/1/bar").data == b"23"
|
|
|
|
assert client.get("/2/bar").data == b"19"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_blueprint_url_processors(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("frontend", __name__, url_prefix="/<lang_code>")
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
@bp.url_defaults
|
|
|
|
def add_language_code(endpoint, values):
|
2019-05-07 03:39:41 +08:00
|
|
|
values.setdefault("lang_code", flask.g.lang_code)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
@bp.url_value_preprocessor
|
|
|
|
def pull_lang_code(endpoint, values):
|
2019-05-07 03:39:41 +08:00
|
|
|
flask.g.lang_code = values.pop("lang_code")
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for(".about")
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/about")
|
2014-09-04 02:56:10 +08:00
|
|
|
def about():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for(".index")
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/de/").data == b"/de/about"
|
|
|
|
assert client.get("/de/about").data == b"/de/"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
|
|
|
|
2014-09-04 20:37:48 +08:00
|
|
|
def test_templates_and_static(test_apps):
|
2014-09-04 02:56:10 +08:00
|
|
|
from blueprintapp import app
|
2019-05-07 03:39:41 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
client = app.test_client()
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"Hello from the Frontend"
|
|
|
|
rv = client.get("/admin/")
|
|
|
|
assert rv.data == b"Hello from the Admin"
|
|
|
|
rv = client.get("/admin/index2")
|
|
|
|
assert rv.data == b"Hello from the Admin"
|
|
|
|
rv = client.get("/admin/static/test.txt")
|
|
|
|
assert rv.data.strip() == b"Admin File"
|
2014-09-04 02:56:10 +08:00
|
|
|
rv.close()
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/admin/static/css/test.css")
|
|
|
|
assert rv.data.strip() == b"/* nested file */"
|
2014-09-04 02:56:10 +08:00
|
|
|
rv.close()
|
|
|
|
|
|
|
|
# try/finally, in case other tests use this app for Blueprint tests.
|
2019-05-07 03:39:41 +08:00
|
|
|
max_age_default = app.config["SEND_FILE_MAX_AGE_DEFAULT"]
|
2014-09-04 02:56:10 +08:00
|
|
|
try:
|
|
|
|
expected_max_age = 3600
|
2019-05-07 03:39:41 +08:00
|
|
|
if app.config["SEND_FILE_MAX_AGE_DEFAULT"] == expected_max_age:
|
2014-09-04 02:56:10 +08:00
|
|
|
expected_max_age = 7200
|
2019-05-07 03:39:41 +08:00
|
|
|
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = expected_max_age
|
|
|
|
rv = client.get("/admin/static/css/test.css")
|
|
|
|
cc = parse_cache_control_header(rv.headers["Cache-Control"])
|
2014-09-04 02:56:10 +08:00
|
|
|
assert cc.max_age == expected_max_age
|
|
|
|
rv.close()
|
|
|
|
finally:
|
2019-05-07 03:39:41 +08:00
|
|
|
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = max_age_default
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
with app.test_request_context():
|
2019-05-07 03:39:41 +08:00
|
|
|
assert (
|
|
|
|
flask.url_for("admin.static", filename="test.txt")
|
|
|
|
== "/admin/static/test.txt"
|
|
|
|
)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
with app.test_request_context():
|
2016-03-04 19:30:40 +08:00
|
|
|
with pytest.raises(TemplateNotFound) as e:
|
2019-05-07 03:39:41 +08:00
|
|
|
flask.render_template("missing.html")
|
|
|
|
assert e.value.name == "missing.html"
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
with flask.Flask(__name__).test_request_context():
|
2019-05-07 03:39:41 +08:00
|
|
|
assert flask.render_template("nested/nested.txt") == "I'm nested"
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2020-11-06 01:00:57 +08:00
|
|
|
def test_default_static_max_age(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
class MyBlueprint(flask.Blueprint):
|
|
|
|
def get_send_file_max_age(self, filename):
|
|
|
|
return 100
|
2014-03-22 05:15:31 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
blueprint = MyBlueprint("blueprint", __name__, static_folder="static")
|
2014-09-04 02:56:10 +08:00
|
|
|
app.register_blueprint(blueprint)
|
2014-03-22 05:15:31 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
# try/finally, in case other tests use this app for Blueprint tests.
|
2019-05-07 03:39:41 +08:00
|
|
|
max_age_default = app.config["SEND_FILE_MAX_AGE_DEFAULT"]
|
2014-09-04 02:56:10 +08:00
|
|
|
try:
|
|
|
|
with app.test_request_context():
|
|
|
|
unexpected_max_age = 3600
|
2019-05-07 03:39:41 +08:00
|
|
|
if app.config["SEND_FILE_MAX_AGE_DEFAULT"] == unexpected_max_age:
|
2014-09-04 02:56:10 +08:00
|
|
|
unexpected_max_age = 7200
|
2019-05-07 03:39:41 +08:00
|
|
|
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = unexpected_max_age
|
|
|
|
rv = blueprint.send_static_file("index.html")
|
|
|
|
cc = parse_cache_control_header(rv.headers["Cache-Control"])
|
2014-09-04 02:56:10 +08:00
|
|
|
assert cc.max_age == 100
|
|
|
|
rv.close()
|
|
|
|
finally:
|
2019-05-07 03:39:41 +08:00
|
|
|
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = max_age_default
|
2014-03-22 05:15:31 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 20:37:48 +08:00
|
|
|
def test_templates_list(test_apps):
|
2014-09-04 02:56:10 +08:00
|
|
|
from blueprintapp import app
|
2019-05-07 03:39:41 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
templates = sorted(app.jinja_env.list_templates())
|
2019-05-07 03:39:41 +08:00
|
|
|
assert templates == ["admin/index.html", "frontend/index.html"]
|
2014-03-22 05:15:31 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
def test_dotted_name_not_allowed(app, client):
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
flask.Blueprint("app.ui", __name__)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2023-03-05 02:09:34 +08:00
|
|
|
def test_empty_name_not_allowed(app, client):
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
flask.Blueprint("", __name__)
|
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_dotted_names_from_app(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
test = flask.Blueprint("test", __name__)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def app_index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for("test.index")
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@test.route("/test/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for("app_index")
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
app.register_blueprint(test)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"/test/"
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_empty_url_defaults(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/", defaults={"page": 1})
|
|
|
|
@bp.route("/page/<int:page>")
|
2014-09-04 02:56:10 +08:00
|
|
|
def something(page):
|
|
|
|
return str(page)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
app.register_blueprint(bp)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/").data == b"1"
|
|
|
|
assert client.get("/page/2").data == b"2"
|
2011-08-26 18:21:26 +08:00
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_route_decorator_custom_endpoint(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/foo")
|
2014-09-04 02:56:10 +08:00
|
|
|
def foo():
|
|
|
|
return flask.request.endpoint
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/bar", endpoint="bar")
|
2014-09-04 02:56:10 +08:00
|
|
|
def foo_bar():
|
|
|
|
return flask.request.endpoint
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/bar/123", endpoint="123")
|
2014-09-04 02:56:10 +08:00
|
|
|
def foo_bar_foo():
|
|
|
|
return flask.request.endpoint
|
2012-03-14 07:34:16 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/bar/foo")
|
2014-09-04 02:56:10 +08:00
|
|
|
def bar_foo():
|
|
|
|
return flask.request.endpoint
|
2011-08-26 18:21:26 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2011-08-31 17:32:59 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
|
|
|
return flask.request.endpoint
|
2011-08-31 17:32:59 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/").data == b"index"
|
|
|
|
assert client.get("/py/foo").data == b"bp.foo"
|
|
|
|
assert client.get("/py/bar").data == b"bp.bar"
|
|
|
|
assert client.get("/py/bar/123").data == b"bp.123"
|
|
|
|
assert client.get("/py/bar/foo").data == b"bp.bar_foo"
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2011-08-31 17:32:59 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_route_decorator_custom_endpoint_with_dots(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2011-08-31 17:32:59 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
bp.route("/", endpoint="a.b")(lambda: "")
|
2019-05-07 03:39:41 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
bp.add_url_rule("/", endpoint="a.b")
|
2017-08-19 11:41:03 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
def view():
|
|
|
|
return ""
|
2017-08-19 11:41:03 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
view.__name__ = "a.b"
|
2018-04-27 19:38:35 +08:00
|
|
|
|
2021-05-14 05:31:50 +08:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
bp.add_url_rule("/", view_func=view)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2016-06-04 06:50:38 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_endpoint_decorator(app, client):
|
2016-06-04 06:50:38 +08:00
|
|
|
from werkzeug.routing import Rule
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.url_map.add(Rule("/foo", endpoint="bar"))
|
|
|
|
|
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2016-06-04 06:50:38 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.endpoint("bar")
|
2016-06-04 06:50:38 +08:00
|
|
|
def foobar():
|
|
|
|
return flask.request.endpoint
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/bp_prefix")
|
2016-06-04 06:50:38 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/foo").data == b"bar"
|
|
|
|
assert client.get("/bp_prefix/bar").status_code == 404
|
2016-06-04 06:50:38 +08:00
|
|
|
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_template_filter(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_filter()
|
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_filter(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
bp.add_app_template_filter(my_reverse)
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_filter_with_name(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.app_template_filter("strrev")
|
2014-09-04 02:56:10 +08:00
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_filter_with_name(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp.add_app_template_filter(my_reverse, "strrev")
|
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_filter_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_filter()
|
|
|
|
def super_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_filter_after_route_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_filter()
|
|
|
|
def super_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_filter_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def super_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
bp.add_app_template_filter(super_reverse)
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_filter_with_name_and_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.app_template_filter("super_reverse")
|
2014-09-04 02:56:10 +08:00
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_filter_with_name_and_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def my_reverse(s):
|
|
|
|
return s[::-1]
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp.add_app_template_filter(my_reverse, "super_reverse")
|
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_filter.html", value="abcd")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert rv.data == b"dcba"
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_test(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_test()
|
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
assert "is_boolean" in app.jinja_env.tests.keys()
|
|
|
|
assert app.jinja_env.tests["is_boolean"] == is_boolean
|
|
|
|
assert app.jinja_env.tests["is_boolean"](False)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_test(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
bp.add_app_template_test(is_boolean)
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
assert "is_boolean" in app.jinja_env.tests.keys()
|
|
|
|
assert app.jinja_env.tests["is_boolean"] == is_boolean
|
|
|
|
assert app.jinja_env.tests["is_boolean"](False)
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_test_with_name(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.app_template_test("boolean")
|
2014-09-04 02:56:10 +08:00
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_test_with_name(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp.add_app_template_test(is_boolean, "boolean")
|
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
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-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_test_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_test()
|
|
|
|
def boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_test_after_route_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@bp.app_template_test()
|
|
|
|
def boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
|
|
|
rv = client.get("/")
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_test_with_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
bp.add_app_template_test(boolean)
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_template_test_with_name_and_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.app_template_test("boolean")
|
2014-09-04 02:56:10 +08:00
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert b"Success!" in rv.data
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_add_template_test_with_name_and_template(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
def is_boolean(value):
|
|
|
|
return isinstance(value, bool)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
bp.add_app_template_test(is_boolean, "boolean")
|
|
|
|
app.register_blueprint(bp, url_prefix="/py")
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2014-09-04 02:56:10 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.render_template("template_test.html", value=False)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/")
|
|
|
|
assert b"Success!" in rv.data
|
2017-05-23 04:06:47 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:42:14 +08:00
|
|
|
def test_context_processing(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
answer_bp = flask.Blueprint("answer_bp", __name__)
|
2017-05-23 04:06:47 +08:00
|
|
|
|
2023-11-10 01:20:27 +08:00
|
|
|
def template_string():
|
|
|
|
return flask.render_template_string(
|
|
|
|
"{% if notanswer %}{{ notanswer }} is not the answer. {% endif %}"
|
|
|
|
"{% if answer %}{{ answer }} is the answer.{% endif %}"
|
|
|
|
)
|
2017-05-23 04:06:47 +08:00
|
|
|
|
|
|
|
# App global context processor
|
|
|
|
@answer_bp.app_context_processor
|
|
|
|
def not_answer_context_processor():
|
2019-05-07 03:39:41 +08:00
|
|
|
return {"notanswer": 43}
|
2017-05-23 04:06:47 +08:00
|
|
|
|
|
|
|
# Blueprint local context processor
|
|
|
|
@answer_bp.context_processor
|
|
|
|
def answer_context_processor():
|
2019-05-07 03:39:41 +08:00
|
|
|
return {"answer": 42}
|
2017-05-23 04:06:47 +08:00
|
|
|
|
|
|
|
# Setup endpoints for testing
|
2019-05-07 03:39:41 +08:00
|
|
|
@answer_bp.route("/bp")
|
2017-05-23 04:06:47 +08:00
|
|
|
def bp_page():
|
|
|
|
return template_string()
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2017-05-23 04:06:47 +08:00
|
|
|
def app_page():
|
|
|
|
return template_string()
|
|
|
|
|
|
|
|
# Register the blueprint
|
|
|
|
app.register_blueprint(answer_bp)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
app_page_bytes = client.get("/").data
|
|
|
|
answer_page_bytes = client.get("/bp").data
|
2017-05-23 04:06:47 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert b"43" in app_page_bytes
|
|
|
|
assert b"42" not in app_page_bytes
|
2017-05-23 04:06:47 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert b"42" in answer_page_bytes
|
|
|
|
assert b"43" in answer_page_bytes
|
2017-05-23 05:14:24 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:42:14 +08:00
|
|
|
def test_template_global(app):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-23 05:14:24 +08:00
|
|
|
@bp.app_template_global()
|
|
|
|
def get_answer():
|
|
|
|
return 42
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-23 05:14:24 +08:00
|
|
|
# Make sure the function is not in the jinja_env already
|
2019-05-07 03:39:41 +08:00
|
|
|
assert "get_answer" not in app.jinja_env.globals.keys()
|
2017-05-23 05:14:24 +08:00
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
|
|
|
# Tests
|
2019-05-07 03:39:41 +08:00
|
|
|
assert "get_answer" in app.jinja_env.globals.keys()
|
|
|
|
assert app.jinja_env.globals["get_answer"] is get_answer
|
|
|
|
assert app.jinja_env.globals["get_answer"]() == 42
|
2017-05-23 05:14:24 +08:00
|
|
|
|
|
|
|
with app.app_context():
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = flask.render_template_string("{{ get_answer() }}")
|
|
|
|
assert rv == "42"
|
2017-05-23 06:49:04 +08:00
|
|
|
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-24 07:42:14 +08:00
|
|
|
def test_request_processing(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-23 06:49:04 +08:00
|
|
|
evts = []
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-23 06:49:04 +08:00
|
|
|
@bp.before_request
|
|
|
|
def before_bp():
|
2019-05-07 03:39:41 +08:00
|
|
|
evts.append("before")
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-23 06:49:04 +08:00
|
|
|
@bp.after_request
|
|
|
|
def after_bp(response):
|
2019-05-07 03:39:41 +08:00
|
|
|
response.data += b"|after"
|
|
|
|
evts.append("after")
|
2017-05-23 06:49:04 +08:00
|
|
|
return response
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-23 07:54:52 +08:00
|
|
|
@bp.teardown_request
|
|
|
|
def teardown_bp(exc):
|
2019-05-07 03:39:41 +08:00
|
|
|
evts.append("teardown")
|
2017-05-23 06:49:04 +08:00
|
|
|
|
|
|
|
# Setup routes for testing
|
2019-05-07 03:39:41 +08:00
|
|
|
@bp.route("/bp")
|
2017-05-23 06:49:04 +08:00
|
|
|
def bp_endpoint():
|
2019-05-07 03:39:41 +08:00
|
|
|
return "request"
|
2017-05-23 06:49:04 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
|
|
|
assert evts == []
|
2019-05-07 03:39:41 +08:00
|
|
|
rv = client.get("/bp")
|
|
|
|
assert rv.data == b"request|after"
|
|
|
|
assert evts == ["before", "after", "teardown"]
|
2017-05-23 06:49:04 +08:00
|
|
|
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-24 07:42:14 +08:00
|
|
|
def test_app_request_processing(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-23 06:49:04 +08:00
|
|
|
evts = []
|
|
|
|
|
|
|
|
@bp.before_app_request
|
|
|
|
def before_app():
|
2019-05-07 03:39:41 +08:00
|
|
|
evts.append("before")
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-23 06:49:04 +08:00
|
|
|
@bp.after_app_request
|
|
|
|
def after_app(response):
|
2019-05-07 03:39:41 +08:00
|
|
|
response.data += b"|after"
|
|
|
|
evts.append("after")
|
2017-05-23 06:49:04 +08:00
|
|
|
return response
|
2017-05-25 08:27:36 +08:00
|
|
|
|
2017-05-23 07:54:52 +08:00
|
|
|
@bp.teardown_app_request
|
|
|
|
def teardown_app(exc):
|
2019-05-07 03:39:41 +08:00
|
|
|
evts.append("teardown")
|
2017-05-23 06:49:04 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
|
|
|
# Setup routes for testing
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/")
|
2017-05-23 06:49:04 +08:00
|
|
|
def bp_endpoint():
|
2019-05-07 03:39:41 +08:00
|
|
|
return "request"
|
2017-05-23 06:49:04 +08:00
|
|
|
|
|
|
|
# before first request
|
|
|
|
assert evts == []
|
|
|
|
|
|
|
|
# first request
|
2019-05-07 03:39:41 +08:00
|
|
|
resp = client.get("/").data
|
|
|
|
assert resp == b"request|after"
|
2023-02-24 00:35:16 +08:00
|
|
|
assert evts == ["before", "after", "teardown"]
|
2017-05-23 06:49:04 +08:00
|
|
|
|
|
|
|
# second request
|
2019-05-07 03:39:41 +08:00
|
|
|
resp = client.get("/").data
|
|
|
|
assert resp == b"request|after"
|
2023-02-24 00:35:16 +08:00
|
|
|
assert evts == ["before", "after", "teardown"] * 2
|
2017-05-24 07:22:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_app_url_processors(app, client):
|
2019-05-07 03:39:41 +08:00
|
|
|
bp = flask.Blueprint("bp", __name__)
|
2017-05-24 07:22:58 +08:00
|
|
|
|
|
|
|
# Register app-wide url defaults and preprocessor on blueprint
|
|
|
|
@bp.app_url_defaults
|
|
|
|
def add_language_code(endpoint, values):
|
2019-05-07 03:39:41 +08:00
|
|
|
values.setdefault("lang_code", flask.g.lang_code)
|
2017-05-24 07:22:58 +08:00
|
|
|
|
|
|
|
@bp.app_url_value_preprocessor
|
|
|
|
def pull_lang_code(endpoint, values):
|
2019-05-07 03:39:41 +08:00
|
|
|
flask.g.lang_code = values.pop("lang_code")
|
2017-05-24 07:22:58 +08:00
|
|
|
|
|
|
|
# Register route rules at the app level
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/<lang_code>/")
|
2017-05-24 07:22:58 +08:00
|
|
|
def index():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for("about")
|
2017-05-24 07:22:58 +08:00
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
@app.route("/<lang_code>/about")
|
2017-05-24 07:22:58 +08:00
|
|
|
def about():
|
2019-05-07 03:39:41 +08:00
|
|
|
return flask.url_for("index")
|
2017-05-24 07:22:58 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
2019-05-07 03:39:41 +08:00
|
|
|
assert client.get("/de/").data == b"/de/about"
|
|
|
|
assert client.get("/de/about").data == b"/de/"
|
2021-02-25 05:18:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_nested_blueprint(app, client):
|
|
|
|
parent = flask.Blueprint("parent", __name__)
|
|
|
|
child = flask.Blueprint("child", __name__)
|
|
|
|
grandchild = flask.Blueprint("grandchild", __name__)
|
|
|
|
|
|
|
|
@parent.errorhandler(403)
|
|
|
|
def forbidden(e):
|
|
|
|
return "Parent no", 403
|
|
|
|
|
|
|
|
@parent.route("/")
|
|
|
|
def parent_index():
|
|
|
|
return "Parent yes"
|
|
|
|
|
|
|
|
@parent.route("/no")
|
|
|
|
def parent_no():
|
|
|
|
flask.abort(403)
|
|
|
|
|
|
|
|
@child.route("/")
|
|
|
|
def child_index():
|
|
|
|
return "Child yes"
|
|
|
|
|
|
|
|
@child.route("/no")
|
|
|
|
def child_no():
|
|
|
|
flask.abort(403)
|
|
|
|
|
|
|
|
@grandchild.errorhandler(403)
|
|
|
|
def grandchild_forbidden(e):
|
|
|
|
return "Grandchild no", 403
|
|
|
|
|
|
|
|
@grandchild.route("/")
|
|
|
|
def grandchild_index():
|
|
|
|
return "Grandchild yes"
|
|
|
|
|
|
|
|
@grandchild.route("/no")
|
|
|
|
def grandchild_no():
|
|
|
|
flask.abort(403)
|
|
|
|
|
|
|
|
child.register_blueprint(grandchild, url_prefix="/grandchild")
|
|
|
|
parent.register_blueprint(child, url_prefix="/child")
|
|
|
|
app.register_blueprint(parent, url_prefix="/parent")
|
|
|
|
|
|
|
|
assert client.get("/parent/").data == b"Parent yes"
|
|
|
|
assert client.get("/parent/child/").data == b"Child yes"
|
|
|
|
assert client.get("/parent/child/grandchild/").data == b"Grandchild yes"
|
|
|
|
assert client.get("/parent/no").data == b"Parent no"
|
|
|
|
assert client.get("/parent/child/no").data == b"Parent no"
|
|
|
|
assert client.get("/parent/child/grandchild/no").data == b"Grandchild no"
|
2021-05-13 18:26:24 +08:00
|
|
|
|
|
|
|
|
2021-08-10 06:23:57 +08:00
|
|
|
def test_nested_callback_order(app, client):
|
|
|
|
parent = flask.Blueprint("parent", __name__)
|
|
|
|
child = flask.Blueprint("child", __name__)
|
|
|
|
|
|
|
|
@app.before_request
|
|
|
|
def app_before1():
|
|
|
|
flask.g.setdefault("seen", []).append("app_1")
|
|
|
|
|
|
|
|
@app.teardown_request
|
|
|
|
def app_teardown1(e=None):
|
|
|
|
assert flask.g.seen.pop() == "app_1"
|
|
|
|
|
|
|
|
@app.before_request
|
|
|
|
def app_before2():
|
|
|
|
flask.g.setdefault("seen", []).append("app_2")
|
|
|
|
|
|
|
|
@app.teardown_request
|
|
|
|
def app_teardown2(e=None):
|
|
|
|
assert flask.g.seen.pop() == "app_2"
|
|
|
|
|
|
|
|
@app.context_processor
|
|
|
|
def app_ctx():
|
|
|
|
return dict(key="app")
|
|
|
|
|
|
|
|
@parent.before_request
|
|
|
|
def parent_before1():
|
|
|
|
flask.g.setdefault("seen", []).append("parent_1")
|
|
|
|
|
|
|
|
@parent.teardown_request
|
|
|
|
def parent_teardown1(e=None):
|
|
|
|
assert flask.g.seen.pop() == "parent_1"
|
|
|
|
|
|
|
|
@parent.before_request
|
|
|
|
def parent_before2():
|
|
|
|
flask.g.setdefault("seen", []).append("parent_2")
|
|
|
|
|
|
|
|
@parent.teardown_request
|
|
|
|
def parent_teardown2(e=None):
|
|
|
|
assert flask.g.seen.pop() == "parent_2"
|
|
|
|
|
|
|
|
@parent.context_processor
|
|
|
|
def parent_ctx():
|
|
|
|
return dict(key="parent")
|
|
|
|
|
|
|
|
@child.before_request
|
|
|
|
def child_before1():
|
|
|
|
flask.g.setdefault("seen", []).append("child_1")
|
|
|
|
|
|
|
|
@child.teardown_request
|
|
|
|
def child_teardown1(e=None):
|
|
|
|
assert flask.g.seen.pop() == "child_1"
|
|
|
|
|
|
|
|
@child.before_request
|
|
|
|
def child_before2():
|
|
|
|
flask.g.setdefault("seen", []).append("child_2")
|
|
|
|
|
|
|
|
@child.teardown_request
|
|
|
|
def child_teardown2(e=None):
|
|
|
|
assert flask.g.seen.pop() == "child_2"
|
|
|
|
|
|
|
|
@child.context_processor
|
|
|
|
def child_ctx():
|
|
|
|
return dict(key="child")
|
|
|
|
|
|
|
|
@child.route("/a")
|
|
|
|
def a():
|
|
|
|
return ", ".join(flask.g.seen)
|
|
|
|
|
|
|
|
@child.route("/b")
|
|
|
|
def b():
|
|
|
|
return flask.render_template_string("{{ key }}")
|
|
|
|
|
|
|
|
parent.register_blueprint(child)
|
|
|
|
app.register_blueprint(parent)
|
|
|
|
assert (
|
|
|
|
client.get("/a").data == b"app_1, app_2, parent_1, parent_2, child_1, child_2"
|
|
|
|
)
|
|
|
|
assert client.get("/b").data == b"child"
|
|
|
|
|
|
|
|
|
2021-05-18 20:06:21 +08:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"parent_init, child_init, parent_registration, child_registration",
|
|
|
|
[
|
|
|
|
("/parent", "/child", None, None),
|
|
|
|
("/parent", None, None, "/child"),
|
|
|
|
(None, None, "/parent", "/child"),
|
|
|
|
("/other", "/something", "/parent", "/child"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_nesting_url_prefixes(
|
|
|
|
parent_init,
|
|
|
|
child_init,
|
|
|
|
parent_registration,
|
|
|
|
child_registration,
|
|
|
|
app,
|
|
|
|
client,
|
|
|
|
) -> None:
|
|
|
|
parent = flask.Blueprint("parent", __name__, url_prefix=parent_init)
|
|
|
|
child = flask.Blueprint("child", __name__, url_prefix=child_init)
|
2021-05-13 18:26:24 +08:00
|
|
|
|
|
|
|
@child.route("/")
|
2021-05-18 20:06:21 +08:00
|
|
|
def index():
|
|
|
|
return "index"
|
2021-05-17 02:32:29 +08:00
|
|
|
|
2021-05-18 20:06:21 +08:00
|
|
|
parent.register_blueprint(child, url_prefix=child_registration)
|
|
|
|
app.register_blueprint(parent, url_prefix=parent_registration)
|
2021-05-17 02:32:29 +08:00
|
|
|
|
2021-05-18 20:06:21 +08:00
|
|
|
response = client.get("/parent/child/")
|
|
|
|
assert response.status_code == 200
|
2021-05-18 20:37:11 +08:00
|
|
|
|
|
|
|
|
2022-10-31 16:49:16 +08:00
|
|
|
def test_nesting_subdomains(app, client) -> None:
|
|
|
|
subdomain = "api"
|
|
|
|
parent = flask.Blueprint("parent", __name__)
|
|
|
|
child = flask.Blueprint("child", __name__)
|
|
|
|
|
|
|
|
@child.route("/child/")
|
|
|
|
def index():
|
|
|
|
return "child"
|
|
|
|
|
|
|
|
parent.register_blueprint(child)
|
|
|
|
app.register_blueprint(parent, subdomain=subdomain)
|
|
|
|
|
|
|
|
client.allow_subdomain_redirects = True
|
|
|
|
|
|
|
|
domain_name = "domain.tld"
|
|
|
|
app.config["SERVER_NAME"] = domain_name
|
|
|
|
response = client.get("/child/", base_url="http://api." + domain_name)
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2023-01-05 00:45:20 +08:00
|
|
|
def test_child_and_parent_subdomain(app, client) -> None:
|
2022-10-31 16:49:16 +08:00
|
|
|
child_subdomain = "api"
|
|
|
|
parent_subdomain = "parent"
|
|
|
|
parent = flask.Blueprint("parent", __name__)
|
|
|
|
child = flask.Blueprint("child", __name__, subdomain=child_subdomain)
|
|
|
|
|
|
|
|
@child.route("/")
|
|
|
|
def index():
|
|
|
|
return "child"
|
|
|
|
|
|
|
|
parent.register_blueprint(child)
|
|
|
|
app.register_blueprint(parent, subdomain=parent_subdomain)
|
|
|
|
|
|
|
|
client.allow_subdomain_redirects = True
|
|
|
|
|
|
|
|
domain_name = "domain.tld"
|
|
|
|
app.config["SERVER_NAME"] = domain_name
|
2023-01-05 00:45:20 +08:00
|
|
|
response = client.get(
|
|
|
|
"/", base_url=f"http://{child_subdomain}.{parent_subdomain}.{domain_name}"
|
|
|
|
)
|
2022-10-31 16:49:16 +08:00
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
response = client.get("/", base_url=f"http://{parent_subdomain}.{domain_name}")
|
|
|
|
|
|
|
|
assert response.status_code == 404
|
|
|
|
|
|
|
|
|
2021-05-18 20:37:11 +08:00
|
|
|
def test_unique_blueprint_names(app, client) -> None:
|
|
|
|
bp = flask.Blueprint("bp", __name__)
|
|
|
|
bp2 = flask.Blueprint("bp", __name__)
|
|
|
|
|
|
|
|
app.register_blueprint(bp)
|
2021-05-21 04:08:28 +08:00
|
|
|
|
2021-11-13 01:37:13 +08:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
app.register_blueprint(bp) # same bp, same name, error
|
2021-05-21 04:08:28 +08:00
|
|
|
|
|
|
|
app.register_blueprint(bp, name="again") # same bp, different name, ok
|
2021-05-18 20:37:11 +08:00
|
|
|
|
|
|
|
with pytest.raises(ValueError):
|
2021-05-21 04:08:28 +08:00
|
|
|
app.register_blueprint(bp2) # different bp, same name, error
|
2021-05-18 20:37:11 +08:00
|
|
|
|
2021-05-21 04:08:28 +08:00
|
|
|
app.register_blueprint(bp2, name="alt") # different bp, different name, ok
|
2021-05-21 22:01:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_self_registration(app, client) -> None:
|
|
|
|
bp = flask.Blueprint("bp", __name__)
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
bp.register_blueprint(bp)
|
2021-05-21 22:02:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_blueprint_renaming(app, client) -> None:
|
|
|
|
bp = flask.Blueprint("bp", __name__)
|
|
|
|
bp2 = flask.Blueprint("bp2", __name__)
|
|
|
|
|
|
|
|
@bp.get("/")
|
|
|
|
def index():
|
|
|
|
return flask.request.endpoint
|
|
|
|
|
2021-06-05 23:08:51 +08:00
|
|
|
@bp.get("/error")
|
|
|
|
def error():
|
|
|
|
flask.abort(403)
|
|
|
|
|
|
|
|
@bp.errorhandler(403)
|
|
|
|
def forbidden(_: Exception):
|
|
|
|
return "Error", 403
|
|
|
|
|
2021-05-21 22:02:05 +08:00
|
|
|
@bp2.get("/")
|
|
|
|
def index2():
|
|
|
|
return flask.request.endpoint
|
|
|
|
|
|
|
|
bp.register_blueprint(bp2, url_prefix="/a", name="sub")
|
|
|
|
app.register_blueprint(bp, url_prefix="/a")
|
|
|
|
app.register_blueprint(bp, url_prefix="/b", name="alt")
|
|
|
|
|
|
|
|
assert client.get("/a/").data == b"bp.index"
|
|
|
|
assert client.get("/b/").data == b"alt.index"
|
|
|
|
assert client.get("/a/a/").data == b"bp.sub.index2"
|
|
|
|
assert client.get("/b/a/").data == b"alt.sub.index2"
|
2021-06-05 23:08:51 +08:00
|
|
|
assert client.get("/a/error").data == b"Error"
|
|
|
|
assert client.get("/b/error").data == b"Error"
|