Migration Guide¶
This guide helps you migrate between different versions of the Chess.com API client. It documents all breaking changes, deprecations, and new features for each version.
Upgrading to 1.0.0¶
Breaking Changes¶
- Async/Await Support
# Old code (0.x)
client = ChessComClient()
player = client.get_player("hikaru")
client.close()
# New code (1.0.0)
async with ChessComClient() as client:
player = await client.get_player("hikaru")
- Type Hints
# Old code (0.x)
def get_player(username):
pass
# New code (1.0.0)
async def get_player(self, username: str) -> Player:
pass
- Exception Hierarchy
# Old code (0.x)
try:
player = client.get_player("username")
except ChessComError:
pass
# New code (1.0.0)
try:
player = await client.get_player("username")
except NotFoundError:
# Handle specific error
pass
except ChessComAPIError:
# Handle general API error
pass
New Features¶
- Rate Limiting
# Configure rate limiting
client = ChessComClient(
rate_limit=300, # Maximum concurrent requests
max_retries=3 # Number of retries
)
- Custom Session Configuration
import aiohttp
session = aiohttp.ClientSession(
timeout=aiohttp.ClientTimeout(total=30),
headers={"User-Agent": "MyApp/1.0"}
)
client = ChessComClient(session=session)
- Model Properties
# Access typed properties
player = await client.get_player("hikaru")
print(player.title) # Type: Optional[str]
print(player.rating) # Type: int
Deprecations¶
- Synchronous Methods
# Deprecated (0.x)
client.get_player_sync("username")
# New approach (1.0.0)
import asyncio
asyncio.run(client.get_player("username"))
- Direct Property Access
Migration Steps¶
- Update Dependencies
# Update to the latest version
pip install --upgrade chess-com-api
# For development
pip install --upgrade chess-com-api[dev]
- Update Imports
# Old imports (0.x)
from chess_com_api import ChessComClient, ChessComError
# New imports (1.0.0)
from chess_com_api import (
ChessComClient,
ChessComAPIError,
NotFoundError,
Player
)
- Update Client Usage
# Old code (0.x)
client = ChessComClient()
try:
player = client.get_player("username")
finally:
client.close()
# New code (1.0.0)
async with ChessComClient() as client:
try:
player = await client.get_player("username")
except NotFoundError:
# Handle error
pass
- Update Type Hints
# Add type hints to your functions
async def get_player_info(username: str) -> Optional[Player]:
async with ChessComClient() as client:
try:
return await client.get_player(username)
except NotFoundError:
return None
Code Examples¶
- Handling Multiple Requests
# Old code (0.x)
results = []
for username in usernames:
try:
player = client.get_player(username)
results.append(player)
except ChessComError:
continue
# New code (1.0.0)
async with ChessComClient() as client:
tasks = [
client.get_player(username)
for username in usernames
]
results = await asyncio.gather(
*tasks,
return_exceptions=True
)
- Custom Error Handling
# Old code (0.x)
def handle_errors(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except ChessComError as e:
logging.error(f"API error: {e}")
raise
return wrapper
# New code (1.0.0)
from functools import wraps
def handle_errors(func):
@wraps(func)
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except NotFoundError as e:
logging.warning(f"Resource not found: {e}")
raise
except ChessComAPIError as e:
logging.error(f"API error: {e}")
raise
return wrapper
- Data Processing
# Old code (0.x)
def process_games(username):
games = client.get_player_games(username)
return [game.get("url") for game in games]
# New code (1.0.0)
async def process_games(username: str) -> List[str]:
async with ChessComClient() as client:
games = await client.get_player_games(username)
return [game.url for game in games]
Testing Updates¶
- Update Test Fixtures
# Old tests (0.x)
def test_get_player(client):
player = client.get_player("hikaru")
assert player["username"] == "hikaru"
# New tests (1.0.0)
@pytest.mark.asyncio
async def test_get_player(client):
player = await client.get_player("hikaru")
assert player.username == "hikaru"
- Update Mock Usage
# Old mocks (0.x)
def test_with_mock(mocker):
mocker.patch("chess_com_api.client.get_player")
# New mocks (1.0.0)
@pytest.mark.asyncio
async def test_with_mock(mocker):
mock = mocker.patch("chess_com_api.client._make_request")
mock.return_value = {"username": "hikaru"}
Configuration Updates¶
Environment Variables¶
# Old environment variables (0.x)
CHESS_COM_TIMEOUT=30
CHESS_COM_RETRY=3
# New environment variables (1.0.0)
CHESS_COM_TIMEOUT=30
CHESS_COM_MAX_RETRIES=3
CHESS_COM_RATE_LIMIT=300
Logging Configuration¶
# Old logging (0.x)
logging.basicConfig(level=logging.INFO)
# New logging (1.0.0)
import logging.config
logging.config.dictConfig({
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO"
}
},
"loggers": {
"chess_com_api": {
"handlers": ["console"],
"level": "INFO",
"propagate": False
}
}
})
Best Practices¶
- Always use async/await with proper error handling
- Implement proper type hints
- Use context managers for client lifecycle
- Handle rate limiting appropriately
- Update tests to use pytest-asyncio
- Use modern Python features (3.8+)
Troubleshooting¶
Common Issues¶
- Async/Await Errors
# Error: Async call in non-async function
# Solution: Add async/await
async def main():
async with ChessComClient() as client:
return await client.get_player("username")
result = asyncio.run(main())
- Type Hint Issues
# Error: Type hint incompatibility
# Solution: Add proper type hints
from typing import Optional, List
async def get_players(
usernames: List[str]
) -> List[Optional[Player]]:
pass
Verification Steps¶
- Check all async/await usage
- Verify type hints
- Update error handling
- Update tests
- Check configuration
- Update dependencies