Skip to main content

Zero-config async web framework for rapid prototyping

Project description

Quicky — zero-config async web framework

Quicky — асинхронный микрофреймворк на Python 3.12+ для сервисов, которым нужны типобезопасные хендлеры, нативная валидация и «боевой» стек middleware без дополнительной конфигурации. Цели проекта:

  • производительность выше типового FastAPI-сервиса за счёт uvloop + httptools + orjson;
  • архитектура «type-first» (PEP 695, Annotated, TypedDict, typing.get_type_hints);
  • встроенный DI, метрики Prometheus, структурированное логирование и gzip out-of-the-box;
  • минимальный код для запуска: app = Quicky() уже готов принимать трафик.

Возможности

  • Декларативная маршрутизация: @app.get("/items/{item_id}") с поддержкой подстановок и HEAD/OPTIONS по умолчанию.
  • DSL для параметров: Path[T], Query[T], Body[T], Header[T] — аннотации превращаются в схему валидации через Pydantic TypeAdapter.
  • Dependency Injection: контейнер с app/request scope, резолвит зависимости по типам или ключам без классов и метакодирования.
  • Zero-config middleware: request-id, gzip, структурное логирование (JSON), latency/throughput-метрики на /metrics.
  • Минимум зависимостей: uvicorn, httptools, orjson, pydantic v2.
  • CLI и рантайм: python -m quicky.cli module:app --reload запускает uvicorn с httptools и uvloop.

Установка

python -m pip install quicky

Требуется Python 3.12+.


Быстрый старт

from typing import TypedDict

from quicky import Body, Path, Quicky

app = Quicky()


class Item(TypedDict):
    id: int
    name: str
    price: float


@app.get("/items/{item_id}")
async def get_item(item_id: Path[int]) -> Item:
    return {"id": item_id, "name": "example", "price": 42.0}


@app.post("/items")
async def create_item(payload: Body[Item]) -> tuple[Item, int]:
    return payload, 201

Запуск:

python -m quicky.cli examples.app:app --reload

Архитектура и ключевые модули

quicky/
├── app.py         # объект Quicky, роутинг, middleware, /metrics
├── routing.py     # сопоставление путей и HTTP-методов
├── types.py       # Request/Response + DSL Path/Query/Body/Header
├── handlers.py    # анализ сигнатур, построение схем, вызов DI
├── di.py          # контейнер зависимостей с app/request scope
├── serializers.py # orjson, tuple/stream ответы, content negotiation
├── middleware.py  # request-id, логирование, метрики, gzip
├── metrics.py     # in-memory Prometheus registry
├── runtime.py     # обёртка над uvicorn (serve/run)
└── cli.py         # `quicky run module:app`

Маршрутизация

  • соответствие метода и пути хранится в routing.Router;
  • паттерны компилируются в сегменты, PEP 634 разрешает match/case поверх HTTP-метода;
  • поддерживается автоматическая обработка HEAD → GET.

Типовая система и валидация

  • Path[T], Query[T], Body[T], Header[T] — это typing.Annotated с ParameterInfo;
  • handlers.build_handler_spec вызывает TypeAdapter для каждой аннотации и кеширует спецификацию;
  • тело запроса читается один раз, JSON парсится через orjson, значения прокидываются в адаптер;
  • отсутствие значения приводит к 422 ValidationError с uniform JSON.

Dependency Injection

  • DependencyContainer регистрирует фабрики по ключу (тип или произвольный hashable);
  • scope app кеширует значение, request пересоздаёт на каждый запрос;
  • при отсутствии зависимости фреймворк вернёт 500, либо используйте дефолт в сигнатуре.

Middleware и метрики

  • pipeline собирается в Quicky.middleware, можно добавлять кастомные функции;
  • дефолтный стек: request-id, Prometheus observer, JSON-логирование, gzip (≥512 B);
  • /metrics отдаёт текст в формате Prometheus (сумма, count, max, avg).

Сериализация

  • serializers.normalize_response принимает Response, tuple (body, status, headers) или любой сериализуемый объект;
  • для генераторов поддерживается streaming через Response.stream;
  • orjson.OPT_SERIALIZE_NUMPY включён по умолчанию.

Runtime и CLI

  • quicky.runtime.run и serve конфигурируют uvicorn (loop=uvloop, http=httptools);
  • CLI умеет читать параметры из переменных окружения (QUICKY_HOST, ..._PORT, ..._WORKERS).

Пример DI и middleware

from collections.abc import AsyncIterator
from quicky import Quicky, Query, Request

app = Quicky()


async def get_db():
    yield {"conn": "stub"}  # request scope


app.dependency("db", get_db, scope="request")


@app.get("/ping")
async def ping(q: Query[str], db = "db", request: Request | None = None):
    return {"q": q, "db": db["conn"], "rid": request.state["request_id"]}

Roadmap

  • v0.1.0 (MVP) — реализовано: маршрутизация, type-first валидация, DI, JSON-сериализация, middleware, gzip, метрики Prometheus.
  • v1.0.0 — запланировано: WebSocket API, GraphQL-декоратор, OpenAPI-генерация, rate limiting (@app.limit), расширенные плагины DI.
  • Дальше — плагины quicky-db, quicky-auth, quicky-testing, встроенные клиенты Observability и инструменты бенчмаркинга.

Лицензия

MIT License (см. 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

quicky-0.1.2.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

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

quicky-0.1.2-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file quicky-0.1.2.tar.gz.

File metadata

  • Download URL: quicky-0.1.2.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for quicky-0.1.2.tar.gz
Algorithm Hash digest
SHA256 e90eca1ef5ac2712953038023de2661758fd10f56c41793d0eb2714356332f52
MD5 500fb354afa51b944d80d71fe8827a5c
BLAKE2b-256 b49f5328a613b852fcc36ff0fc97ea0a580cc63b7a193f889d62e816062fda92

See more details on using hashes here.

File details

Details for the file quicky-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: quicky-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 17.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for quicky-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3183caa055cbb043532166fbd09c9033a65b99c5b6df585bf4f3be992adfbe2f
MD5 2ece9beecd615532edd25d67e4bee65c
BLAKE2b-256 52a80d39eb6eda8b8f262e40e22a94cfd0214eaf207224616dbc3f726241f018

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