Files
bracket/backend/tests/integration_tests/api/shared.py
dependabot[bot] cc41d79759 Bump uvicorn from 0.35.0 to 0.38.0 in /backend (#1428)
Bumps [uvicorn](https://github.com/Kludex/uvicorn) from 0.35.0 to
0.38.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/uvicorn/releases">uvicorn's
releases</a>.</em></p>
<blockquote>
<h2>Version 0.38.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Support Python 3.14 by <a
href="https://github.com/Kludex"><code>@​Kludex</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2723">Kludex/uvicorn#2723</a></li>
</ul>
<hr />
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/NGANAMODEIJunior"><code>@​NGANAMODEIJunior</code></a>
made their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2713">Kludex/uvicorn#2713</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/uvicorn/compare/0.37.0...0.38.0">https://github.com/Kludex/uvicorn/compare/0.37.0...0.38.0</a></p>
<h2>Version 0.37.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add <code>--timeout-worker-healthcheck</code> setting by <a
href="https://github.com/Kludex"><code>@​Kludex</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2711">Kludex/uvicorn#2711</a></li>
<li>Add <code>os.PathLike[str]</code> type to <code>ssl_ca_certs</code>
by <a href="https://github.com/rnv812"><code>@​rnv812</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2676">Kludex/uvicorn#2676</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/LincolnPuzey"><code>@​LincolnPuzey</code></a>
made their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2669">Kludex/uvicorn#2669</a></li>
<li><a href="https://github.com/rnv812"><code>@​rnv812</code></a> made
their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2676">Kludex/uvicorn#2676</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/uvicorn/compare/0.36.1...0.37.0">https://github.com/Kludex/uvicorn/compare/0.36.1...0.37.0</a></p>
<h2>Version 0.36.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Raise an exception when calling removed
<code>Config.setup_event_loop()</code> by <a
href="https://github.com/Kludex"><code>@​Kludex</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2709">Kludex/uvicorn#2709</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/uvicorn/compare/0.36.0...0.36.1">https://github.com/Kludex/uvicorn/compare/0.36.0...0.36.1</a></p>
<h2>Version 0.36.0</h2>
<h2>Added</h2>
<ul>
<li>Support custom IOLOOPs by <a
href="https://github.com/gnir-work"><code>@​gnir-work</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2435">Kludex/uvicorn#2435</a></li>
<li>Allow to provide importable string in <code>--http</code>,
<code>--ws</code> and <code>--loop</code> by <a
href="https://github.com/Kludex"><code>@​Kludex</code></a> in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2658">Kludex/uvicorn#2658</a></li>
</ul>
<hr />
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/gnir-work"><code>@​gnir-work</code></a>
made their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2435">Kludex/uvicorn#2435</a></li>
<li><a
href="https://github.com/musicinmybrain"><code>@​musicinmybrain</code></a>
made their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2659">Kludex/uvicorn#2659</a></li>
<li><a
href="https://github.com/secrett2633"><code>@​secrett2633</code></a>
made their first contribution in <a
href="https://redirect.github.com/Kludex/uvicorn/pull/2684">Kludex/uvicorn#2684</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/uvicorn/compare/0.35.0...0.36.0">https://github.com/Kludex/uvicorn/compare/0.35.0...0.36.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/uvicorn/blob/main/docs/release-notes.md">uvicorn's
changelog</a>.</em></p>
<blockquote>
<h2>0.38.0 (October 18, 2025)</h2>
<h3>Added</h3>
<ul>
<li>Support Python 3.14 (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2723">#2723</a>)</li>
</ul>
<h2>0.37.0 (September 23, 2025)</h2>
<h3>Added</h3>
<ul>
<li>Add <code>--timeout-worker-healthcheck</code> option (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2711">#2711</a>)</li>
<li>Add <code>os.PathLike[str]</code> type to <code>ssl_ca_certs</code>
(<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2676">#2676</a>)</li>
</ul>
<h2>0.36.1 (September 23, 2025)</h2>
<h3>Fixed</h3>
<ul>
<li>Raise an exception when calling removed
<code>Config.setup_event_loop()</code> (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2709">#2709</a>)</li>
</ul>
<h2>0.36.0 (September 20, 2025)</h2>
<h3>Added</h3>
<ul>
<li>Support custom IOLOOPs (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2435">#2435</a>)</li>
<li>Allow to provide importable string in <code>--http</code>,
<code>--ws</code> and <code>--loop</code> (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2658">#2658</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3850ad6520"><code>3850ad6</code></a>
Version 0.38.0 (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2733">#2733</a>)</li>
<li><a
href="9b3f17a549"><code>9b3f17a</code></a>
Support Python 3.14 (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2723">#2723</a>)</li>
<li><a
href="ce79f95d06"><code>ce79f95</code></a>
Revert &quot;Add Marcelo Trylesinski to the license (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2699">#2699</a>)&quot;
(<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2730">#2730</a>)</li>
<li><a
href="dbf8797b47"><code>dbf8797</code></a>
docs: add social icons (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2728">#2728</a>)</li>
<li><a
href="58f28be98e"><code>58f28be</code></a>
Add section about event loop (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2725">#2725</a>)</li>
<li><a
href="93d9510749"><code>93d9510</code></a>
Bump docs dependencies (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2724">#2724</a>)</li>
<li><a
href="9b1c6c45ed"><code>9b1c6c4</code></a>
Move Marcelo Trylesinski to maintainers in <code>pyproject.toml</code>
(<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2719">#2719</a>)</li>
<li><a
href="57a61d86f2"><code>57a61d8</code></a>
Add discord to README (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2718">#2718</a>)</li>
<li><a
href="7ef5f9f5e7"><code>7ef5f9f</code></a>
chore(deps): bump astral-sh/setup-uv from 6.7.0 to 6.8.0 (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2717">#2717</a>)</li>
<li><a
href="6d26d88970"><code>6d26d88</code></a>
Update pyproject.toml for PEP639 compliance (<a
href="https://redirect.github.com/Kludex/uvicorn/issues/2713">#2713</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/Kludex/uvicorn/compare/0.35.0...0.38.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=uvicorn&package-manager=uv&previous-version=0.35.0&new-version=0.38.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Erik Vroon <erik.vroon@channable.com>
2025-11-14 08:57:18 +00:00

123 lines
3.7 KiB
Python

import asyncio
import socket
from collections.abc import AsyncIterator, Sequence
from contextlib import closing
from typing import Final
import aiohttp
import uvicorn
from fastapi import FastAPI
from bracket.app import app
from bracket.routes.models import SuccessResponse
from bracket.utils.http import HTTPMethod
from bracket.utils.types import JsonDict
from tests.integration_tests.models import AuthContext
SUCCESS_RESPONSE = SuccessResponse().model_dump()
def find_free_port() -> int:
"""
Ask the OS for an available port on localhost and then immediately give
it back so it can be used in our test. This way we don't have to hard code
a port to something and accidentally collide.
"""
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.bind(("", 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port: int = s.getsockname()[1]
return port
TEST_HOST: Final[str] = "127.0.0.1"
TEST_PORT: Final[int] = find_free_port()
def get_root_uvicorn_url() -> str:
return f"http://{TEST_HOST}:{TEST_PORT}/"
class UvicornTestServer(uvicorn.Server):
"""
Uvicorn test server. Used as a test fixture to do
integration tests against our FastAPI app.
"""
def __init__(self, _app: FastAPI = app, host: str = TEST_HOST, port: int = TEST_PORT):
self._startup_done = asyncio.Event()
self._serve_task: asyncio.Task[None] | None = None
self.should_exit: bool = False
super().__init__(config=uvicorn.Config(_app, host=host, port=port))
async def startup(self, sockets: Sequence[socket.socket] | None = None) -> None:
sockets_list = list(sockets) if sockets is not None else sockets
await super().startup(sockets=sockets_list)
self._startup_done.set()
async def up(self) -> None:
self._serve_task = asyncio.create_task(self.serve())
# If the startup takes longer than 5 seconds something is wrong and we can terminate it
await asyncio.wait_for(self._startup_done.wait(), 5)
async def down(self) -> None:
self.should_exit = True
assert self._serve_task is not None
await self._serve_task
async def send_request(
method: HTTPMethod,
endpoint: str,
body: JsonDict | AsyncIterator[bytes] | aiohttp.FormData | None = None,
json: JsonDict | None = None,
headers: JsonDict = {},
) -> JsonDict:
async with aiohttp.ClientSession() as session:
async with session.request(
method=method.value,
url=get_root_uvicorn_url() + endpoint,
data=body,
json=json,
headers=headers,
) as resp:
response: JsonDict = await resp.json()
return response
async def send_request_raw(method: HTTPMethod, endpoint: str) -> str:
async with aiohttp.ClientSession() as session:
async with session.request(
method=method.value,
url=get_root_uvicorn_url() + endpoint,
) as resp:
return await resp.text()
async def send_auth_request(
method: HTTPMethod,
endpoint: str,
auth_context: AuthContext,
body: JsonDict | None = None,
json: JsonDict | None = None,
) -> JsonDict:
return await send_request(
method=method, endpoint=endpoint, body=body, json=json, headers=auth_context.headers
)
async def send_tournament_request(
method: HTTPMethod,
endpoint: str,
auth_context: AuthContext,
body: JsonDict | AsyncIterator[bytes] | aiohttp.FormData | None = None,
json: JsonDict | None = None,
) -> JsonDict:
return await send_request(
method=method,
endpoint=f"tournaments/{auth_context.tournament.id}/{endpoint}",
body=body,
json=json,
headers=auth_context.headers,
)