Coverage for src/usls/ports/outbound.py: 100%
11 statements
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-05 10:11 +0000
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-05 10:11 +0000
1"""Outbound ports — interfaces the application layer depends on.
3These are the contracts that secondary/driven adapters must satisfy. The
4application layer only imports these protocols; it never references concrete
5implementations. This is what makes the hexagonal boundary testable and
6swap-able (e.g. real HTTP adapter vs. an in-memory stub).
7"""
9from typing import Protocol
11from ..domain.models import Match, MatchDetails, NewsArticle, Player, Standing, Team
14class USLSAPIPort(Protocol):
15 """Contract for the upstream USL Super League data source (ESPN API)."""
17 async def get_teams(self) -> list[Team]:
18 """Return all active USL Super League teams."""
19 ...
21 async def get_team(self, team_id: str) -> Team:
22 """Return a single team by its ESPN team ID.
24 Raises:
25 USLSNotFoundError: If no team with that ID exists.
26 """
27 ...
29 async def get_scoreboard(self, date: str | None = None, end_date: str | None = None) -> list[Match]:
30 """Return matches on the given date or date range, or today if date is None.
32 When ``end_date`` is provided, ``date`` is the start of the range and the
33 upstream is queried with ``dates=START-END``.
34 """
35 ...
37 async def get_news(self, limit: int) -> list[NewsArticle]:
38 """Return up to ``limit`` recent USL Super League news articles."""
39 ...
41 async def get_roster(self, team_id: str) -> list[Player]:
42 """Return the active roster for a team.
44 Raises:
45 USLSNotFoundError: If no team with that ID exists.
46 """
47 ...
49 async def get_match_details(self, match_id: str) -> MatchDetails:
50 """Return detailed information for a single match.
52 Raises:
53 USLSNotFoundError: If no match with that ID exists.
54 """
55 ...
57 async def get_team_schedule(self, team_id: str) -> list[Match]:
58 """Return all scheduled and completed matches for a team in the current season.
60 Raises:
61 USLSNotFoundError: If no team with that ID exists.
62 """
63 ...
65 async def get_standings(self) -> list[Standing]:
66 """Return the current USL Super League standings ordered by points descending.
68 Each Standing carries its ``conference`` label ("Eastern Conference" /
69 "Western Conference") so callers can group when needed. The list is
70 flat across both conferences.
71 """
72 ...