Migrated to ruff for faster, modern code formatting and linting: Configuration changes: - pyproject.toml: Added ruff 0.8.6, removed black/flake8 - Configured ruff with black-compatible formatting (88 chars) - Enabled comprehensive linting rules (pycodestyle, pyflakes, isort, pyupgrade, bugbear, comprehensions, simplify, return) - Updated CLAUDE.md: Changed code quality commands to use ruff Code improvements (490 auto-fixes): - Modernized type hints: List[T] → list[T], Dict[K,V] → dict[K,V], Optional[T] → T | None - Sorted all imports (isort integration) - Removed unused imports - Fixed whitespace issues - Reformatted 38 files for consistency Bug fixes: - app/core/play_resolver.py: Fixed type hint bug (any → Any) - tests/unit/core/test_runner_advancement.py: Removed obsolete random mock Testing: - All 739 unit tests passing (100%) - No regressions introduced 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
116 lines
3.4 KiB
Python
116 lines
3.4 KiB
Python
"""
|
|
SBA API client for fetching player data.
|
|
|
|
Integrates with SBA REST API to retrieve player information
|
|
for use in game lineup display.
|
|
|
|
Author: Claude
|
|
Date: 2025-01-10
|
|
"""
|
|
|
|
import logging
|
|
|
|
import httpx
|
|
|
|
from app.models.player_models import SbaPlayer
|
|
|
|
logger = logging.getLogger(f"{__name__}.SbaApiClient")
|
|
|
|
|
|
class SbaApiClient:
|
|
"""Client for SBA API player data lookups."""
|
|
|
|
def __init__(self, base_url: str = "https://api.sba.manticorum.com"):
|
|
"""
|
|
Initialize SBA API client.
|
|
|
|
Args:
|
|
base_url: Base URL for SBA API (default: production)
|
|
"""
|
|
self.base_url = base_url
|
|
self.timeout = httpx.Timeout(10.0, connect=5.0)
|
|
|
|
async def get_player(self, player_id: int) -> SbaPlayer:
|
|
"""
|
|
Fetch player data from SBA API.
|
|
|
|
Args:
|
|
player_id: SBA player ID
|
|
|
|
Returns:
|
|
SbaPlayer instance with all player data
|
|
|
|
Raises:
|
|
httpx.HTTPError: If API request fails
|
|
|
|
Example:
|
|
player = await client.get_player(12288)
|
|
print(f"Name: {player.name}") # "Ronald Acuna Jr"
|
|
print(f"Positions: {player.get_positions()}") # ['RF']
|
|
"""
|
|
url = f"{self.base_url}/players/{player_id}"
|
|
|
|
try:
|
|
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
|
response = await client.get(url)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
player = SbaPlayer.from_api_response(data)
|
|
|
|
logger.info(f"Loaded player {player_id}: {player.name}")
|
|
return player
|
|
|
|
except httpx.HTTPError as e:
|
|
logger.error(f"Failed to fetch player {player_id}: {e}")
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Unexpected error fetching player {player_id}: {e}")
|
|
raise
|
|
|
|
async def get_players_batch(self, player_ids: list[int]) -> dict[int, SbaPlayer]:
|
|
"""
|
|
Fetch multiple players in parallel.
|
|
|
|
Args:
|
|
player_ids: List of SBA player IDs to fetch
|
|
|
|
Returns:
|
|
Dictionary mapping player_id to SbaPlayer instance
|
|
Players that fail to load will be omitted from the result
|
|
|
|
Example:
|
|
players = await client.get_players_batch([12288, 12289, 12290])
|
|
for player_id, player in players.items():
|
|
print(f"{player.name}: {player.get_positions()}")
|
|
"""
|
|
if not player_ids:
|
|
return {}
|
|
|
|
results: dict[int, SbaPlayer] = {}
|
|
|
|
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
|
for player_id in player_ids:
|
|
try:
|
|
url = f"{self.base_url}/players/{player_id}"
|
|
response = await client.get(url)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
player = SbaPlayer.from_api_response(data)
|
|
results[player_id] = player
|
|
|
|
except httpx.HTTPError as e:
|
|
logger.warning(f"Failed to fetch player {player_id}: {e}")
|
|
# Continue with other players
|
|
except Exception as e:
|
|
logger.warning(f"Unexpected error fetching player {player_id}: {e}")
|
|
# Continue with other players
|
|
|
|
logger.info(f"Loaded {len(results)}/{len(player_ids)} players")
|
|
return results
|
|
|
|
|
|
# Singleton instance
|
|
sba_api_client = SbaApiClient()
|