strategy:
matrix:
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: "actions/checkout@v4"
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
"Topic :: Internet :: WWW/HTTP",
]
dependencies = [
"trio==0.31.0",
"trio-typing==0.10.0",
"trustme==1.2.1",
- "uvicorn==0.35.0",
+ "uvicorn==0.38.0",
]
docs = [
"mkdocs==1.6.1",
async def serve(self, sockets=None):
self.restart_requested = asyncio.Event()
- loop = asyncio.get_event_loop()
tasks = {
- loop.create_task(super().serve(sockets=sockets)),
- loop.create_task(self.watch_restarts()),
+ asyncio.create_task(super().serve(sockets=sockets)),
+ asyncio.create_task(self.watch_restarts()),
}
await asyncio.wait(tasks)
def serve_in_thread(server: TestServer) -> typing.Iterator[TestServer]:
- thread = threading.Thread(target=server.run)
+ def run_server() -> None:
+ loop = asyncio.new_event_loop()
+ asyncio.set_event_loop(loop)
+ try:
+ loop.run_until_complete(server.serve()) # type: ignore
+ finally:
+ loop.close()
+
+ thread = threading.Thread(target=run_server)
thread.start()
try:
while not server.started:
@pytest.fixture(scope="session")
def server() -> typing.Iterator[TestServer]:
- config = Config(app=app, lifespan="off", loop="asyncio")
+ config = Config(app=app, lifespan="off")
server = TestServer(config=config)
yield from serve_in_thread(server)
await client.get(server.url.copy_with(path="/slow_response"))
+# TODO: Fix ResourceWarning in this test for Python>=3.14
+@pytest.mark.filterwarnings("ignore::ResourceWarning")
@pytest.mark.anyio
async def test_write_timeout(server):
timeout = httpx.Timeout(None, write=1e-6)
{ name = "trio-typing", specifier = "==0.10.0" },
{ name = "trustme", specifier = "==1.2.1" },
{ name = "twine", specifier = "==6.1.0" },
- { name = "uvicorn", specifier = "==0.35.0" },
+ { name = "uvicorn", specifier = "==0.38.0" },
]
docs = [
{ name = "mkautodoc", specifier = "==0.2.0" },
{ name = "trio", specifier = "==0.31.0" },
{ name = "trio-typing", specifier = "==0.10.0" },
{ name = "trustme", specifier = "==1.2.1" },
- { name = "uvicorn", specifier = "==0.35.0" },
+ { name = "uvicorn", specifier = "==0.38.0" },
]
[[package]]
[[package]]
name = "uvicorn"
-version = "0.35.0"
+version = "0.38.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "h11" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/f06b84e2697fef4688ca63bdb2fdf113ca0a3be33f94488f2cadb690b0cf/uvicorn-0.38.0.tar.gz", hash = "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d", size = 80605, upload-time = "2025-10-18T13:46:44.63Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/d9/d88e73ca598f4f6ff671fb5fde8a32925c2e08a637303a1d12883c7305fa/uvicorn-0.38.0-py3-none-any.whl", hash = "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02", size = 68109, upload-time = "2025-10-18T13:46:42.958Z" },
]
[[package]]