mirror of
https://github.com/evroon/bracket.git
synced 2026-01-24 14:08:58 -05:00
Updates the requirements on [ruff](https://github.com/astral-sh/ruff) to permit the latest version. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.11.0</h2> <h2>Release Notes</h2> <p>This is a follow-up to <a href="https://github.com/astral-sh/ruff/releases/tag/0.10.0">release 0.10.0</a>. The <code>requires-python</code> inference changes were unintentionally omitted from 0.10.0, and have been included here. This release also includes stabilization of the preview behavior for <code>PGH004</code>.</p> <h3>Breaking changes</h3> <ul> <li> <p><strong>Changes to how the Python version is inferred when a <code>target-version</code> is not specified</strong> (<a href="https://redirect.github.com/astral-sh/ruff/pull/16319">#16319</a>)</p> <p>In previous versions of Ruff, you could specify your Python version with:</p> <ul> <li>The <code>target-version</code> option in a <code>ruff.toml</code> file or the <code>[tool.ruff]</code> section of a pyproject.toml file.</li> <li>The <code>project.requires-python</code> field in a <code>pyproject.toml</code> file with a <code>[tool.ruff]</code> section.</li> </ul> <p>These options worked well in most cases, and are still recommended for fine control of the Python version. However, because of the way Ruff discovers config files, <code>pyproject.toml</code> files without a <code>[tool.ruff]</code> section would be ignored, including the <code>requires-python</code> setting. Ruff would then use the default Python version (3.9 as of this writing) instead, which is surprising when you've attempted to request another version.</p> <p>In v0.10, config discovery has been updated to address this issue:</p> <ul> <li>If Ruff finds a <code>ruff.toml</code> file without a <code>target-version</code>, it will check for a <code>pyproject.toml</code> file in the same directory and respect its <code>requires-python</code> version, even if it does not contain a <code>[tool.ruff]</code> section.</li> <li>If Ruff finds a user-level configuration, the <code>requires-python</code> field of the closest <code>pyproject.toml</code> in a parent directory will take precedence.</li> <li>If there is no config file (<code>ruff.toml</code>or <code>pyproject.toml</code> with a <code>[tool.ruff]</code> section) in the directory of the file being checked, Ruff will search for the closest <code>pyproject.toml</code> in the parent directories and use its <code>requires-python</code> setting.</li> </ul> </li> </ul> <h3>Stabilization</h3> <p>The following behaviors have been stabilized:</p> <ul> <li><a href="https://docs.astral.sh/ruff/rules/blanket-noqa/"><code>blanket-noqa</code></a> (<code>PGH004</code>): Also detect blanked file-level noqa comments (and not just line level comments).</li> </ul> <h3>Preview features</h3> <ul> <li>[syntax-errors] Tuple unpacking in <code>for</code> statement iterator clause before Python 3.9 (<a href="https://redirect.github.com/astral-sh/ruff/pull/16558">#16558</a>)</li> </ul> <h2>Install ruff 0.11.0</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.11.0/ruff-installer.sh | sh </code></pre> <h3>Install prebuilt binaries via powershell script</h3> <pre lang="sh"><code>powershell -ExecutionPolicy ByPass -c "irm https://github.com/astral-sh/ruff/releases/download/0.11.0/ruff-installer.ps1 | iex" </tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.11.0</h2> <p>This is a follow-up to release 0.10.0. Because of a mistake in the release process, the <code>requires-python</code> inference changes were not included in that release. Ruff 0.11.0 now includes this change as well as the stabilization of the preview behavior for <code>PGH004</code>.</p> <h3>Breaking changes</h3> <ul> <li> <p><strong>Changes to how the Python version is inferred when a <code>target-version</code> is not specified</strong> (<a href="https://redirect.github.com/astral-sh/ruff/pull/16319">#16319</a>)</p> <p>In previous versions of Ruff, you could specify your Python version with:</p> <ul> <li>The <code>target-version</code> option in a <code>ruff.toml</code> file or the <code>[tool.ruff]</code> section of a pyproject.toml file.</li> <li>The <code>project.requires-python</code> field in a <code>pyproject.toml</code> file with a <code>[tool.ruff]</code> section.</li> </ul> <p>These options worked well in most cases, and are still recommended for fine control of the Python version. However, because of the way Ruff discovers config files, <code>pyproject.toml</code> files without a <code>[tool.ruff]</code> section would be ignored, including the <code>requires-python</code> setting. Ruff would then use the default Python version (3.9 as of this writing) instead, which is surprising when you've attempted to request another version.</p> <p>In v0.10, config discovery has been updated to address this issue:</p> <ul> <li>If Ruff finds a <code>ruff.toml</code> file without a <code>target-version</code>, it will check for a <code>pyproject.toml</code> file in the same directory and respect its <code>requires-python</code> version, even if it does not contain a <code>[tool.ruff]</code> section.</li> <li>If Ruff finds a user-level configuration, the <code>requires-python</code> field of the closest <code>pyproject.toml</code> in a parent directory will take precedence.</li> <li>If there is no config file (<code>ruff.toml</code>or <code>pyproject.toml</code> with a <code>[tool.ruff]</code> section) in the directory of the file being checked, Ruff will search for the closest <code>pyproject.toml</code> in the parent directories and use its <code>requires-python</code> setting.</li> </ul> </li> </ul> <h3>Stabilization</h3> <p>The following behaviors have been stabilized:</p> <ul> <li><a href="https://docs.astral.sh/ruff/rules/blanket-noqa/"><code>blanket-noqa</code></a> (<code>PGH004</code>): Also detect blanked file-level noqa comments (and not just line level comments).</li> </ul> <h3>Preview features</h3> <ul> <li>[syntax-errors] Tuple unpacking in <code>for</code> statement iterator clause before Python 3.9 (<a href="https://redirect.github.com/astral-sh/ruff/pull/16558">#16558</a>)</li> </ul> <h2>0.10.0</h2> <p>Check out the <a href="https://astral.sh/blog/ruff-v0.10.0">blog post</a> for a migration guide and overview of the changes!</p> <h3>Breaking changes</h3> <p>See also, the "Remapped rules" section which may result in disabled rules.</p> <ul> <li> <p><strong>Changes to how the Python version is inferred when a <code>target-version</code> is not specified</strong> (<a href="https://redirect.github.com/astral-sh/ruff/pull/16319">#16319</a>)</p> <p>Because of a mistake in the release process, the <code>requires-python</code> inference changes are not included in this release and instead shipped as part of 0.11.0. You can find a description of this change in the 0.11.0 section.</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="2cd25ef641"><code>2cd25ef</code></a> Ruff 0.11.0 (<a href="https://redirect.github.com/astral-sh/ruff/issues/16723">#16723</a>)</li> <li><a href="a22d206db2"><code>a22d206</code></a> [red-knot] Preliminary tests for typing.Final (<a href="https://redirect.github.com/astral-sh/ruff/issues/15917">#15917</a>)</li> <li><a href="270318c2e0"><code>270318c</code></a> [red-knot] fix: improve type inference for binary ops on tuples (<a href="https://redirect.github.com/astral-sh/ruff/issues/16725">#16725</a>)</li> <li><a href="d03b12e711"><code>d03b12e</code></a> [red-knot] Assignments to attributes (<a href="https://redirect.github.com/astral-sh/ruff/issues/16705">#16705</a>)</li> <li><a href="14c5ed5d7d"><code>14c5ed5</code></a> [<code>pygrep-hooks</code>]: Detect file-level suppressions comments without rul… (<a href="https://redirect.github.com/astral-sh/ruff/issues/16720">#16720</a>)</li> <li><a href="595565015b"><code>5955650</code></a> Fallback to requires-python in certain cases when target-version is not found...</li> <li><a href="2382fe1f25"><code>2382fe1</code></a> [syntax-errors] Tuple unpacking in <code>for</code> statement iterator clause before Pyt...</li> <li><a href="27e9d1fe3e"><code>27e9d1f</code></a> Ruff v0.10 Release (<a href="https://redirect.github.com/astral-sh/ruff/issues/16708">#16708</a>)</li> <li><a href="acf35c55f8"><code>acf35c5</code></a> Add new <code>noqa</code> specification to the docs (<a href="https://redirect.github.com/astral-sh/ruff/issues/16703">#16703</a>)</li> <li><a href="b9b256209b"><code>b9b2562</code></a> describe requires-python fallback in docs (<a href="https://redirect.github.com/astral-sh/ruff/issues/16704">#16704</a>)</li> <li>Additional commits viewable in <a href="https://github.com/astral-sh/ruff/compare/0.9.1...0.11.0">compare view</a></li> </ul> </details> <br /> 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>
201 lines
7.2 KiB
Python
201 lines
7.2 KiB
Python
from collections.abc import AsyncIterator
|
|
from contextlib import asynccontextmanager
|
|
from typing import cast
|
|
|
|
from sqlalchemy import Table
|
|
|
|
from bracket.database import database
|
|
from bracket.models.db.club import Club, ClubInsertable
|
|
from bracket.models.db.court import Court, CourtInsertable
|
|
from bracket.models.db.match import Match, MatchInsertable
|
|
from bracket.models.db.player import Player, PlayerInsertable
|
|
from bracket.models.db.player_x_team import PlayerXTeamInsertable
|
|
from bracket.models.db.ranking import Ranking, RankingInsertable
|
|
from bracket.models.db.round import Round, RoundInsertable
|
|
from bracket.models.db.stage import Stage, StageInsertable
|
|
from bracket.models.db.stage_item import StageItem, StageItemInsertable
|
|
from bracket.models.db.stage_item_inputs import (
|
|
StageItemInputBase,
|
|
StageItemInputEmpty,
|
|
StageItemInputFinal,
|
|
StageItemInputInsertable,
|
|
)
|
|
from bracket.models.db.team import Team, TeamInsertable
|
|
from bracket.models.db.tournament import Tournament, TournamentInsertable
|
|
from bracket.models.db.user import UserInDB, UserInsertable
|
|
from bracket.models.db.user_x_club import UserXClub, UserXClubInsertable, UserXClubRelation
|
|
from bracket.schema import (
|
|
clubs,
|
|
courts,
|
|
matches,
|
|
players,
|
|
players_x_teams,
|
|
rankings,
|
|
rounds,
|
|
stage_item_inputs,
|
|
stage_items,
|
|
stages,
|
|
teams,
|
|
tournaments,
|
|
users,
|
|
users_x_clubs,
|
|
)
|
|
from bracket.sql.teams import get_teams_by_id
|
|
from bracket.utils.db import insert_generic
|
|
from bracket.utils.dummy_records import DUMMY_CLUB, DUMMY_RANKING1, DUMMY_TOURNAMENT
|
|
from bracket.utils.id_types import TeamId
|
|
from bracket.utils.types import BaseModelT
|
|
from tests.integration_tests.mocks import get_mock_token, get_mock_user
|
|
from tests.integration_tests.models import AuthContext
|
|
|
|
|
|
async def assert_row_count_and_clear(table: Table, expected_rows: int) -> None:
|
|
# assert len(await database.fetch_all(query=table.select())) == expected_rows
|
|
await database.execute(query=table.delete())
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_generic(
|
|
data_model: BaseModelT, table: Table, return_type: type[BaseModelT]
|
|
) -> AsyncIterator[BaseModelT]:
|
|
last_record_id, row_inserted = await insert_generic(database, data_model, table, return_type)
|
|
|
|
try:
|
|
yield row_inserted
|
|
finally:
|
|
await database.execute(query=table.delete().where(table.c.id == last_record_id))
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_user(user: UserInsertable) -> AsyncIterator[UserInDB]:
|
|
async with inserted_generic(user, users, UserInDB) as row_inserted:
|
|
yield cast("UserInDB", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_club(club: ClubInsertable) -> AsyncIterator[Club]:
|
|
async with inserted_generic(club, clubs, Club) as row_inserted:
|
|
yield cast("Club", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_tournament(tournament: TournamentInsertable) -> AsyncIterator[Tournament]:
|
|
async with inserted_generic(tournament, tournaments, Tournament) as row_inserted:
|
|
yield cast("Tournament", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_team(team: TeamInsertable) -> AsyncIterator[Team]:
|
|
async with inserted_generic(team, teams, Team) as row_inserted:
|
|
yield cast("Team", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_court(court: CourtInsertable) -> AsyncIterator[Court]:
|
|
async with inserted_generic(court, courts, Court) as row_inserted:
|
|
yield cast("Court", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_ranking(ranking: RankingInsertable) -> AsyncIterator[Ranking]:
|
|
async with inserted_generic(ranking, rankings, Ranking) as row_inserted:
|
|
yield cast("Ranking", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_player(player: PlayerInsertable) -> AsyncIterator[Player]:
|
|
async with inserted_generic(player, players, Player) as row_inserted:
|
|
yield cast("Player", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_player_in_team(
|
|
player: PlayerInsertable, team_id: TeamId
|
|
) -> AsyncIterator[Player]:
|
|
async with inserted_generic(player, players, Player) as row_inserted:
|
|
async with inserted_generic(
|
|
PlayerXTeamInsertable(player_id=cast("Player", row_inserted).id, team_id=team_id),
|
|
players_x_teams,
|
|
PlayerXTeamInsertable,
|
|
):
|
|
yield cast("Player", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_stage(stage: StageInsertable) -> AsyncIterator[Stage]:
|
|
async with inserted_generic(stage, stages, Stage) as row_inserted:
|
|
yield cast("Stage", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_stage_item(stage_item: StageItemInsertable) -> AsyncIterator[StageItem]:
|
|
async with inserted_generic(stage_item, stage_items, StageItem) as row_inserted:
|
|
yield StageItem(**row_inserted.model_dump())
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_stage_item_input(
|
|
stage_item_input: StageItemInputInsertable,
|
|
) -> AsyncIterator[StageItemInputFinal | StageItemInputEmpty]:
|
|
async with inserted_generic(
|
|
stage_item_input, stage_item_inputs, StageItemInputBase
|
|
) as row_inserted:
|
|
if stage_item_input.team_id is not None:
|
|
[team] = await get_teams_by_id(
|
|
{stage_item_input.team_id}, stage_item_input.tournament_id
|
|
)
|
|
yield StageItemInputFinal.model_validate(
|
|
row_inserted.model_dump() | {"team": team, "team_id": team.id}
|
|
)
|
|
else:
|
|
yield StageItemInputEmpty.model_validate(row_inserted.model_dump())
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_round(round_: RoundInsertable) -> AsyncIterator[Round]:
|
|
async with inserted_generic(round_, rounds, Round) as row_inserted:
|
|
yield cast("Round", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_match(match: MatchInsertable) -> AsyncIterator[Match]:
|
|
async with inserted_generic(match, matches, Match) as row_inserted:
|
|
yield cast("Match", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_user_x_club(user_x_club: UserXClubInsertable) -> AsyncIterator[UserXClub]:
|
|
async with inserted_generic(user_x_club, users_x_clubs, UserXClub) as row_inserted:
|
|
yield cast("UserXClub", row_inserted)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def inserted_auth_context() -> AsyncIterator[AuthContext]:
|
|
mock_user = get_mock_user()
|
|
headers = {"Authorization": f"Bearer {get_mock_token(mock_user)}"}
|
|
async with (
|
|
inserted_user(mock_user) as user_inserted,
|
|
inserted_club(DUMMY_CLUB) as club_inserted,
|
|
inserted_tournament(
|
|
DUMMY_TOURNAMENT.model_copy(update={"club_id": club_inserted.id})
|
|
) as tournament_inserted,
|
|
inserted_ranking(
|
|
DUMMY_RANKING1.model_copy(update={"tournament_id": tournament_inserted.id})
|
|
) as ranking_inserted,
|
|
inserted_user_x_club(
|
|
UserXClubInsertable(
|
|
user_id=user_inserted.id,
|
|
club_id=club_inserted.id,
|
|
relation=UserXClubRelation.OWNER,
|
|
)
|
|
) as user_x_club_inserted,
|
|
):
|
|
yield AuthContext(
|
|
headers=headers,
|
|
user=user_inserted,
|
|
club=club_inserted,
|
|
tournament=tournament_inserted,
|
|
user_x_club=user_x_club_inserted,
|
|
ranking=ranking_inserted,
|
|
)
|