Async OpenDota API client built on Niquests with typed models and HTTP/2–3 multiplexing.
Project description
opendota-async
Production-oriented async client for the OpenDota API (Dota 2 stats), built on Niquests: HTTP/1.1, HTTP/2, and HTTP/3 with connection pooling and optional multiplexed fan-out.
Install
pip install opendota-async
HTTP/3 (QUIC) extras (when you need wheels/protocol guarantees):
pip install 'opendota-async[http3]'
Quickstart (30 seconds)
import asyncio
from opendota_async import OpenDotaClient
async def main():
async with OpenDotaClient() as client:
profile = await client.players.get(86745912)
print(profile.model_dump())
asyncio.run(main())
API key
Register at OpenDota API keys and pass a key (query param api_key or Bearer header — both are supported):
async with OpenDotaClient(api_key="YOUR_KEY") as client:
...
# or
async with OpenDotaClient(bearer_token="YOUR_KEY") as client:
...
Environment variables (logged when used, never silently): OPENDOTA_API_KEY, OPENDOTA_BASE_URL, OPENDOTA_TIMEOUT, … — see OpenDotaClientConfig.from_env().
Multiplexed fan-out
gather_get temporarily enables Niquests multiplexing, issues parallel GETs, calls
session.gather(), then parses JSON. Use it for fan-out; ordinary request() calls keep
multiplexing off so responses are not lazy ResponsePromise objects.
profiles = await client.players.gather_get([86745912, 302214028, 105248644])
Error handling
from opendota_async import NotFoundError, RateLimitError, OpenDotaClient
async def safe():
try:
async with OpenDotaClient() as c:
await c.players.get(1)
except NotFoundError as e:
print(e.status_code, e.negotiated_protocol, e.response_body)
except RateLimitError as e:
print("retry after", e.retry_after)
Pagination
async with OpenDotaClient() as client:
async for m in client.players.matches(86745912, hero_id=74):
print(m.match_id)
Sync usage
A blocking OpenDotaSyncClient shares the same configuration model and serializers:
from opendota_async import OpenDotaSyncClient
with OpenDotaSyncClient() as c:
p = c.players.get(86745912)
Design notes
- Lifecycle: Always use
async with OpenDotaClient(...) as c:orawait client.aclose(). Do not rely on__del__. - Event loops: One client per event loop; Niquests sessions are not safe across loops.
- Retries: Idempotent verbs retry on connection errors, timeouts, 429, and 502/503/504 with backoff + jitter; POST retries for status codes are opt-in via
retry_post=TrueonRetryPolicy/ config. - Types: Responses are Pydantic models; use
.model_dump()for raw dicts.client.last_raw_responseis per-async-task forOpenDotaClientand per-thread forOpenDotaSyncClient(safe under concurrent tasks/threads).
Testing
pytest runs unit tests and live checks against https://api.opendota.com (no key required). To skip network calls (e.g. offline CI), set OPENDOTA_OFFLINE=1.
Documentation
Full docs (MkDocs Material / Read the Docs) will expand on streaming, SSE/WebSockets where applicable. See docs/index.md for the deprecation policy.
Publishing (GitHub → PyPI)
CI and release workflows live in .github/workflows/. Step-by-step instructions: docs/publishing.md (tag a v* release after bumping version in pyproject.toml).
Changelog
See CHANGELOG.md.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opendota_async-0.1.0.tar.gz.
File metadata
- Download URL: opendota_async-0.1.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26cc63969b6f2041e9260ab0ee7587b489d166584202e5e25ef364e61eb06d78
|
|
| MD5 |
75c829773ba68ca517a40c63d75f163d
|
|
| BLAKE2b-256 |
5c9883adf2dbc8e118d75927968e48b9302f4395b33f4f18c0c17a9ee7c88d80
|
Provenance
The following attestation bundles were made for opendota_async-0.1.0.tar.gz:
Publisher:
publish.yml on Vasiliy566/opendota_async
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opendota_async-0.1.0.tar.gz -
Subject digest:
26cc63969b6f2041e9260ab0ee7587b489d166584202e5e25ef364e61eb06d78 - Sigstore transparency entry: 1312290047
- Sigstore integration time:
-
Permalink:
Vasiliy566/opendota_async@15c427d489c6db71ba70d47cc22cee805b79e482 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Vasiliy566
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@15c427d489c6db71ba70d47cc22cee805b79e482 -
Trigger Event:
push
-
Statement type:
File details
Details for the file opendota_async-0.1.0-py3-none-any.whl.
File metadata
- Download URL: opendota_async-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57bc1a1336810674842cf3b73147083083d443b83f748dd01fbe0a75568b6142
|
|
| MD5 |
53d8356e96c04f23097e852013511200
|
|
| BLAKE2b-256 |
ee62a0fd7308ab832642bdfc4f912e8e98a12d0a54ca2e97e9e610ed0a48cb8c
|
Provenance
The following attestation bundles were made for opendota_async-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Vasiliy566/opendota_async
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opendota_async-0.1.0-py3-none-any.whl -
Subject digest:
57bc1a1336810674842cf3b73147083083d443b83f748dd01fbe0a75568b6142 - Sigstore transparency entry: 1312290106
- Sigstore integration time:
-
Permalink:
Vasiliy566/opendota_async@15c427d489c6db71ba70d47cc22cee805b79e482 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Vasiliy566
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@15c427d489c6db71ba70d47cc22cee805b79e482 -
Trigger Event:
push
-
Statement type: