Auto extend with Sanic Extensions (#2308)

This commit is contained in:
Adam Hopkins
2021-12-25 22:20:06 +02:00
committed by GitHub
parent b91ffed010
commit dc3ccba527
16 changed files with 264 additions and 48 deletions

View File

@@ -6,8 +6,10 @@ import string
import sys
import uuid
from contextlib import suppress
from logging import LogRecord
from typing import Callable, List, Tuple
from typing import List, Tuple
from unittest.mock import MagicMock
import pytest
@@ -184,3 +186,21 @@ def message_in_records():
return error_captured
return msg_in_log
@pytest.fixture
def ext_instance():
ext_instance = MagicMock()
ext_instance.injection = MagicMock()
return ext_instance
@pytest.fixture(autouse=True) # type: ignore
def sanic_ext(ext_instance): # noqa
sanic_ext = MagicMock(__version__="1.2.3")
sanic_ext.Extend = MagicMock()
sanic_ext.Extend.return_value = ext_instance
sys.modules["sanic_ext"] = sanic_ext
yield sanic_ext
with suppress(KeyError):
del sys.modules["sanic_ext"]

View File

@@ -32,6 +32,12 @@ def starting_line(lines):
return 0
def read_app_info(lines):
for line in lines:
if line.startswith(b"{") and line.endswith(b"}"):
return json.loads(line)
@pytest.mark.parametrize(
"appname",
(
@@ -199,9 +205,7 @@ def test_debug(cmd):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
app_info = lines[starting_line(lines) + 9]
info = json.loads(app_info)
info = read_app_info(lines)
assert info["debug"] is True
assert info["auto_reload"] is True
@@ -212,9 +216,7 @@ def test_auto_reload(cmd):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
app_info = lines[starting_line(lines) + 9]
info = json.loads(app_info)
info = read_app_info(lines)
assert info["debug"] is False
assert info["auto_reload"] is True
@@ -227,9 +229,7 @@ def test_access_logs(cmd, expected):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
app_info = lines[starting_line(lines) + 8]
info = json.loads(app_info)
info = read_app_info(lines)
assert info["access_log"] is expected
@@ -254,8 +254,6 @@ def test_noisy_exceptions(cmd, expected):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
app_info = lines[starting_line(lines) + 8]
info = json.loads(app_info)
info = read_app_info(lines)
assert info["noisy_exceptions"] is expected

View File

@@ -0,0 +1,84 @@
import sys
from unittest.mock import MagicMock
import pytest
from sanic import Sanic
try:
import sanic_ext
SANIC_EXT_IN_ENV = True
except ImportError:
SANIC_EXT_IN_ENV = False
@pytest.fixture
def stoppable_app(app):
@app.before_server_start
async def stop(*_):
app.stop()
return app
def test_ext_is_loaded(stoppable_app: Sanic, sanic_ext):
stoppable_app.run()
sanic_ext.Extend.assert_called_once_with(stoppable_app)
def test_ext_is_not_loaded(stoppable_app: Sanic, sanic_ext):
stoppable_app.config.AUTO_EXTEND = False
stoppable_app.run()
sanic_ext.Extend.assert_not_called()
def test_extend_with_args(stoppable_app: Sanic, sanic_ext):
stoppable_app.extend(built_in_extensions=False)
stoppable_app.run()
sanic_ext.Extend.assert_called_once_with(
stoppable_app, built_in_extensions=False, config=None, extensions=None
)
def test_access_object_sets_up_extension(app: Sanic, sanic_ext):
app.ext
sanic_ext.Extend.assert_called_once_with(app)
def test_extend_cannot_be_called_multiple_times(app: Sanic, sanic_ext):
app.extend()
message = "Cannot extend Sanic after Sanic Extensions has been setup."
with pytest.raises(RuntimeError, match=message):
app.extend()
sanic_ext.Extend.assert_called_once_with(
app, extensions=None, built_in_extensions=True, config=None
)
@pytest.mark.skipif(
SANIC_EXT_IN_ENV,
reason="Running tests with sanic_ext already in the environment",
)
def test_fail_if_not_loaded(app: Sanic):
del sys.modules["sanic_ext"]
with pytest.raises(
RuntimeError, match="Sanic Extensions is not installed.*"
):
app.extend(built_in_extensions=False)
def test_can_access_app_ext_while_running(app: Sanic, sanic_ext, ext_instance):
class IceCream:
flavor: str
@app.before_server_start
async def injections(*_):
app.ext.injection(IceCream)
app.stop()
app.run()
ext_instance.injection.assert_called_with(IceCream)