Skip to content

A Riot API wrapper specifically for League of Legends.

License

Notifications You must be signed in to change notification settings

diodemusic/pyke

Repository files navigation

pyke

PyPI - Version Documentation PyPI - Downloads Coverage License: MIT

pyke is a production-ready Riot API wrapper with intelligent rate limiting and robust error handling, specifically designed for League of Legends.

Key Features

  • Smart Rate Limiting - Dynamic request throttling based on API headers to maximize throughput while preventing 429 errors
  • Resilient Retry Logic - Retry strategies for rate limits and server errors with intelligent exponential backoff
  • Type-Safe - Full Pydantic model support with comprehensive type hints for autocompletion and validation
  • Pythonic API - Clean, intuitive interface that mirrors Riot's API structure exactly
  • Production Logging - Standard Python logging integration with configurable levels
  • Highly Configurable - Customize timeouts, retry limits, rate limiting behavior, and more

Installation

Install the latest version directly from PyPI:

pip install pyke-lol

Note: You need Python 3.9+ to use pyke.


Quickstart

from pyke import Continent, Pyke, exceptions

# Initialize the API
api = Pyke("RGAPI-...")

# Every pyke method follows the same convention as the Riot API
# For example account/v1/accounts/by-riot-id/{gameName}/{tagLine} becomes:
account = api.account.by_riot_id(Continent.EUROPE, "saves", "000")

# Every response is a Pydantic model with dot notation access
print(f"Riot ID: {account.game_name}#{account.tag_line}")
print(f"PUUID:   {account.puuid}")

# Pydantic models provide convenient serialization
print(account.model_dump_json())  # JSON string
print(account.model_dump())       # Python dictionary

# pyke throws typed exceptions matching Riot API error codes
try:
    region = api.account.region_by_puuid(Continent.EUROPE, account.puuid)
except exceptions.DataNotFound as e:
    print(e)  # Output: Data not found (Error Code: 404)
    quit()

print(f"PUUID:  {region.puuid}")
print(f"Game:   {region.game}")
print(f"Region: {region.region}")

Configuration

pyke offers extensive configuration options for production use:

from pyke import Pyke

api = Pyke(
    api_key="RGAPI-...",
    smart_rate_limiting=True,      # Enable intelligent rate limiting (default: True)
    timeout=60,                    # Request timeout in seconds (default: 60)
    max_rate_limit_retries=5,      # Max retries for 429 errors (default: 5)
    max_server_error_retries=3,    # Max retries for 502/503/504 (default: 3)
)

Smart Rate Limiting

pyke's rate limiting algorithm analyzes response headers to:

  • Calculate optimal wait times between requests
  • Maximize throughput without hitting rate limits
  • Automatically respect Retry-After headers on 429 responses

Result: Zero rate limit violations while maintaining maximum request speed.

Intelligent Retry Logic

pyke uses separate retry strategies for different error types:

Rate Limit Errors (429):

  • Independent retry counter (default: 5 attempts)
  • Respects Retry-After header from API
  • Logs retry progress: Rate limit retries: 2/5

Server Errors (502/503/504):

  • Separate retry counter (default: 3 attempts)
  • Error-specific exponential backoff:
    • 504 Gateway Timeout: 10s base (10s → 20s → 40s) - longer recovery for backend timeouts
    • 502/503 Server Errors: 5s base (5s → 10s → 20s) - faster recovery for transient issues
  • Prevents infinite retry loops while maintaining resilience

Logging

pyke uses Python's standard logging module for comprehensive diagnostics:

import logging
from pyke import Pyke

# Configure logging before creating Pyke instance
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    datefmt="%H:%M:%S",
)

api = Pyke("RGAPI-...")

Log Levels

  • DEBUG: Detailed diagnostic information
  • INFO: Request URLs with rate limit tracking: (45/100) - https://na1.api.riotgames.com/...
  • WARNING: Retries, rate limiting, malformed API responses
  • ERROR: Critical failures

Common Configurations

# Production (quiet) - only warnings and errors
logging.basicConfig(level=logging.WARNING)

# Development (verbose) - see all requests
logging.basicConfig(level=logging.INFO)

# Debugging - maximum verbosity
logging.basicConfig(level=logging.DEBUG)

# Completely silent
logging.getLogger('pyke').setLevel(logging.CRITICAL)

# Log to file
logging.basicConfig(
    level=logging.INFO,
    filename="api_requests.log",
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s"
)

Advanced Features

Type Safety with Pydantic Models

All API responses are Pydantic models with full type hints:

from pyke import Pyke, Region

api = Pyke("RGAPI-...")

account = api.account.by_riot_id(Continent.EUROPE, "saves", "000")
summoner = api.summoner.by_puuid(Region.EUW, account.puuid)

# Dot notation access with autocomplete
print(summoner.puuid)             # Type: str
print(summoner.summoner_level)    # Type: int
print(summoner.profile_icon_id)   # Type: int

# JSON serialization
json_str = summoner.model_dump_json()
dict_data = summoner.model_dump()

Custom Exception Handling

pyke provides typed exceptions for all HTTP status codes:

from pyke import exceptions

try:
    summoner = api.summoner.by_puuid(Region.EUW, "NonExistentPuuid")
except exceptions.DataNotFound as e:
    print(f"Not found: {e}")     # Data not found (Error Code: 404)
except exceptions.RateLimitExceeded as e:
    print(f"Rate limited: {e}")  # Rate limit exceeded after 5 retries (Error Code: 429)
except exceptions.InternalServerError as e:
    print(f"Server error: {e}")  # Internal server error (Error Code: 500)

Available exceptions: BadRequest (400), Unauthorized (401), Forbidden (403), DataNotFound (404), MethodNotAllowed (405), UnsupportedMediaType (415), RateLimitExceeded (429), InternalServerError (500), BadGateway (502), ServiceUnavailable (503), GatewayTimeout (504)

Continental vs Regional Routing

pyke automatically handles Riot's routing requirements:

from pyke import Continent, Region

# Continental routing (Account-V1, Match-V5)
account = api.account.by_riot_id(Continent.EUROPE, "saves", "000")

# Regional routing (Summoner-V4, League-V4, etc.)
summoner = api.summoner.by_puuid(Region.EUW, account.puuid)

Continental Routing:

  • AMERICAS: NA, BR, LAN, LAS
  • ASIA: KR, JP
  • EUROPE: EUNE, EUW, ME1, TR, RU
  • SEA: OCE, SG2, TW2, VN2

Complete Feature List

  • Smart Rate Limiting - Dynamic throttling based on API headers
  • Dual Retry Strategies - Separate 429 and 50x retry logic with exponential backoff
  • Type-Safe Models - 97 Pydantic models with full type hints
  • Production Logging - Standard Python logging with configurable levels
  • Custom Exceptions - 11 typed exception classes for precise error handling
  • Continental Routing - Automatic routing for Account/Match endpoints
  • Configurable Timeouts - Adjust request timeouts for slow endpoints
  • Mirror API Design - Intuitive mapping to Riot's API structure
  • Pythonic Interface - Clean, idiomatic Python code
  • 94% Test Coverage - Comprehensive integration test suite
  • Python 3.9-3.14 - Tested across 6 Python versions

Documentation & Resources


Contributing & Support

Found a bug or have a feature request? Open an issue on GitHub.

For questions or help, reach out on Discord: .irm


License

MIT License - see LICENSE.txt for details.


Made with ❤️ for the League of Legends developer community