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.
  • mango modules / mango routes — list registered modules (mount order, depends_on) or every mounted HTTP route, without booting the server and clicking through /docs.
  • mango remove-module — deletes a module's directory and un-wires its registry.py import; the inverse of new-module.
  • mango doctor — sanity-checks an existing project: modules created by hand but never wired into registry.py (or the reverse — a stale import pointing at a deleted module), a missing .env, a pyproject.toml that lost its mangoframe dependency.
  • mango migrate "<message>" — wraps the two-command Alembic loop (revision --autogenerate + upgrade head) every model change needs.

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.5.0.tar.gz (75.6 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.5.0-py3-none-any.whl (51.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for mangoframe-0.5.0.tar.gz
Algorithm Hash digest
SHA256 af59998cfcf7cf84e9cb0584334aea1768fb037baa1ad8099eab1c2b806ce733
MD5 516bf5ef127323407f4ef8a66f2ee90f
BLAKE2b-256 54ff20720b5f58da81e26c7d1f5720830cd05fcea499ec6d0ddf789c1b39ddfa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mangoframe-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 51.1 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c65e3b76ca890e064b2306176e72d9f1d56fd873bab366e00cc398e51a72628b
MD5 2d9c9a188fdb242cd40e0782dcb76790
BLAKE2b-256 901ffebb7a31d1da23e59afb5fb27b784abaeeab118b451151454967c4b9bc44

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