Skip to content

Commit eb2d7e3

Browse files
committed
feat(asgi): winloop for uvicorn
1 parent 37b436d commit eb2d7e3

4 files changed

Lines changed: 64 additions & 3 deletions

File tree

pdm.lock

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ uvicorn = [
3333
"uvicorn>=0.35.0",
3434
"uvloop>=0.18.0; sys_platform != \"win32\"",
3535
"websockets>=15.0.1",
36+
"winloop>=0.3.0; sys_platform == \"win32\"",
3637
]
3738

3839
[build-system]

src/graia/amnesia/builtins/asgi/uvicorn.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@
99
from launart.utilles import any_completed
1010
from loguru import logger
1111
from uvicorn import Config, Server
12-
from uvicorn.config import LOG_LEVELS, HTTPProtocolType, LifespanType, WSProtocolType
12+
from uvicorn.config import LOG_LEVELS, LOOP_FACTORIES, HTTPProtocolType, LifespanType, WSProtocolType
1313

1414
from ..utils import LoguruHandler
1515
from . import asgitypes
1616
from .common import empty_asgi_handler
1717
from .middleware import DispatcherMiddleware
1818

1919

20+
LOOP_FACTORIES["winloop"] = "graia.amnesia.builtins.asgi.winloop:winloop_loop_factory"
21+
22+
2023
class WithoutSigHandlerServer(Server):
2124
def install_signal_handlers(self) -> None:
2225
pass
@@ -27,7 +30,7 @@ class UvicornOptions(TypedDict, total=False):
2730
"""default: None"""
2831
fd: int | None
2932
"""default: None"""
30-
loop: Literal["none", "auto", "asyncio", "uvloop"]
33+
loop: Literal["none", "auto", "asyncio", "uvloop", "winloop"]
3134
"""default: 'auto'"""
3235
http: type[asyncio.Protocol] | HTTPProtocolType
3336
"""default: 'auto'"""
@@ -133,6 +136,24 @@ def __init__(
133136
self.patch_logger = patch_logger
134137
self.middleware = DispatcherMiddleware(mounts or {"\0\0\0": empty_asgi_handler})
135138
self.options: UvicornOptions = options or {}
139+
140+
if self.options.get("loop", "auto") == "auto":
141+
try:
142+
import uvloop # type: ignore
143+
144+
self.options["loop"] = "uvloop"
145+
except ImportError:
146+
pass
147+
148+
try:
149+
import winloop
150+
151+
self.options["loop"] = "winloop"
152+
except ImportError:
153+
pass
154+
155+
self.options["loop"] = "asyncio"
156+
136157
super().__init__()
137158

138159
@property
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from __future__ import annotations
2+
3+
import asyncio
4+
from collections.abc import Callable
5+
6+
import winloop
7+
8+
9+
def winloop_loop_factory(use_subprocess: bool = False) -> Callable[[], asyncio.AbstractEventLoop]:
10+
return winloop.new_event_loop

0 commit comments

Comments
 (0)