pallets/flask

Generated 2026-08-05

Flask is a lightweight WSGI web framework built on Werkzeug and Jinja. The public API (src/flask/__init__.py) is a thin, IO-capable layer — Flask and Blueprint — sitting on top of a larger "sansio" base package that holds most of the actual implementation and is written to be usable by non-Flask, non-WSGI implementations (e.g. Quart) as well.

Architecture

ComponentPathRoleDepends on
flask (public API)src/flask/__init__.pyThe entire public surface re-exported in one 39-line file: Flask, Blueprint, current_app/request/g/session, render_template, url_for, redirect, jsonify, signals. Read this before anything else to see what the library actually offers.
Flask (app.py)src/flask/app.pyDefines `class Flask(App)` — the object every user instantiates. Adds the IO-touching behavior (the dev server, CLI wiring) on top of the sansio App base class.sansio.app
sansio.app (App base class)src/flask/sansio/app.pyDefines `class App` — 43 methods, more than Flask's own subclass (38). This is where most of Flask's actual request-handling, config, and routing logic lives, written IO-free so it can be reused by non-WSGI implementations.sansio.scaffold
sansio.scaffoldsrc/flask/sansio/scaffold.pyShared base between App and Blueprint — route registration, static/template folder resolution, the `@app.route` decorator machinery.
Blueprint (app-side + sansio-side)src/flask/blueprints.py + src/flask/sansio/blueprints.pySame App/sansio split repeated for Blueprint: a 128-line app-side subclass over a 692-line sansio base.sansio.scaffold
ctxsrc/flask/ctx.pyApplication/request context push-pop machinery — the part of Flask's design that makes `current_app`/`request`/`g` work as implicit globals during a request.globals
globalssrc/flask/globals.pyThe context-local proxy objects (current_app, request, g, session) themselves.
clisrc/flask/cli.pyThe `flask` command-line tool (run, shell, routes) — the largest file after app.py, and mostly independent of the request-handling path.app.py
teststests/27 test files, roughly one per src/flask/*.py module — the fastest way to see intended behavior confirmed by something that actually runs.

Read First

  1. src/flask/__init__.py — 39 lines, every public name re-exported in one place — the fastest possible answer to 'what does this library offer.'
  2. src/flask/app.py (class Flask(App), line 109) — The object every Flask app instantiates (`Flask(__name__)`); the natural entry point for reading everything else — but see the gotcha below before assuming its methods live here.
  3. src/flask/sansio/app.py (class App) — Defines more methods (43) than Flask's own subclass (38) — a majority of what Flask actually does lives here, not in app.py. Skipping this file means missing most of the implementation.
  4. src/flask/ctx.py — The context push/pop machinery behind current_app/request/g — the least obvious part of Flask's design if you've only read route-handler code, and everything that uses `g` or `current_app` depends on it.
  5. tests/test_basic.py — The most representative test of the primary use case — a minimal app, routes, and a request/response cycle. Teaches the intended usage faster than reading app.py in isolation, and it's guaranteed accurate since it runs in CI.

Gotchas

SeverityGotchaEvidence
HIGHFlask the class is a thin subclass — most of its behavior is inherited — class Flask(App) in app.py defines 38 methods; its parent class App in sansio/app.py defines 43. A reader searching app.py for a method like add_url_rule or the route-registration logic won't find it there and needs to know to check the sansio parent.grep -c ' def ' src/flask/app.py src/flask/sansio/app.py → 38 vs 43; src/flask/app.py:109 `class Flask(App):`
MEDIUMThe sansio/ architectural constraint is documented but not enforced — sansio/README.md states code in that package "cannot do any IO, nor be part of a likely IO path" and "cannot use the Flask globals" — but this is a 4-line README, not a lint rule or CI check. A contributor could violate it and nothing would catch it automatically.src/flask/sansio/README.md (full contents: 4 lines, no enforcement mechanism found in pyproject.toml or CI config checked)
MEDIUMThe App/sansio split is repeated for Blueprint, easy to only half-read — Same pattern as Flask/App: blueprints.py (128 lines) is a thin subclass over sansio/blueprints.py (692 lines). Reading only the top-level blueprints.py under-explains Blueprint the same way reading only app.py under-explains Flask.wc -l src/flask/blueprints.py src/flask/sansio/blueprints.py → 128 vs 692

Good First Tasks

Docs Gaps