🐍 Chilo
Chilo is a lightweight, form-meets-function, opinionated (yet highly configurable) API framework.
Chilo (short for chilorhinophis, the two-headed snake) auto-routes requests straight from your directory tree, applies OpenAPI or custom validation before your handlers run, and keeps REST + gRPC services declarative and composable.
📖 Documentation & Examples
Full Documentation · Examples · Community Discussions
🎯 Why Chilo?
- 🚀 Zero Route Boilerplate – File paths become URLs; dynamic segments are inferred from file names.
- ✅ Built-in Validation – Apply OpenAPI schemas (request + response) or lightweight requirement decorators.
- 🧱 Middlewares Everywhere –
before,after,when_auth_required, and global hooks keep cross-cutting logic centralized. - 🔔 Lifecycle Hooks –
on_startup/on_shutdownlet you register callables that fire once when the router boots and when it stops. - 🔁 REST + gRPC – Switch between HTTP and gRPC by flipping
api_typeand pointing at protobufs. - 📜 Spec Generation – Inspect handlers + requirements to emit
openapi.yml/openapi.jsonwith a single CLI command. - ⚙️ Deploy-Friendly – Works with gunicorn or the built-in CLI; supports TLS, CORS, hot reload, and custom executors.
Happy Path Programming
Validate the world up front, then write business logic as if everything is already correct.
# ❌ Without Chilo
def handler(environ, start_response):
body = json.loads(environ.get('body') or '{}')
if 'email' not in body:
return error(400, 'email required')
if '@' not in body['email']:
return error(400, 'invalid email')
# more guards ...
return ok({'user': create(body)})
# ✅ With Chilo
from chilo_api import requirements, Request, Response
@requirements(required_body='v1-create-user')
def post(request: Request, response: Response) -> Response:
response.body = {'user': create(request.body)} # already validated
return response
📦 Installation
pip install chilo_api
# pipenv install chilo_api
# poetry add chilo_api
Supports Python 3.8
🚀 Quick Start · REST
1. Configure the API (e.g., api/main.py)
from chilo_api import Chilo
from chilo_api import logger
def cleanup_connections():
# close DB pools, flush caches, etc.
pass
api = Chilo(
base_path='/',
handlers='api/handlers',
cors=True,
on_startup=[lambda: logger.log(level='INFO', log='API booted')],
on_shutdown=[cleanup_connections],
openapi='api/openapi.yml', # optional
openapi_validate_request=False, # flip on when ready
openapi_validate_response=False
)
2. Create a Handler (api/handlers/__init__.py)
from chilo_api import Request, Response, requirements
@requirements(required_query=['greeting'])
def get(request: Request, response: Response) -> Response:
response.body = {'hello': request.query_params['greeting']}
return response
3. Run It
python -m chilo_api serve --api=api.main --reload=true
Visit http://127.0.0.1:3000/?greeting=developer
Directory → Route Mapping
api/handlers
├── __init__.py → /
├── user/__init__.py → /user
├── user/_user_id.py → /user/{user_id}
└── reports/daily.py → /reports/daily
Dynamic segments are prefixed with _ in file names (or directories) and become {param} tokens at runtime.
📡 Quick Start · gRPC
1. Define the API (api/main_grpc.py)
from chilo_api import Chilo
api = Chilo(
api_type='grpc',
handlers='api/handlers',
protobufs='api/protobufs',
reflection=True,
port=50051
)
2. Author Your Proto (api/protobufs/calculator.proto)
syntax = "proto3";
package calculator;
service Calculator {
rpc Add(CalcRequest) returns (CalcResponse);
}
message CalcRequest { double num1 = 1; double num2 = 2; }
message CalcResponse { double result = 1; }
3. Implement the Handler (api/handlers/__init__.py)
from chilo_api import requirements, Request, Response
@requirements(protobuf='calculator.proto', service='Calculator', rpc='Add')
def add(request: Request, response: Response) -> Response:
response.body = {'result': request.body.get('num1', 0) + request.body.get('num2', 0)}
return response
4. Serve It
python -m chilo_api serve --api=api.main_grpc
🧰 CLI Highlights
| Command | Description |
|---|---|
python -m chilo_api serve --api=api.main |
Run REST or gRPC servers with hot reload, TLS, verbose logging, etc. |
python -m chilo_api generate-openapi --api=api.main --output=docs --format=yml,json |
Inspect handlers + requirements to (re)build OpenAPI docs. |
Both commands accept switches for host, port, reload, private key/cert, worker count, and validation flags.
🤝 Contributing
Issues and PRs are welcome! Check SECURITY.md before reporting vulnerabilities and open a discussion if you want to propose larger features. For docs fixes, see chilo-docs.
📜 License
Chilo is released under the MIT License.
Metadata
Release files for chilo-api 2.0.2
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 | Actions |
|---|---|---|---|---|
| chilo_api-2.0.2.tar.gz | 84.3 kB | Without provenance | Details for chilo_api-2.0.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| chilo_api-2.0.2-py3-none-any.whl | Python 3 | none | any | Details for chilo_api-2.0.2-py3-none-any.whl |
Total release size: 198.7 kB
Release files / chilo_api-2.0.2.tar.gz
| Download URL | chilo_api-2.0.2.tar.gz |
|---|---|
| Size | 84.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eaf097ffd5a35ce3e026fa7280a77c45a1a6eed6718aaee21c3a8cfc201f2ee9
|
|
BLAKE2b-256 checksum How to use checksums |
aa0309c8a223ad8753a1ea5f05bfa9be8733f08cbe4c04d3979697fb25f550a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.17
|
Release files / chilo_api-2.0.2-py3-none-any.whl
| Download URL | chilo_api-2.0.2-py3-none-any.whl |
|---|---|
| Size | 114.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc7dec4de04a86d1cc9edc3fcb33b7e98c221ded905b26d5c8b4284f4675dc86
|
|
BLAKE2b-256 checksum How to use checksums |
f3c064ea78938feecd1e95bc703d4b397ed6d4a75ee426f5766e951c7ba7793c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.17
|
Security for chilo-api 2.0.2
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.