File py314.patch of Package python-uvicorn

From 208a37a4de8f2fd6697dc3eaf076bac7442f5628 Mon Sep 17 00:00:00 2001
From: Thomas Grainger <tagrain@gmail.com>
Date: Sat, 14 Oct 2023 11:48:19 +0100
Subject: [PATCH 01/19] use asyncio.run(..., loop_factory) to avoid
 asyncio.set_event_loop_policy

---
 tests/test_auto_detection.py | 11 ++---
 uvicorn/_compat.py           | 86 ++++++++++++++++++++++++++++++++++++
 uvicorn/config.py            | 17 +++----
 uvicorn/loops/asyncio.py     | 13 ++++--
 uvicorn/loops/auto.py        | 18 +++++---
 uvicorn/loops/uvloop.py      |  9 +++-
 uvicorn/main.py              |  4 +-
 uvicorn/server.py            |  4 +-
 uvicorn/workers.py           |  6 +--
 9 files changed, 138 insertions(+), 30 deletions(-)
 create mode 100644 uvicorn/_compat.py

Index: uvicorn-0.36.0/tests/test_auto_detection.py
===================================================================
--- uvicorn-0.36.0.orig/tests/test_auto_detection.py
+++ uvicorn-0.36.0/tests/test_auto_detection.py
@@ -1,6 +1,7 @@
 import asyncio
 import contextlib
 import importlib
+import sys
 
 import pytest
 
@@ -12,9 +13,14 @@ from uvicorn.server import ServerState
 
 try:
     importlib.import_module("uvloop")
-    expected_loop = "uvloop"  # pragma: py-win32
 except ImportError:  # pragma: py-not-win32
     expected_loop = "asyncio"
+except AttributeError:  # pragma: py-lt-314  # pragma: py-win32
+    if sys.version_info < (3, 14):  # pragma: no cover
+        raise
+    expected_loop = "asyncio"
+else:  # pragma: py-win32  # pragma: py-gte-314
+    expected_loop = "uvloop"
 
 try:
     importlib.import_module("httptools")
Index: uvicorn-0.36.0/uvicorn/_compat.py
===================================================================
--- uvicorn-0.36.0.orig/uvicorn/_compat.py
+++ uvicorn-0.36.0/uvicorn/_compat.py
@@ -5,6 +5,13 @@ import sys
 from collections.abc import Callable, Coroutine
 from typing import Any, TypeVar
 
+__all__ = ["asyncio_run", "iscoroutinefunction"]
+
+if sys.version_info >= (3, 14):
+    from inspect import iscoroutinefunction
+else:
+    from asyncio import iscoroutinefunction
+
 _T = TypeVar("_T")
 
 if sys.version_info >= (3, 12):
Index: uvicorn-0.36.0/uvicorn/config.py
===================================================================
--- uvicorn-0.36.0.orig/uvicorn/config.py
+++ uvicorn-0.36.0/uvicorn/config.py
@@ -16,6 +16,7 @@ from typing import IO, Any, Callable, Li
 
 import click
 
+from uvicorn._compat import iscoroutinefunction
 from uvicorn._types import ASGIApplication
 from uvicorn.importer import ImportFromStringError, import_from_string
 from uvicorn.logging import TRACE_LOG_LEVEL
Index: uvicorn-0.36.0/uvicorn/loops/auto.py
===================================================================
--- uvicorn-0.36.0.orig/uvicorn/loops/auto.py
+++ uvicorn-0.36.0/uvicorn/loops/auto.py
@@ -1,17 +1,23 @@
 from __future__ import annotations
 
 import asyncio
+import sys
 from collections.abc import Callable
 
 
-def auto_loop_factory(use_subprocess: bool = False) -> Callable[[], asyncio.AbstractEventLoop]:
+def auto_loop_factory(use_subprocess: bool = False) -> Callable[[], asyncio.AbstractEventLoop]:  # pragma: no cover
     try:
         import uvloop  # noqa
     except ImportError:  # pragma: no cover
-        from uvicorn.loops.asyncio import asyncio_loop_factory as loop_factory
-
-        return loop_factory(use_subprocess=use_subprocess)
+        pass
+    except AttributeError:  # pragma: no cover
+        if sys.version_info < (3, 14):
+            raise
     else:  # pragma: no cover
         from uvicorn.loops.uvloop import uvloop_loop_factory
 
         return uvloop_loop_factory(use_subprocess=use_subprocess)
+
+    from uvicorn.loops.asyncio import asyncio_loop_factory as loop_factory
+
+    return loop_factory(use_subprocess=use_subprocess)
Index: uvicorn-0.36.0/pyproject.toml
===================================================================
--- uvicorn-0.36.0.orig/pyproject.toml
+++ uvicorn-0.36.0/pyproject.toml
@@ -25,6 +25,7 @@ classifiers = [
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
     "Programming Language :: Python :: 3.13",
+    "Programming Language :: Python :: 3.14",
     "Programming Language :: Python :: Implementation :: CPython",
     "Programming Language :: Python :: Implementation :: PyPy",
     "Topic :: Internet :: WWW/HTTP",
@@ -160,6 +161,7 @@ exclude_lines = [
     "tests/supervisors/test_multiprocess.py",
 ]
 "sys_platform != 'win32'" = ["uvicorn/loops/asyncio.py"]
+"sys_version_info >= (3, 14)" = ["uvicorn/loops/uvloop.py"]
 
 [tool.coverage.coverage_conditional_plugin.rules]
 py-win32 = "sys_platform == 'win32'"
@@ -173,3 +175,5 @@ py-gte-310 = "sys_version_info >= (3, 10
 py-lt-310 = "sys_version_info < (3, 10)"
 py-gte-311 = "sys_version_info >= (3, 11)"
 py-lt-311 = "sys_version_info < (3, 11)"
+py-gte-314 = "sys_version_info >= (3, 14)"
+py-lt-314 = "sys_version_info < (3, 14)"
Index: uvicorn-0.36.0/tests/test_compat.py
===================================================================
--- uvicorn-0.36.0.orig/tests/test_compat.py
+++ uvicorn-0.36.0/tests/test_compat.py
@@ -1,6 +1,7 @@
 from __future__ import annotations
 
 import asyncio
+import sys
 from asyncio import AbstractEventLoop
 
 import pytest
@@ -23,7 +24,7 @@ def test_asyncio_run__custom_loop_factor
 
 
 def test_asyncio_run__passing_a_non_awaitable_callback_should_throw_error() -> None:
-    with pytest.raises(ValueError):
+    with pytest.raises(TypeError if sys.version_info >= (3, 14) else ValueError):
         asyncio_run(
             lambda: None,  # type: ignore
             loop_factory=CustomLoop,
openSUSE Build Service is sponsored by