diff --git a/pyproject.toml b/pyproject.toml index 2883c690a..0d9a5d17a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ standard = [ "python-dotenv>=0.13", "PyYAML>=5.1", "uvloop>=0.14.0,!=0.15.0,!=0.15.1; sys_platform != 'win32' and (sys_platform != 'cygwin' and platform_python_implementation != 'PyPy')", + "winloop>=0.1.7; sys_platform == 'win32' or (sys_platform == 'cygwin' and platform_python_implementation != 'PyPy')", "watchfiles>=0.13", "websockets>=10.4", ] diff --git a/uvicorn/config.py b/uvicorn/config.py index 664d1918f..f5bf46d40 100644 --- a/uvicorn/config.py +++ b/uvicorn/config.py @@ -27,7 +27,7 @@ HTTPProtocolType = Literal["auto", "h11", "httptools"] WSProtocolType = Literal["auto", "none", "websockets", "wsproto"] LifespanType = Literal["auto", "on", "off"] -LoopSetupType = Literal["none", "auto", "asyncio", "uvloop"] +LoopSetupType = Literal["none", "auto", "asyncio", "uvloop", "winloop"] InterfaceType = Literal["auto", "asgi3", "asgi2", "wsgi"] LOG_LEVELS: dict[str, int] = { @@ -59,7 +59,9 @@ "auto": "uvicorn.loops.auto:auto_loop_setup", "asyncio": "uvicorn.loops.asyncio:asyncio_setup", "uvloop": "uvicorn.loops.uvloop:uvloop_setup", + "winloop": "uvicorn.loops.winloop:winloop_setup", } + INTERFACES: list[InterfaceType] = ["auto", "asgi3", "asgi2", "wsgi"] SSL_PROTOCOL_VERSION: int = ssl.PROTOCOL_TLS_SERVER diff --git a/uvicorn/loops/auto.py b/uvicorn/loops/auto.py index 2285457bf..d211d6dd9 100644 --- a/uvicorn/loops/auto.py +++ b/uvicorn/loops/auto.py @@ -2,10 +2,17 @@ def auto_loop_setup(use_subprocess: bool = False) -> None: try: import uvloop # noqa except ImportError: # pragma: no cover - from uvicorn.loops.asyncio import asyncio_setup as loop_setup + try: + import winloop # noqa + except ImportError: + from uvicorn.loops.asyncio import asyncio_setup as loop_setup - loop_setup(use_subprocess=use_subprocess) + loop_setup(use_subprocess=use_subprocess) + else: + from uvicorn.loops.winloop import winloop_setup as loop_setup + + loop_setup(use_subprocess=use_subprocess) else: # pragma: no cover from uvicorn.loops.uvloop import uvloop_setup - uvloop_setup(use_subprocess=use_subprocess) + diff --git a/uvicorn/loops/winloop.py b/uvicorn/loops/winloop.py new file mode 100644 index 000000000..a5a95867e --- /dev/null +++ b/uvicorn/loops/winloop.py @@ -0,0 +1,7 @@ +import asyncio + +import winloop + + +def winloop_setup(use_subprocess: bool = False) -> None: + asyncio.set_event_loop_policy(winloop.EventLoopPolicy())