Implement 0.6 routing and some cleanup (#2117)
* Implement 0.6 routing and some cleanup * Additional tests and annotation cleanup * Resolve sorting * cleanup test with encoding
This commit is contained in:
@@ -80,7 +80,7 @@ def test_dont_load_env():
|
||||
del environ["SANIC_TEST_ANSWER"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('load_env', [None, False, "", "MYAPP_"])
|
||||
@pytest.mark.parametrize("load_env", [None, False, "", "MYAPP_"])
|
||||
def test_load_env_deprecation(load_env):
|
||||
with pytest.warns(DeprecationWarning, match=r"21\.12"):
|
||||
_ = Sanic(name=__name__, load_env=load_env)
|
||||
@@ -93,7 +93,7 @@ def test_load_env_prefix():
|
||||
del environ["MYAPP_TEST_ANSWER"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('env_prefix', [None, ""])
|
||||
@pytest.mark.parametrize("env_prefix", [None, ""])
|
||||
def test_empty_load_env_prefix(env_prefix):
|
||||
environ["SANIC_TEST_ANSWER"] = "42"
|
||||
app = Sanic(name=__name__, env_prefix=env_prefix)
|
||||
|
||||
@@ -209,13 +209,13 @@ def test_named_static_routes():
|
||||
return text("OK2")
|
||||
|
||||
assert app.router.routes_all[("test",)].name == "app.route_test"
|
||||
assert app.router.routes_static[("test",)].name == "app.route_test"
|
||||
assert app.router.routes_static[("test",)][0].name == "app.route_test"
|
||||
assert app.url_for("route_test") == "/test"
|
||||
with pytest.raises(URLBuildError):
|
||||
app.url_for("handler1")
|
||||
|
||||
assert app.router.routes_all[("pizazz",)].name == "app.route_pizazz"
|
||||
assert app.router.routes_static[("pizazz",)].name == "app.route_pizazz"
|
||||
assert app.router.routes_static[("pizazz",)][0].name == "app.route_pizazz"
|
||||
assert app.url_for("route_pizazz") == "/pizazz"
|
||||
with pytest.raises(URLBuildError):
|
||||
app.url_for("handler2")
|
||||
@@ -347,13 +347,13 @@ def test_static_add_named_route():
|
||||
app.add_route(handler2, "/test2", name="route_test2")
|
||||
|
||||
assert app.router.routes_all[("test",)].name == "app.route_test"
|
||||
assert app.router.routes_static[("test",)].name == "app.route_test"
|
||||
assert app.router.routes_static[("test",)][0].name == "app.route_test"
|
||||
assert app.url_for("route_test") == "/test"
|
||||
with pytest.raises(URLBuildError):
|
||||
app.url_for("handler1")
|
||||
|
||||
assert app.router.routes_all[("test2",)].name == "app.route_test2"
|
||||
assert app.router.routes_static[("test2",)].name == "app.route_test2"
|
||||
assert app.router.routes_static[("test2",)][0].name == "app.route_test2"
|
||||
assert app.url_for("route_test2") == "/test2"
|
||||
with pytest.raises(URLBuildError):
|
||||
app.url_for("handler2")
|
||||
|
||||
@@ -106,7 +106,7 @@ def test_route_assigned_to_request(app):
|
||||
return response.empty()
|
||||
|
||||
request, _ = app.test_client.get("/")
|
||||
assert request.route is list(app.router.routes.values())[0]
|
||||
assert request.route is list(app.router.routes)[0]
|
||||
|
||||
|
||||
def test_protocol_attribute(app):
|
||||
|
||||
@@ -253,6 +253,31 @@ async def test_empty_json_asgi(app):
|
||||
assert response.body == b"null"
|
||||
|
||||
|
||||
def test_echo_json(app):
|
||||
@app.post("/")
|
||||
async def handler(request):
|
||||
return json(request.json)
|
||||
|
||||
data = {"foo": "bar"}
|
||||
request, response = app.test_client.post("/", json=data)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.json == data
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_echo_json_asgi(app):
|
||||
@app.post("/")
|
||||
async def handler(request):
|
||||
return json(request.json)
|
||||
|
||||
data = {"foo": "bar"}
|
||||
request, response = await app.asgi_client.post("/", json=data)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.json == data
|
||||
|
||||
|
||||
def test_invalid_json(app):
|
||||
@app.post("/")
|
||||
async def handler(request):
|
||||
@@ -291,18 +316,18 @@ def test_query_string(app):
|
||||
assert request.args.getlist("test1") == ["1"]
|
||||
assert request.args.get("test3", default="My value") == "My value"
|
||||
|
||||
|
||||
def test_popped_stays_popped(app):
|
||||
@app.route("/")
|
||||
async def handler(request):
|
||||
return text("OK")
|
||||
|
||||
request, response = app.test_client.get(
|
||||
"/", params=[("test1", "1")]
|
||||
)
|
||||
request, response = app.test_client.get("/", params=[("test1", "1")])
|
||||
|
||||
assert request.args.pop("test1") == ["1"]
|
||||
assert "test1" not in request.args
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_string_asgi(app):
|
||||
@app.route("/")
|
||||
@@ -2170,3 +2195,72 @@ def test_safe_method_with_body(app):
|
||||
assert request.body == data.encode("utf-8")
|
||||
assert request.json.get("test") == "OK"
|
||||
assert response.body == b"OK"
|
||||
|
||||
|
||||
def test_conflicting_body_methods_overload(app):
|
||||
@app.put("/")
|
||||
@app.put("/p/")
|
||||
@app.put("/p/<foo>")
|
||||
async def put(request, foo=None):
|
||||
return json(
|
||||
{"name": request.route.name, "body": str(request.body), "foo": foo}
|
||||
)
|
||||
|
||||
@app.delete("/p/<foo>")
|
||||
async def delete(request, foo):
|
||||
return json(
|
||||
{"name": request.route.name, "body": str(request.body), "foo": foo}
|
||||
)
|
||||
|
||||
payload = {"test": "OK"}
|
||||
data = str(json_dumps(payload).encode())
|
||||
|
||||
_, response = app.test_client.put("/", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"foo": None,
|
||||
"body": data,
|
||||
}
|
||||
_, response = app.test_client.put("/p", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"foo": None,
|
||||
"body": data,
|
||||
}
|
||||
_, response = app.test_client.put("/p/test", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"foo": "test",
|
||||
"body": data,
|
||||
}
|
||||
_, response = app.test_client.delete("/p/test")
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.delete",
|
||||
"foo": "test",
|
||||
"body": str("".encode()),
|
||||
}
|
||||
|
||||
|
||||
def test_handler_overload(app):
|
||||
@app.get(
|
||||
"/long/sub/route/param_a/<param_a:string>/param_b/<param_b:string>"
|
||||
)
|
||||
@app.post("/long/sub/route/")
|
||||
def handler(request, **kwargs):
|
||||
return json(kwargs)
|
||||
|
||||
_, response = app.test_client.get(
|
||||
"/long/sub/route/param_a/foo/param_b/bar"
|
||||
)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"param_a": "foo",
|
||||
"param_b": "bar",
|
||||
}
|
||||
_, response = app.test_client.post("/long/sub/route")
|
||||
assert response.status == 200
|
||||
assert response.json == {}
|
||||
|
||||
@@ -60,7 +60,9 @@ def test_method_not_allowed():
|
||||
}
|
||||
|
||||
request, response = app.test_client.post("/")
|
||||
assert set(response.headers["Allow"].split(", ")) == {"GET", "HEAD"}
|
||||
assert set(response.headers["Allow"].split(", ")) == {
|
||||
"GET",
|
||||
}
|
||||
|
||||
app.router.reset()
|
||||
|
||||
@@ -73,7 +75,6 @@ def test_method_not_allowed():
|
||||
assert set(response.headers["Allow"].split(", ")) == {
|
||||
"GET",
|
||||
"POST",
|
||||
"HEAD",
|
||||
}
|
||||
assert response.headers["Content-Length"] == "0"
|
||||
|
||||
@@ -82,7 +83,6 @@ def test_method_not_allowed():
|
||||
assert set(response.headers["Allow"].split(", ")) == {
|
||||
"GET",
|
||||
"POST",
|
||||
"HEAD",
|
||||
}
|
||||
assert response.headers["Content-Length"] == "0"
|
||||
|
||||
|
||||
@@ -543,9 +543,6 @@ def test_dynamic_route_regex(app):
|
||||
async def handler(request, folder_id):
|
||||
return text("OK")
|
||||
|
||||
app.router.finalize()
|
||||
print(app.router.find_route_src)
|
||||
|
||||
request, response = app.test_client.get("/folder/test")
|
||||
assert response.status == 200
|
||||
|
||||
@@ -587,6 +584,9 @@ def test_dynamic_route_path(app):
|
||||
async def handler(request, path):
|
||||
return text("OK")
|
||||
|
||||
app.router.finalize()
|
||||
print(app.router.find_route_src)
|
||||
|
||||
request, response = app.test_client.get("/path/1/info")
|
||||
assert response.status == 200
|
||||
|
||||
@@ -1008,14 +1008,8 @@ def test_unmergeable_overload_routes(app):
|
||||
async def handler2(request):
|
||||
return text("OK1")
|
||||
|
||||
assert (
|
||||
len(
|
||||
dict(list(app.router.static_routes.values())[0].handlers)[
|
||||
"overload_whole"
|
||||
]
|
||||
)
|
||||
== 3
|
||||
)
|
||||
assert len(app.router.static_routes) == 1
|
||||
assert len(app.router.static_routes[("overload_whole",)].methods) == 3
|
||||
|
||||
request, response = app.test_client.get("/overload_whole")
|
||||
assert response.text == "OK1"
|
||||
|
||||
@@ -28,7 +28,8 @@ def test_add_signal_decorator(app):
|
||||
async def async_signal(*_):
|
||||
...
|
||||
|
||||
assert len(app.signal_router.routes) == 1
|
||||
assert len(app.signal_router.routes) == 2
|
||||
assert len(app.signal_router.dynamic_routes) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -79,13 +80,13 @@ async def test_dispatch_signal_triggers_triggers_event(app):
|
||||
def sync_signal(*args):
|
||||
nonlocal app
|
||||
nonlocal counter
|
||||
signal, *_ = app.signal_router.get("foo.bar.baz")
|
||||
counter += signal.ctx.event.is_set()
|
||||
group, *_ = app.signal_router.get("foo.bar.baz")
|
||||
for signal in group:
|
||||
counter += signal.ctx.event.is_set()
|
||||
|
||||
app.signal_router.finalize()
|
||||
|
||||
await app.dispatch("foo.bar.baz")
|
||||
signal, *_ = app.signal_router.get("foo.bar.baz")
|
||||
|
||||
assert counter == 1
|
||||
|
||||
@@ -224,7 +225,7 @@ async def test_dispatch_signal_triggers_event_on_bp(app):
|
||||
|
||||
app.blueprint(bp)
|
||||
app.signal_router.finalize()
|
||||
signal, *_ = app.signal_router.get(
|
||||
signal_group, *_ = app.signal_router.get(
|
||||
"foo.bar.baz", condition={"blueprint": "bp"}
|
||||
)
|
||||
|
||||
@@ -233,7 +234,8 @@ async def test_dispatch_signal_triggers_event_on_bp(app):
|
||||
assert isawaitable(waiter)
|
||||
|
||||
fut = asyncio.ensure_future(do_wait())
|
||||
signal.ctx.event.set()
|
||||
for signal in signal_group:
|
||||
signal.ctx.event.set()
|
||||
await fut
|
||||
|
||||
assert bp_counter == 1
|
||||
|
||||
@@ -490,3 +490,20 @@ def test_no_stack_trace_on_not_found(app, static_file_directory, caplog):
|
||||
assert counter[logging.INFO] == 5
|
||||
assert logging.ERROR not in counter
|
||||
assert response.text == "No file: /static/non_existing_file.file"
|
||||
|
||||
|
||||
def test_multiple_statics(app, static_file_directory):
|
||||
app.static("/file", get_file_path(static_file_directory, "test.file"))
|
||||
app.static("/png", get_file_path(static_file_directory, "python.png"))
|
||||
|
||||
_, response = app.test_client.get("/file")
|
||||
assert response.status == 200
|
||||
assert response.body == get_file_content(
|
||||
static_file_directory, "test.file"
|
||||
)
|
||||
|
||||
_, response = app.test_client.get("/png")
|
||||
assert response.status == 200
|
||||
assert response.body == get_file_content(
|
||||
static_file_directory, "python.png"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user