Asas framework, high performance, easy to learn, fast to code, ready for production
Asas is a Python framework for building typed, simple API clients in a few lines. You write a subclass, annotate methods with
@get/@post/…, and Asas handles request building, parameter routing, Pydantic validation, authentication, refresh-and-retry, and paging for you — for synchronous and asynchronous code with the same decorators.
Why Asas?
Traditional HTTP clients bury your API's shape in a pile of requests.get(...) calls, string
URLs, and manual JSON wrangling. Asas flips that: your client class is your API client,
declared once and typed end-to-end.
- Write your whole API client as a class with decorators — no boilerplate to maintain.
- One signature drives path segments, query params, and JSON bodies automatically.
- Pydantic in, validated Pydantic out. No hand-rolling
json.loads+ dict lookups. - Ready for real APIs: auth, automatic token refresh (even on custom conditions), and resource CRUD with paging that needs no page-loop code.
Installation
pip install asas-py # + Pydantic + httpx (the default engine)
pip install "asas-py[requests]" # + the optional sync-only requests engine
Python 3.9+ (see Documentation for the Arabic guide).
Quick start
Subclass a client and declare your endpoints. That's it.
from pydantic import BaseModel
from asas import AsasClient, get
class Todo(BaseModel):
id: int
todo: str
completed: bool
class TodoClient(AsasClient):
@get("/todos/{id}", response_model=Todo)
def get_todo(self, todo: Todo, id: int) -> Todo:
return todo
client = TodoClient(base_url="https://dummyjson.com")
task = client.get_todo(id=1)
print(task.todo)
id is a path placeholder, Todo validates the JSON response, and todo is injected as the
first argument after self. Want async? Use @get on an async def with
AsasAsyncClient — the decorators are identical. This snippet runs as-is against
dummyjson.com (a free public REST API).
Try it live
from typing import List
from pydantic import BaseModel
from asas import AsasClient, get
class Product(BaseModel):
id: int
title: str
price: float
class ProductPage(BaseModel):
products: List[Product]
class StoreClient(AsasClient):
@get("/products", response_model=ProductPage)
def products(self, page: ProductPage) -> List[Product]:
return page.products
client = StoreClient(base_url="https://dummyjson.com")
first = client.products()
print(f"{len(first)} products, first: {first[0].title} (${first[0].price})")
Resources & lazy pagination — no page-loop code
from pydantic import BaseModel
from asas import AsasClient, AsasResource, OffsetPaginator
class User(BaseModel):
id: int
name: str
class Users(AsasResource):
path = "/users"
model = User
paginator = OffsetPaginator(limit=100, items_key="users")
class Client(AsasClient):
users = Users()
client = Client(base_url="https://api.example.com")
for user in client.users: # pages fetched on demand, loop ends itself
print(user.name)
single = client.users.get(42) # generated CRUD, too
Authentication & automatic refresh
from asas import AsasClient, RefreshingBearerAuth, Response, get, refresh_on_keyword
auth = RefreshingBearerAuth(
"expired-token",
refresh_callback=lambda: mint_new_token(),
refresh_when=refresh_on_keyword("token_expired"), # refresh on a 200, too
)
class MyClient(AsasClient):
@get("/me")
def me(self, response: Response) -> dict:
return response.json()
client = MyClient(base_url="https://api.example.com", auth=auth)
Features
- Sync & async clients that share the same
@get/@post/@put/@delete/@patchdecorators — Asas auto-detectsasync def. - Automatic parameter routing — path placeholders, Pydantic-model bodies, and query params from a single method signature.
- Pydantic responses via
response_model: validated, typed results with zero manual parsing. - Resources + lazy pagination —
AsasResourcegiveslist/get/create/update/deleteand iterator-style paging (page-number, offset, cursor, and Link-header strategies). - Authentication out of the box —
NoAuth,BasicAuth,BearerAuth,APIKeyAuth(header/query/cookie),RefreshingBearerAuth, andCompositeAuth, with swappable runtime auth and easy-to-test refresh conditions. - Transport-agnostic core —
httpxis bundled; bring your own engine (an optional, sync-onlyrequestsengine ships behind the[requests]extra).
Roadmap
Planned and share-worthy next features:
- OpenAPI / Swagger client generation — generate a full typed client (Pydantic models + client code) straight from an OpenAPI schema.
- GraphQL support — query / mutation / subscription decorators with typed responses.
- Testing module — fixtures and helpers to make writing client tests trivial (respx mocks, base harnesses, captured requests).
- Plugin / hook system — request/response lifecycle hooks, middleware, and event listeners.
- Cookie & session helpers — first-class session management, cookie jars, and CSRF handling.
Have a feature in mind? Open an issue or start a discussion — contributions and ideas are very welcome.
Contributing
Contributions of all kinds are welcome — bug reports, documentation, examples, and features.
- Fork & clone the repo.
- Set up:
make dev-install(installs deps + git hooks). - Develop: write your code with type hints, then
make formatandmake lint. - Test:
make test. - Commit with a clear message and open a Pull Request.
See CONTRIBUTING.md for the full workflow and coding standards.
Documentation
Full docs (English + العربية): heshammoawad.github.io/asas-py
- Clients
- Routing & Parameters
- Request Bodies & Responses
- Resources & Pagination
- Authentication
- Engines & Transports
- Core Models
License
Released under the MIT License.
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 asas_py-0.1.0.tar.gz.
File metadata
- Download URL: asas_py-0.1.0.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75993e69080004479270e12c5e007a0e7cd011e3949c4199b7c97cf2f90ea5fa
|
|
| MD5 |
65d1568c647481fc2c9a241bc00e8923
|
|
| BLAKE2b-256 |
15518a30b0a4c0fdb9d149a91ebf1aa5342f18b762990b6d20434eafa53e6cab
|
File details
Details for the file asas_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: asas_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3079be4879d842b5b49abc0034c4cd3550744adb1e4446f2526a1d371fd259ea
|
|
| MD5 |
fc6dbf02f4b876a4d54aee68c0429a2d
|
|
| BLAKE2b-256 |
4805e56c0ff1ba5abc4e7670627baeb0d0a4cfdae314f6dc41c4b55a29013fab
|