From 648e2fa7b8de1f42581e50c70710cc022abdedaf Mon Sep 17 00:00:00 2001 From: Dan Trickey Date: Sat, 11 Mar 2023 18:30:09 +0000 Subject: [PATCH 1/2] Bump typing-extensions to 4.x This is the miniumum version that backports `NotRequired`, which we need for responses where some keys are not always present. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e2f5503..63d5b26 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ 'Werkzeug >= 2, <3', 'simplejson >=3.6, <4', 'python-dateutil >=2.2, <3', - 'typing-extensions >=3.7.4.2, <5', + 'typing-extensions >=4, <5', ], python_requires='>=3.7', entry_points={ From cc10d9a3b0731e6f1cca7086258a77a309fa0100 Mon Sep 17 00:00:00 2001 From: Dan Trickey Date: Sat, 11 Mar 2023 18:31:13 +0000 Subject: [PATCH 2/2] Use a TypedDict for team_info --- sr/comp/http/server.py | 31 ++++++++++++++++--------------- sr/comp/http/structs.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 sr/comp/http/structs.py diff --git a/sr/comp/http/server.py b/sr/comp/http/server.py index 4352783..de1517b 100644 --- a/sr/comp/http/server.py +++ b/sr/comp/http/server.py @@ -22,6 +22,7 @@ from sr.comp.types import ArenaName, MatchNumber, Region, RegionName, TLA from .query_utils import MatchInfo +from .structs import NameWithURL, TeamInfo, TeamScores app = Flask('sr.comp.http') app.json_encoder = JsonEncoder # type: ignore[assignment] @@ -121,24 +122,24 @@ def get_location(name: str) -> Response: return jsonify(format_location(location)) -def team_info(comp: SRComp, team: Team) -> dict[str, Any]: +def team_info(comp: SRComp, team: Team) -> TeamInfo: scores = comp.scores.league.teams[team.tla] league_pos = comp.scores.league.positions[team.tla] location = comp.venue.get_team_location(team.tla) - info = { - 'name': team.name, - 'get': url_for('get_team', tla=team.tla), - 'tla': team.tla, - 'league_pos': league_pos, - 'location': { - 'name': location, - 'get': url_for('get_location', name=location), - }, - 'scores': { - 'league': scores.league_points, - 'game': scores.game_points, - }, - } + info = TeamInfo( + name=team.name, + get=url_for('get_team', tla=team.tla), + tla=team.tla, + league_pos=league_pos, + location=NameWithURL( + name=location, + get=url_for('get_location', name=location), + ), + scores=TeamScores( + league=scores.league_points, + game=scores.game_points, + ), + ) if os.path.exists(os.path.join( g.comp_man.root_dir, diff --git a/sr/comp/http/structs.py b/sr/comp/http/structs.py new file mode 100644 index 0000000..1dc4b40 --- /dev/null +++ b/sr/comp/http/structs.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from typing_extensions import NotRequired, TypedDict + +from league_ranker import LeaguePoints + +from sr.comp.scores import LeaguePosition +from sr.comp.types import GamePoints + + +class NameWithURL(TypedDict): + + name: str + get: str + + +class TeamScores(TypedDict): + + league: LeaguePoints + game: GamePoints + + +class TeamInfo(TypedDict): + + name: str + get: str + tla: str + league_pos: LeaguePosition + location: NameWithURL + scores: TeamScores + image_url: NotRequired[str]