requester-kit
Async HTTP connector toolkit with retries, typed responses, and decorator-driven Prometheus metrics.
Install
uv add requester-kit
Metrics extra:
uv add --extra metrics requester-kit
Quickstart
from uuid import UUID
from pydantic import BaseModel
from requester_kit import BaseRequesterKit, RequesterKitResponse, prometheus_metrics
class UserInfo(BaseModel):
id: UUID
name: str
class UsersAPI(BaseRequesterKit):
@prometheus_metrics()
async def get_user_info(self, user_id: UUID) -> RequesterKitResponse[UserInfo]:
return await self.get(f"/users/{user_id}", response_model=UserInfo)
async def run():
users = UsersAPI(base_url="https://api.example.com")
response = await users.get_user_info(UUID("00000000-0000-0000-0000-000000000000"))
if response.is_ok and response.parsed_data:
print(response.parsed_data.name)
Retries and logging
from requester_kit import BaseRequesterKit
from requester_kit.types import LoggerSettings, RetrySettings
client = BaseRequesterKit(
base_url="https://api.example.com",
retryer_settings=RetrySettings(
retries=3,
delay=0.2,
increment=0.1,
custom_status_codes={429},
),
logger_settings=LoggerSettings(
log_error_for_4xx=False,
log_error_for_5xx=True,
),
)
Prometheus metrics
Use @prometheus_metrics(...) on external requester methods to enable Prometheus collection for that operation.
Each HTTP call records a Histogram named requester_kit_request_duration_seconds with labels:
method (for example UsersAPI.get_user_info), status_code, status_class, and attempt.
This provides request count and timing via the standard _count and _sum series.
Errors are counted in requester_kit_request_errors_total with labels:
method, status_code, error_type (http_status or http_error), and attempt.
Payload sizes are recorded in Histograms:
requester_kit_request_payload_bytes and requester_kit_response_bytes with the same labels as
requester_kit_request_duration_seconds. They are optional and are only collected when
count_payload_bytes=True or count_response_bytes=True is set on the decorator.
If name is omitted, the method label is always ClassName.method_name. You can override only the method part:
from requester_kit import BaseRequesterKit, prometheus_metrics
class UsersAPI(BaseRequesterKit):
@prometheus_metrics()
async def get_user_info(self, user_id: str):
return await self.get(f"/users/{user_id}")
@prometheus_metrics("load_profile", count_response_bytes=True)
async def get_profile(self, user_id: str):
return await self.get(f"/profiles/{user_id}")
@prometheus_metrics(count_payload_bytes=True)
async def create_user(self, payload: dict):
return await self.post("/users", json=payload)
If a method is not decorated, Prometheus metrics are not recorded for it.
Expose metrics in FastAPI:
from fastapi import FastAPI, Response
from prometheus_client import CONTENT_TYPE_LATEST, generate_latest
app = FastAPI()
@app.get("/metrics")
def metrics():
return Response(generate_latest(), media_type=CONTENT_TYPE_LATEST)
Expose metrics using prometheus-fastapi-instrumentator:
from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator
app = FastAPI()
Instrumentator().instrument(app).expose(app, endpoint="/metrics")
Why this works: BaseRequesterKit writes metrics to the default Prometheus registry, and both generate_latest()
and prometheus-fastapi-instrumentator expose that same registry, so your HTTP client metrics appear alongside
your app metrics on /metrics.
Release
- Update the package version in
pyproject.toml. - Add a new entry to
CHANGELOG.mdwith the release date and notable changes. - Run checks:
uv run pytest -q
uv run ruff check requester_kit tests
- Commit the changes and create a git tag matching the version:
git tag v0.5.4
git push origin main --tags
- Build and publish the package:
uv build
uv publish
If you also keep uv.lock in sync for releases, refresh it before tagging with uv lock.
Testing
Use pytest-mock to stub out connector methods:
from unittest import mock
from pydantic import BaseModel
from requester_kit import BaseRequesterKit
from requester_kit.types import RequesterKitResponse
class UserInfo(BaseModel):
id: str
name: str
class UsersAPI(BaseRequesterKit):
async def get_user_info(self, user_id: str) -> RequesterKitResponse[UserInfo]:
return await self.get(f"/users/{user_id}", response_model=UserInfo)
async def test_get_user_info(mocker):
mocker.patch.object(
UsersAPI,
"get_user_info",
new=mock.AsyncMock(
return_value=RequesterKitResponse(
status_code=200,
is_ok=True,
parsed_data=UserInfo(id="1", name="Ada"),
)
),
)
client = UsersAPI(base_url="https://api.example.com")
response = await client.get_user_info("1")
assert response.is_ok
Metadata
Release files for requester-kit 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| requester_kit-0.6.0.tar.gz | 84.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| requester_kit-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.3 kB
Release files / requester_kit-0.6.0.tar.gz
| Download URL | requester_kit-0.6.0.tar.gz |
|---|---|
| Size | 84.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8df3a52d1709f55fba7c04a9f7100cba78e917ced6a85f9838194e843d31b9bf
|
|
BLAKE2b-256 checksum How to use checksums |
c1a60d94052f03edc88a0033d22207774e732da1765afe11d24e0ccc7848ef0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 5, 2026.
Transparency logRelease files / requester_kit-0.6.0-py3-none-any.whl
| Download URL | requester_kit-0.6.0-py3-none-any.whl |
|---|---|
| Size | 9.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b1263ad0aef96e744a19e208c01f92f94fd018019b3bb2a80486677e517c64da
|
|
BLAKE2b-256 checksum How to use checksums |
9dc4f3fa1230411824103ede839d378880440eb2ad03fed2fb184da25d237643
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 5, 2026.
Transparency log