Event autoregister (#2140)
* Add event autoregistration * Setup tests * Cleanup IDE added imports * Remove unused imports
This commit is contained in:
parent
16875b1f41
commit
0c3a8392f2
14
sanic/app.py
14
sanic/app.py
@ -382,11 +382,19 @@ class Sanic(BaseSanic):
|
|||||||
condition=condition,
|
condition=condition,
|
||||||
)
|
)
|
||||||
|
|
||||||
def event(self, event: str, timeout: Optional[Union[int, float]] = None):
|
async def event(
|
||||||
|
self, event: str, timeout: Optional[Union[int, float]] = None
|
||||||
|
):
|
||||||
signal = self.signal_router.name_index.get(event)
|
signal = self.signal_router.name_index.get(event)
|
||||||
if not signal:
|
if not signal:
|
||||||
raise NotFound("Could not find signal %s" % event)
|
if self.config.EVENT_AUTOREGISTER:
|
||||||
return wait_for(signal.ctx.event.wait(), timeout=timeout)
|
self.signal_router.reset()
|
||||||
|
self.add_signal(None, event)
|
||||||
|
signal = self.signal_router.name_index.get(event)
|
||||||
|
self.signal_router.finalize()
|
||||||
|
else:
|
||||||
|
raise NotFound("Could not find signal %s" % event)
|
||||||
|
return await wait_for(signal.ctx.event.wait(), timeout=timeout)
|
||||||
|
|
||||||
def enable_websocket(self, enable=True):
|
def enable_websocket(self, enable=True):
|
||||||
"""Enable or disable the support for websocket.
|
"""Enable or disable the support for websocket.
|
||||||
|
@ -16,28 +16,29 @@ BASE_LOGO = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"REQUEST_MAX_SIZE": 100000000, # 100 megabytes
|
"ACCESS_LOG": True,
|
||||||
|
"EVENT_AUTOREGISTER": False,
|
||||||
|
"FALLBACK_ERROR_FORMAT": "html",
|
||||||
|
"FORWARDED_FOR_HEADER": "X-Forwarded-For",
|
||||||
|
"FORWARDED_SECRET": None,
|
||||||
|
"GRACEFUL_SHUTDOWN_TIMEOUT": 15.0, # 15 sec
|
||||||
|
"KEEP_ALIVE_TIMEOUT": 5, # 5 seconds
|
||||||
|
"KEEP_ALIVE": True,
|
||||||
|
"PROXIES_COUNT": None,
|
||||||
|
"REAL_IP_HEADER": None,
|
||||||
|
"REGISTER": True,
|
||||||
"REQUEST_BUFFER_QUEUE_SIZE": 100,
|
"REQUEST_BUFFER_QUEUE_SIZE": 100,
|
||||||
"REQUEST_BUFFER_SIZE": 65536, # 64 KiB
|
"REQUEST_BUFFER_SIZE": 65536, # 64 KiB
|
||||||
|
"REQUEST_ID_HEADER": "X-Request-ID",
|
||||||
|
"REQUEST_MAX_SIZE": 100000000, # 100 megabytes
|
||||||
"REQUEST_TIMEOUT": 60, # 60 seconds
|
"REQUEST_TIMEOUT": 60, # 60 seconds
|
||||||
"RESPONSE_TIMEOUT": 60, # 60 seconds
|
"RESPONSE_TIMEOUT": 60, # 60 seconds
|
||||||
"KEEP_ALIVE": True,
|
|
||||||
"KEEP_ALIVE_TIMEOUT": 5, # 5 seconds
|
|
||||||
"WEBSOCKET_MAX_SIZE": 2 ** 20, # 1 megabyte
|
|
||||||
"WEBSOCKET_MAX_QUEUE": 32,
|
"WEBSOCKET_MAX_QUEUE": 32,
|
||||||
|
"WEBSOCKET_MAX_SIZE": 2 ** 20, # 1 megabyte
|
||||||
|
"WEBSOCKET_PING_INTERVAL": 20,
|
||||||
|
"WEBSOCKET_PING_TIMEOUT": 20,
|
||||||
"WEBSOCKET_READ_LIMIT": 2 ** 16,
|
"WEBSOCKET_READ_LIMIT": 2 ** 16,
|
||||||
"WEBSOCKET_WRITE_LIMIT": 2 ** 16,
|
"WEBSOCKET_WRITE_LIMIT": 2 ** 16,
|
||||||
"WEBSOCKET_PING_TIMEOUT": 20,
|
|
||||||
"WEBSOCKET_PING_INTERVAL": 20,
|
|
||||||
"GRACEFUL_SHUTDOWN_TIMEOUT": 15.0, # 15 sec
|
|
||||||
"ACCESS_LOG": True,
|
|
||||||
"FORWARDED_SECRET": None,
|
|
||||||
"REAL_IP_HEADER": None,
|
|
||||||
"PROXIES_COUNT": None,
|
|
||||||
"FORWARDED_FOR_HEADER": "X-Forwarded-For",
|
|
||||||
"REQUEST_ID_HEADER": "X-Request-ID",
|
|
||||||
"FALLBACK_ERROR_FORMAT": "html",
|
|
||||||
"REGISTER": True,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Callable, Dict, Set
|
from typing import Any, Callable, Dict, Optional, Set
|
||||||
|
|
||||||
from sanic.models.futures import FutureSignal
|
from sanic.models.futures import FutureSignal
|
||||||
from sanic.models.handler_types import SignalHandler
|
from sanic.models.handler_types import SignalHandler
|
||||||
@ -60,10 +60,16 @@ class SignalMixin:
|
|||||||
|
|
||||||
def add_signal(
|
def add_signal(
|
||||||
self,
|
self,
|
||||||
handler,
|
handler: Optional[Callable[..., Any]],
|
||||||
event: str,
|
event: str,
|
||||||
condition: Dict[str, Any] = None,
|
condition: Dict[str, Any] = None,
|
||||||
):
|
):
|
||||||
|
if not handler:
|
||||||
|
|
||||||
|
async def noop():
|
||||||
|
...
|
||||||
|
|
||||||
|
handler = noop
|
||||||
self.signal(event=event, condition=condition)(handler)
|
self.signal(event=event, condition=condition)(handler)
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
|
@ -257,17 +257,60 @@ def test_bad_finalize(app):
|
|||||||
assert counter == 0
|
assert counter == 0
|
||||||
|
|
||||||
|
|
||||||
def test_event_not_exist(app):
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_not_exist(app):
|
||||||
with pytest.raises(NotFound, match="Could not find signal does.not.exist"):
|
with pytest.raises(NotFound, match="Could not find signal does.not.exist"):
|
||||||
app.event("does.not.exist")
|
await app.event("does.not.exist")
|
||||||
|
|
||||||
|
|
||||||
def test_event_not_exist_on_bp(app):
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_not_exist_on_bp(app):
|
||||||
bp = Blueprint("bp")
|
bp = Blueprint("bp")
|
||||||
app.blueprint(bp)
|
app.blueprint(bp)
|
||||||
|
|
||||||
with pytest.raises(NotFound, match="Could not find signal does.not.exist"):
|
with pytest.raises(NotFound, match="Could not find signal does.not.exist"):
|
||||||
bp.event("does.not.exist")
|
await bp.event("does.not.exist")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_event_not_exist_with_autoregister(app):
|
||||||
|
app.config.EVENT_AUTOREGISTER = True
|
||||||
|
try:
|
||||||
|
await app.event("does.not.exist", timeout=0.1)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_dispatch_signal_triggers_non_exist_event_with_autoregister(app):
|
||||||
|
@app.signal("some.stand.in")
|
||||||
|
async def signal_handler():
|
||||||
|
...
|
||||||
|
|
||||||
|
app.config.EVENT_AUTOREGISTER = True
|
||||||
|
app_counter = 0
|
||||||
|
app.signal_router.finalize()
|
||||||
|
|
||||||
|
async def do_wait():
|
||||||
|
nonlocal app_counter
|
||||||
|
await app.event("foo.bar.baz")
|
||||||
|
app_counter += 1
|
||||||
|
|
||||||
|
fut = asyncio.ensure_future(do_wait())
|
||||||
|
await app.dispatch("foo.bar.baz")
|
||||||
|
await fut
|
||||||
|
|
||||||
|
assert app_counter == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_dispatch_not_exist(app):
|
||||||
|
@app.signal("do.something.start")
|
||||||
|
async def signal_handler():
|
||||||
|
...
|
||||||
|
|
||||||
|
app.signal_router.finalize()
|
||||||
|
await app.dispatch("does.not.exist")
|
||||||
|
|
||||||
|
|
||||||
def test_event_on_bp_not_registered():
|
def test_event_on_bp_not_registered():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user