pyrest-model-client
A simple, flexible Python HTTP client and API modeling toolkit built on top of httpx and pydantic. Easily integrate robust API requests and resource models into your Python projects.
🚀 Features
- Model-driven: Define and interact with API resources as Python classes using
BaseAPIModel. - Easy HTTP Requests:
RestApiClientfor GET, POST, PUT, PATCH, DELETE with automatic header and base URL management. - Async Support: Full async/await support with
AsyncRestApiClientfor high-performance concurrent requests. - Automatic Endpoint Normalization: Configurable endpoint path normalization (trailing slash handling).
- Resource Path Integration: Models can use their
resource_pathto generate endpoints and URLs automatically. - Flexible Authentication: Support for Token and Bearer authentication via
build_header()helper. - Response to Model Conversion:
get_model_fields()helper converts API responses to typed model instances. - Configurable Client: Customizable timeout, connection pool limits, and redirect handling.
- Type Safety: All models use Pydantic for automatic validation and serialization.
- Error Handling: Automatic HTTP status error handling with
raise_for_status(). - Extensible: Easily create new models for any RESTful resource by extending
BaseAPIModel.
📦 Installation
uv add pyrest-model-client
🔧 Usage
1. Define Your Models
from pyrest_model_client.base import BaseAPIModel
class User(BaseAPIModel):
name: str
email: str
resource_path: str = "user"
class Environment(BaseAPIModel):
name: str
resource_path: str = "environment"
2. Initialize the Client and Make Requests
import os
from dotenv import load_dotenv
from pyrest_model_client import BaseAPIModel, RestApiClient, build_header, get_model_fields
load_dotenv()
TOKEN = os.getenv("TOKEN")
BASE_URL = f'{os.getenv("BASE_URL")}:{os.getenv("PORT")}'
class FirstApp(BaseAPIModel):
name: str
description: str | None = None
resource_path: str = "first_app"
header = build_header(token=TOKEN)
# Use as a context manager (auto-closes the connection)
# Optionally configure timeout and connection pool limits:
# timeout=httpx.Timeout(60.0, connect=10.0)
# limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
with RestApiClient(base_url=BASE_URL, header=header) as client:
# Example: Use resource_path from model
app = FirstApp(name="My App", description="Test")
endpoint = app.get_endpoint() # Returns "first_app"
full_url = app.get_resource_url(client) # Returns full URL
# Example: Get all items (paginated) — get_model_fields returns list[FirstApp],
# so type checkers infer the concrete subclass on every element.
item_list: list[FirstApp] = []
params = None
while True:
res = client.get("first_app", params=params)
data = res.json()
item_list.extend(get_model_fields(data["results"], model=FirstApp))
if not data["next"]:
break
params = {"page": data["next"].split("/?page=")[-1]}
# Example: Create a new item
new_item = client.post("first_app", data={"name": "My App", "description": "A new app"})
# Example: Full update
updated_item = client.put("first_app/1", data={"name": "Updated App"})
# Example: Partial update
patched_item = client.patch("first_app/1", data={"description": "New description"})
# Example: Delete an item
client.delete("first_app/1")
3. Using Async Client
import asyncio
import os
from dotenv import load_dotenv
from pyrest_model_client import AsyncRestApiClient, build_header
load_dotenv()
TOKEN = os.getenv("TOKEN")
BASE_URL = f'{os.getenv("BASE_URL")}:{os.getenv("PORT")}'
async def main() -> None:
header = build_header(token=TOKEN)
async with AsyncRestApiClient(base_url=BASE_URL, header=header) as client:
data = (await client.get("first_app")).json()
await client.post("first_app", data={"name": "Async App"})
await client.put("first_app/1", data={"name": "Updated"})
await client.patch("first_app/1", data={"description": "Patched"})
await client.delete("first_app/1")
asyncio.run(main())
🤝 Contributing
Contributions are welcome! Please fork the repo, create a branch, and submit a pull request.
📄 License
MIT License — see LICENSE for details.
Metadata
Release files for pyrest-model-client 2.1.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 | |
|---|---|---|---|
| pyrest_model_client-2.1.0.tar.gz | 10.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyrest_model_client-2.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 19.0 kB
Release files / pyrest_model_client-2.1.0.tar.gz
| Download URL | pyrest_model_client-2.1.0.tar.gz |
|---|---|
| Size | 10.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f5cd3d7a8d44304f3ccb254e0a66e5a32a42aa0d58f154e5a65a3feb0c92b3b8
|
|
BLAKE2b-256 checksum How to use checksums |
913a832fe24d0f8f5c5d1de85733c9dbcafbd486238a92d1ffc992a5d0194c2e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyrest_model_client-2.1.0-py3-none-any.whl
| Download URL | pyrest_model_client-2.1.0-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f9a5bc1e85361119dabc1232bff0577aa511e60d4bf31878c8f702b222cad69
|
|
BLAKE2b-256 checksum How to use checksums |
0d570491b891e05d7583df6fc243fc8c6abdfe49c8eb0c704a861490bd309590
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|