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.
  • 🔁 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

api = Chilo(
    base_path='/',
    handlers='api/handlers',
    cors=True,
    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.1.tar.gz (82.6 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.1-py3-none-any.whl (112.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: chilo_api-2.0.1.tar.gz
  • Upload date:
  • Size: 82.6 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.1.tar.gz
Algorithm Hash digest
SHA256 596f2b5ea2d5faa8b33cc14fa4d8f3ed40073402a3359baf45f247ba6e1e8946
MD5 7eab77002ed4e660e5c4eb2246d3482d
BLAKE2b-256 ab49f0b0046ee578de164fd9e6369c50c6d7cf3dc35689c0ad6edcbe7d0813ae

See more details on using hashes here.

File details

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

File metadata

  • Download URL: chilo_api-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 112.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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 515042ed64cddcfdead59c26fb4afab413e9b561ca0e0cc64358cb7ca3a8ac2b
MD5 5046a1aeb31ad8873184658369d7ebae
BLAKE2b-256 0d49cea5d0af5587c8a6eb4e9b62a6bbcffd389d59b2794d2ef37ca3a0cfe026

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