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.
Full Documentation Β· Examples Β· Community Discussions
- π 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.
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 responsepip install chilo_api
# pipenv install chilo_api
# poetry add chilo_apifrom 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
)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 responsepython -m chilo_api serve --api=api.main --reload=trueVisit http://127.0.0.1:3000/?greeting=developer
api/handlers
βββ __init__.py β /
βββ user/__init__.py β /user
βββ user/_user_id.py β /user/{user_id}
βββ reports/daily.py β /reports/dailyDynamic segments are prefixed with _ in file names (or directories) and become {param} tokens at runtime.
from chilo_api import Chilo
api = Chilo(
api_type='grpc',
handlers='api/handlers',
protobufs='api/protobufs',
reflection=True,
port=50051
)syntax = "proto3";
package calculator;
service Calculator {
rpc Add(CalcRequest) returns (CalcResponse);
}
message CalcRequest { double num1 = 1; double num2 = 2; }
message CalcResponse { double result = 1; }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 responsepython -m chilo_api serve --api=api.main_grpc| 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.
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.
Chilo is released under the MIT License.
