Skip to main content

A thin convention-and-scaffolding layer over FastAPI + SQLAlchemy — collapses the model/repository/service/schema/router module shape into one declaration.

Project description

🥭 mango

FastAPI + SQLAlchemy, without the boilerplate.

mango.Router is fastapi.APIRouter. mango.Schema is pydantic.BaseModel. mango doesn't reimplement your stack — it gives it one front door, then removes everything you'd otherwise hand-write around it: module wiring, CRUD repositories, DB setup, auth guards, error mapping, pagination, background jobs, migrations, and security middleware.

PyPI CI Python License: MIT

Quickstart · Why mango · Full guide · Project structure · Contributing


The pitch, in code

Without mango — a plain-CRUD module is a router, a repository, a schema file, engine/session setup, and manual error handling:

# ~80+ lines across models.py / repository.py / schemas.py / router.py / main.py

With mango — the same module, in full:

import uuid
from mango import Router, Schema, MangoRepository, build_crud_router, Database

class Thing(Base):
    __tablename__ = "things"
    id: Mapped[uuid.UUID] = mapped_column(primary_key=True)
    name: Mapped[str]

class ThingRepository(MangoRepository[Thing]):
    model = Thing

class ThingRead(Schema):
    id: uuid.UUID
    name: str

router = build_crud_router(
    repository=ThingRepository, read_schema=ThingRead,
    get_db=db.get_db, id_type=uuid.UUID, prefix="/things",
)

That's a full GET /things/, GET /things/{id}, DELETE /things/{id} REST endpoint set — 404s, pagination, error handling, all included. No import fastapi. No import pydantic. No hand-wired main.py.


🚀 Quickstart

pip install mangoframe
mango init demo_shop
cd demo_shop
mango new-module items

mango new-module auto-detects the project via project.mango (written by mango init) and wires the new module into app/registry.py for you — run it from anywhere inside the project, no directory argument needed.

Already made and cd'd into an empty folder (maybe one git init ran in already)? mango init . scaffolds it in place instead of nesting a redundant subdirectory — the project name is taken from the folder.

# app/main.py — generated for you, shown here for reference
import mango
from app import registry  # imports every module for its registration side effect

app = mango.App(title="demo_shop")
app.mount_all()
DATABASE_URL=postgresql+asyncpg://user:pass@localhost/demo_shop uvicorn app.main:app --reload

pip install name is mangoframe (mango and mango-framework were already taken on PyPI) — the import name is always mango.


🥭 Why mango

FastAPI and SQLAlchemy are both excellent at what they do. What they don't give you is a convention — every team ends up hand-rolling the same models.py/repository.py/service.py/schemas.py/router.py/ __init__.py shape, the same main.py router-mounting list, the same generic CRUD repository, the same try/except HTTPException translation at every error site. mango is that convention, packaged:

You'd hand-write mango gives you
__init__.py re-exports per module @mango.module — derived, not maintained
main.py router-mounting list app.mount_all()
A generic repository base class MangoRepository — get/add/update/delete/list/count/search, plus get_or_404, batch ops, eager-loading
create_async_engine + get_db() boilerplate mango.Database(url)
Domain-error → HTTP status try/except raise mango.NotFoundError(...)
A full CRUD router mango.build_crud_router(...) — optionally paginated
verify-token → load-user → check-role chain mango.Auth — pluggable, not opinionated about your token provider
Security headers / rate limiting On by default in mango.App, or one kwarg
alembic.ini + async env.py mango init-migrations app.db:Base
A new project's folder skeleton mango init <name>

A module with real, non-generic business logic still writes that logic by hand — mango only removes the boilerplate around it. See the size table below for the receipts.

No magic, no lock-in. mango.Router/mango.Schema/etc. are the literal FastAPI/Pydantic classes — anything written for FastAPI directly (a raw APIRouter, a third-party plugin, an app you're migrating incrementally) works alongside mango without conversion.


What's inside

  • App — owns its FastAPI instance, ASGI-callable, wires in security headers by default and opt-in CORS/rate-limiting, exposes a Plugin extension point and on_startup/on_shutdown hooks.
  • MangoModule + @mango.module — declare a module as one class; mango derives its public API instead of a hand-written __init__.py.
  • MangoRepository — generic async CRUD, get_or_404, exists, add_many/delete_many, filter_by(**equals), eager-loading via options=, and list_page/search_page for pagination.
  • Auth — pluggable token verification + user loading + require_role/require/current_user FastAPI dependencies.
  • MangoError + subclasses + register_error_handlers — domain exceptions that map straight to clean HTTP responses, plus a catch-all so an unhandled bug returns a generic 500, never a leaked traceback.
  • build_crud_router — a full list/get/create/update/delete router from a repository + schemas, one call.
  • run_in_background / Database.spawn — fire-and-forget work with its own session and a logged (not swallowed) exception on failure.
  • init_migrations / init_project — scaffold Alembic and a whole new project's folder structure, via the mango CLI.

Full tour with examples: docs/GUIDE.md. Folder-structure convention and the reasoning behind it: docs/PROJECT_STRUCTURE.md.


📏 What it actually cuts

Every piece exists to measurably shorten a project's code — not to add abstraction for its own sake. Per module, roughly:

What you'd hand-write Lines With mango
__init__.py re-exports 15–30 0
main.py router mounting 1–2/module 0
Generic repository CRUD 30–50 0
DB engine/session/get_db() ~15 3
Plain-CRUD router 60–90 ~10
Domain-error → HTTP mapping 5–10/site 0
Auth guard 20–40 ~10
Background task + own session 10–15 1
Alembic env.py ~100 0
Security headers middleware ~15 0
New project skeleton ~80 0

Development

git clone https://github.com/rhydham-mittal27/mango.git
cd mango
pip install -e ".[dev]"
pytest -q

See CONTRIBUTING.md for the ground rules (every change ships with a test and a changelog entry, no exceptions).

Status

Module registry, generic repository, pagination, mount ordering, DB setup, background tasks, auth guards, error mapping, generated CRUD routers, Alembic + project scaffolding, production hardening, a plugin system, and a full FastAPI/Pydantic re-export surface are all in place — a project can be built end to end importing only mango. CI runs the full suite across Python 3.11/3.12/3.13 on every push.

Honestly: this is a young project. No production mileage beyond one real integration, a small test suite, a single maintainer. If you use it and something breaks, that's expected — open an issue or a PR. See CONTRIBUTING.md.

License

MIT — use it for anything, including in production, at your own judgment given the "Status" section above.

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

mangoframe-0.4.0.tar.gz (68.8 kB view details)

Uploaded Source

Built Distribution

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

mangoframe-0.4.0-py3-none-any.whl (46.5 kB view details)

Uploaded Python 3

File details

Details for the file mangoframe-0.4.0.tar.gz.

File metadata

  • Download URL: mangoframe-0.4.0.tar.gz
  • Upload date:
  • Size: 68.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for mangoframe-0.4.0.tar.gz
Algorithm Hash digest
SHA256 a67e263ccdf5cdc2dc7d3c04b340c6d943ea698f4c9802e93e7330bfbebc99c6
MD5 c1de9c414e26e29674acb35a879deeaf
BLAKE2b-256 6f77b873c18d37bbde5ab5c39e53adbc220809e475c024a661c3dd89494ac296

See more details on using hashes here.

File details

Details for the file mangoframe-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: mangoframe-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 46.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for mangoframe-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 188595c9dab14387cc702b6c0a17f2a74a941eb6a86d13abcc80b988f56b2c1a
MD5 098d0220d4cfd9ae63f9b1f99f42bf1e
BLAKE2b-256 ac6bd53b6a37ce82704e13b5b5499a460c25337c70f704338a763db5ea5f5390

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