Skip to main content

Chilo is a lightweight, form-meets-function, opinionated (yet highly configurable) api framework.

Project description

🐍 Chilo

Chilo

Chilo is a lightweight, form-meets-function, opinionated (yet highly configurable) API framework.

CircleCI Quality Gate Status Coverage Bugs PyPI Python Inline docs Contributions welcome

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 Everywherebefore, after, when_auth_required, and global hooks keep cross-cutting logic centralized.
  • 🔔 Lifecycle Hookson_startup / on_shutdown let you register callables that fire once when the router boots and when it stops.
  • 🔁 REST + gRPC – Switch between HTTP and gRPC by flipping api_type and pointing at protobufs.
  • 📜 Spec Generation – Inspect handlers + requirements to emit openapi.yml/openapi.json with 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chilo_api-2.0.2.tar.gz (84.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chilo_api-2.0.2-py3-none-any.whl (114.4 kB view details)

Uploaded Python 3

File details

Details for the file chilo_api-2.0.2.tar.gz.

File metadata

  • Download URL: chilo_api-2.0.2.tar.gz
  • Upload date:
  • Size: 84.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.17

File hashes

Hashes for chilo_api-2.0.2.tar.gz
Algorithm Hash digest
SHA256 eaf097ffd5a35ce3e026fa7280a77c45a1a6eed6718aaee21c3a8cfc201f2ee9
MD5 2bea296e2e69a3ec1be6c28e752cd59c
BLAKE2b-256 aa0309c8a223ad8753a1ea5f05bfa9be8733f08cbe4c04d3979697fb25f550a7

See more details on using hashes here.

File details

Details for the file chilo_api-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: chilo_api-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 114.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.17

File hashes

Hashes for chilo_api-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 dc7dec4de04a86d1cc9edc3fcb33b7e98c221ded905b26d5c8b4284f4675dc86
MD5 2b4b4686092a3319e39c61b457350fbb
BLAKE2b-256 f3c064ea78938feecd1e95bc703d4b397ed6d4a75ee426f5766e951c7ba7793c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page