This release is a pre-release and may not be stable for production use.
half-orm-litestar
A halfORM extension that generates a Litestar REST API from your halfORM relation classes by decorating their methods.
Installation
pip install half-orm-litestar
Requires half-orm-dev to be installed (for project introspection):
pip install half-orm-dev
Quick start
1. Decorate your halfORM methods
In any halfORM relation class, import tools and annotate the methods you
want to expose as API routes:
# myproject/actor/user.py
from half_orm_litestar import tools
class User(MODEL.get_relation_class('actor.user')):
@tools.api_get('/user/{id: uuid}', guards=['public'])
async def get_user(self, request: "Request"):
actor_id = request.path_params['id']
return self.load_user(actor_id)
@tools.api_get('/user/{user_id: uuid}/group_accesses', guards=['has_user_access'])
async def get_user_group_accesses(self, request: "Request"):
actor_id = request.path_params['user_id']
return [dict(row) for row in self.rfk_group_accesses(actor_id=actor_id)]
@tools.api_post('/users', guards=['connected'])
async def create_user(self, request: "Request"):
data = await request.json()
...
The decorators accept the same arguments as the corresponding Litestar
decorators (@get, @post, @put, @patch, @delete).
Available decorators:
| Decorator | HTTP method |
|---|---|
tools.api_get |
GET |
tools.api_post |
POST |
tools.api_put |
PUT |
tools.api_patch |
PATCH |
tools.api_delete |
DELETE |
2. Generate the API
From the root of your half-orm-dev project:
half_orm litestar generate
This command:
- Scans all halfORM relation classes for
@api_*decorated methods. - Creates missing scaffolding files in
api/(only on first run — existing files are never overwritten). - Writes
api/app.py, the ready-to-run Litestar application.
3. Run the API
uvicorn api.app:application --reload
Project structure after generate
myproject/
├── api/
│ ├── __init__.py
│ ├── guards.py ← authentication guards (edit this)
│ ├── app.py ← generated, do not edit by hand
│ └── custom/
│ ├── __init__.py
│ ├── routes.py ← hand-written extra routes
│ └── middlewares/
│ ├── __init__.py ← extra middlewares list
│ └── authorization.py ← authentication middleware (edit this)
Files in api/ (except app.py) are created once and never overwritten.
Regenerating only rewrites app.py.
Customisation
Guards (api/guards.py)
Guards are async callables that receive the ASGI connection and raise an
exception to deny access. Two minimal guards are provided out of the box:
public (allow all) and connected (require authenticated user).
Add your own project-specific guards in api/guards.py:
# api/guards.py
from litestar.connection import ASGIConnection
from litestar.handlers.base import BaseRouteHandler
from litestar.exceptions import HTTPException
async def has_user_access(
connection: ASGIConnection, handler: BaseRouteHandler = None
) -> None:
"""Allow only the user identified by the ``user_id`` path parameter."""
if not connection.user:
raise HTTPException(status_code=401)
if connection.user != str(connection.path_params.get('user_id')):
raise HTTPException(status_code=403)
Then reference the guard by name in your decorator:
@tools.api_get('/user/{user_id: uuid}/profile', guards=['has_user_access'])
async def get_profile(self, request: "Request"):
...
Authorization middleware (api/custom/middlewares/authorization.py)
Implement the Authorization class to decode tokens / sessions and populate
connection.user. When the file exists, Authorization is automatically
placed first in the middleware stack.
# api/custom/middlewares/authorization.py
import jwt
from litestar.middleware import AbstractAuthenticationMiddleware, AuthenticationResult
from litestar.connection import ASGIConnection
SECRET = "change-me"
class Authorization(AbstractAuthenticationMiddleware):
async def authenticate_request(self, connection: ASGIConnection) -> AuthenticationResult:
token = (
connection.headers.get("Authorization", "")
.removeprefix("Bearer ")
.strip()
)
try:
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
return AuthenticationResult(user=payload["sub"], auth=token)
except Exception:
return AuthenticationResult(user=None, auth=None)
Extra routes (api/custom/routes.py)
Hand-written Litestar route handlers can be added here:
# api/custom/routes.py
from litestar import get
@get('/health')
async def health_check() -> dict:
return {'status': 'ok'}
routes = [health_check]
Extra middlewares (api/custom/middlewares/__init__.py)
# api/custom/middlewares/__init__.py
from .my_middleware import MyMiddleware
middlewares = [MyMiddleware]
Path prefix
The generated routes are automatically prefixed with the project's database
name. For a project named mydb, '/user/{id: uuid}' becomes
'/mydb/user/{id: uuid}'.
Advanced: using without half-orm-dev
GenApi can be used programmatically without a Repo object by supplying the
relation classes directly:
from half_orm_litestar.generate import GenApi
GenApi(
relation_classes=my_classes, # iterable of (RelationClass, type) pairs
module_name='mydb',
base_dir='/path/to/project',
)
Metadata
Release files for half-orm-litestar 1.0.0a5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| half_orm_litestar-1.0.0a5.tar.gz | 29.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| half_orm_litestar-1.0.0a5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.8 kB
Release files / half_orm_litestar-1.0.0a5.tar.gz
| Download URL | half_orm_litestar-1.0.0a5.tar.gz |
|---|---|
| Size | 29.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
72eda25083212e6b3d008ee2965249400dfa148ac1defe05a47d17c9517549f1
|
|
BLAKE2b-256 checksum How to use checksums |
8b34fde7cf06a12bbc841b31f9262b13dbb49d11ea7c266903bf04b257bd2a41
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / half_orm_litestar-1.0.0a5-py3-none-any.whl
| Download URL | half_orm_litestar-1.0.0a5-py3-none-any.whl |
|---|---|
| Size | 26.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
088357d0543dfa713a1608c25836f1479676717a1bfc263eb438e3e618e8c389
|
|
BLAKE2b-256 checksum How to use checksums |
be7c093c3e1f299fcdeecf6f2d84abe296b74bf312ec0be501165642bcb456f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Security for half-orm-litestar 1.0.0a5
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.