nhl_scrabble.api
NHL API client module.
This package provides the NHL API client and related utilities for fetching team and roster data from the official NHL API.
- Public API:
NHLApiClient: Main API client class
Error classes: NHLApiError, NHLApiConnectionError, NHLApiNotFoundError, NHLApiSSLError
Retry utilities: get_retry_after (from api.retry)
Error handlers: handle_http_error, handle_connection_error (from api.errors)
Functions
|
Extract Retry-After header value from 429 response. |
|
Handle connection errors after retries exhausted. |
|
Handle HTTP errors and convert to appropriate NHL API exceptions. |
Classes
|
Client for interacting with the NHL API. |
Exceptions
Raised when unable to connect to the NHL API. |
|
Base exception for NHL API errors. |
|
Raised when the requested resource is not found (404). |
|
Raised when SSL/TLS certificate verification fails. |
- class nhl_scrabble.api.NHLApiClient(base_url=None, timeout=10, retries=3, rate_limit_max_requests=30, rate_limit_window=60.0, backoff_factor=2.0, max_backoff=30.0, cache_enabled=True, cache_expiry=3600, cache_dir=None, verify_ssl=True, dos_max_connections=10, dos_max_per_host=5, dos_circuit_breaker_threshold=5, dos_circuit_breaker_timeout=60.0)[source][source]
Bases:
objectClient for interacting with the NHL API.
This client provides methods to fetch team standings and roster data from the official NHL API with built-in retry logic, rate limiting, SSRF protection, DoS prevention, and enforced SSL/TLS certificate verification.
- SSL/TLS Security:
Certificate verification is always enabled and cannot be disabled
Uses certifi CA bundle for up-to-date certificate authorities
SSL errors are caught and logged for security monitoring
- DoS Prevention:
Circuit breaker pattern to prevent cascading failures
Connection pool limits to prevent resource exhaustion
Configurable failure thresholds and timeouts
- __init__(base_url=None, timeout=10, retries=3, rate_limit_max_requests=30, rate_limit_window=60.0, backoff_factor=2.0, max_backoff=30.0, cache_enabled=True, cache_expiry=3600, cache_dir=None, verify_ssl=True, dos_max_connections=10, dos_max_per_host=5, dos_circuit_breaker_threshold=5, dos_circuit_breaker_timeout=60.0)[source][source]
Initialize the NHL API client.
- Parameters:
base_url (
str|None) – Base URL for NHL API (default: https://api-web.nhle.com/v1). Will be validated for SSRF protection on first request.timeout (
int) – Request timeout in seconds (default: 10)retries (
int) – Number of retry attempts for failed requests (default: 3)rate_limit_max_requests (
int) – Maximum requests per time window (default: 30)rate_limit_window (
float) – Time window for rate limiting in seconds (default: 60.0)backoff_factor (
float) – Exponential backoff multiplier (default: 2.0)max_backoff (
float) – Maximum backoff delay in seconds (default: 30.0)cache_enabled (
bool) – Enable HTTP caching (default: True)cache_expiry (
int) – Cache expiration in seconds (default: 3600 = 1 hour)cache_dir (
str|Path|None) – Cache directory path (default: platform-specific user cache directory)verify_ssl (
bool) – SSL verification (must be True, cannot be disabled for security)dos_max_connections (
int) – Maximum connection pool connections (default: 10)dos_max_per_host (
int) – Maximum connections per host (default: 5)dos_circuit_breaker_threshold (
int) – Circuit breaker failure threshold (default: 5)dos_circuit_breaker_timeout (
float) – Circuit breaker timeout in seconds (default: 60.0)
- Raises:
NHLApiError – If base_url fails SSRF protection validation or cache directory not writable
ValueError – If verify_ssl is False (SSL verification cannot be disabled)
- __del__()[source][source]
Destructor - close session if not already closed (safety net).
- Return type:
- get_teams(season=None)[source][source]
Fetch all NHL teams with division and conference information.
This method uses the retry decorator to automatically retry on network errors. The URL is validated with SSRF protection before making the request.
- Parameters:
season (
str|None) – Optional season in format ‘YYYYYYYY’ (e.g., ‘20222023’ for 2022-23). If None, fetches current season data.- Returns:
- {
‘TOR’: {‘division’: ‘Atlantic’, ‘conference’: ‘Eastern’}, ‘MTL’: {‘division’: ‘Atlantic’, ‘conference’: ‘Eastern’}, …
}
- Return type:
- Raises:
NHLApiConnectionError – If unable to connect to the API
NHLApiError – For other API errors, including SSRF protection blocks
Examples
>>> client = NHLApiClient() >>> teams = client.get_teams() >>> "TOR" in teams True >>> teams_2022 = client.get_teams(season="20222023") >>> "TOR" in teams_2022 True
- get_team_roster(team_abbrev, season=None)[source][source]
Fetch the roster for a specific team with input and response validation.
Validates team abbreviation before making API call and validates response structure to prevent errors from malformed data.
The URL is validated with SSRF protection before making the request.
- Parameters:
- Return type:
- Returns:
Dictionary containing roster data with ‘forwards’, ‘defensemen’, and ‘goalies’ keys
- Raises:
ValidationError – If team abbreviation is invalid
NHLApiNotFoundError – If the roster is not found (404 response)
NHLApiConnectionError – If unable to connect to the API after all retries
NHLApiError – For other API errors, including SSRF protection blocks and malformed responses
- Security:
Validates team abbreviation to prevent injection attacks
Validates response structure to prevent KeyError exceptions
Sanitizes player names from API responses
SSRF protection on all API requests
Examples
>>> client = NHLApiClient() >>> roster = client.get_team_roster("TOR") >>> "forwards" in roster True >>> roster_2022 = client.get_team_roster("TOR", season="20222023") >>> "forwards" in roster_2022 True >>> client.get_team_roster("INVALID") Traceback (most recent call last): ValidationError: Team abbreviation must be 2-3 characters...
- get_player_details(player_id)[source][source]
Fetch detailed player information from NHL API.
- Parameters:
player_id (
int) – NHL player ID (numeric)- Return type:
- Returns:
Player detail data including photo, birthplace, position, etc.
- Raises:
NHLApiNotFoundError – If player not found
NHLApiConnectionError – If unable to connect to the API
NHLApiError – If API request fails
Examples
>>> client = NHLApiClient() >>> try: ... player = client.get_player_details(8478402) # Connor McDavid ... assert "playerId" in player ... assert "firstName" in player ... finally: ... client.close()
- get_rate_limit_stats()[source][source]
Get rate limiter statistics.
- Returns:
total_requests: Total requests made
total_waits: Total times waited for tokens
total_wait_time: Total time spent waiting
average_wait: Average wait time per wait
current_tokens: Current token count
max_tokens: Maximum token capacity
- Return type:
Examples
>>> client = NHLApiClient() >>> stats = client.get_rate_limit_stats() >>> "total_requests" in stats True
- get_cache_info()[source][source]
Get cache statistics and information.
- Returns:
enabled (bool): Whether caching is enabled
backend (str | None): Cache backend type (e.g., “sqlite”)
size (int | None): Number of cached responses
expiry (int): Cache expiry time in seconds
- Return type:
Examples
>>> client = NHLApiClient(cache_enabled=True) >>> info = client.get_cache_info() >>> print(info["enabled"]) True >>> print(info["backend"]) 'sqlite'
- exception nhl_scrabble.api.NHLApiConnectionError[source][source]
Bases:
NHLApiErrorRaised when unable to connect to the NHL API.
This includes network timeouts, connection refused, DNS failures, and other connection-related issues.
Examples
>>> raise NHLApiConnectionError("Unable to connect to NHL API after 3 retries") Traceback (most recent call last): NHLApiConnectionError: Unable to connect to NHL API after 3 retries
- exception nhl_scrabble.api.NHLApiError[source][source]
Bases:
APIErrorBase exception for NHL API errors.
Raised for NHL API-specific errors including HTTP errors, invalid responses, and API-level failures.
Examples
>>> raise NHLApiError("NHL API returned invalid data") Traceback (most recent call last): NHLApiError: NHL API returned invalid data
- exception nhl_scrabble.api.NHLApiNotFoundError[source][source]
Bases:
NHLApiErrorRaised when the requested resource is not found (404).
Indicates that the NHL API returned a 404 status code, meaning the requested resource (team, roster, etc.) does not exist.
Examples
>>> raise NHLApiNotFoundError("Roster not found for team: XYZ") Traceback (most recent call last): NHLApiNotFoundError: Roster not found for team: XYZ
- exception nhl_scrabble.api.NHLApiSSLError[source][source]
Bases:
NHLApiErrorRaised when SSL/TLS certificate verification fails.
Indicates a problem with SSL/TLS certificate validation, which could be a security issue or a configuration problem.
Examples
>>> raise NHLApiSSLError("SSL certificate verification failed for api.nhle.com") Traceback (most recent call last): NHLApiSSLError: SSL certificate verification failed for api.nhle.com
- nhl_scrabble.api.get_retry_after(response)[source][source]
Extract Retry-After header value from 429 response.
The Retry-After header can be either: - An integer (seconds to wait) - An HTTP date (less common for 429 responses)
If no valid Retry-After header is found, returns 1.0 second as default.
- Parameters:
response (
Response) – HTTP response with 429 status- Return type:
- Returns:
Seconds to wait before retry (minimum 1.0)
Examples
>>> from unittest.mock import Mock >>> response = Mock() >>> response.headers = {"Retry-After": "60"} >>> get_retry_after(response) 60.0
>>> response.headers = {} >>> get_retry_after(response) 1.0
>>> response.headers = {"Retry-After": "invalid"} >>> get_retry_after(response) 1.0
- nhl_scrabble.api.handle_connection_error(error, context='', retries=3)[source][source]
Handle connection errors after retries exhausted.
- Parameters:
error (
RequestException) – The connection errorcontext (
str) – Optional context stringretries (
int) – Number of retries that were attempted
- Raises:
NHLApiSSLError – If SSL certificate verification failed
NHLApiConnectionError – For other connection errors
- Return type:
Examples
>>> import requests >>> error = requests.exceptions.Timeout("Connection timeout") >>> try: ... handle_connection_error(error, "fetching teams", retries=3) ... except NHLApiConnectionError as e: ... print("timeout" in str(e).lower()) True
- nhl_scrabble.api.handle_http_error(error, context='')[source][source]
Handle HTTP errors and convert to appropriate NHL API exceptions.
- Parameters:
- Raises:
NHLApiNotFoundError – If 404 status code
NHLApiError – For other HTTP errors
- Return type:
Examples
>>> import requests >>> from unittest.mock import Mock >>> response = Mock() >>> response.status_code = 404 >>> error = requests.exceptions.HTTPError(response=response) >>> try: ... handle_http_error(error, "team TOR") ... except NHLApiNotFoundError as e: ... print(str(e)) Not found: team TOR