Full Code of pallets/flask for AI

main 4cae5d8e411b cached
226 files
1.1 MB
274.7k tokens
933 symbols
3 requests
Download .txt
Showing preview only (1,195K chars total). Download the full file or copy to clipboard to get everything.
Repository: pallets/flask
Branch: main
Commit: 4cae5d8e411b
Files: 226
Total size: 1.1 MB

Directory structure:
gitextract_e1znr51w/

├── .devcontainer/
│   ├── devcontainer.json
│   └── on-create-command.sh
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   └── feature-request.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── lock.yaml
│       ├── pre-commit.yaml
│       ├── publish.yaml
│       ├── tests.yaml
│       └── zizmor.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── CHANGES.rst
├── LICENSE.txt
├── README.md
├── docs/
│   ├── Makefile
│   ├── api.rst
│   ├── appcontext.rst
│   ├── async-await.rst
│   ├── blueprints.rst
│   ├── changes.rst
│   ├── cli.rst
│   ├── conf.py
│   ├── config.rst
│   ├── contributing.rst
│   ├── debugging.rst
│   ├── deploying/
│   │   ├── apache-httpd.rst
│   │   ├── asgi.rst
│   │   ├── eventlet.rst
│   │   ├── gevent.rst
│   │   ├── gunicorn.rst
│   │   ├── index.rst
│   │   ├── mod_wsgi.rst
│   │   ├── nginx.rst
│   │   ├── proxy_fix.rst
│   │   ├── uwsgi.rst
│   │   └── waitress.rst
│   ├── design.rst
│   ├── errorhandling.rst
│   ├── extensiondev.rst
│   ├── extensions.rst
│   ├── gevent.rst
│   ├── index.rst
│   ├── installation.rst
│   ├── license.rst
│   ├── lifecycle.rst
│   ├── logging.rst
│   ├── make.bat
│   ├── patterns/
│   │   ├── appdispatch.rst
│   │   ├── appfactories.rst
│   │   ├── caching.rst
│   │   ├── celery.rst
│   │   ├── deferredcallbacks.rst
│   │   ├── favicon.rst
│   │   ├── fileuploads.rst
│   │   ├── flashing.rst
│   │   ├── index.rst
│   │   ├── javascript.rst
│   │   ├── jquery.rst
│   │   ├── lazyloading.rst
│   │   ├── methodoverrides.rst
│   │   ├── mongoengine.rst
│   │   ├── packages.rst
│   │   ├── requestchecksum.rst
│   │   ├── singlepageapplications.rst
│   │   ├── sqlalchemy.rst
│   │   ├── sqlite3.rst
│   │   ├── streaming.rst
│   │   ├── subclassing.rst
│   │   ├── templateinheritance.rst
│   │   ├── urlprocessors.rst
│   │   ├── viewdecorators.rst
│   │   └── wtforms.rst
│   ├── quickstart.rst
│   ├── reqcontext.rst
│   ├── server.rst
│   ├── shell.rst
│   ├── signals.rst
│   ├── templating.rst
│   ├── testing.rst
│   ├── tutorial/
│   │   ├── blog.rst
│   │   ├── database.rst
│   │   ├── deploy.rst
│   │   ├── factory.rst
│   │   ├── index.rst
│   │   ├── install.rst
│   │   ├── layout.rst
│   │   ├── next.rst
│   │   ├── static.rst
│   │   ├── templates.rst
│   │   ├── tests.rst
│   │   └── views.rst
│   ├── views.rst
│   └── web-security.rst
├── examples/
│   ├── celery/
│   │   ├── README.md
│   │   ├── make_celery.py
│   │   ├── pyproject.toml
│   │   ├── requirements.txt
│   │   └── src/
│   │       └── task_app/
│   │           ├── __init__.py
│   │           ├── tasks.py
│   │           ├── templates/
│   │           │   └── index.html
│   │           └── views.py
│   ├── javascript/
│   │   ├── .gitignore
│   │   ├── LICENSE.txt
│   │   ├── README.rst
│   │   ├── js_example/
│   │   │   ├── __init__.py
│   │   │   ├── templates/
│   │   │   │   ├── base.html
│   │   │   │   ├── fetch.html
│   │   │   │   ├── jquery.html
│   │   │   │   └── xhr.html
│   │   │   └── views.py
│   │   ├── pyproject.toml
│   │   └── tests/
│   │       ├── conftest.py
│   │       └── test_js_example.py
│   └── tutorial/
│       ├── .gitignore
│       ├── LICENSE.txt
│       ├── README.rst
│       ├── flaskr/
│       │   ├── __init__.py
│       │   ├── auth.py
│       │   ├── blog.py
│       │   ├── db.py
│       │   ├── schema.sql
│       │   ├── static/
│       │   │   └── style.css
│       │   └── templates/
│       │       ├── auth/
│       │       │   ├── login.html
│       │       │   └── register.html
│       │       ├── base.html
│       │       └── blog/
│       │           ├── create.html
│       │           ├── index.html
│       │           └── update.html
│       ├── pyproject.toml
│       └── tests/
│           ├── conftest.py
│           ├── data.sql
│           ├── test_auth.py
│           ├── test_blog.py
│           ├── test_db.py
│           └── test_factory.py
├── pyproject.toml
├── src/
│   └── flask/
│       ├── __init__.py
│       ├── __main__.py
│       ├── app.py
│       ├── blueprints.py
│       ├── cli.py
│       ├── config.py
│       ├── ctx.py
│       ├── debughelpers.py
│       ├── globals.py
│       ├── helpers.py
│       ├── json/
│       │   ├── __init__.py
│       │   ├── provider.py
│       │   └── tag.py
│       ├── logging.py
│       ├── py.typed
│       ├── sansio/
│       │   ├── README.md
│       │   ├── app.py
│       │   ├── blueprints.py
│       │   └── scaffold.py
│       ├── sessions.py
│       ├── signals.py
│       ├── templating.py
│       ├── testing.py
│       ├── typing.py
│       ├── views.py
│       └── wrappers.py
└── tests/
    ├── conftest.py
    ├── static/
    │   ├── config.json
    │   ├── config.toml
    │   └── index.html
    ├── templates/
    │   ├── _macro.html
    │   ├── context_template.html
    │   ├── escaping_template.html
    │   ├── mail.txt
    │   ├── nested/
    │   │   └── nested.txt
    │   ├── non_escaping_template.txt
    │   ├── simple_template.html
    │   ├── template_filter.html
    │   └── template_test.html
    ├── test_appctx.py
    ├── test_apps/
    │   ├── .flaskenv
    │   ├── blueprintapp/
    │   │   ├── __init__.py
    │   │   └── apps/
    │   │       ├── __init__.py
    │   │       ├── admin/
    │   │       │   ├── __init__.py
    │   │       │   ├── static/
    │   │       │   │   ├── css/
    │   │       │   │   │   └── test.css
    │   │       │   │   └── test.txt
    │   │       │   └── templates/
    │   │       │       └── admin/
    │   │       │           └── index.html
    │   │       └── frontend/
    │   │           ├── __init__.py
    │   │           └── templates/
    │   │               └── frontend/
    │   │                   └── index.html
    │   ├── cliapp/
    │   │   ├── __init__.py
    │   │   ├── app.py
    │   │   ├── factory.py
    │   │   ├── importerrorapp.py
    │   │   ├── inner1/
    │   │   │   ├── __init__.py
    │   │   │   └── inner2/
    │   │   │       ├── __init__.py
    │   │   │       └── flask.py
    │   │   ├── message.txt
    │   │   └── multiapp.py
    │   ├── helloworld/
    │   │   ├── hello.py
    │   │   └── wsgi.py
    │   └── subdomaintestmodule/
    │       ├── __init__.py
    │       └── static/
    │           └── hello.txt
    ├── test_async.py
    ├── test_basic.py
    ├── test_blueprints.py
    ├── test_cli.py
    ├── test_config.py
    ├── test_converters.py
    ├── test_helpers.py
    ├── test_instance_config.py
    ├── test_json.py
    ├── test_json_tag.py
    ├── test_logging.py
    ├── test_regression.py
    ├── test_reqctx.py
    ├── test_request.py
    ├── test_session_interface.py
    ├── test_signals.py
    ├── test_subclassing.py
    ├── test_templating.py
    ├── test_testing.py
    ├── test_user_error_handler.py
    ├── test_views.py
    └── type_check/
        ├── typing_app_decorators.py
        ├── typing_error_handler.py
        └── typing_route.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/devcontainer.json
================================================
{
  "name": "pallets/flask",
  "image": "mcr.microsoft.com/devcontainers/python:3",
  "customizations": {
    "vscode": {
      "settings": {
        "python.defaultInterpreterPath": "${workspaceFolder}/.venv",
        "python.terminal.activateEnvInCurrentTerminal": true,
        "python.terminal.launchArgs": [
          "-X",
          "dev"
        ]
      }
    }
  },
  "onCreateCommand": ".devcontainer/on-create-command.sh"
}


================================================
FILE: .devcontainer/on-create-command.sh
================================================
#!/bin/bash
set -e
python3 -m venv --upgrade-deps .venv
. .venv/bin/activate
pip install -r requirements/dev.txt
pip install -e .
pre-commit install --install-hooks


================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
charset = utf-8
max_line_length = 88

[*.{css,html,js,json,jsx,scss,ts,tsx,yaml,yml}]
indent_size = 2


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug report
about: Report a bug in Flask (not other projects which depend on Flask)
---

<!--
This issue tracker is a tool to address bugs in Flask itself. Please use
GitHub Discussions or the Pallets Discord for questions about your own code.

Replace this comment with a clear outline of what the bug is.
-->

<!--
Describe how to replicate the bug.

Include a minimal reproducible example that demonstrates the bug.
Include the full traceback if there was an exception.
-->

<!--
Describe the expected behavior that should have happened but didn't.
-->

Environment:

- Python version:
- Flask version:


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Security issue
    url: https://github.com/pallets/flask/security/advisories/new
    about: Do not report security issues publicly. Create a private advisory.
  - name: Questions on GitHub Discussions
    url: https://github.com/pallets/flask/discussions/
    about: Ask questions about your own code on the Discussions tab.
  - name: Questions on Discord
    url: https://discord.gg/pallets
    about: Ask questions about your own code on our Discord chat.


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature request
about: Suggest a new feature for Flask
---

<!--
Replace this comment with a description of what the feature should do.
Include details such as links to relevant specs or previous discussions.
-->

<!--
Replace this comment with an example of the problem which this feature
would resolve. Is this problem solvable without changes to Flask, such
as by subclassing or using an extension?
-->


================================================
FILE: .github/pull_request_template.md
================================================
<!--
Before opening a PR, open a ticket describing the issue or feature the
PR will address. An issue is not required for fixing typos in
documentation, or other simple non-code changes.

Replace this comment with a description of the change. Describe how it
addresses the linked ticket.
-->

<!--
Link to relevant issues or previous PRs, one per line. Use "fixes" to
automatically close an issue.

fixes #<issue number>
-->

<!--
Ensure each step in CONTRIBUTING.rst is complete, especially the following:

- Add tests that demonstrate the correct behavior of the change. Tests
  should fail without the change.
- Add or update relevant docs, in the docs folder and in code.
- Add an entry in CHANGES.rst summarizing the change and linking to the issue.
- Add `.. versionchanged::` entries in any relevant code docs.
-->


================================================
FILE: .github/workflows/lock.yaml
================================================
name: Lock inactive closed issues
# Lock closed issues that have not received any further activity for two weeks.
# This does not close open issues, only humans may do that. It is easier to
# respond to new issues with fresh examples rather than continuing discussions
# on old issues.

on:
  schedule:
    - cron: '0 0 * * *'
permissions: {}
concurrency:
  group: lock
  cancel-in-progress: true
jobs:
  lock:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
      discussions: write
    steps:
      - uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0
        with:
          issue-inactive-days: 14
          pr-inactive-days: 14
          discussion-inactive-days: 14


================================================
FILE: .github/workflows/pre-commit.yaml
================================================
name: pre-commit
on:
  pull_request:
  push:
    branches: [main, stable]
permissions: {}
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true
jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
        with:
          enable-cache: true
          prune-cache: false
      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        id: setup-python
        with:
          python-version-file: pyproject.toml
      - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
        with:
          path: ~/.cache/pre-commit
          key: pre-commit|${{ hashFiles('pyproject.toml', '.pre-commit-config.yaml') }}
      - run: uv run --locked --group pre-commit pre-commit run --show-diff-on-failure --color=always --all-files


================================================
FILE: .github/workflows/publish.yaml
================================================
name: Publish
on:
  push:
    tags: ['*']
permissions: {}
concurrency:
  group: publish-${{ github.event.push.ref }}
  cancel-in-progress: true
jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
        with:
          enable-cache: false
          prune-cache: false
      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version-file: pyproject.toml
      - run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
      - run: uv build
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        id: upload-artifact
        with:
          name: dist
          path: dist/
          if-no-files-found: error
  create-release:
    needs: [build]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          artifact-ids: ${{ needs.build.outputs.artifact-id }}
          path: dist/
      - name: create release
        run: gh release create --draft --repo ${GITHUB_REPOSITORY} ${GITHUB_REF_NAME} dist/*
        env:
          GH_TOKEN: ${{ github.token }}
  publish-pypi:
    needs: [build]
    environment:
      name: publish
      url: https://pypi.org/project/Flask/${{ github.ref_name }}
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          artifact-ids: ${{ needs.build.outputs.artifact-id }}
          path: dist/
      - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
        with:
          packages-dir: "dist/"


================================================
FILE: .github/workflows/tests.yaml
================================================
name: Tests
on:
  pull_request:
    paths-ignore: ['docs/**', 'README.md']
  push:
    branches: [main, stable]
    paths-ignore: ['docs/**', 'README.md']
permissions: {}
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true
jobs:
  tests:
    name: ${{ matrix.name || matrix.python }}
    runs-on: ${{ matrix.os || 'ubuntu-latest' }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - {python: '3.14'}
          - {python: '3.14t'}
          - {name: Windows, python: '3.14', os: windows-latest}
          - {name: Mac, python: '3.14', os: macos-latest}
          - {python: '3.13'}
          - {python: '3.12'}
          - {python: '3.11'}
          - {python: '3.10'}
          - {name: PyPy, python: 'pypy-3.11', tox: pypy3.11}
          - {name: Minimum Versions, python: '3.14', tox: tests-min}
          - {name: Development Versions, python: '3.10', tox: tests-dev}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
        with:
          enable-cache: true
          prune-cache: false
      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: ${{ matrix.python }}
      - run: uv run --locked tox run
        env:
          TOX_ENV: ${{ matrix.tox || format('py{0}', matrix.python) }}
  typing:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
        with:
          enable-cache: true
          prune-cache: false
      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version-file: pyproject.toml
      - name: cache mypy
        uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
        with:
          path: ./.mypy_cache
          key: mypy|${{ hashFiles('pyproject.toml') }}
      - run: uv run --locked tox run -e typing


================================================
FILE: .github/workflows/zizmor.yaml
================================================
name: GitHub Actions security analysis with zizmor
on:
  pull_request:
    paths: ["**/*.yaml?"]
  push:
    branches: [main, stable]
    paths: ["**/*.yaml?"]
permissions: {}
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true
jobs:
  zizmor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: zizmorcore/zizmor-action@195d10ad90f31d8cd6ea1efd6ecc12969ddbe73f # v0.5.1
        with:
          advanced-security: false
          annotations: true


================================================
FILE: .gitignore
================================================
.idea/
.vscode/
__pycache__/
dist/
.coverage*
htmlcov/
.tox/
docs/_build/


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: b969e2851312ca2b24bbec879ba4954341d1bd12  # frozen: v0.15.5
    hooks:
      - id: ruff-check
      - id: ruff-format
  - repo: https://github.com/astral-sh/uv-pre-commit
    rev: e38709b2694c2988ab0c618ee63ac156e155d5c4  # frozen: 0.10.9
    hooks:
      - id: uv-lock
  - repo: https://github.com/codespell-project/codespell
    rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a  # frozen: v2.4.2
    hooks:
      - id: codespell
        args: ['--write-changes']
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c  # frozen: v6.0.0
    hooks:
      - id: check-merge-conflict
      - id: debug-statements
      - id: fix-byte-order-marker
      - id: trailing-whitespace
      - id: end-of-file-fixer


================================================
FILE: .readthedocs.yaml
================================================
version: 2
build:
  os: ubuntu-24.04
  tools:
    python: '3.13'
  commands:
    - asdf plugin add uv
    - asdf install uv latest
    - asdf global uv latest
    - uv run --group docs sphinx-build -W -b dirhtml docs $READTHEDOCS_OUTPUT/html


================================================
FILE: CHANGES.rst
================================================
Version 3.2.0
-------------

Unreleased

-   Drop support for Python 3.9. :pr:`5730`
-   Remove previously deprecated code: ``__version__``. :pr:`5648`
-   ``RequestContext`` has merged with ``AppContext``. ``RequestContext`` is now
    a deprecated alias. If an app context is already pushed, it is not reused
    when dispatching a request. This greatly simplifies the internal code for tracking
    the active context. :issue:`5639`
-   Many ``Flask`` methods involved in request dispatch now take the current
    ``AppContext`` as the first parameter, instead of using the proxy objects.
    If subclasses were overriding these methods, the old signature is detected,
    shows a deprecation warning, and will continue to work during the
    deprecation period. :issue:`5815`
-   All teardown callbacks are called, even if any raise an error. :pr:`5928`
-   The ``should_ignore_error`` is deprecated. Handle errors as needed in
    teardown handlers instead. :issue:`5816`
-   ``template_filter``, ``template_test``, and ``template_global`` decorators
    can be used without parentheses. :issue:`5729`
-   ``redirect`` returns a ``303`` status code by default instead of ``302``.
    This tells the client to always switch to ``GET``, rather than only
    switching ``POST`` to ``GET``. This preserves the current behavior of
    ``GET`` and ``POST`` redirects, and is also correct for frontend libraries
    such as HTMX. :issue:`5895`
-   ``provide_automatic_options=True`` can be used to enable it for a view when
    it's disabled in config. Previously, only disabling worked. :issue:`5916`


Version 3.1.3
-------------

Released 2026-02-18

-   The session is marked as accessed for operations that only access the keys
    but not the values, such as ``in`` and ``len``. :ghsa:`68rp-wp8r-4726`


Version 3.1.2
-------------

Released 2025-08-19

-   ``stream_with_context`` does not fail inside async views. :issue:`5774`
-   When using ``follow_redirects`` in the test client, the final state
    of ``session`` is correct. :issue:`5786`
-   Relax type hint for passing bytes IO to ``send_file``. :issue:`5776`


Version 3.1.1
-------------

Released 2025-05-13

-   Fix signing key selection order when key rotation is enabled via
    ``SECRET_KEY_FALLBACKS``. :ghsa:`4grg-w6v8-c28g`
-   Fix type hint for ``cli_runner.invoke``. :issue:`5645`
-   ``flask --help`` loads the app and plugins first to make sure all commands
    are shown. :issue:`5673`
-   Mark sans-io base class as being able to handle views that return
    ``AsyncIterable``. This is not accurate for Flask, but makes typing easier
    for Quart. :pr:`5659`


Version 3.1.0
-------------

Released 2024-11-13

-   Drop support for Python 3.8. :pr:`5623`
-   Update minimum dependency versions to latest feature releases.
    Werkzeug >= 3.1, ItsDangerous >= 2.2, Blinker >= 1.9. :pr:`5624,5633`
-   Provide a configuration option to control automatic option
    responses. :pr:`5496`
-   ``Flask.open_resource``/``open_instance_resource`` and
    ``Blueprint.open_resource`` take an ``encoding`` parameter to use when
    opening in text mode. It defaults to ``utf-8``. :issue:`5504`
-   ``Request.max_content_length`` can be customized per-request instead of only
    through the ``MAX_CONTENT_LENGTH`` config. Added
    ``MAX_FORM_MEMORY_SIZE`` and ``MAX_FORM_PARTS`` config. Added documentation
    about resource limits to the security page. :issue:`5625`
-   Add support for the ``Partitioned`` cookie attribute (CHIPS), with the
    ``SESSION_COOKIE_PARTITIONED`` config. :issue:`5472`
-   ``-e path`` takes precedence over default ``.env`` and ``.flaskenv`` files.
    ``load_dotenv`` loads default files in addition to a path unless
    ``load_defaults=False`` is passed. :issue:`5628`
-   Support key rotation with the ``SECRET_KEY_FALLBACKS`` config, a list of old
    secret keys that can still be used for unsigning. Extensions will need to
    add support. :issue:`5621`
-   Fix how setting ``host_matching=True`` or ``subdomain_matching=False``
    interacts with ``SERVER_NAME``. Setting ``SERVER_NAME`` no longer restricts
    requests to only that domain. :issue:`5553`
-   ``Request.trusted_hosts`` is checked during routing, and can be set through
    the ``TRUSTED_HOSTS`` config. :issue:`5636`


Version 3.0.3
-------------

Released 2024-04-07

-   The default ``hashlib.sha1`` may not be available in FIPS builds. Don't
    access it at import time so the developer has time to change the default.
    :issue:`5448`
-   Don't initialize the ``cli`` attribute in the sansio scaffold, but rather in
    the ``Flask`` concrete class. :pr:`5270`


Version 3.0.2
-------------

Released 2024-02-03

-   Correct type for ``jinja_loader`` property. :issue:`5388`
-   Fix error with ``--extra-files`` and ``--exclude-patterns`` CLI options.
    :issue:`5391`


Version 3.0.1
-------------

Released 2024-01-18

-   Correct type for ``path`` argument to ``send_file``. :issue:`5336`
-   Fix a typo in an error message for the ``flask run --key`` option. :pr:`5344`
-   Session data is untagged without relying on the built-in ``json.loads``
    ``object_hook``. This allows other JSON providers that don't implement that.
    :issue:`5381`
-   Address more type findings when using mypy strict mode. :pr:`5383`


Version 3.0.0
-------------

Released 2023-09-30

-   Remove previously deprecated code. :pr:`5223`
-   Deprecate the ``__version__`` attribute. Use feature detection, or
    ``importlib.metadata.version("flask")``, instead. :issue:`5230`
-   Restructure the code such that the Flask (app) and Blueprint
    classes have Sans-IO bases. :pr:`5127`
-   Allow self as an argument to url_for. :pr:`5264`
-   Require Werkzeug >= 3.0.0.


Version 2.3.3
-------------

Released 2023-08-21

-   Python 3.12 compatibility.
-   Require Werkzeug >= 2.3.7.
-   Use ``flit_core`` instead of ``setuptools`` as build backend.
-   Refactor how an app's root and instance paths are determined. :issue:`5160`


Version 2.3.2
-------------

Released 2023-05-01

-   Set ``Vary: Cookie`` header when the session is accessed, modified, or refreshed.
-   Update Werkzeug requirement to >=2.3.3 to apply recent bug fixes.
    :ghsa:`m2qf-hxjv-5gpq`


Version 2.3.1
-------------

Released 2023-04-25

-   Restore deprecated ``from flask import Markup``. :issue:`5084`


Version 2.3.0
-------------

Released 2023-04-25

-   Drop support for Python 3.7. :pr:`5072`
-   Update minimum requirements to the latest versions: Werkzeug>=2.3.0, Jinja2>3.1.2,
    itsdangerous>=2.1.2, click>=8.1.3.
-   Remove previously deprecated code. :pr:`4995`

    -   The ``push`` and ``pop`` methods of the deprecated ``_app_ctx_stack`` and
        ``_request_ctx_stack`` objects are removed. ``top`` still exists to give
        extensions more time to update, but it will be removed.
    -   The ``FLASK_ENV`` environment variable, ``ENV`` config key, and ``app.env``
        property are removed.
    -   The ``session_cookie_name``, ``send_file_max_age_default``, ``use_x_sendfile``,
        ``propagate_exceptions``, and ``templates_auto_reload`` properties on ``app``
        are removed.
    -   The ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_MIMETYPE``, and
        ``JSONIFY_PRETTYPRINT_REGULAR`` config keys are removed.
    -   The ``app.before_first_request`` and ``bp.before_app_first_request`` decorators
        are removed.
    -   ``json_encoder`` and ``json_decoder`` attributes on app and blueprint, and the
        corresponding ``json.JSONEncoder`` and ``JSONDecoder`` classes, are removed.
    -   The ``json.htmlsafe_dumps`` and ``htmlsafe_dump`` functions are removed.
    -   Calling setup methods on blueprints after registration is an error instead of a
        warning. :pr:`4997`

-   Importing ``escape`` and ``Markup`` from ``flask`` is deprecated. Import them
    directly from ``markupsafe`` instead. :pr:`4996`
-   The ``app.got_first_request`` property is deprecated. :pr:`4997`
-   The ``locked_cached_property`` decorator is deprecated. Use a lock inside the
    decorated function if locking is needed. :issue:`4993`
-   Signals are always available. ``blinker>=1.6.2`` is a required dependency. The
    ``signals_available`` attribute is deprecated. :issue:`5056`
-   Signals support ``async`` subscriber functions. :pr:`5049`
-   Remove uses of locks that could cause requests to block each other very briefly.
    :issue:`4993`
-   Use modern packaging metadata with ``pyproject.toml`` instead of ``setup.cfg``.
    :pr:`4947`
-   Ensure subdomains are applied with nested blueprints. :issue:`4834`
-   ``config.from_file`` can use ``text=False`` to indicate that the parser wants a
    binary file instead. :issue:`4989`
-   If a blueprint is created with an empty name it raises a ``ValueError``.
    :issue:`5010`
-   ``SESSION_COOKIE_DOMAIN`` does not fall back to ``SERVER_NAME``. The default is not
    to set the domain, which modern browsers interpret as an exact match rather than
    a subdomain match. Warnings about ``localhost`` and IP addresses are also removed.
    :issue:`5051`
-   The ``routes`` command shows each rule's ``subdomain`` or ``host`` when domain
    matching is in use. :issue:`5004`
-   Use postponed evaluation of annotations. :pr:`5071`


Version 2.2.5
-------------

Released 2023-05-02

-   Update for compatibility with Werkzeug 2.3.3.
-   Set ``Vary: Cookie`` header when the session is accessed, modified, or refreshed.


Version 2.2.4
-------------

Released 2023-04-25

-   Update for compatibility with Werkzeug 2.3.


Version 2.2.3
-------------

Released 2023-02-15

-   Autoescape is enabled by default for ``.svg`` template files. :issue:`4831`
-   Fix the type of ``template_folder`` to accept ``pathlib.Path``. :issue:`4892`
-   Add ``--debug`` option to the ``flask run`` command. :issue:`4777`


Version 2.2.2
-------------

Released 2022-08-08

-   Update Werkzeug dependency to >= 2.2.2. This includes fixes related
    to the new faster router, header parsing, and the development
    server. :pr:`4754`
-   Fix the default value for ``app.env`` to be ``"production"``. This
    attribute remains deprecated. :issue:`4740`


Version 2.2.1
-------------

Released 2022-08-03

-   Setting or accessing ``json_encoder`` or ``json_decoder`` raises a
    deprecation warning. :issue:`4732`


Version 2.2.0
-------------

Released 2022-08-01

-   Remove previously deprecated code. :pr:`4667`

    -   Old names for some ``send_file`` parameters have been removed.
        ``download_name`` replaces ``attachment_filename``, ``max_age``
        replaces ``cache_timeout``, and ``etag`` replaces ``add_etags``.
        Additionally, ``path`` replaces ``filename`` in
        ``send_from_directory``.
    -   The ``RequestContext.g`` property returning ``AppContext.g`` is
        removed.

-   Update Werkzeug dependency to >= 2.2.
-   The app and request contexts are managed using Python context vars
    directly rather than Werkzeug's ``LocalStack``. This should result
    in better performance and memory use. :pr:`4682`

    -   Extension maintainers, be aware that ``_app_ctx_stack.top``
        and ``_request_ctx_stack.top`` are deprecated. Store data on
        ``g`` instead using a unique prefix, like
        ``g._extension_name_attr``.

-   The ``FLASK_ENV`` environment variable and ``app.env`` attribute are
    deprecated, removing the distinction between development and debug
    mode. Debug mode should be controlled directly using the ``--debug``
    option or ``app.run(debug=True)``. :issue:`4714`
-   Some attributes that proxied config keys on ``app`` are deprecated:
    ``session_cookie_name``, ``send_file_max_age_default``,
    ``use_x_sendfile``, ``propagate_exceptions``, and
    ``templates_auto_reload``. Use the relevant config keys instead.
    :issue:`4716`
-   Add new customization points to the ``Flask`` app object for many
    previously global behaviors.

    -   ``flask.url_for`` will call ``app.url_for``. :issue:`4568`
    -   ``flask.abort`` will call ``app.aborter``.
        ``Flask.aborter_class`` and ``Flask.make_aborter`` can be used
        to customize this aborter. :issue:`4567`
    -   ``flask.redirect`` will call ``app.redirect``. :issue:`4569`
    -   ``flask.json`` is an instance of ``JSONProvider``. A different
        provider can be set to use a different JSON library.
        ``flask.jsonify`` will call ``app.json.response``, other
        functions in ``flask.json`` will call corresponding functions in
        ``app.json``. :pr:`4692`

-   JSON configuration is moved to attributes on the default
    ``app.json`` provider. ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``,
    ``JSONIFY_MIMETYPE``, and ``JSONIFY_PRETTYPRINT_REGULAR`` are
    deprecated. :pr:`4692`
-   Setting custom ``json_encoder`` and ``json_decoder`` classes on the
    app or a blueprint, and the corresponding ``json.JSONEncoder`` and
    ``JSONDecoder`` classes, are deprecated. JSON behavior can now be
    overridden using the ``app.json`` provider interface. :pr:`4692`
-   ``json.htmlsafe_dumps`` and ``json.htmlsafe_dump`` are deprecated,
    the function is built-in to Jinja now. :pr:`4692`
-   Refactor ``register_error_handler`` to consolidate error checking.
    Rewrite some error messages to be more consistent. :issue:`4559`
-   Use Blueprint decorators and functions intended for setup after
    registering the blueprint will show a warning. In the next version,
    this will become an error just like the application setup methods.
    :issue:`4571`
-   ``before_first_request`` is deprecated. Run setup code when creating
    the application instead. :issue:`4605`
-   Added the ``View.init_every_request`` class attribute. If a view
    subclass sets this to ``False``, the view will not create a new
    instance on every request. :issue:`2520`.
-   A ``flask.cli.FlaskGroup`` Click group can be nested as a
    sub-command in a custom CLI. :issue:`3263`
-   Add ``--app`` and ``--debug`` options to the ``flask`` CLI, instead
    of requiring that they are set through environment variables.
    :issue:`2836`
-   Add ``--env-file`` option to the ``flask`` CLI. This allows
    specifying a dotenv file to load in addition to ``.env`` and
    ``.flaskenv``. :issue:`3108`
-   It is no longer required to decorate custom CLI commands on
    ``app.cli`` or ``blueprint.cli`` with ``@with_appcontext``, an app
    context will already be active at that point. :issue:`2410`
-   ``SessionInterface.get_expiration_time`` uses a timezone-aware
    value. :pr:`4645`
-   View functions can return generators directly instead of wrapping
    them in a ``Response``. :pr:`4629`
-   Add ``stream_template`` and ``stream_template_string`` functions to
    render a template as a stream of pieces. :pr:`4629`
-   A new implementation of context preservation during debugging and
    testing. :pr:`4666`

    -   ``request``, ``g``, and other context-locals point to the
        correct data when running code in the interactive debugger
        console. :issue:`2836`
    -   Teardown functions are always run at the end of the request,
        even if the context is preserved. They are also run after the
        preserved context is popped.
    -   ``stream_with_context`` preserves context separately from a
        ``with client`` block. It will be cleaned up when
        ``response.get_data()`` or ``response.close()`` is called.

-   Allow returning a list from a view function, to convert it to a
    JSON response like a dict is. :issue:`4672`
-   When type checking, allow ``TypedDict`` to be returned from view
    functions. :pr:`4695`
-   Remove the ``--eager-loading/--lazy-loading`` options from the
    ``flask run`` command. The app is always eager loaded the first
    time, then lazily loaded in the reloader. The reloader always prints
    errors immediately but continues serving. Remove the internal
    ``DispatchingApp`` middleware used by the previous implementation.
    :issue:`4715`


Version 2.1.3
-------------

Released 2022-07-13

-   Inline some optional imports that are only used for certain CLI
    commands. :pr:`4606`
-   Relax type annotation for ``after_request`` functions. :issue:`4600`
-   ``instance_path`` for namespace packages uses the path closest to
    the imported submodule. :issue:`4610`
-   Clearer error message when ``render_template`` and
    ``render_template_string`` are used outside an application context.
    :pr:`4693`


Version 2.1.2
-------------

Released 2022-04-28

-   Fix type annotation for ``json.loads``, it accepts str or bytes.
    :issue:`4519`
-   The ``--cert`` and ``--key`` options on ``flask run`` can be given
    in either order. :issue:`4459`


Version 2.1.1
-------------

Released on 2022-03-30

-   Set the minimum required version of importlib_metadata to 3.6.0,
    which is required on Python < 3.10. :issue:`4502`


Version 2.1.0
-------------

Released 2022-03-28

-   Drop support for Python 3.6. :pr:`4335`
-   Update Click dependency to >= 8.0. :pr:`4008`
-   Remove previously deprecated code. :pr:`4337`

    -   The CLI does not pass ``script_info`` to app factory functions.
    -   ``config.from_json`` is replaced by
        ``config.from_file(name, load=json.load)``.
    -   ``json`` functions no longer take an ``encoding`` parameter.
    -   ``safe_join`` is removed, use ``werkzeug.utils.safe_join``
        instead.
    -   ``total_seconds`` is removed, use ``timedelta.total_seconds``
        instead.
    -   The same blueprint cannot be registered with the same name. Use
        ``name=`` when registering to specify a unique name.
    -   The test client's ``as_tuple`` parameter is removed. Use
        ``response.request.environ`` instead. :pr:`4417`

-   Some parameters in ``send_file`` and ``send_from_directory`` were
    renamed in 2.0. The deprecation period for the old names is extended
    to 2.2. Be sure to test with deprecation warnings visible.

    -   ``attachment_filename`` is renamed to ``download_name``.
    -   ``cache_timeout`` is renamed to ``max_age``.
    -   ``add_etags`` is renamed to ``etag``.
    -   ``filename`` is renamed to ``path``.

-   The ``RequestContext.g`` property is deprecated. Use ``g`` directly
    or ``AppContext.g`` instead. :issue:`3898`
-   ``copy_current_request_context`` can decorate async functions.
    :pr:`4303`
-   The CLI uses ``importlib.metadata`` instead of ``pkg_resources`` to
    load command entry points. :issue:`4419`
-   Overriding ``FlaskClient.open`` will not cause an error on redirect.
    :issue:`3396`
-   Add an ``--exclude-patterns`` option to the ``flask run`` CLI
    command to specify patterns that will be ignored by the reloader.
    :issue:`4188`
-   When using lazy loading (the default with the debugger), the Click
    context from the ``flask run`` command remains available in the
    loader thread. :issue:`4460`
-   Deleting the session cookie uses the ``httponly`` flag.
    :issue:`4485`
-   Relax typing for ``errorhandler`` to allow the user to use more
    precise types and decorate the same function multiple times.
    :issue:`4095, 4295, 4297`
-   Fix typing for ``__exit__`` methods for better compatibility with
    ``ExitStack``. :issue:`4474`
-   From Werkzeug, for redirect responses the ``Location`` header URL
    will remain relative, and exclude the scheme and domain, by default.
    :pr:`4496`
-   Add ``Config.from_prefixed_env()`` to load config values from
    environment variables that start with ``FLASK_`` or another prefix.
    This parses values as JSON by default, and allows setting keys in
    nested dicts. :pr:`4479`


Version 2.0.3
-------------

Released 2022-02-14

-   The test client's ``as_tuple`` parameter is deprecated and will be
    removed in Werkzeug 2.1. It is now also deprecated in Flask, to be
    removed in Flask 2.1, while remaining compatible with both in
    2.0.x. Use ``response.request.environ`` instead. :pr:`4341`
-   Fix type annotation for ``errorhandler`` decorator. :issue:`4295`
-   Revert a change to the CLI that caused it to hide ``ImportError``
    tracebacks when importing the application. :issue:`4307`
-   ``app.json_encoder`` and ``json_decoder`` are only passed to
    ``dumps`` and ``loads`` if they have custom behavior. This improves
    performance, mainly on PyPy. :issue:`4349`
-   Clearer error message when ``after_this_request`` is used outside a
    request context. :issue:`4333`


Version 2.0.2
-------------

Released 2021-10-04

-   Fix type annotation for ``teardown_*`` methods. :issue:`4093`
-   Fix type annotation for ``before_request`` and ``before_app_request``
    decorators. :issue:`4104`
-   Fixed the issue where typing requires template global
    decorators to accept functions with no arguments. :issue:`4098`
-   Support View and MethodView instances with async handlers. :issue:`4112`
-   Enhance typing of ``app.errorhandler`` decorator. :issue:`4095`
-   Fix registering a blueprint twice with differing names. :issue:`4124`
-   Fix the type of ``static_folder`` to accept ``pathlib.Path``.
    :issue:`4150`
-   ``jsonify`` handles ``decimal.Decimal`` by encoding to ``str``.
    :issue:`4157`
-   Correctly handle raising deferred errors in CLI lazy loading.
    :issue:`4096`
-   The CLI loader handles ``**kwargs`` in a ``create_app`` function.
    :issue:`4170`
-   Fix the order of ``before_request`` and other callbacks that trigger
    before the view returns. They are called from the app down to the
    closest nested blueprint. :issue:`4229`


Version 2.0.1
-------------

Released 2021-05-21

-   Re-add the ``filename`` parameter in ``send_from_directory``. The
    ``filename`` parameter has been renamed to ``path``, the old name
    is deprecated. :pr:`4019`
-   Mark top-level names as exported so type checking understands
    imports in user projects. :issue:`4024`
-   Fix type annotation for ``g`` and inform mypy that it is a namespace
    object that has arbitrary attributes. :issue:`4020`
-   Fix some types that weren't available in Python 3.6.0. :issue:`4040`
-   Improve typing for ``send_file``, ``send_from_directory``, and
    ``get_send_file_max_age``. :issue:`4044`, :pr:`4026`
-   Show an error when a blueprint name contains a dot. The ``.`` has
    special meaning, it is used to separate (nested) blueprint names and
    the endpoint name. :issue:`4041`
-   Combine URL prefixes when nesting blueprints that were created with
    a ``url_prefix`` value. :issue:`4037`
-   Revert a change to the order that URL matching was done. The
    URL is again matched after the session is loaded, so the session is
    available in custom URL converters. :issue:`4053`
-   Re-add deprecated ``Config.from_json``, which was accidentally
    removed early. :issue:`4078`
-   Improve typing for some functions using ``Callable`` in their type
    signatures, focusing on decorator factories. :issue:`4060`
-   Nested blueprints are registered with their dotted name. This allows
    different blueprints with the same name to be nested at different
    locations. :issue:`4069`
-   ``register_blueprint`` takes a ``name`` option to change the
    (pre-dotted) name the blueprint is registered with. This allows the
    same blueprint to be registered multiple times with unique names for
    ``url_for``. Registering the same blueprint with the same name
    multiple times is deprecated. :issue:`1091`
-   Improve typing for ``stream_with_context``. :issue:`4052`


Version 2.0.0
-------------

Released 2021-05-11

-   Drop support for Python 2 and 3.5.
-   Bump minimum versions of other Pallets projects: Werkzeug >= 2,
    Jinja2 >= 3, MarkupSafe >= 2, ItsDangerous >= 2, Click >= 8. Be sure
    to check the change logs for each project. For better compatibility
    with other applications (e.g. Celery) that still require Click 7,
    there is no hard dependency on Click 8 yet, but using Click 7 will
    trigger a DeprecationWarning and Flask 2.1 will depend on Click 8.
-   JSON support no longer uses simplejson. To use another JSON module,
    override ``app.json_encoder`` and ``json_decoder``. :issue:`3555`
-   The ``encoding`` option to JSON functions is deprecated. :pr:`3562`
-   Passing ``script_info`` to app factory functions is deprecated. This
    was not portable outside the ``flask`` command. Use
    ``click.get_current_context().obj`` if it's needed. :issue:`3552`
-   The CLI shows better error messages when the app failed to load
    when looking up commands. :issue:`2741`
-   Add ``SessionInterface.get_cookie_name`` to allow setting the
    session cookie name dynamically. :pr:`3369`
-   Add ``Config.from_file`` to load config using arbitrary file
    loaders, such as ``toml.load`` or ``json.load``.
    ``Config.from_json`` is deprecated in favor of this. :pr:`3398`
-   The ``flask run`` command will only defer errors on reload. Errors
    present during the initial call will cause the server to exit with
    the traceback immediately. :issue:`3431`
-   ``send_file`` raises a ``ValueError`` when passed an ``io`` object
    in text mode. Previously, it would respond with 200 OK and an empty
    file. :issue:`3358`
-   When using ad-hoc certificates, check for the cryptography library
    instead of PyOpenSSL. :pr:`3492`
-   When specifying a factory function with ``FLASK_APP``, keyword
    argument can be passed. :issue:`3553`
-   When loading a ``.env`` or ``.flaskenv`` file, the current working
    directory is no longer changed to the location of the file.
    :pr:`3560`
-   When returning a ``(response, headers)`` tuple from a view, the
    headers replace rather than extend existing headers on the response.
    For example, this allows setting the ``Content-Type`` for
    ``jsonify()``. Use ``response.headers.extend()`` if extending is
    desired. :issue:`3628`
-   The ``Scaffold`` class provides a common API for the ``Flask`` and
    ``Blueprint`` classes. ``Blueprint`` information is stored in
    attributes just like ``Flask``, rather than opaque lambda functions.
    This is intended to improve consistency and maintainability.
    :issue:`3215`
-   Include ``samesite`` and ``secure`` options when removing the
    session cookie. :pr:`3726`
-   Support passing a ``pathlib.Path`` to ``static_folder``. :pr:`3579`
-   ``send_file`` and ``send_from_directory`` are wrappers around the
    implementations in ``werkzeug.utils``. :pr:`3828`
-   Some ``send_file`` parameters have been renamed, the old names are
    deprecated. ``attachment_filename`` is renamed to ``download_name``.
    ``cache_timeout`` is renamed to ``max_age``. ``add_etags`` is
    renamed to ``etag``. :pr:`3828, 3883`
-   ``send_file`` passes ``download_name`` even if
    ``as_attachment=False`` by using ``Content-Disposition: inline``.
    :pr:`3828`
-   ``send_file`` sets ``conditional=True`` and ``max_age=None`` by
    default. ``Cache-Control`` is set to ``no-cache`` if ``max_age`` is
    not set, otherwise ``public``. This tells browsers to validate
    conditional requests instead of using a timed cache. :pr:`3828`
-   ``helpers.safe_join`` is deprecated. Use
    ``werkzeug.utils.safe_join`` instead. :pr:`3828`
-   The request context does route matching before opening the session.
    This could allow a session interface to change behavior based on
    ``request.endpoint``. :issue:`3776`
-   Use Jinja's implementation of the ``|tojson`` filter. :issue:`3881`
-   Add route decorators for common HTTP methods. For example,
    ``@app.post("/login")`` is a shortcut for
    ``@app.route("/login", methods=["POST"])``. :pr:`3907`
-   Support async views, error handlers, before and after request, and
    teardown functions. :pr:`3412`
-   Support nesting blueprints. :issue:`593, 1548`, :pr:`3923`
-   Set the default encoding to "UTF-8" when loading ``.env`` and
    ``.flaskenv`` files to allow to use non-ASCII characters. :issue:`3931`
-   ``flask shell`` sets up tab and history completion like the default
    ``python`` shell if ``readline`` is installed. :issue:`3941`
-   ``helpers.total_seconds()`` is deprecated. Use
    ``timedelta.total_seconds()`` instead. :pr:`3962`
-   Add type hinting. :pr:`3973`.


Version 1.1.4
-------------

Released 2021-05-13

-   Update ``static_folder`` to use ``_compat.fspath`` instead of
    ``os.fspath`` to continue supporting Python < 3.6 :issue:`4050`


Version 1.1.3
-------------

Released 2021-05-13

-   Set maximum versions of Werkzeug, Jinja, Click, and ItsDangerous.
    :issue:`4043`
-   Re-add support for passing a ``pathlib.Path`` for ``static_folder``.
    :pr:`3579`


Version 1.1.2
-------------

Released 2020-04-03

-   Work around an issue when running the ``flask`` command with an
    external debugger on Windows. :issue:`3297`
-   The static route will not catch all URLs if the ``Flask``
    ``static_folder`` argument ends with a slash. :issue:`3452`


Version 1.1.1
-------------

Released 2019-07-08

-   The ``flask.json_available`` flag was added back for compatibility
    with some extensions. It will raise a deprecation warning when used,
    and will be removed in version 2.0.0. :issue:`3288`


Version 1.1.0
-------------

Released 2019-07-04

-   Bump minimum Werkzeug version to >= 0.15.
-   Drop support for Python 3.4.
-   Error handlers for ``InternalServerError`` or ``500`` will always be
    passed an instance of ``InternalServerError``. If they are invoked
    due to an unhandled exception, that original exception is now
    available as ``e.original_exception`` rather than being passed
    directly to the handler. The same is true if the handler is for the
    base ``HTTPException``. This makes error handler behavior more
    consistent. :pr:`3266`

    -   ``Flask.finalize_request`` is called for all unhandled
        exceptions even if there is no ``500`` error handler.

-   ``Flask.logger`` takes the same name as ``Flask.name`` (the value
    passed as ``Flask(import_name)``. This reverts 1.0's behavior of
    always logging to ``"flask.app"``, in order to support multiple apps
    in the same process. A warning will be shown if old configuration is
    detected that needs to be moved. :issue:`2866`
-   ``RequestContext.copy`` includes the current session object in the
    request context copy. This prevents ``session`` pointing to an
    out-of-date object. :issue:`2935`
-   Using built-in RequestContext, unprintable Unicode characters in
    Host header will result in a HTTP 400 response and not HTTP 500 as
    previously. :pr:`2994`
-   ``send_file`` supports ``PathLike`` objects as described in
    :pep:`519`, to support ``pathlib`` in Python 3. :pr:`3059`
-   ``send_file`` supports ``BytesIO`` partial content.
    :issue:`2957`
-   ``open_resource`` accepts the "rt" file mode. This still does the
    same thing as "r". :issue:`3163`
-   The ``MethodView.methods`` attribute set in a base class is used by
    subclasses. :issue:`3138`
-   ``Flask.jinja_options`` is a ``dict`` instead of an
    ``ImmutableDict`` to allow easier configuration. Changes must still
    be made before creating the environment. :pr:`3190`
-   Flask's ``JSONMixin`` for the request and response wrappers was
    moved into Werkzeug. Use Werkzeug's version with Flask-specific
    support. This bumps the Werkzeug dependency to >= 0.15.
    :issue:`3125`
-   The ``flask`` command entry point is simplified to take advantage
    of Werkzeug 0.15's better reloader support. This bumps the Werkzeug
    dependency to >= 0.15. :issue:`3022`
-   Support ``static_url_path`` that ends with a forward slash.
    :issue:`3134`
-   Support empty ``static_folder`` without requiring setting an empty
    ``static_url_path`` as well. :pr:`3124`
-   ``jsonify`` supports ``dataclass`` objects. :pr:`3195`
-   Allow customizing the ``Flask.url_map_class`` used for routing.
    :pr:`3069`
-   The development server port can be set to 0, which tells the OS to
    pick an available port. :issue:`2926`
-   The return value from ``cli.load_dotenv`` is more consistent with
    the documentation. It will return ``False`` if python-dotenv is not
    installed, or if the given path isn't a file. :issue:`2937`
-   Signaling support has a stub for the ``connect_via`` method when
    the Blinker library is not installed. :pr:`3208`
-   Add an ``--extra-files`` option to the ``flask run`` CLI command to
    specify extra files that will trigger the reloader on change.
    :issue:`2897`
-   Allow returning a dictionary from a view function. Similar to how
    returning a string will produce a ``text/html`` response, returning
    a dict will call ``jsonify`` to produce a ``application/json``
    response. :pr:`3111`
-   Blueprints have a ``cli`` Click group like ``app.cli``. CLI commands
    registered with a blueprint will be available as a group under the
    ``flask`` command. :issue:`1357`.
-   When using the test client as a context manager (``with client:``),
    all preserved request contexts are popped when the block exits,
    ensuring nested contexts are cleaned up correctly. :pr:`3157`
-   Show a better error message when the view return type is not
    supported. :issue:`3214`
-   ``flask.testing.make_test_environ_builder()`` has been deprecated in
    favour of a new class ``flask.testing.EnvironBuilder``. :pr:`3232`
-   The ``flask run`` command no longer fails if Python is not built
    with SSL support. Using the ``--cert`` option will show an
    appropriate error message. :issue:`3211`
-   URL matching now occurs after the request context is pushed, rather
    than when it's created. This allows custom URL converters to access
    the app and request contexts, such as to query a database for an id.
    :issue:`3088`


Version 1.0.4
-------------

Released 2019-07-04

-   The key information for ``BadRequestKeyError`` is no longer cleared
    outside debug mode, so error handlers can still access it. This
    requires upgrading to Werkzeug 0.15.5. :issue:`3249`
-   ``send_file`` url quotes the ":" and "/" characters for more
    compatible UTF-8 filename support in some browsers. :issue:`3074`
-   Fixes for :pep:`451` import loaders and pytest 5.x. :issue:`3275`
-   Show message about dotenv on stderr instead of stdout. :issue:`3285`


Version 1.0.3
-------------

Released 2019-05-17

-   ``send_file`` encodes filenames as ASCII instead of Latin-1
    (ISO-8859-1). This fixes compatibility with Gunicorn, which is
    stricter about header encodings than :pep:`3333`. :issue:`2766`
-   Allow custom CLIs using ``FlaskGroup`` to set the debug flag without
    it always being overwritten based on environment variables.
    :pr:`2765`
-   ``flask --version`` outputs Werkzeug's version and simplifies the
    Python version. :pr:`2825`
-   ``send_file`` handles an ``attachment_filename`` that is a native
    Python 2 string (bytes) with UTF-8 coded bytes. :issue:`2933`
-   A catch-all error handler registered for ``HTTPException`` will not
    handle ``RoutingException``, which is used internally during
    routing. This fixes the unexpected behavior that had been introduced
    in 1.0. :pr:`2986`
-   Passing the ``json`` argument to ``app.test_client`` does not
    push/pop an extra app context. :issue:`2900`


Version 1.0.2
-------------

Released 2018-05-02

-   Fix more backwards compatibility issues with merging slashes between
    a blueprint prefix and route. :pr:`2748`
-   Fix error with ``flask routes`` command when there are no routes.
    :issue:`2751`


Version 1.0.1
-------------

Released 2018-04-29

-   Fix registering partials (with no ``__name__``) as view functions.
    :pr:`2730`
-   Don't treat lists returned from view functions the same as tuples.
    Only tuples are interpreted as response data. :issue:`2736`
-   Extra slashes between a blueprint's ``url_prefix`` and a route URL
    are merged. This fixes some backwards compatibility issues with the
    change in 1.0. :issue:`2731`, :issue:`2742`
-   Only trap ``BadRequestKeyError`` errors in debug mode, not all
    ``BadRequest`` errors. This allows ``abort(400)`` to continue
    working as expected. :issue:`2735`
-   The ``FLASK_SKIP_DOTENV`` environment variable can be set to ``1``
    to skip automatically loading dotenv files. :issue:`2722`


Version 1.0
-----------

Released 2018-04-26

-   Python 2.6 and 3.3 are no longer supported.
-   Bump minimum dependency versions to the latest stable versions:
    Werkzeug >= 0.14, Jinja >= 2.10, itsdangerous >= 0.24, Click >= 5.1.
    :issue:`2586`
-   Skip ``app.run`` when a Flask application is run from the command
    line. This avoids some behavior that was confusing to debug.
-   Change the default for ``JSONIFY_PRETTYPRINT_REGULAR`` to
    ``False``. ``~json.jsonify`` returns a compact format by default,
    and an indented format in debug mode. :pr:`2193`
-   ``Flask.__init__`` accepts the ``host_matching`` argument and sets
    it on ``Flask.url_map``. :issue:`1559`
-   ``Flask.__init__`` accepts the ``static_host`` argument and passes
    it as the ``host`` argument when defining the static route.
    :issue:`1559`
-   ``send_file`` supports Unicode in ``attachment_filename``.
    :pr:`2223`
-   Pass ``_scheme`` argument from ``url_for`` to
    ``Flask.handle_url_build_error``. :pr:`2017`
-   ``Flask.add_url_rule`` accepts the ``provide_automatic_options``
    argument to disable adding the ``OPTIONS`` method. :pr:`1489`
-   ``MethodView`` subclasses inherit method handlers from base classes.
    :pr:`1936`
-   Errors caused while opening the session at the beginning of the
    request are handled by the app's error handlers. :pr:`2254`
-   Blueprints gained ``Blueprint.json_encoder`` and
    ``Blueprint.json_decoder`` attributes to override the app's
    encoder and decoder. :pr:`1898`
-   ``Flask.make_response`` raises ``TypeError`` instead of
    ``ValueError`` for bad response types. The error messages have been
    improved to describe why the type is invalid. :pr:`2256`
-   Add ``routes`` CLI command to output routes registered on the
    application. :pr:`2259`
-   Show warning when session cookie domain is a bare hostname or an IP
    address, as these may not behave properly in some browsers, such as
    Chrome. :pr:`2282`
-   Allow IP address as exact session cookie domain. :pr:`2282`
-   ``SESSION_COOKIE_DOMAIN`` is set if it is detected through
    ``SERVER_NAME``. :pr:`2282`
-   Auto-detect zero-argument app factory called ``create_app`` or
    ``make_app`` from ``FLASK_APP``. :pr:`2297`
-   Factory functions are not required to take a ``script_info``
    parameter to work with the ``flask`` command. If they take a single
    parameter or a parameter named ``script_info``, the ``ScriptInfo``
    object will be passed. :pr:`2319`
-   ``FLASK_APP`` can be set to an app factory, with arguments if
    needed, for example ``FLASK_APP=myproject.app:create_app('dev')``.
    :pr:`2326`
-   ``FLASK_APP`` can point to local packages that are not installed in
    editable mode, although ``pip install -e`` is still preferred.
    :pr:`2414`
-   The ``View`` class attribute
    ``View.provide_automatic_options`` is set in ``View.as_view``, to be
    detected by ``Flask.add_url_rule``. :pr:`2316`
-   Error handling will try handlers registered for ``blueprint, code``,
    ``app, code``, ``blueprint, exception``, ``app, exception``.
    :pr:`2314`
-   ``Cookie`` is added to the response's ``Vary`` header if the session
    is accessed at all during the request (and not deleted). :pr:`2288`
-   ``Flask.test_request_context`` accepts ``subdomain`` and
    ``url_scheme`` arguments for use when building the base URL.
    :pr:`1621`
-   Set ``APPLICATION_ROOT`` to ``'/'`` by default. This was already the
    implicit default when it was set to ``None``.
-   ``TRAP_BAD_REQUEST_ERRORS`` is enabled by default in debug mode.
    ``BadRequestKeyError`` has a message with the bad key in debug mode
    instead of the generic bad request message. :pr:`2348`
-   Allow registering new tags with ``TaggedJSONSerializer`` to support
    storing other types in the session cookie. :pr:`2352`
-   Only open the session if the request has not been pushed onto the
    context stack yet. This allows ``stream_with_context`` generators to
    access the same session that the containing view uses. :pr:`2354`
-   Add ``json`` keyword argument for the test client request methods.
    This will dump the given object as JSON and set the appropriate
    content type. :pr:`2358`
-   Extract JSON handling to a mixin applied to both the ``Request`` and
    ``Response`` classes. This adds the ``Response.is_json`` and
    ``Response.get_json`` methods to the response to make testing JSON
    response much easier. :pr:`2358`
-   Removed error handler caching because it caused unexpected results
    for some exception inheritance hierarchies. Register handlers
    explicitly for each exception if you want to avoid traversing the
    MRO. :pr:`2362`
-   Fix incorrect JSON encoding of aware, non-UTC datetimes. :pr:`2374`
-   Template auto reloading will honor debug mode even if
    ``Flask.jinja_env`` was already accessed. :pr:`2373`
-   The following old deprecated code was removed. :issue:`2385`

    -   ``flask.ext`` - import extensions directly by their name instead
        of through the ``flask.ext`` namespace. For example,
        ``import flask.ext.sqlalchemy`` becomes
        ``import flask_sqlalchemy``.
    -   ``Flask.init_jinja_globals`` - extend
        ``Flask.create_jinja_environment`` instead.
    -   ``Flask.error_handlers`` - tracked by
        ``Flask.error_handler_spec``, use ``Flask.errorhandler``
        to register handlers.
    -   ``Flask.request_globals_class`` - use
        ``Flask.app_ctx_globals_class`` instead.
    -   ``Flask.static_path`` - use ``Flask.static_url_path`` instead.
    -   ``Request.module`` - use ``Request.blueprint`` instead.

-   The ``Request.json`` property is no longer deprecated. :issue:`1421`
-   Support passing a ``EnvironBuilder`` or ``dict`` to
    ``test_client.open``. :pr:`2412`
-   The ``flask`` command and ``Flask.run`` will load environment
    variables from ``.env`` and ``.flaskenv`` files if python-dotenv is
    installed. :pr:`2416`
-   When passing a full URL to the test client, the scheme in the URL is
    used instead of ``PREFERRED_URL_SCHEME``. :pr:`2430`
-   ``Flask.logger`` has been simplified. ``LOGGER_NAME`` and
    ``LOGGER_HANDLER_POLICY`` config was removed. The logger is always
    named ``flask.app``. The level is only set on first access, it
    doesn't check ``Flask.debug`` each time. Only one format is used,
    not different ones depending on ``Flask.debug``. No handlers are
    removed, and a handler is only added if no handlers are already
    configured. :pr:`2436`
-   Blueprint view function names may not contain dots. :pr:`2450`
-   Fix a ``ValueError`` caused by invalid ``Range`` requests in some
    cases. :issue:`2526`
-   The development server uses threads by default. :pr:`2529`
-   Loading config files with ``silent=True`` will ignore ``ENOTDIR``
    errors. :pr:`2581`
-   Pass ``--cert`` and ``--key`` options to ``flask run`` to run the
    development server over HTTPS. :pr:`2606`
-   Added ``SESSION_COOKIE_SAMESITE`` to control the ``SameSite``
    attribute on the session cookie. :pr:`2607`
-   Added ``Flask.test_cli_runner`` to create a Click runner that can
    invoke Flask CLI commands for testing. :pr:`2636`
-   Subdomain matching is disabled by default and setting
    ``SERVER_NAME`` does not implicitly enable it. It can be enabled by
    passing ``subdomain_matching=True`` to the ``Flask`` constructor.
    :pr:`2635`
-   A single trailing slash is stripped from the blueprint
    ``url_prefix`` when it is registered with the app. :pr:`2629`
-   ``Request.get_json`` doesn't cache the result if parsing fails when
    ``silent`` is true. :issue:`2651`
-   ``Request.get_json`` no longer accepts arbitrary encodings. Incoming
    JSON should be encoded using UTF-8 per :rfc:`8259`, but Flask will
    autodetect UTF-8, -16, or -32. :pr:`2691`
-   Added ``MAX_COOKIE_SIZE`` and ``Response.max_cookie_size`` to
    control when Werkzeug warns about large cookies that browsers may
    ignore. :pr:`2693`
-   Updated documentation theme to make docs look better in small
    windows. :pr:`2709`
-   Rewrote the tutorial docs and example project to take a more
    structured approach to help new users avoid common pitfalls.
    :pr:`2676`


Version 0.12.5
--------------

Released 2020-02-10

-   Pin Werkzeug to < 1.0.0. :issue:`3497`


Version 0.12.4
--------------

Released 2018-04-29

-   Repackage 0.12.3 to fix package layout issue. :issue:`2728`


Version 0.12.3
--------------

Released 2018-04-26

-   ``Request.get_json`` no longer accepts arbitrary encodings.
    Incoming JSON should be encoded using UTF-8 per :rfc:`8259`, but
    Flask will autodetect UTF-8, -16, or -32. :issue:`2692`
-   Fix a Python warning about imports when using ``python -m flask``.
    :issue:`2666`
-   Fix a ``ValueError`` caused by invalid ``Range`` requests in some
    cases.


Version 0.12.2
--------------

Released 2017-05-16

-   Fix a bug in ``safe_join`` on Windows.


Version 0.12.1
--------------

Released 2017-03-31

-   Prevent ``flask run`` from showing a ``NoAppException`` when an
    ``ImportError`` occurs within the imported application module.
-   Fix encoding behavior of ``app.config.from_pyfile`` for Python 3.
    :issue:`2118`
-   Use the ``SERVER_NAME`` config if it is present as default values
    for ``app.run``. :issue:`2109`, :pr:`2152`
-   Call ``ctx.auto_pop`` with the exception object instead of ``None``,
    in the event that a ``BaseException`` such as ``KeyboardInterrupt``
    is raised in a request handler.


Version 0.12
------------

Released 2016-12-21, codename Punsch

-   The cli command now responds to ``--version``.
-   Mimetype guessing and ETag generation for file-like objects in
    ``send_file`` has been removed. :issue:`104`, :pr`1849`
-   Mimetype guessing in ``send_file`` now fails loudly and doesn't fall
    back to ``application/octet-stream``. :pr:`1988`
-   Make ``flask.safe_join`` able to join multiple paths like
    ``os.path.join`` :pr:`1730`
-   Revert a behavior change that made the dev server crash instead of
    returning an Internal Server Error. :pr:`2006`
-   Correctly invoke response handlers for both regular request
    dispatching as well as error handlers.
-   Disable logger propagation by default for the app logger.
-   Add support for range requests in ``send_file``.
-   ``app.test_client`` includes preset default environment, which can
    now be directly set, instead of per ``client.get``.
-   Fix crash when running under PyPy3. :pr:`1814`


Version 0.11.1
--------------

Released 2016-06-07

-   Fixed a bug that prevented ``FLASK_APP=foobar/__init__.py`` from
    working. :pr:`1872`


Version 0.11
------------

Released 2016-05-29, codename Absinthe

-   Added support to serializing top-level arrays to ``jsonify``. This
    introduces a security risk in ancient browsers.
-   Added before_render_template signal.
-   Added ``**kwargs`` to ``Flask.test_client`` to support passing
    additional keyword arguments to the constructor of
    ``Flask.test_client_class``.
-   Added ``SESSION_REFRESH_EACH_REQUEST`` config key that controls the
    set-cookie behavior. If set to ``True`` a permanent session will be
    refreshed each request and get their lifetime extended, if set to
    ``False`` it will only be modified if the session actually modifies.
    Non permanent sessions are not affected by this and will always
    expire if the browser window closes.
-   Made Flask support custom JSON mimetypes for incoming data.
-   Added support for returning tuples in the form ``(response,
    headers)`` from a view function.
-   Added ``Config.from_json``.
-   Added ``Flask.config_class``.
-   Added ``Config.get_namespace``.
-   Templates are no longer automatically reloaded outside of debug
    mode. This can be configured with the new ``TEMPLATES_AUTO_RELOAD``
    config key.
-   Added a workaround for a limitation in Python 3.3's namespace
    loader.
-   Added support for explicit root paths when using Python 3.3's
    namespace packages.
-   Added ``flask`` and the ``flask.cli`` module to start the
    local debug server through the click CLI system. This is recommended
    over the old ``flask.run()`` method as it works faster and more
    reliable due to a different design and also replaces
    ``Flask-Script``.
-   Error handlers that match specific classes are now checked first,
    thereby allowing catching exceptions that are subclasses of HTTP
    exceptions (in ``werkzeug.exceptions``). This makes it possible for
    an extension author to create exceptions that will by default result
    in the HTTP error of their choosing, but may be caught with a custom
    error handler if desired.
-   Added ``Config.from_mapping``.
-   Flask will now log by default even if debug is disabled. The log
    format is now hardcoded but the default log handling can be disabled
    through the ``LOGGER_HANDLER_POLICY`` configuration key.
-   Removed deprecated module functionality.
-   Added the ``EXPLAIN_TEMPLATE_LOADING`` config flag which when
    enabled will instruct Flask to explain how it locates templates.
    This should help users debug when the wrong templates are loaded.
-   Enforce blueprint handling in the order they were registered for
    template loading.
-   Ported test suite to py.test.
-   Deprecated ``request.json`` in favour of ``request.get_json()``.
-   Add "pretty" and "compressed" separators definitions in jsonify()
    method. Reduces JSON response size when
    ``JSONIFY_PRETTYPRINT_REGULAR=False`` by removing unnecessary white
    space included by default after separators.
-   JSON responses are now terminated with a newline character, because
    it is a convention that UNIX text files end with a newline and some
    clients don't deal well when this newline is missing. :pr:`1262`
-   The automatically provided ``OPTIONS`` method is now correctly
    disabled if the user registered an overriding rule with the
    lowercase-version ``options``. :issue:`1288`
-   ``flask.json.jsonify`` now supports the ``datetime.date`` type.
    :pr:`1326`
-   Don't leak exception info of already caught exceptions to context
    teardown handlers. :pr:`1393`
-   Allow custom Jinja environment subclasses. :pr:`1422`
-   Updated extension dev guidelines.
-   ``flask.g`` now has ``pop()`` and ``setdefault`` methods.
-   Turn on autoescape for ``flask.templating.render_template_string``
    by default. :pr:`1515`
-   ``flask.ext`` is now deprecated. :pr:`1484`
-   ``send_from_directory`` now raises BadRequest if the filename is
    invalid on the server OS. :pr:`1763`
-   Added the ``JSONIFY_MIMETYPE`` configuration variable. :pr:`1728`
-   Exceptions during teardown handling will no longer leave bad
    application contexts lingering around.
-   Fixed broken ``test_appcontext_signals()`` test case.
-   Raise an ``AttributeError`` in ``helpers.find_package`` with a
    useful message explaining why it is raised when a :pep:`302` import
    hook is used without an ``is_package()`` method.
-   Fixed an issue causing exceptions raised before entering a request
    or app context to be passed to teardown handlers.
-   Fixed an issue with query parameters getting removed from requests
    in the test client when absolute URLs were requested.
-   Made ``@before_first_request`` into a decorator as intended.
-   Fixed an etags bug when sending a file streams with a name.
-   Fixed ``send_from_directory`` not expanding to the application root
    path correctly.
-   Changed logic of before first request handlers to flip the flag
    after invoking. This will allow some uses that are potentially
    dangerous but should probably be permitted.
-   Fixed Python 3 bug when a handler from
    ``app.url_build_error_handlers`` reraises the ``BuildError``.


Version 0.10.1
--------------

Released 2013-06-14

-   Fixed an issue where ``|tojson`` was not quoting single quotes which
    made the filter not work properly in HTML attributes. Now it's
    possible to use that filter in single quoted attributes. This should
    make using that filter with angular.js easier.
-   Added support for byte strings back to the session system. This
    broke compatibility with the common case of people putting binary
    data for token verification into the session.
-   Fixed an issue where registering the same method twice for the same
    endpoint would trigger an exception incorrectly.


Version 0.10
------------

Released 2013-06-13, codename Limoncello

-   Changed default cookie serialization format from pickle to JSON to
    limit the impact an attacker can do if the secret key leaks.
-   Added ``template_test`` methods in addition to the already existing
    ``template_filter`` method family.
-   Added ``template_global`` methods in addition to the already
    existing ``template_filter`` method family.
-   Set the content-length header for x-sendfile.
-   ``tojson`` filter now does not escape script blocks in HTML5
    parsers.
-   ``tojson`` used in templates is now safe by default. This was
    allowed due to the different escaping behavior.
-   Flask will now raise an error if you attempt to register a new
    function on an already used endpoint.
-   Added wrapper module around simplejson and added default
    serialization of datetime objects. This allows much easier
    customization of how JSON is handled by Flask or any Flask
    extension.
-   Removed deprecated internal ``flask.session`` module alias. Use
    ``flask.sessions`` instead to get the session module. This is not to
    be confused with ``flask.session`` the session proxy.
-   Templates can now be rendered without request context. The behavior
    is slightly different as the ``request``, ``session`` and ``g``
    objects will not be available and blueprint's context processors are
    not called.
-   The config object is now available to the template as a real global
    and not through a context processor which makes it available even in
    imported templates by default.
-   Added an option to generate non-ascii encoded JSON which should
    result in less bytes being transmitted over the network. It's
    disabled by default to not cause confusion with existing libraries
    that might expect ``flask.json.dumps`` to return bytes by default.
-   ``flask.g`` is now stored on the app context instead of the request
    context.
-   ``flask.g`` now gained a ``get()`` method for not erroring out on
    non existing items.
-   ``flask.g`` now can be used with the ``in`` operator to see what's
    defined and it now is iterable and will yield all attributes stored.
-   ``flask.Flask.request_globals_class`` got renamed to
    ``flask.Flask.app_ctx_globals_class`` which is a better name to what
    it does since 0.10.
-   ``request``, ``session`` and ``g`` are now also added as proxies to
    the template context which makes them available in imported
    templates. One has to be very careful with those though because
    usage outside of macros might cause caching.
-   Flask will no longer invoke the wrong error handlers if a proxy
    exception is passed through.
-   Added a workaround for chrome's cookies in localhost not working as
    intended with domain names.
-   Changed logic for picking defaults for cookie values from sessions
    to work better with Google Chrome.
-   Added ``message_flashed`` signal that simplifies flashing testing.
-   Added support for copying of request contexts for better working
    with greenlets.
-   Removed custom JSON HTTP exception subclasses. If you were relying
    on them you can reintroduce them again yourself trivially. Using
    them however is strongly discouraged as the interface was flawed.
-   Python requirements changed: requiring Python 2.6 or 2.7 now to
    prepare for Python 3.3 port.
-   Changed how the teardown system is informed about exceptions. This
    is now more reliable in case something handles an exception halfway
    through the error handling process.
-   Request context preservation in debug mode now keeps the exception
    information around which means that teardown handlers are able to
    distinguish error from success cases.
-   Added the ``JSONIFY_PRETTYPRINT_REGULAR`` configuration variable.
-   Flask now orders JSON keys by default to not trash HTTP caches due
    to different hash seeds between different workers.
-   Added ``appcontext_pushed`` and ``appcontext_popped`` signals.
-   The builtin run method now takes the ``SERVER_NAME`` into account
    when picking the default port to run on.
-   Added ``flask.request.get_json()`` as a replacement for the old
    ``flask.request.json`` property.


Version 0.9
-----------

Released 2012-07-01, codename Campari

-   The ``Request.on_json_loading_failed`` now returns a JSON formatted
    response by default.
-   The ``url_for`` function now can generate anchors to the generated
    links.
-   The ``url_for`` function now can also explicitly generate URL rules
    specific to a given HTTP method.
-   Logger now only returns the debug log setting if it was not set
    explicitly.
-   Unregister a circular dependency between the WSGI environment and
    the request object when shutting down the request. This means that
    environ ``werkzeug.request`` will be ``None`` after the response was
    returned to the WSGI server but has the advantage that the garbage
    collector is not needed on CPython to tear down the request unless
    the user created circular dependencies themselves.
-   Session is now stored after callbacks so that if the session payload
    is stored in the session you can still modify it in an after request
    callback.
-   The ``Flask`` class will avoid importing the provided import name if
    it can (the required first parameter), to benefit tools which build
    Flask instances programmatically. The Flask class will fall back to
    using import on systems with custom module hooks, e.g. Google App
    Engine, or when the import name is inside a zip archive (usually an
    egg) prior to Python 2.7.
-   Blueprints now have a decorator to add custom template filters
    application wide, ``Blueprint.app_template_filter``.
-   The Flask and Blueprint classes now have a non-decorator method for
    adding custom template filters application wide,
    ``Flask.add_template_filter`` and
    ``Blueprint.add_app_template_filter``.
-   The ``get_flashed_messages`` function now allows rendering flashed
    message categories in separate blocks, through a ``category_filter``
    argument.
-   The ``Flask.run`` method now accepts ``None`` for ``host`` and
    ``port`` arguments, using default values when ``None``. This allows
    for calling run using configuration values, e.g.
    ``app.run(app.config.get('MYHOST'), app.config.get('MYPORT'))``,
    with proper behavior whether or not a config file is provided.
-   The ``render_template`` method now accepts a either an iterable of
    template names or a single template name. Previously, it only
    accepted a single template name. On an iterable, the first template
    found is rendered.
-   Added ``Flask.app_context`` which works very similar to the request
    context but only provides access to the current application. This
    also adds support for URL generation without an active request
    context.
-   View functions can now return a tuple with the first instance being
    an instance of ``Response``. This allows for returning
    ``jsonify(error="error msg"), 400`` from a view function.
-   ``Flask`` and ``Blueprint`` now provide a ``get_send_file_max_age``
    hook for subclasses to override behavior of serving static files
    from Flask when using ``Flask.send_static_file`` (used for the
    default static file handler) and ``helpers.send_file``. This hook is
    provided a filename, which for example allows changing cache
    controls by file extension. The default max-age for ``send_file``
    and static files can be configured through a new
    ``SEND_FILE_MAX_AGE_DEFAULT`` configuration variable, which is used
    in the default ``get_send_file_max_age`` implementation.
-   Fixed an assumption in sessions implementation which could break
    message flashing on sessions implementations which use external
    storage.
-   Changed the behavior of tuple return values from functions. They are
    no longer arguments to the response object, they now have a defined
    meaning.
-   Added ``Flask.request_globals_class`` to allow a specific class to
    be used on creation of the ``g`` instance of each request.
-   Added ``required_methods`` attribute to view functions to force-add
    methods on registration.
-   Added ``flask.after_this_request``.
-   Added ``flask.stream_with_context`` and the ability to push contexts
    multiple times without producing unexpected behavior.


Version 0.8.1
-------------

Released 2012-07-01

-   Fixed an issue with the undocumented ``flask.session`` module to not
    work properly on Python 2.5. It should not be used but did cause
    some problems for package managers.


Version 0.8
-----------

Released 2011-09-29, codename Rakija

-   Refactored session support into a session interface so that the
    implementation of the sessions can be changed without having to
    override the Flask class.
-   Empty session cookies are now deleted properly automatically.
-   View functions can now opt out of getting the automatic OPTIONS
    implementation.
-   HTTP exceptions and Bad Request errors can now be trapped so that
    they show up normally in the traceback.
-   Flask in debug mode is now detecting some common problems and tries
    to warn you about them.
-   Flask in debug mode will now complain with an assertion error if a
    view was attached after the first request was handled. This gives
    earlier feedback when users forget to import view code ahead of
    time.
-   Added the ability to register callbacks that are only triggered once
    at the beginning of the first request with
    ``Flask.before_first_request``.
-   Malformed JSON data will now trigger a bad request HTTP exception
    instead of a value error which usually would result in a 500
    internal server error if not handled. This is a backwards
    incompatible change.
-   Applications now not only have a root path where the resources and
    modules are located but also an instance path which is the
    designated place to drop files that are modified at runtime (uploads
    etc.). Also this is conceptually only instance depending and outside
    version control so it's the perfect place to put configuration files
    etc.
-   Added the ``APPLICATION_ROOT`` configuration variable.
-   Implemented ``TestClient.session_transaction`` to easily modify
    sessions from the test environment.
-   Refactored test client internally. The ``APPLICATION_ROOT``
    configuration variable as well as ``SERVER_NAME`` are now properly
    used by the test client as defaults.
-   Added ``View.decorators`` to support simpler decorating of pluggable
    (class-based) views.
-   Fixed an issue where the test client if used with the "with"
    statement did not trigger the execution of the teardown handlers.
-   Added finer control over the session cookie parameters.
-   HEAD requests to a method view now automatically dispatch to the
    ``get`` method if no handler was implemented.
-   Implemented the virtual ``flask.ext`` package to import extensions
    from.
-   The context preservation on exceptions is now an integral component
    of Flask itself and no longer of the test client. This cleaned up
    some internal logic and lowers the odds of runaway request contexts
    in unittests.
-   Fixed the Jinja environment's ``list_templates`` method not
    returning the correct names when blueprints or modules were
    involved.


Version 0.7.2
-------------

Released 2011-07-06

-   Fixed an issue with URL processors not properly working on
    blueprints.


Version 0.7.1
-------------

Released 2011-06-29

-   Added missing future import that broke 2.5 compatibility.
-   Fixed an infinite redirect issue with blueprints.


Version 0.7
-----------

Released 2011-06-28, codename Grappa

-   Added ``Flask.make_default_options_response`` which can be used by
    subclasses to alter the default behavior for ``OPTIONS`` responses.
-   Unbound locals now raise a proper ``RuntimeError`` instead of an
    ``AttributeError``.
-   Mimetype guessing and etag support based on file objects is now
    deprecated for ``send_file`` because it was unreliable. Pass
    filenames instead or attach your own etags and provide a proper
    mimetype by hand.
-   Static file handling for modules now requires the name of the static
    folder to be supplied explicitly. The previous autodetection was not
    reliable and caused issues on Google's App Engine. Until 1.0 the old
    behavior will continue to work but issue dependency warnings.
-   Fixed a problem for Flask to run on jython.
-   Added a ``PROPAGATE_EXCEPTIONS`` configuration variable that can be
    used to flip the setting of exception propagation which previously
    was linked to ``DEBUG`` alone and is now linked to either ``DEBUG``
    or ``TESTING``.
-   Flask no longer internally depends on rules being added through the
    ``add_url_rule`` function and can now also accept regular werkzeug
    rules added to the url map.
-   Added an ``endpoint`` method to the flask application object which
    allows one to register a callback to an arbitrary endpoint with a
    decorator.
-   Use Last-Modified for static file sending instead of Date which was
    incorrectly introduced in 0.6.
-   Added ``create_jinja_loader`` to override the loader creation
    process.
-   Implemented a silent flag for ``config.from_pyfile``.
-   Added ``teardown_request`` decorator, for functions that should run
    at the end of a request regardless of whether an exception occurred.
    Also the behavior for ``after_request`` was changed. It's now no
    longer executed when an exception is raised.
-   Implemented ``has_request_context``.
-   Deprecated ``init_jinja_globals``. Override the
    ``Flask.create_jinja_environment`` method instead to achieve the
    same functionality.
-   Added ``safe_join``.
-   The automatic JSON request data unpacking now looks at the charset
    mimetype parameter.
-   Don't modify the session on ``get_flashed_messages`` if there are no
    messages in the session.
-   ``before_request`` handlers are now able to abort requests with
    errors.
-   It is not possible to define user exception handlers. That way you
    can provide custom error messages from a central hub for certain
    errors that might occur during request processing (for instance
    database connection errors, timeouts from remote resources etc.).
-   Blueprints can provide blueprint specific error handlers.
-   Implemented generic class-based views.


Version 0.6.1
-------------

Released 2010-12-31

-   Fixed an issue where the default ``OPTIONS`` response was not
    exposing all valid methods in the ``Allow`` header.
-   Jinja template loading syntax now allows "./" in front of a
    template load path. Previously this caused issues with module
    setups.
-   Fixed an issue where the subdomain setting for modules was ignored
    for the static folder.
-   Fixed a security problem that allowed clients to download arbitrary
    files if the host server was a windows based operating system and
    the client uses backslashes to escape the directory the files where
    exposed from.


Version 0.6
-----------

Released 2010-07-27, codename Whisky

-   After request functions are now called in reverse order of
    registration.
-   OPTIONS is now automatically implemented by Flask unless the
    application explicitly adds 'OPTIONS' as method to the URL rule. In
    this case no automatic OPTIONS handling kicks in.
-   Static rules are now even in place if there is no static folder for
    the module. This was implemented to aid GAE which will remove the
    static folder if it's part of a mapping in the .yml file.
-   ``Flask.config`` is now available in the templates as ``config``.
-   Context processors will no longer override values passed directly to
    the render function.
-   Added the ability to limit the incoming request data with the new
    ``MAX_CONTENT_LENGTH`` configuration value.
-   The endpoint for the ``Module.add_url_rule`` method is now optional
    to be consistent with the function of the same name on the
    application object.
-   Added a ``make_response`` function that simplifies creating response
    object instances in views.
-   Added signalling support based on blinker. This feature is currently
    optional and supposed to be used by extensions and applications. If
    you want to use it, make sure to have ``blinker`` installed.
-   Refactored the way URL adapters are created. This process is now
    fully customizable with the ``Flask.create_url_adapter`` method.
-   Modules can now register for a subdomain instead of just an URL
    prefix. This makes it possible to bind a whole module to a
    configurable subdomain.


Version 0.5.2
-------------

Released 2010-07-15

-   Fixed another issue with loading templates from directories when
    modules were used.


Version 0.5.1
-------------

Released 2010-07-06

-   Fixes an issue with template loading from directories when modules
    where used.


Version 0.5
-----------

Released 2010-07-06, codename Calvados

-   Fixed a bug with subdomains that was caused by the inability to
    specify the server name. The server name can now be set with the
    ``SERVER_NAME`` config key. This key is now also used to set the
    session cookie cross-subdomain wide.
-   Autoescaping is no longer active for all templates. Instead it is
    only active for ``.html``, ``.htm``, ``.xml`` and ``.xhtml``. Inside
    templates this behavior can be changed with the ``autoescape`` tag.
-   Refactored Flask internally. It now consists of more than a single
    file.
-   ``send_file`` now emits etags and has the ability to do conditional
    responses builtin.
-   (temporarily) dropped support for zipped applications. This was a
    rarely used feature and led to some confusing behavior.
-   Added support for per-package template and static-file directories.
-   Removed support for ``create_jinja_loader`` which is no longer used
    in 0.5 due to the improved module support.
-   Added a helper function to expose files from any directory.


Version 0.4
-----------

Released 2010-06-18, codename Rakia

-   Added the ability to register application wide error handlers from
    modules.
-   ``Flask.after_request`` handlers are now also invoked if the request
    dies with an exception and an error handling page kicks in.
-   Test client has not the ability to preserve the request context for
    a little longer. This can also be used to trigger custom requests
    that do not pop the request stack for testing.
-   Because the Python standard library caches loggers, the name of the
    logger is configurable now to better support unittests.
-   Added ``TESTING`` switch that can activate unittesting helpers.
-   The logger switches to ``DEBUG`` mode now if debug is enabled.


Version 0.3.1
-------------

Released 2010-05-28

-   Fixed a error reporting bug with ``Config.from_envvar``.
-   Removed some unused code.
-   Release does no longer include development leftover files (.git
    folder for themes, built documentation in zip and pdf file and some
    .pyc files)


Version 0.3
-----------

Released 2010-05-28, codename Schnaps

-   Added support for categories for flashed messages.
-   The application now configures a ``logging.Handler`` and will log
    request handling exceptions to that logger when not in debug mode.
    This makes it possible to receive mails on server errors for
    example.
-   Added support for context binding that does not require the use of
    the with statement for playing in the console.
-   The request context is now available within the with statement
    making it possible to further push the request context or pop it.
-   Added support for configurations.


Version 0.2
-----------

Released 2010-05-12, codename J?germeister

-   Various bugfixes
-   Integrated JSON support
-   Added ``get_template_attribute`` helper function.
-   ``Flask.add_url_rule`` can now also register a view function.
-   Refactored internal request dispatching.
-   Server listens on 127.0.0.1 by default now to fix issues with
    chrome.
-   Added external URL support.
-   Added support for ``send_file``.
-   Module support and internal request handling refactoring to better
    support pluggable applications.
-   Sessions can be set to be permanent now on a per-session basis.
-   Better error reporting on missing secret keys.
-   Added support for Google Appengine.


Version 0.1
-----------

Released 2010-04-16

-   First public preview release.


================================================
FILE: LICENSE.txt
================================================
Copyright 2010 Pallets

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

1.  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

2.  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

3.  Neither the name of the copyright holder nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
<div align="center"><img src="https://raw.githubusercontent.com/pallets/flask/refs/heads/stable/docs/_static/flask-name.svg" alt="" height="150"></div>

# Flask

Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.

Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.

[WSGI]: https://wsgi.readthedocs.io/
[Werkzeug]: https://werkzeug.palletsprojects.com/
[Jinja]: https://jinja.palletsprojects.com/

## A Simple Example

```python
# save this as app.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"
```

```
$ flask run
  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

## Donate

The Pallets organization develops and supports Flask and the libraries
it uses. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today].

[please donate today]: https://palletsprojects.com/donate

## Contributing

See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.

[contrib]: https://palletsprojects.com/contributing/


================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)


================================================
FILE: docs/api.rst
================================================
API
===

.. module:: flask

This part of the documentation covers all the interfaces of Flask. For
parts where Flask depends on external libraries, we document the most
important right here and provide links to the canonical documentation.


Application Object
------------------

.. autoclass:: Flask
   :members:
   :inherited-members:


Blueprint Objects
-----------------

.. autoclass:: Blueprint
   :members:
   :inherited-members:

Incoming Request Data
---------------------

.. autoclass:: Request
    :members:
    :inherited-members:
    :exclude-members: json_module

.. data:: request

    A proxy to the request data for the current request, an instance of
    :class:`.Request`.

    This is only available when a :doc:`request context </appcontext>` is
    active.

    This is a proxy. See :ref:`context-visibility` for more information.


Response Objects
----------------

.. autoclass:: flask.Response
    :members:
    :inherited-members:
    :exclude-members: json_module

Sessions
--------

If you have set :attr:`Flask.secret_key` (or configured it from
:data:`SECRET_KEY`) you can use sessions in Flask applications. A session makes
it possible to remember information from one request to another. The way Flask
does this is by using a signed cookie. The user can look at the session
contents, but can't modify it unless they know the secret key, so make sure to
set that to something complex and unguessable.

To access the current session you can use the :data:`.session` proxy.

.. data:: session

    A proxy to the session data for the current request, an instance of
    :class:`.SessionMixin`.

    This is only available when a :doc:`request context </appcontext>` is
    active.

    This is a proxy. See :ref:`context-visibility` for more information.

    The session object works like a dict but tracks assignment and access to its
    keys. It cannot track modifications to mutable values, you need to set
    :attr:`~.SessionMixin.modified` manually when modifying a list, dict, etc.

    .. code-block:: python

          # appending to a list is not detected
          session["numbers"].append(42)
          # so mark it as modified yourself
          session.modified = True

    The session is persisted across requests using a cookie. By default the
    users's browser will clear the cookie when it is closed. Set
    :attr:`~.SessionMixin.permanent` to ``True`` to persist the cookie for
    :data:`PERMANENT_SESSION_LIFETIME`.


Session Interface
-----------------

.. versionadded:: 0.8

The session interface provides a simple way to replace the session
implementation that Flask is using.

.. currentmodule:: flask.sessions

.. autoclass:: SessionInterface
   :members:

.. autoclass:: SecureCookieSessionInterface
   :members:

.. autoclass:: SecureCookieSession
   :members:

.. autoclass:: NullSession
   :members:

.. autoclass:: SessionMixin
   :members:

.. admonition:: Notice

    The :data:`PERMANENT_SESSION_LIFETIME` config can be an integer or ``timedelta``.
    The :attr:`~flask.Flask.permanent_session_lifetime` attribute is always a
    ``timedelta``.


Test Client
-----------

.. currentmodule:: flask.testing

.. autoclass:: FlaskClient
   :members:


Test CLI Runner
---------------

.. currentmodule:: flask.testing

.. autoclass:: FlaskCliRunner
    :members:


Application Globals
-------------------

.. currentmodule:: flask

To share data that is valid for one request only from one function to
another, a global variable is not good enough because it would break in
threaded environments. Flask provides you with a special object that
ensures it is only valid for the active request and that will return
different values for each request. In a nutshell: it does the right
thing, like it does for :data:`.request` and :data:`.session`.

.. data:: g

    A proxy to a namespace object used to store data during a single request or
    app context. An instance of :attr:`.Flask.app_ctx_globals_class`, which
    defaults to :class:`._AppCtxGlobals`.

    This is a good place to store resources during a request. For example, a
    :meth:`~.Flask.before_request` function could load a user object from a
    session id, then set ``g.user`` to be used in the view function.

    This is only available when an :doc:`app context </appcontext>` is active.

    This is a proxy. See :ref:`context-visibility` for more information.

    .. versionchanged:: 0.10
        Bound to the application context instead of the request context.

.. autoclass:: flask.ctx._AppCtxGlobals
    :members:


Useful Functions and Classes
----------------------------

.. data:: current_app

    A proxy to the :class:`.Flask` application handling the current request or
    other activity.

    This is useful to access the application without needing to import it, or if
    it can't be imported, such as when using the application factory pattern or
    in blueprints and extensions.

    This is only available when an :doc:`app context </appcontext>` is active.

    This is a proxy. See :ref:`context-visibility` for more information.

.. autofunction:: has_request_context

.. autofunction:: copy_current_request_context

.. autofunction:: has_app_context

.. autofunction:: url_for

.. autofunction:: abort

.. autofunction:: redirect

.. autofunction:: make_response

.. autofunction:: after_this_request

.. autofunction:: send_file

.. autofunction:: send_from_directory


Message Flashing
----------------

.. autofunction:: flash

.. autofunction:: get_flashed_messages


JSON Support
------------

.. module:: flask.json

Flask uses Python's built-in :mod:`json` module for handling JSON by
default. The JSON implementation can be changed by assigning a different
provider to :attr:`flask.Flask.json_provider_class` or
:attr:`flask.Flask.json`. The functions provided by ``flask.json`` will
use methods on ``app.json`` if an app context is active.

Jinja's ``|tojson`` filter is configured to use the app's JSON provider.
The filter marks the output with ``|safe``. Use it to render data inside
HTML ``<script>`` tags.

.. sourcecode:: html+jinja

    <script>
        const names = {{ names|tojson }};
        renderChart(names, {{ axis_data|tojson }});
    </script>

.. autofunction:: jsonify

.. autofunction:: dumps

.. autofunction:: dump

.. autofunction:: loads

.. autofunction:: load

.. autoclass:: flask.json.provider.JSONProvider
    :members:
    :member-order: bysource

.. autoclass:: flask.json.provider.DefaultJSONProvider
    :members:
    :member-order: bysource

.. automodule:: flask.json.tag


Template Rendering
------------------

.. currentmodule:: flask

.. autofunction:: render_template

.. autofunction:: render_template_string

.. autofunction:: stream_template

.. autofunction:: stream_template_string

.. autofunction:: get_template_attribute

Configuration
-------------

.. autoclass:: Config
   :members:


Stream Helpers
--------------

.. autofunction:: stream_with_context

Useful Internals
----------------

.. autoclass:: flask.ctx.AppContext
   :members:

.. data:: flask.globals.app_ctx

    A proxy to the active :class:`.AppContext`.

    This is an internal object that is essential to how Flask handles requests.
    Accessing this should not be needed in most cases. Most likely you want
    :data:`.current_app`, :data:`.g`, :data:`.request`, and :data:`.session` instead.

    This is only available when a :doc:`request context </appcontext>` is
    active.

    This is a proxy. See :ref:`context-visibility` for more information.

.. class:: flask.ctx.RequestContext

    .. deprecated:: 3.2
        Merged with :class:`AppContext`. This alias will be removed in Flask 4.0.

.. data:: flask.globals.request_ctx

    .. deprecated:: 3.2
        Merged with :data:`.app_ctx`. This alias will be removed in Flask 4.0.

.. autoclass:: flask.blueprints.BlueprintSetupState
   :members:

.. _core-signals-list:

Signals
-------

Signals are provided by the `Blinker`_ library. See :doc:`signals` for an introduction.

.. _blinker: https://blinker.readthedocs.io/

.. data:: template_rendered

   This signal is sent when a template was successfully rendered. The
   signal is invoked with the instance of the template as `template`
   and the context as dictionary (named `context`).

   Example subscriber::

        def log_template_renders(sender, template, context, **extra):
            sender.logger.debug('Rendering template "%s" with context %s',
                                template.name or 'string template',
                                context)

        from flask import template_rendered
        template_rendered.connect(log_template_renders, app)

.. data:: flask.before_render_template
   :noindex:

   This signal is sent before template rendering process. The
   signal is invoked with the instance of the template as `template`
   and the context as dictionary (named `context`).

   Example subscriber::

        def log_template_renders(sender, template, context, **extra):
            sender.logger.debug('Rendering template "%s" with context %s',
                                template.name or 'string template',
                                context)

        from flask import before_render_template
        before_render_template.connect(log_template_renders, app)

.. data:: request_started

   This signal is sent when the request context is set up, before
   any request processing happens. Because the request context is already
   bound, the subscriber can access the request with the standard global
   proxies such as :class:`~flask.request`.

   Example subscriber::

        def log_request(sender, **extra):
            sender.logger.debug('Request context is set up')

        from flask import request_started
        request_started.connect(log_request, app)

.. data:: request_finished

   This signal is sent right before the response is sent to the client.
   It is passed the response to be sent named `response`.

   Example subscriber::

        def log_response(sender, response, **extra):
            sender.logger.debug('Request context is about to close down. '
                                'Response: %s', response)

        from flask import request_finished
        request_finished.connect(log_response, app)

.. data:: got_request_exception

    This signal is sent when an unhandled exception happens during
    request processing, including when debugging. The exception is
    passed to the subscriber as ``exception``.

    This signal is not sent for
    :exc:`~werkzeug.exceptions.HTTPException`, or other exceptions that
    have error handlers registered, unless the exception was raised from
    an error handler.

    This example shows how to do some extra logging if a theoretical
    ``SecurityException`` was raised:

    .. code-block:: python

        from flask import got_request_exception

        def log_security_exception(sender, exception, **extra):
            if not isinstance(exception, SecurityException):
                return

            security_logger.exception(
                f"SecurityException at {request.url!r}",
                exc_info=exception,
            )

        got_request_exception.connect(log_security_exception, app)

.. data:: request_tearing_down

   This signal is sent when the request is tearing down. This is always
   called, even if an exception is caused. Currently functions listening
   to this signal are called after the regular teardown handlers, but this
   is not something you can rely on.

   Example subscriber::

        def close_db_connection(sender, **extra):
            session.close()

        from flask import request_tearing_down
        request_tearing_down.connect(close_db_connection, app)

   As of Flask 0.9, this will also be passed an `exc` keyword argument
   that has a reference to the exception that caused the teardown if
   there was one.

.. data:: appcontext_tearing_down

   This signal is sent when the app context is tearing down. This is always
   called, even if an exception is caused. Currently functions listening
   to this signal are called after the regular teardown handlers, but this
   is not something you can rely on.

   Example subscriber::

        def close_db_connection(sender, **extra):
            session.close()

        from flask import appcontext_tearing_down
        appcontext_tearing_down.connect(close_db_connection, app)

   This will also be passed an `exc` keyword argument that has a reference
   to the exception that caused the teardown if there was one.

.. data:: appcontext_pushed

   This signal is sent when an application context is pushed. The sender
   is the application. This is usually useful for unittests in order to
   temporarily hook in information. For instance it can be used to
   set a resource early onto the `g` object.

   Example usage::

        from contextlib import contextmanager
        from flask import appcontext_pushed

        @contextmanager
        def user_set(app, user):
            def handler(sender, **kwargs):
                g.user = user
            with appcontext_pushed.connected_to(handler, app):
                yield

   And in the testcode::

        def test_user_me(self):
            with user_set(app, 'john'):
                c = app.test_client()
                resp = c.get('/users/me')
                assert resp.data == 'username=john'

   .. versionadded:: 0.10

.. data:: appcontext_popped

   This signal is sent when an application context is popped. The sender
   is the application. This usually falls in line with the
   :data:`appcontext_tearing_down` signal.

   .. versionadded:: 0.10

.. data:: message_flashed

   This signal is sent when the application is flashing a message. The
   messages is sent as `message` keyword argument and the category as
   `category`.

   Example subscriber::

        recorded = []
        def record(sender, message, category, **extra):
            recorded.append((message, category))

        from flask import message_flashed
        message_flashed.connect(record, app)

   .. versionadded:: 0.10


Class-Based Views
-----------------

.. versionadded:: 0.7

.. currentmodule:: None

.. autoclass:: flask.views.View
   :members:

.. autoclass:: flask.views.MethodView
   :members:

.. _url-route-registrations:

URL Route Registrations
-----------------------

Generally there are three ways to define rules for the routing system:

1.  You can use the :meth:`flask.Flask.route` decorator.
2.  You can use the :meth:`flask.Flask.add_url_rule` function.
3.  You can directly access the underlying Werkzeug routing system
    which is exposed as :attr:`flask.Flask.url_map`.

Variable parts in the route can be specified with angular brackets
(``/user/<username>``). By default a variable part in the URL accepts any
string without a slash however a different converter can be specified as
well by using ``<converter:name>``.

Variable parts are passed to the view function as keyword arguments.

The following converters are available:

=========== ===============================================
`string`    accepts any text without a slash (the default)
`int`       accepts integers
`float`     like `int` but for floating point values
`path`      like the default but also accepts slashes
`any`       matches one of the items provided
`uuid`      accepts UUID strings
=========== ===============================================

Custom converters can be defined using :attr:`flask.Flask.url_map`.

Here are some examples::

    @app.route('/')
    def index():
        pass

    @app.route('/<username>')
    def show_user(username):
        pass

    @app.route('/post/<int:post_id>')
    def show_post(post_id):
        pass

An important detail to keep in mind is how Flask deals with trailing
slashes. The idea is to keep each URL unique so the following rules
apply:

1. If a rule ends with a slash and is requested without a slash by the
   user, the user is automatically redirected to the same page with a
   trailing slash attached.
2. If a rule does not end with a trailing slash and the user requests the
   page with a trailing slash, a 404 not found is raised.

This is consistent with how web servers deal with static files. This
also makes it possible to use relative link targets safely.

You can also define multiple rules for the same function. They have to be
unique however. Defaults can also be specified. Here for example is a
definition for a URL that accepts an optional page::

    @app.route('/users/', defaults={'page': 1})
    @app.route('/users/page/<int:page>')
    def show_users(page):
        pass

This specifies that ``/users/`` will be the URL for page one and
``/users/page/N`` will be the URL for page ``N``.

If a URL contains a default value, it will be redirected to its simpler
form with a 308 redirect. In the above example, ``/users/page/1`` will
be redirected to ``/users/``. If your route handles ``GET`` and ``POST``
requests, make sure the default route only handles ``GET``, as redirects
can't preserve form data. ::

   @app.route('/region/', defaults={'id': 1})
   @app.route('/region/<int:id>', methods=['GET', 'POST'])
   def region(id):
      pass

Here are the parameters that :meth:`~flask.Flask.route` and
:meth:`~flask.Flask.add_url_rule` accept. The only difference is that
with the route parameter the view function is defined with the decorator
instead of the `view_func` parameter.

=============== ==========================================================
`rule`          the URL rule as string
`endpoint`      the endpoint for the registered URL rule. Flask itself
                assumes that the name of the view function is the name
                of the endpoint if not explicitly stated.
`view_func`     the function to call when serving a request to the
                provided endpoint. If this is not provided one can
                specify the function later by storing it in the
                :attr:`~flask.Flask.view_functions` dictionary with the
                endpoint as key.
`defaults`      A dictionary with defaults for this rule. See the
                example above for how defaults work.
`subdomain`     specifies the rule for the subdomain in case subdomain
                matching is in use. If not specified the default
                subdomain is assumed.
`**options`     the options to be forwarded to the underlying
                :class:`~werkzeug.routing.Rule` object. A change to
                Werkzeug is handling of method options. methods is a list
                of methods this rule should be limited to (``GET``, ``POST``
                etc.). By default a rule just listens for ``GET`` (and
                implicitly ``HEAD``). Starting with Flask 0.6, ``OPTIONS`` is
                implicitly added and handled by the standard request
                handling. They have to be specified as keyword arguments.
=============== ==========================================================


View Function Options
---------------------

For internal usage the view functions can have some attributes attached to
customize behavior the view function would normally not have control over.
The following attributes can be provided optionally to either override
some defaults to :meth:`~flask.Flask.add_url_rule` or general behavior:

-   `__name__`: The name of a function is by default used as endpoint. If
    endpoint is provided explicitly this value is used. Additionally this
    will be prefixed with the name of the blueprint by default which
    cannot be customized from the function itself.

-   `methods`: If methods are not provided when the URL rule is added,
    Flask will look on the view function object itself if a `methods`
    attribute exists. If it does, it will pull the information for the
    methods from there.

-   `provide_automatic_options`: if this attribute is set Flask will
    either force enable or disable the automatic implementation of the
    HTTP ``OPTIONS`` response. This can be useful when working with
    decorators that want to customize the ``OPTIONS`` response on a per-view
    basis.

-   `required_methods`: if this attribute is set, Flask will always add
    these methods when registering a URL rule even if the methods were
    explicitly overridden in the ``route()`` call.

Full example::

    def index():
        if request.method == 'OPTIONS':
            # custom options handling here
            ...
        return 'Hello World!'
    index.provide_automatic_options = False
    index.methods = ['GET', 'OPTIONS']

    app.add_url_rule('/', index)

.. versionadded:: 0.8
   The `provide_automatic_options` functionality was added.

Command Line Interface
----------------------

.. currentmodule:: flask.cli

.. autoclass:: FlaskGroup
   :members:

.. autoclass:: AppGroup
   :members:

.. autoclass:: ScriptInfo
   :members:

.. autofunction:: load_dotenv

.. autofunction:: with_appcontext

.. autofunction:: pass_script_info

   Marks a function so that an instance of :class:`ScriptInfo` is passed
   as first argument to the click callback.

.. autodata:: run_command

.. autodata:: shell_command


================================================
FILE: docs/appcontext.rst
================================================
The App and Request Context
===========================

The context keeps track of data and objects during a request, CLI command, or
other activity. Rather than passing this data around to every function, the
:data:`.current_app`, :data:`.g`, :data:`.request`, and :data:`.session` proxies
are accessed instead.

When handling a request, the context is referred to as the "request context"
because it contains request data in addition to application data. Otherwise,
such as during a CLI command, it is referred to as the "app context". During an
app context, :data:`.current_app` and :data:`.g` are available, while during a
request context :data:`.request` and :data:`.session` are also available.


Purpose of the Context
----------------------

The context and proxies help solve two development issues: circular imports, and
passing around global data during a request.

The :class:`.Flask` application object has attributes, such as
:attr:`~.Flask.config`, that are useful to access within views and other
functions. However, importing the ``app`` instance within the modules in your
project is prone to circular import issues. When using the
:doc:`app factory pattern </patterns/appfactories>` or writing reusable
:doc:`blueprints </blueprints>` or :doc:`extensions </extensions>` there won't
be an ``app`` instance to import at all.

When the application handles a request, it creates a :class:`.Request` object.
Because a *worker* handles only one request at a time, the request data can be
considered global to that worker during that request. Passing it as an argument
through every function during the request becomes verbose and redundant.

Flask solves these issues with the *active context* pattern. Rather than
importing an ``app`` directly, or having to pass it and the request through to
every single function, you import and access the proxies, which point to the
currently active application and request data. This is sometimes referred to
as "context local" data.


Context During Setup
--------------------

If you try to access :data:`.current_app`, :data:`.g`, or anything that uses it,
outside an app context, you'll get this error message:

.. code-block:: pytb

    RuntimeError: Working outside of application context.

    Attempted to use functionality that expected a current application to be
    set. To solve this, set up an app context using 'with app.app_context()'.
    See the documentation on app context for more information.

If you see that error while configuring your application, such as when
initializing an extension, you can push a context manually since you have direct
access to the ``app``. Use :meth:`.Flask.app_context` in a ``with`` block.

.. code-block:: python

    def create_app():
        app = Flask(__name__)

        with app.app_context():
            init_db()

        return app

If you see that error somewhere else in your code not related to setting up the
application, it most likely indicates that you should move that code into a view
function or CLI command.


Context During Testing
----------------------

See :doc:`/testing` for detailed information about managing the context during
tests.

If you try to access :data:`.request`, :data:`.session`, or anything that uses
it, outside a request context, you'll get this error message:

.. code-block:: pytb

    RuntimeError: Working outside of request context.

    Attempted to use functionality that expected an active HTTP request. See the
    documentation on request context for more information.

This will probably only happen during tests. If you see that error somewhere
else in your code not related to testing, it most likely indicates that you
should move that code into a view function.

The primary way to solve this is to use :meth:`.Flask.test_client` to simulate
a full request.

If you only want to unit test one function, rather than a full request, use
:meth:`.Flask.test_request_context` in a ``with`` block.

.. code-block:: python

    def generate_report(year):
        format = request.args.get("format")
        ...

    with app.test_request_context(
        "/make_report/2017", query_string={"format": "short"}
    ):
        generate_report()


.. _context-visibility:

Visibility of the Context
-------------------------

The context will have the same lifetime as an activity, such as a request, CLI
command, or ``with`` block. Various callbacks and signals registered with the
app will be run during the context.

When a Flask application handles a request, it pushes a request context
to set the active application and request data. When it handles a CLI command,
it pushes an app context to set the active application. When the activity ends,
it pops that context. Proxy objects like :data:`.request`, :data:`.session`,
:data:`.g`, and :data:`.current_app`, are accessible while the context is pushed
and active, and are not accessible after the context is popped.

The context is unique to each thread (or other worker type). The proxies cannot
be passed to another worker, which has a different context space and will not
know about the active context in the parent's space.

Besides being scoped to each worker, the proxy object has a separate type and
identity than the proxied real object. In some cases you'll need access to the
real object, rather than the proxy. Use the
:meth:`~.LocalProxy._get_current_object` method in those cases.

.. code-block:: python

    app = current_app._get_current_object()
    my_signal.send(app)


Lifecycle of the Context
------------------------

Flask dispatches a request in multiple stages which can affect the request,
response, and how errors are handled. See :doc:`/lifecycle` for a list of all
the steps, callbacks, and signals during each request. The following are the
steps directly related to the context.

-   The app context is pushed, the proxies are available.
-   The :data:`.appcontext_pushed` signal is sent.
-   The request is dispatched.
-   Any :meth:`.Flask.teardown_request` decorated functions are called.
-   The :data:`.request_tearing_down` signal is sent.
-   Any :meth:`.Flask.teardown_appcontext` decorated functions are called.
-   The :data:`.appcontext_tearing_down` signal is sent.
-   The app context is popped, the proxies are no longer available.
-   The :data:`.appcontext_popped` signal is sent.

The teardown callbacks are called by the context when it is popped. They are
called even if there is an unhandled exception during dispatch. They may be
called multiple times in some test scenarios. This means there is no guarantee
that any other parts of the request dispatch have run. Be sure to write these
functions in a way that does not depend on other callbacks. All callbacks are
called even if any raise an error.


How the Context Works
---------------------

Context locals are implemented using Python's :mod:`contextvars` and Werkzeug's
:class:`~werkzeug.local.LocalProxy`. Python's contextvars are a low level
structure to manage data local to a thread or coroutine. ``LocalProxy`` wraps
the contextvar so that access to any attributes and methods is forwarded to the
object stored in the contextvar.

The context is tracked like a stack, with the active context at the top of the
stack. Flask manages pushing and popping contexts during requests, CLI commands,
testing, ``with`` blocks, etc. The proxies access attributes on the active
context.

Because it is a stack, other contexts may be pushed to change the proxies during
an already active context. This is not a common pattern, but can be used in
advanced use cases. For example, a Flask application can be used as WSGI
middleware, calling another wrapped Flask app from a view.


================================================
FILE: docs/async-await.rst
================================================
.. _async_await:

Using ``async`` and ``await``
=============================

.. versionadded:: 2.0

Routes, error handlers, before request, after request, and teardown
functions can all be coroutine functions if Flask is installed with the
``async`` extra (``pip install flask[async]``). This allows views to be
defined with ``async def`` and use ``await``.

.. code-block:: python

    @app.route("/get-data")
    async def get_data():
        data = await async_db_query(...)
        return jsonify(data)

Pluggable class-based views also support handlers that are implemented as
coroutines. This applies to the :meth:`~flask.views.View.dispatch_request`
method in views that inherit from the :class:`flask.views.View` class, as
well as all the HTTP method handlers in views that inherit from the
:class:`flask.views.MethodView` class.


Performance
-----------

Async functions require an event loop to run. Flask, as a WSGI
application, uses one worker to handle one request/response cycle.
When a request comes in to an async view, Flask will start an event loop
in a thread, run the view function there, then return the result.

Each request still ties up one worker, even for async views. The upside
is that you can run async code within a view, for example to make
multiple concurrent database queries, HTTP requests to an external API,
etc. However, the number of requests your application can handle at one
time will remain the same.

**Async is not inherently faster than sync code.** Async is beneficial
when performing concurrent IO-bound tasks, but will probably not improve
CPU-bound tasks. Traditional Flask views will still be appropriate for
most use cases, but Flask's async support enables writing and using
code that wasn't possible natively before.


Background tasks
----------------

Async functions will run in an event loop until they complete, at
which stage the event loop will stop. This means any additional
spawned tasks that haven't completed when the async function completes
will be cancelled. Therefore you cannot spawn background tasks, for
example via ``asyncio.create_task``.

If you wish to use background tasks it is best to use a task queue to
trigger background work, rather than spawn tasks in a view
function. With that in mind you can spawn asyncio tasks by serving
Flask with an ASGI server and utilising the asgiref WsgiToAsgi adapter
as described in :doc:`deploying/asgi`. This works as the adapter creates
an event loop that runs continually.


When to use Quart instead
-------------------------

Flask's async support is less performant than async-first frameworks due
to the way it is implemented. If you have a mainly async codebase it
would make sense to consider `Quart`_. Quart is a reimplementation of
Flask based on the `ASGI`_ standard instead of WSGI. This allows it to
handle many concurrent requests, long running requests, and websockets
without requiring multiple worker processes or threads.

It has also already been possible to :doc:`run Flask with Gevent </gevent>` to
get many of the benefits of async request handling. Gevent patches low-level
Python functions to accomplish this, whereas ``async``/``await`` and ASGI use
standard, modern Python capabilities. Deciding whether you should use gevent
with Flask, or Quart, or something else is ultimately up to understanding the
specific needs of your project.

.. _Quart: https://quart.palletsprojects.com
.. _ASGI: https://asgi.readthedocs.io


Extensions
----------

Flask extensions predating Flask's async support do not expect async views.
If they provide decorators to add functionality to views, those will probably
not work with async views because they will not await the function or be
awaitable. Other functions they provide will not be awaitable either and
will probably be blocking if called within an async view.

Extension authors can support async functions by utilising the
:meth:`flask.Flask.ensure_sync` method. For example, if the extension
provides a view function decorator add ``ensure_sync`` before calling
the decorated function,

.. code-block:: python

    def extension(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            ...  # Extension logic
            return current_app.ensure_sync(func)(*args, **kwargs)

        return wrapper

Check the changelog of the extension you want to use to see if they've
implemented async support, or make a feature request or PR to them.


Other event loops
-----------------

At the moment Flask only supports :mod:`asyncio`. It's possible to override
:meth:`flask.Flask.ensure_sync` to change how async functions are wrapped to use
a different library. See :ref:`gevent-asyncio` for an example.


================================================
FILE: docs/blueprints.rst
================================================
Modular Applications with Blueprints
====================================

.. currentmodule:: flask

.. versionadded:: 0.7

Flask uses a concept of *blueprints* for making application components and
supporting common patterns within an application or across applications.
Blueprints can greatly simplify how large applications work and provide a
central means for Flask extensions to register operations on applications.
A :class:`Blueprint` object works similarly to a :class:`Flask`
application object, but it is not actually an application.  Rather it is a
*blueprint* of how to construct or extend an application.

Why Blueprints?
---------------

Blueprints in Flask are intended for these cases:

* Factor an application into a set of blueprints.  This is ideal for
  larger applications; a project could instantiate an application object,
  initialize several extensions, and register a collection of blueprints.
* Register a blueprint on an application at a URL prefix and/or subdomain.
  Parameters in the URL prefix/subdomain become common view arguments
  (with defaults) across all view functions in the blueprint.
* Register a blueprint multiple times on an application with different URL
  rules.
* Provide template filters, static files, templates, and other utilities
  through blueprints.  A blueprint does not have to implement applications
  or view functions.
* Register a blueprint on an application for any of these cases when
  initializing a Flask extension.

A blueprint in Flask is not a pluggable app because it is not actually an
application -- it's a set of operations which can be registered on an
application, even multiple times.  Why not have multiple application
objects?  You can do that (see :doc:`/patterns/appdispatch`), but your
applications will have separate configs and will be managed at the WSGI
layer.

Blueprints instead provide separation at the Flask level, share
application config, and can change an application object as necessary with
being registered. The downside is that you cannot unregister a blueprint
once an application was created without having to destroy the whole
application object.

The Concept of Blueprints
-------------------------

The basic concept of blueprints is that they record operations to execute
when registered on an application.  Flask associates view functions with
blueprints when dispatching requests and generating URLs from one endpoint
to another.

My First Blueprint
------------------

This is what a very basic blueprint looks like.  In this case we want to
implement a blueprint that does simple rendering of static templates::

    from flask import Blueprint, render_template, abort
    from jinja2 import TemplateNotFound

    simple_page = Blueprint('simple_page', __name__,
                            template_folder='templates')

    @simple_page.route('/', defaults={'page': 'index'})
    @simple_page.route('/<page>')
    def show(page):
        try:
            return render_template(f'pages/{page}.html')
        except TemplateNotFound:
            abort(404)

When you bind a function with the help of the ``@simple_page.route``
decorator, the blueprint will record the intention of registering the
function ``show`` on the application when it's later registered.
Additionally it will prefix the endpoint of the function with the
name of the blueprint which was given to the :class:`Blueprint`
constructor (in this case also ``simple_page``). The blueprint's name
does not modify the URL, only the endpoint.

Registering Blueprints
----------------------

So how do you register that blueprint?  Like this::

    from flask import Flask
    from yourapplication.simple_page import simple_page

    app = Flask(__name__)
    app.register_blueprint(simple_page)

If you check the rules registered on the application, you will find
these::

    >>> app.url_map
    Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
     <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
     <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>])

The first one is obviously from the application itself for the static
files.  The other two are for the `show` function of the ``simple_page``
blueprint.  As you can see, they are also prefixed with the name of the
blueprint and separated by a dot (``.``).

Blueprints however can also be mounted at different locations::

    app.register_blueprint(simple_page, url_prefix='/pages')

And sure enough, these are the generated rules::

    >>> app.url_map
    Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
     <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
     <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>])

On top of that you can register blueprints multiple times though not every
blueprint might respond properly to that.  In fact it depends on how the
blueprint is implemented if it can be mounted more than once.

Nesting Blueprints
------------------

It is possible to register a blueprint on another blueprint.

.. code-block:: python

    parent = Blueprint('parent', __name__, url_prefix='/parent')
    child = Blueprint('child', __name__, url_prefix='/child')
    parent.register_blueprint(child)
    app.register_blueprint(parent)

The child blueprint will gain the parent's name as a prefix to its
name, and child URLs will be prefixed with the parent's URL prefix.

.. code-block:: python

    url_for('parent.child.create')
    /parent/child/create

In addition a child blueprint's will gain their parent's subdomain,
with their subdomain as prefix if present i.e.

.. code-block:: python

    parent = Blueprint('parent', __name__, subdomain='parent')
    child = Blueprint('child', __name__, subdomain='child')
    parent.register_blueprint(child)
    app.register_blueprint(parent)

    url_for('parent.child.create', _external=True)
    "child.parent.domain.tld"

Blueprint-specific before request functions, etc. registered with the
parent will trigger for the child. If a child does not have an error
handler that can handle a given exception, the parent's will be tried.


Blueprint Resources
-------------------

Blueprints can provide resources as well.  Sometimes you might want to
introduce a blueprint only for the resources it provides.

Blueprint Resource Folder
`````````````````````````

Like for regular applications, blueprints are considered to be contained
in a folder.  While multiple blueprints can originate from the same folder,
it does not have to be the case and it's usually not recommended.

The folder is inferred from the second argument to :class:`Blueprint` which
is usually `__name__`.  This argument specifies what logical Python
module or package corresponds to the blueprint.  If it points to an actual
Python package that package (which is a folder on the filesystem) is the
resource folder.  If it's a module, the package the module is contained in
will be the resource folder.  You can access the
:attr:`Blueprint.root_path` property to see what the resource folder is::

    >>> simple_page.root_path
    '/Users/username/TestProject/yourapplication'

To quickly open sources from this folder you can use the
:meth:`~Blueprint.open_resource` function::

    with simple_page.open_resource('static/style.css') as f:
        code = f.read()

Static Files
````````````

A blueprint can expose a folder with static files by providing the path
to the folder on the filesystem with the ``static_folder`` argument.
It is either an absolute path or relative to the blueprint's location::

    admin = Blueprint('admin', __name__, static_folder='static')

By default the rightmost part of the path is where it is exposed on the
web. This can be changed with the ``static_url_path`` argument. Because the
folder is called ``static`` here it will be available at the
``url_prefix`` of the blueprint + ``/static``. If the blueprint
has the prefix ``/admin``, the static URL will be ``/admin/static``.

The endpoint is named ``blueprint_name.static``. You can generate URLs
to it with :func:`url_for` like you would with the static folder of the
application::

    url_for('admin.static', filename='style.css')

However, if the blueprint does not have a ``url_prefix``, it is not
possible to access the blueprint's static folder. This is because the
URL would be ``/static`` in this case, and the application's ``/static``
route takes precedence. Unlike template folders, blueprint static
folders are not searched if the file does not exist in the application
static folder.

Templates
`````````

If you want the blueprint to expose templates you can do that by providing
the `template_folder` parameter to the :class:`Blueprint` constructor::

    admin = Blueprint('admin', __name__, template_folder='templates')

For static files, the path can be absolute or relative to the blueprint
resource folder.

The template folder is added to the search path of templates but with a lower
priority than the actual application's template folder. That way you can
easily override templates that a blueprint provides in the actual application.
This also means that if you don't want a blueprint template to be accidentally
overridden, make sure that no other blueprint or actual application template
has the same relative path. When multiple blueprints provide the same relative
template path the first blueprint registered takes precedence over the others.


So if you have a blueprint in the folder ``yourapplication/admin`` and you
want to render the template ``'admin/index.html'`` and you have provided
``templates`` as a `template_folder` you will have to create a file like
this: :file:`yourapplication/admin/templates/admin/index.html`. The reason
for the extra ``admin`` folder is to avoid getting our template overridden
by a template named ``index.html`` in the actual application template
folder.

To further reiterate this: if you have a blueprint named ``admin`` and you
want to render a template called :file:`index.html` which is specific to this
blueprint, the best idea is to lay out your templates like this::

    yourpackage/
        blueprints/
            admin/
                templates/
                    admin/
                        index.html
                __init__.py

And then when you want to render the template, use :file:`admin/index.html` as
the name to look up the template by.  If you encounter problems loading
the correct templates enable the ``EXPLAIN_TEMPLATE_LOADING`` config
variable which will instruct Flask to print out the steps it goes through
to locate templates on every ``render_template`` call.

Building URLs
-------------

If you want to link from one page to another you can use the
:func:`url_for` function just like you normally would do just that you
prefix the URL endpoint with the name of the blueprint and a dot (``.``)::

    url_for('admin.index')

Additionally if you are in a view function of a blueprint or a rendered
template and you want to link to another endpoint of the same blueprint,
you can use relative redirects by prefixing the endpoint with a dot only::

    url_for('.index')

This will link to ``admin.index`` for instance in case the current request
was dispatched to any other admin blueprint endpoint.


Blueprint Error Handlers
------------------------

Blueprints support the ``errorhandler`` decorator just like the :class:`Flask`
application object, so it is easy to make Blueprint-specific custom error
pages.

Here is an example for a "404 Page Not Found" exception::

    @simple_page.errorhandler(404)
    def page_not_found(e):
        return render_template('pages/404.html')

Most errorhandlers will simply work as expected; however, there is a caveat
concerning handlers for 404 and 405 exceptions.  These errorhandlers are only
invoked from an appropriate ``raise`` statement or a call to ``abort`` in another
of the blueprint's view functions; they are not invoked by, e.g., an invalid URL
access.  This is because the blueprint does not "own" a certain URL space, so
the application instance has no way of knowing which blueprint error handler it
should run if given an invalid URL.  If you would like to execute different
handling strategies for these errors based on URL prefixes, they may be defined
at the application level using the ``request`` proxy object::

    @app.errorhandler(404)
    @app.errorhandler(405)
    def _handle_api_error(ex):
        if request.path.startswith('/api/'):
            return jsonify(error=str(ex)), ex.code
        else:
            return ex

See :doc:`/errorhandling`.


================================================
FILE: docs/changes.rst
================================================
Changes
=======

.. include:: ../CHANGES.rst


================================================
FILE: docs/cli.rst
================================================
.. currentmodule:: flask

Command Line Interface
======================

Installing Flask installs the ``flask`` script, a `Click`_ command line
interface, in your virtualenv. Executed from the terminal, this script gives
access to built-in, extension, and application-defined commands. The ``--help``
option will give more information about any commands and options.

.. _Click: https://click.palletsprojects.com/


Application Discovery
---------------------

The ``flask`` command is installed by Flask, not your application; it must be
told where to find your application in order to use it. The ``--app``
option is used to specify how to load the application.

While ``--app`` supports a variety of options for specifying your
application, most use cases should be simple. Here are the typical values:

(nothing)
    The name "app" or "wsgi" is imported (as a ".py" file, or package),
    automatically detecting an app (``app`` or ``application``) or
    factory (``create_app`` or ``make_app``).

``--app hello``
    The given name is imported, automatically detecting an app (``app``
    or ``application``) or factory (``create_app`` or ``make_app``).

----

``--app`` has three parts: an optional path that sets the current working
directory, a Python file or dotted import path, and an optional variable
name of the instance or factory. If the name is a factory, it can optionally
be followed by arguments in parentheses. The following values demonstrate these
parts:

``--app src/hello``
    Sets the current working directory to ``src`` then imports ``hello``.

``--app hello.web``
    Imports the path ``hello.web``.

``--app hello:app2``
    Uses the ``app2`` Flask instance in ``hello``.

``--app 'hello:create_app("dev")'``
    The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
    as the argument.

If ``--app`` is not set, the command will try to import "app" or
"wsgi" (as a ".py" file, or package) and try to detect an application
instance or factory.

Within the given import, the command looks for an application instance named
``app`` or ``application``, then any application instance. If no instance is
found, the command looks for a factory function named ``create_app`` or
``make_app`` that returns an instance.

If parentheses follow the factory name, their contents are parsed as
Python literals and passed as arguments and keyword arguments to the
function. This means that strings must still be in quotes.


Run the Development Server
--------------------------

The :func:`run <cli.run_command>` command will start the development server. It
replaces the :meth:`Flask.run` method in most cases. ::

    $ flask --app hello run
     * Serving Flask app "hello"
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

.. warning:: Do not use this command to run your application in production.
    Only use the development server during development. The development server
    is provided for convenience, but is not designed to be particularly secure,
    stable, or efficient. See :doc:`/deploying/index` for how to run in production.

If another program is already using port 5000, you'll see
``OSError: [Errno 98]`` or ``OSError: [WinError 10013]`` when the
server tries to start. See :ref:`address-already-in-use` for how to
handle that.


Debug Mode
~~~~~~~~~~

In debug mode, the ``flask run`` command will enable the interactive debugger and the
reloader by default, and make errors easier to see and debug. To enable debug mode, use
the ``--debug`` option.

.. code-block:: console

     $ flask --app hello run --debug
      * Serving Flask app "hello"
      * Debug mode: on
      * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
      * Restarting with inotify reloader
      * Debugger is active!
      * Debugger PIN: 223-456-919

The ``--debug`` option can also be passed to the top level ``flask`` command to enable
debug mode for any command. The following two ``run`` calls are equivalent.

.. code-block:: console

    $ flask --app hello --debug run
    $ flask --app hello run --debug


Watch and Ignore Files with the Reloader
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When using debug mode, the reloader will trigger whenever your Python code or imported
modules change. The reloader can watch additional files with the ``--extra-files``
option. Multiple paths are separated with ``:``, or ``;`` on Windows.

.. code-block:: text

    $ flask run --extra-files file1:dirA/file2:dirB/
     * Running on http://127.0.0.1:8000/
     * Detected change in '/path/to/file1', reloading

The reloader can also ignore files using :mod:`fnmatch` patterns with the
``--exclude-patterns`` option. Multiple patterns are separated with ``:``, or ``;`` on
Windows.


Open a Shell
------------

To explore the data in your application, you can start an interactive Python
shell with the :func:`shell <cli.shell_command>` command. An application
context will be active, and the app instance will be imported. ::

    $ flask shell
    Python 3.10.0 (default, Oct 27 2021, 06:59:51) [GCC 11.1.0] on linux
    App: example [production]
    Instance: /home/david/Projects/pallets/flask/instance
    >>>

Use :meth:`~Flask.shell_context_processor` to add other automatic imports.


.. _dotenv:

Environment Variables From dotenv
---------------------------------

The ``flask`` command supports setting any option for any command with
environment variables. The variables are named like ``FLASK_OPTION`` or
``FLASK_COMMAND_OPTION``, for example ``FLASK_APP`` or
``FLASK_RUN_PORT``.

Rather than passing options every time you run a command, or environment
variables every time you open a new terminal, you can use Flask's dotenv
support to set environment variables automatically.

If `python-dotenv`_ is installed, running the ``flask`` command will set
environment variables defined in the files ``.env`` and ``.flaskenv``.
You can also specify an extra file to load with the ``--env-file``
option. Dotenv files can be used to avoid having to set ``--app`` or
``FLASK_APP`` manually, and to set configuration using environment
variables similar to how some deployment services work.

Variables set on the command line are used over those set in :file:`.env`,
which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
used for public variables, such as ``FLASK_APP``, while :file:`.env` should not
be committed to your repository so that it can set private variables.

Directories are scanned upwards from the directory you call ``flask``
from to locate the files.

The files are only loaded by the ``flask`` command or calling
:meth:`~Flask.run`. If you would like to load these files when running in
production, you should call :func:`~cli.load_dotenv` manually.

.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme


Setting Command Options
~~~~~~~~~~~~~~~~~~~~~~~

Click is configured to load default values for command options from
environment variables. The variables use the pattern
``FLASK_COMMAND_OPTION``. For example, to set the port for the run
command, instead of ``flask run --port 8000``:

.. tabs::

   .. group-tab:: Bash

      .. code-block:: text

         $ export FLASK_RUN_PORT=8000
         $ flask run
          * Running on http://127.0.0.1:8000/

   .. group-tab:: Fish

      .. code-block:: text

         $ set -x FLASK_RUN_PORT 8000
         $ flask run
          * Running on http://127.0.0.1:8000/

   .. group-tab:: CMD

      .. code-block:: text

         > set FLASK_RUN_PORT=8000
         > flask run
          * Running on http://127.0.0.1:8000/

   .. group-tab:: Powershell

      .. code-block:: text

         > $env:FLASK_RUN_PORT = 8000
         > flask run
          * Running on http://127.0.0.1:8000/

These can be added to the ``.flaskenv`` file just like ``FLASK_APP`` to
control default command options.


Disable dotenv
~~~~~~~~~~~~~~

The ``flask`` command will show a message if it detects dotenv files but
python-dotenv is not installed.

.. code-block:: bash

    $ flask run
     * Tip: There are .env files present. Do "pip install python-dotenv" to use them.

You can tell Flask not to load dotenv files even when python-dotenv is
installed by setting the ``FLASK_SKIP_DOTENV`` environment variable.
This can be useful if you want to load them manually, or if you're using
a project runner that loads them already. Keep in mind that the
environment variables must be set before the app loads or it won't
configure as expected.

.. tabs::

   .. group-tab:: Bash

      .. code-block:: text

         $ export FLASK_SKIP_DOTENV=1
         $ flask run

   .. group-tab:: Fish

      .. code-block:: text

         $ set -x FLASK_SKIP_DOTENV 1
         $ flask run

   .. group-tab:: CMD

      .. code-block:: text

         > set FLASK_SKIP_DOTENV=1
         > flask run

   .. group-tab:: Powershell

      .. code-block:: text

         > $env:FLASK_SKIP_DOTENV = 1
         > flask run


Environment Variables From virtualenv
-------------------------------------

If you do not want to install dotenv support, you can still set environment
variables by adding them to the end of the virtualenv's :file:`activate`
script. Activating the virtualenv will set the variables.

.. tabs::

   .. group-tab:: Bash

      Unix Bash, :file:`.venv/bin/activate`::

          $ export FLASK_APP=hello

   .. group-tab:: Fish

      Fish, :file:`.venv/bin/activate.fish`::

          $ set -x FLASK_APP hello

   .. group-tab:: CMD

      Windows CMD, :file:`.venv\\Scripts\\activate.bat`::

          > set FLASK_APP=hello

   .. group-tab:: Powershell

      Windows Powershell, :file:`.venv\\Scripts\\activate.ps1`::

          > $env:FLASK_APP = "hello"

It is preferred to use dotenv support over this, since :file:`.flaskenv` can be
committed to the repository so that it works automatically wherever the project
is checked out.


Custom Commands
---------------

The ``flask`` command is implemented using `Click`_. See that project's
documentation for full information about writing commands.

This example adds the command ``create-user`` that takes the argument
``name``. ::

    import click
    from flask import Flask

    app = Flask(__name__)

    @app.cli.command("create-user")
    @click.argument("name")
    def create_user(name):
        ...

::

    $ flask create-user admin

This example adds the same command, but as ``user create``, a command in a
group. This is useful if you want to organize multiple related commands. ::

    import click
    from flask import Flask
    from flask.cli import AppGroup

    app = Flask(__name__)
    user_cli = AppGroup('user')

    @user_cli.command('create')
    @click.argument('name')
    def create_user(name):
        ...

    app.cli.add_command(user_cli)

::

    $ flask user create demo

See :ref:`testing-cli` for an overview of how to test your custom
commands.


Registering Commands with Blueprints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If your application uses blueprints, you can optionally register CLI
commands directly onto them. When your blueprint is registered onto your
application, the associated commands will be available to the ``flask``
command. By default, those commands will be nested in a group matching
the name of the blueprint.

.. code-block:: python

    from flask import Blueprint

    bp = Blueprint('students', __name__)

    @bp.cli.command('create')
    @click.argument('name')
    def create(name):
        ...

    app.register_blueprint(bp)

.. code-block:: text

    $ flask students create alice

You can alter the group name by specifying the ``cli_group`` parameter
when creating the :class:`Blueprint` object, or later with
:meth:`app.register_blueprint(bp, cli_group='...') <Flask.register_blueprint>`.
The following are equivalent:

.. code-block:: python

    bp = Blueprint('students', __name__, cli_group='other')
    # or
    app.register_blueprint(bp, cli_group='other')

.. code-block:: text

    $ flask other create alice

Specifying ``cli_group=None`` will remove the nesting and merge the
commands directly to the application's level:

.. code-block:: python

    bp = Blueprint('students', __name__, cli_group=None)
    # or
    app.register_blueprint(bp, cli_group=None)

.. code-block:: text

    $ flask create alice


Application Context
~~~~~~~~~~~~~~~~~~~

Commands added using the Flask app's :attr:`~Flask.cli` or
:class:`~flask.cli.FlaskGroup` :meth:`~cli.AppGroup.command` decorator
will be executed with an application context pushed, so your custom
commands and parameters have access to the app and its configuration. The
:func:`~cli.with_appcontext` decorator can be used to get the same
behavior, but is not needed in most cases.

.. code-block:: python

    import click
    from flask.cli import with_appcontext

    @click.command()
    @with_appcontext
    def do_work():
        ...

    app.cli.add_command(do_work)


Plugins
-------

Flask will automatically load commands specified in the ``flask.commands``
`entry point`_. This is useful for extensions that want to add commands when
they are installed. Entry points are specified in :file:`pyproject.toml`:

.. code-block:: toml

    [project.entry-points."flask.commands"]
    my-command = "my_extension.commands:cli"

.. _entry point: https://packaging.python.org/tutorials/packaging-projects/#entry-points

Inside :file:`my_extension/commands.py` you can then export a Click
object::

    import click

    @click.command()
    def cli():
        ...

Once that package is installed in the same virtualenv as your Flask project,
you can run ``flask my-command`` to invoke the command.


.. _custom-scripts:

Custom Scripts
--------------

When you are using the app factory pattern, it may be more convenient to define
your own Click script. Instead of using ``--app`` and letting Flask load
your application, you can create your own Click object and export it as a
`console script`_ entry point.

Create an instance of :class:`~cli.FlaskGroup` and pass it the factory::

    import click
    from flask import Flask
    from flask.cli import FlaskGroup

    def create_app():
        app = Flask('wiki')
        # other setup
        return app

    @click.group(cls=FlaskGroup, create_app=create_app)
    def cli():
        """Management script for the Wiki application."""

Define the entry point in :file:`pyproject.toml`:

.. code-block:: toml

    [project.scripts]
    wiki = "wiki:cli"

Install the application in the virtualenv in editable mode and the custom
script is available. Note that you don't need to set ``--app``. ::

    $ pip install -e .
    $ wiki run

.. admonition:: Errors in Custom Scripts

    When using a custom script, if you introduce an error in your
    module-level code, the reloader will fail because it can no longer
    load the entry point.

    The ``flask`` command, being separate from your code, does not have
    this issue and is recommended in most cases.

.. _console script: https://packaging.python.org/tutorials/packaging-projects/#console-scripts


PyCharm Integration
-------------------

PyCharm Professional provides a special Flask run configuration to run the development
server. For the Community Edition, and for other commands besides ``run``, you need to
create a custom run configuration. These instructions should be similar for any other
IDE you use.

In PyCharm, with your project open, click on *Run* from the menu bar and go to *Edit
Configurations*. You'll see a screen similar to this:

.. image:: _static/pycharm-run-config.png
    :align: center
    :class: screenshot
    :alt: Screenshot of PyCharm run configuration.

Once you create a configuration for the ``flask run``, you can copy and change it to
call any other command.

Click the *+ (Add New Configuration)* button and select *Python*. Give the configuration
a name such as "flask run".

Click the *Script path* dropdown and change it to *Module name*, then input ``flask``.

The *Parameters* field is set to the CLI command to execute along with any arguments.
This example uses ``--app hello run --debug``, which will run the development server in
debug mode. ``--app hello`` should be the import or file with your Flask app.

If you installed your project as a package in your virtualenv, you may uncheck the
*PYTHONPATH* options. This will more accurately match how you deploy later.

Click *OK* to save and close the configuration. Select the configuration in the main
PyCharm window and click the play button next to it to run the server.

Now that you have a configuration for ``flask run``, you can copy that configuration and
change the *Parameters* argument to run a different CLI command.


================================================
FILE: docs/conf.py
================================================
import packaging.version
from pallets_sphinx_themes import get_version
from pallets_sphinx_themes import ProjectLink

# Project --------------------------------------------------------------

project = "Flask"
copyright = "2010 Pallets"
author = "Pallets"
release, version = get_version("Flask")

# General --------------------------------------------------------------

default_role = "code"
extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.extlinks",
    "sphinx.ext.intersphinx",
    "sphinxcontrib.log_cabinet",
    "sphinx_tabs.tabs",
    "pallets_sphinx_themes",
]
autodoc_member_order = "bysource"
autodoc_typehints = "description"
autodoc_preserve_defaults = True
extlinks = {
    "issue": ("https://github.com/pallets/flask/issues/%s", "#%s"),
    "pr": ("https://github.com/pallets/flask/pull/%s", "#%s"),
    "ghsa": ("https://github.com/pallets/flask/security/advisories/GHSA-%s", "GHSA-%s"),
}
intersphinx_mapping = {
    "python": ("https://docs.python.org/3/", None),
    "werkzeug": ("https://werkzeug.palletsprojects.com/", None),
    "click": ("https://click.palletsprojects.com/", None),
    "jinja": ("https://jinja.palletsprojects.com/", None),
    "itsdangerous": ("https://itsdangerous.palletsprojects.com/", None),
    "sqlalchemy": ("https://docs.sqlalchemy.org/", None),
    "wtforms": ("https://wtforms.readthedocs.io/", None),
    "blinker": ("https://blinker.readthedocs.io/", None),
}

# HTML -----------------------------------------------------------------

html_theme = "flask"
html_theme_options = {"index_sidebar_logo": False}
html_context = {
    "project_links": [
        ProjectLink("Donate", "https://palletsprojects.com/donate"),
        ProjectLink("PyPI Releases", "https://pypi.org/project/Flask/"),
        ProjectLink("Source Code", "https://github.com/pallets/flask/"),
        ProjectLink("Issue Tracker", "https://github.com/pallets/flask/issues/"),
        ProjectLink("Chat", "https://discord.gg/pallets"),
    ]
}
html_sidebars = {
    "index": ["project.html", "localtoc.html", "searchbox.html", "ethicalads.html"],
    "**": ["localtoc.html", "relations.html", "searchbox.html", "ethicalads.html"],
}
singlehtml_sidebars = {"index": ["project.html", "localtoc.html", "ethicalads.html"]}
html_static_path = ["_static"]
html_favicon = "_static/flask-icon.svg"
html_logo = "_static/flask-logo.svg"
html_title = f"Flask Documentation ({version})"
html_show_sourcelink = False

gettext_uuid = True
gettext_compact = False

# Local Extensions -----------------------------------------------------


def github_link(name, rawtext, text, lineno, inliner, options=None, content=None):
    app = inliner.document.settings.env.app
    release = app.config.release
    base_url = "https://github.com/pallets/flask/tree/"

    if text.endswith(">"):
        words, text = text[:-1].rsplit("<", 1)
        words = words.strip()
    else:
        words = None

    if packaging.version.parse(release).is_devrelease:
        url = f"{base_url}main/{text}"
    else:
        url = f"{base_url}{release}/{text}"

    if words is None:
        words = url

    from docutils.nodes import reference
    from docutils.parsers.rst.roles import set_classes

    options = options or {}
    set_classes(options)
    node = reference(rawtext, words, refuri=url, **options)
    return [node], []


def setup(app):
    app.add_role("gh", github_link)


================================================
FILE: docs/config.rst
================================================
Configuration Handling
======================

Applications need some kind of configuration.  There are different settings
you might want to change depending on the application environment like
toggling the debug mode, setting the secret key, and other such
environment-specific things.

The way Flask is designed usually requires the configuration to be
available when the application starts up.  You can hard code the
configuration in the code, which for many small applications is not
actually that bad, but there are better ways.

Independent of how you load your config, there is a config object
available which holds the loaded configuration values:
The :attr:`~flask.Flask.config` attribute of the :class:`~flask.Flask`
object.  This is the place where Flask itself puts certain configuration
values and also where extensions can put their configuration values.  But
this is also where you can have your own configuration.


Configuration Basics
--------------------

The :attr:`~flask.Flask.config` is actually a subclass of a dictionary and
can be modified just like any dictionary::

    app = Flask(__name__)
    app.config['TESTING'] = True

Certain configuration values are also forwarded to the
:attr:`~flask.Flask` object so you can read and write them from there::

    app.testing = True

To update multiple keys at once you can use the :meth:`dict.update`
method::

    app.config.update(
        TESTING=True,
        SECRET_KEY='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
    )


Debug Mode
----------

The :data:`DEBUG` config value is special because it may behave inconsistently if
changed after the app has begun setting up. In order to set debug mode reliably, use the
``--debug`` option on the ``flask`` or ``flask run`` command. ``flask run`` will use the
interactive debugger and reloader by default in debug mode.

.. code-block:: text

    $ flask --app hello run --debug

Using the option is recommended. While it is possible to set :data:`DEBUG` in your
config or code, this is strongly discouraged. It can't be read early by the
``flask run`` command, and some systems or extensions may have already configured
themselves based on a previous value.


Builtin Configuration Values
----------------------------

The following configuration values are used internally by Flask:

.. py:data:: DEBUG

    Whether debug mode is enabled. When using ``flask run`` to start the development
    server, an interactive debugger will be shown for unhandled exceptions, and the
    server will be reloaded when code changes. The :attr:`~flask.Flask.debug` attribute
    maps to this config key. This is set with the ``FLASK_DEBUG`` environment variable.
    It may not behave as expected if set in code.

    **Do not enable debug mode when deploying in production.**

    Default: ``False``

.. py:data:: TESTING

    Enable testing mode. Exceptions are propagated rather than handled by the
    the app's error handlers. Extensions may also change their behavior to
    facilitate easier testing. You should enable this in your own tests.

    Default: ``False``

.. py:data:: PROPAGATE_EXCEPTIONS

    Exceptions are re-raised rather than being handled by the app's error
    handlers. If not set, this is implicitly true if ``TESTING`` or ``DEBUG``
    is enabled.

    Default: ``None``

.. py:data:: TRAP_HTTP_EXCEPTIONS

    If there is no handler for an ``HTTPException``-type exception, re-raise it
    to be handled by the interactive debugger instead of returning it as a
    simple error response.

    Default: ``False``

.. py:data:: TRAP_BAD_REQUEST_ERRORS

    Trying to access a key that doesn't exist from request dicts like ``args``
    and ``form`` will return a 400 Bad Request error page. Enable this to treat
    the error as an unhandled exception instead so that you get the interactive
    debugger. This is a more specific version of ``TRAP_HTTP_EXCEPTIONS``. If
    unset, it is enabled in debug mode.

    Default: ``None``

.. py:data:: SECRET_KEY

    A secret key that will be used for securely signing the session cookie
    and can be used for any other security related needs by extensions or your
    application. It should be a long random ``bytes`` or ``str``. For
    example, copy the output of this to your config::

        $ python -c 'import secrets; print(secrets.token_hex())'
        '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

    **Do not reveal the secret key when posting questions or committing code.**

    Default: ``None``

.. py:data:: SECRET_KEY_FALLBACKS

    A list of old secret keys that can still be used for unsigning. This allows
    a project to implement key rotation without invalidating active sessions or
    other recently-signed secrets.

    Keys should be removed after an appropriate period of time, as checking each
    additional key adds some overhead.

    Order should not matter, but the default implementation will test the last
    key in the list first, so it might make sense to order oldest to newest.

    Flask's built-in secure cookie session supports this. Extensions that use
    :data:`SECRET_KEY` may not support this yet.

    Default: ``None``

    .. versionadded:: 3.1

.. py:data:: SESSION_COOKIE_NAME

    The name of the session cookie. Can be changed in case you already have a
    cookie with the same name.

    Default: ``'session'``

.. py:data:: SESSION_COOKIE_DOMAIN

    The value of the ``Domain`` parameter on the session cookie. If not set, browsers
    will only send the cookie to the exact domain it was set from. Otherwise, they
    will send it to any subdomain of the given value as well.

    Not setting this value is more restricted and secure than setting it.

    Default: ``None``

    .. warning::
        If this is changed after the browser created a cookie is created with
        one setting, it may result in another being created. Browsers may send
        send both in an undefined order. In that case, you may want to change
        :data:`SESSION_COOKIE_NAME` as well or otherwise invalidate old sessions.

    .. versionchanged:: 2.3
        Not set by default, does not fall back to ``SERVER_NAME``.

.. py:data:: SESSION_COOKIE_PATH

    The path that the session cookie will be valid for. If not set, the cookie
    will be valid underneath ``APPLICATION_ROOT`` or ``/`` if that is not set.

    Default: ``None``

.. py:data:: SESSION_COOKIE_HTTPONLY

    Browsers will not allow JavaScript access to cookies marked as "HTTP only"
    for security.

    Default: ``True``

.. py:data:: SESSION_COOKIE_SECURE

    Browsers will only send cookies with requests over HTTPS if the cookie is
    marked "secure". The application must be served over HTTPS for this to make
    sense.

    Default: ``False``

.. py:data:: SESSION_COOKIE_PARTITIONED

    Browsers will send cookies based on the top-level document's domain, rather
    than only the domain of the document setting the cookie. This prevents third
    party cookies set in iframes from "leaking" between separate sites.

    Browsers are beginning to disallow non-partitioned third party cookies, so
    you need to mark your cookies partitioned if you expect them to work in such
    embedded situations.

    Enabling this implicitly enables :data:`SESSION_COOKIE_SECURE` as well, as
    it is only valid when served over HTTPS.

    Default: ``False``

    .. versionadded:: 3.1

.. py:data:: SESSION_COOKIE_SAMESITE

    Restrict how cookies are sent with requests from external sites. Can
    be set to ``'Lax'`` (recommended) or ``'Strict'``.
    See :ref:`security-cookie`.

    Default: ``None``

    .. versionadded:: 1.0

.. py:data:: PERMANENT_SESSION_LIFETIME

    If ``session.permanent`` is true, the cookie's expiration will be set this
    number of seconds in the future. Can either be a
    :class:`datetime.timedelta` or an ``int``.

    Flask's default cookie implementation validates that the cryptographic
    signature is not older than this value.

    Default: ``timedelta(days=31)`` (``2678400`` seconds)

.. py:data:: SESSION_REFRESH_EACH_REQUEST

    Control whether the cookie is sent with every response when
    ``session.permanent`` is true. Sending the cookie every time (the default)
    can more reliably keep the session from expiring, but uses more bandwidth.
    Non-permanent sessions are not affected.

    Default: ``True``

.. py:data:: USE_X_SENDFILE

    When serving files, set the ``X-Sendfile`` header instead of serving the
    data with Flask. Some web servers, such as Apache, recognize this and serve
    the data more efficiently. This only makes sense when using such a server.

    Default: ``False``

.. py:data:: SEND_FILE_MAX_AGE_DEFAULT

    When serving files, set the cache control max age to this number of
    seconds. Can be a :class:`datetime.timedelta` or an ``int``.
    Override this value on a per-file basis using
    :meth:`~flask.Flask.get_send_file_max_age` on the application or
    blueprint.

    If ``None``, ``send_file`` tells the browser to use conditional
    requests will be used instead of a timed cache, which is usually
    preferable.

    Default: ``None``

.. py:data:: TRUSTED_HOSTS

    Validate :attr:`.Request.host` and other attributes that use it against
    these trusted values. Raise a :exc:`~werkzeug.exceptions.SecurityError` if
    the host is invalid, which results in a 400 error. If it is ``None``, all
    hosts are valid. Each value is either an exact match, or can start with
    a dot ``.`` to match any subdomain.

    Validation is done during routing against this value. ``before_request`` and
    ``after_request`` callbacks will still be called.

    Default: ``None``

    .. versionadded:: 3.1

.. py:data:: SERVER_NAME

    Inform the application what host and port it is bound to.

    Must be set if ``subdomain_matching`` is enabled, to be able to extract the
    subdomain from the request.

    Must be set for ``url_for`` to generate external URLs outside of a
    request context.

    Default: ``None``

    .. versionchanged:: 3.1
        Does not restrict requests to only this domain, for both
        ``subdomain_matching`` and ``host_matching``.

    .. versionchanged:: 1.0
        Does not implicitly enable ``subdomain_matching``.

    .. versionchanged:: 2.3
        Does not affect ``SESSION_COOKIE_DOMAIN``.

.. py:data:: APPLICATION_ROOT

    Inform the application what path it is mounted under by the application /
    web server.  This is used for generating URLs outside the context of a
    request (inside a request, the dispatcher is responsible for setting
    ``SCRIPT_NAME`` instead; see :doc:`/patterns/appdispatch`
    for examples of dispatch configuration).

    Will be used for the session cookie path if ``SESSION_COOKIE_PATH`` is not
    set.

    Default: ``'/'``

.. py:data:: PREFERRED_URL_SCHEME

    Use this scheme for generating external URLs when not in a request context.

    Default: ``'http'``

.. py:data:: MAX_CONTENT_LENGTH

    The maximum number of bytes that will be read during this request. If
    this limit is exceeded, a 413 :exc:`~werkzeug.exceptions.RequestEntityTooLarge`
    error is raised. If it is set to ``None``, no limit is enforced at the
    Flask application level. However, if it is ``None`` and the request has no
    ``Content-Length`` header and the WSGI server does not indicate that it
    terminates the stream, then no data is read to avoid an infinite stream.

    Each request defaults to this config. It can be set on a specific
    :attr:`.Request.max_content_length` to apply the limit to that specific
    view. This should be set appropriately based on an application's or view's
    specific needs.

    Default: ``None``

    .. versionadded:: 0.6

.. py:data:: MAX_FORM_MEMORY_SIZE

    The maximum size in bytes any non-file form field may be in a
    ``multipart/form-data`` body. If this limit is exceeded, a 413
    :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it is
    set to ``None``, no limit is enforced at the Flask application level.

    Each request defaults to this config. It can be set on a specific
    :attr:`.Request.max_form_memory_parts` to apply the limit to that specific
    view. This should be set appropriately based on an application's or view's
    specific needs.

    Default: ``500_000``

    .. versionadded:: 3.1

.. py:data:: MAX_FORM_PARTS

    The maximum number of fields that may be present in a
    ``multipart/form-data`` body. If this limit is exceeded, a 413
    :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it
    is set to ``None``, no limit is enforced at the Flask application level.

    Each request defaults to this config. It can be set on a specific
    :attr:`.Request.max_form_parts` to apply the limit to that specific view.
    This should be set appropriately based on an application's or view's
    specific needs.

    Default: ``1_000``

    .. versionadded:: 3.1

.. py:data:: TEMPLATES_AUTO_RELOAD

    Reload templates when they are changed. If not set, it will be enabled in
    debug mode.

    Default: ``None``

.. py:data:: EXPLAIN_TEMPLATE_LOADING

    Log debugging information tracing how a template file was loaded. This can
    be useful to figure out why a template was not loaded or the wrong file
    appears to be loaded.

    Default: ``False``

.. py:data:: MAX_COOKIE_SIZE

    Warn if cookie headers are larger than this many bytes. Defaults to
    ``4093``. Larger cookies may be silently ignored by browsers. Set to
    ``0`` to disable the warning.

.. py:data:: PROVIDE_AUTOMATIC_OPTIONS

    Set to ``False`` to disable the automatic addition of OPTIONS
    responses. This can be overridden per route by altering the
    ``provide_automatic_options`` attribute.

.. versionadded:: 0.4
   ``LOGGER_NAME``

.. versionadded:: 0.5
   ``SERVER_NAME``

.. versionadded:: 0.6
   ``MAX_CONTENT_LENGTH``

.. versionadded:: 0.7
   ``PROPAGATE_EXCEPTIONS``, ``PRESERVE_CONTEXT_ON_EXCEPTION``

.. versionadded:: 0.8
   ``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS``,
   ``APPLICATION_ROOT``, ``SESSION_COOKIE_DOMAIN``,
   ``SESSION_COOKIE_PATH``, ``SESSION_COOKIE_HTTPONLY``,
   ``SESSION_COOKIE_SECURE``

.. versionadded:: 0.9
   ``PREFERRED_URL_SCHEME``

.. versionadded:: 0.10
   ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_PRETTYPRINT_REGULAR``

.. versionadded:: 0.11
   ``SESSION_REFRESH_EACH_REQUEST``, ``TEMPLATES_AUTO_RELOAD``,
   ``LOGGER_HANDLER_POLICY``, ``EXPLAIN_TEMPLATE_LOADING``

.. versionchanged:: 1.0
    ``LOGGER_NAME`` and ``LOGGER_HANDLER_POLICY`` were removed. See
    :doc:`/logging` for information about configuration.

    Added :data:`ENV` to reflect the :envvar:`FLASK_ENV` environment
    variable.

    Added :data:`SESSION_COOKIE_SAMESITE` to control the session
    cookie's ``SameSite`` option.

    Added :data:`MAX_COOKIE_SIZE` to control a warning from Werkzeug.

.. versionchanged:: 2.2
    Removed ``PRESERVE_CONTEXT_ON_EXCEPTION``.

.. versionchanged:: 2.3
    ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_MIMETYPE``, and
    ``JSONIFY_PRETTYPRINT_REGULAR`` were removed. The default ``app.json`` provider has
    equivalent attributes instead.

.. versionchanged:: 2.3
    ``ENV`` was removed.

.. versionadded:: 3.1
    Added :data:`PROVIDE_AUTOMATIC_OPTIONS` to control the default
    addition of autogenerated OPTIONS responses.


Configuring from Python Files
-----------------------------

Configuration becomes more useful if you can store it in a separate file, ideally
located outside the actual application package. You can deploy your application, then
separately configure it for the specific deployment.

A common pattern is this::

    app = Flask(__name__)
    app.config.from_object('yourapplication.default_settings')
    app.config.from_envvar('YOURAPPLICATION_SETTINGS')

This first loads the configuration from the
`yourapplication.default_settings` module and then overrides the values
with the contents of the file the :envvar:`YOURAPPLICATION_SETTINGS`
environment variable points to.  This environment variable can be set
in the shell before starting the server:

.. tabs::

   .. group-tab:: Bash

      .. code-block:: text

         $ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
         $ flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: Fish

      .. code-block:: text

         $ set -x YOURAPPLICATION_SETTINGS /path/to/settings.cfg
         $ flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: CMD

      .. code-block:: text

         > set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
         > flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: Powershell

      .. code-block:: text

         > $env:YOURAPPLICATION_SETTINGS = "\path\to\settings.cfg"
         > flask run
          * Running on http://127.0.0.1:5000/

The configuration files themselves are actual Python files.  Only values
in uppercase are actually stored in the config object later on.  So make
sure to use uppercase letters for your config keys.

Here is an example of a configuration file::

    # Example configuration
    SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

Make sure to load the configuration very early on, so that extensions have
the ability to access the configuration when starting up.  There are other
methods on the config object as well to load from individual files.  For a
complete reference, read the :class:`~flask.Config` object's
documentation.


Configuring from Data Files
---------------------------

It is also possible to load configuration from a file in a format of
your choice using :meth:`~flask.Config.from_file`. For example to load
from a TOML file:

.. code-block:: python

    import tomllib
    app.config.from_file("config.toml", load=tomllib.load, text=False)

Or from a JSON file:

.. code-block:: python

    import json
    app.config.from_file("config.json", load=json.load)


Configuring from Environment Variables
--------------------------------------

In addition to pointing to configuration files using environment
variables, you may find it useful (or necessary) to control your
configuration values directly from the environment. Flask can be
instructed to load all environment variables starting with a specific
prefix into the config using :meth:`~flask.Config.from_prefixed_env`.

Environment variables can be set in the shell before starting the
server:

.. tabs::

   .. group-tab:: Bash

      .. code-block:: text

         $ export FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f"
         $ export FLASK_MAIL_ENABLED=false
         $ flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: Fish

      .. code-block:: text

         $ set -x FLASK_SECRET_KEY "5f352379324c22463451387a0aec5d2f"
         $ set -x FLASK_MAIL_ENABLED false
         $ flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: CMD

      .. code-block:: text

         > set FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f"
         > set FLASK_MAIL_ENABLED=false
         > flask run
          * Running on http://127.0.0.1:5000/

   .. group-tab:: Powershell

      .. code-block:: text

         > $env:FLASK_SECRET_KEY = "5f352379324c22463451387a0aec5d2f"
         > $env:FLASK_MAIL_ENABLED = "false"
         > flask run
          * Running on http://127.0.0.1:5000/

The variables can then be loaded and accessed via the config with a key
equal to the environment variable name without the prefix i.e.

.. code-block:: python

    app.config.from_prefixed_env()
    app.config["SECRET_KEY"]  # Is "5f352379324c22463451387a0aec5d2f"

The prefix is ``FLASK_`` by default. This is configurable via the
``prefix`` argument of :meth:`~flask.Config.from_prefixed_env`.

Values will be parsed to attempt to convert them to a more specific type
than strings. By default :func:`json.loads` is used, so any valid JSON
value is possible, including lists and dicts. This is configurable via
the ``loads`` argument of :meth:`~flask.Config.from_prefixed_env`.

When adding a boolean value with the default JSON parsing, only "true"
and "false", lowercase, are valid values. Keep in mind that any
non-empty string is considered ``True`` by Python.

It is possible to set keys in nested dictionaries by separating the
keys with double underscore (``__``). Any intermediate keys that don't
exist on the parent dict will be initialized to an empty dict.

.. code-block:: text

    $ export FLASK_MYAPI__credentials__username=user123

.. code-block:: python

    app.config["MYAPI"]["credentials"]["username"]  # Is "user123"

On Windows, environment variable keys are always uppercase, therefore
the above example would end up as ``MYAPI__CREDENTIALS__USERNAME``.

For even more config loading features, including merging and
case-insensitive Windows support, try a dedicated library such as
Dynaconf_, which includes integration with Flask.

.. _Dynaconf: https://www.dynaconf.com/


Configuration Best Practices
----------------------------

The downside with the approach mentioned earlier is that it makes testing
a little harder.  There is no single 100% solution for this problem in
general, but there are a couple of things you can keep in mind to improve
that experience:

1.  Create your application in a function and register blueprints on it.
    That way you can create multiple instances of your application with
    different configurations attached which makes unit testing a lot
    easier.  You can use this to pass in configuration as needed.

2.  Do not write code that needs the configuration at import time.  If you
    limit yourself to request-only accesses to the configuration you can
    reconfigure the object later on as needed.

3.  Make sure to load the configuration very early on, so that
    extensions can access the configuration when calling ``init_app``.


.. _config-dev-prod:

Development / Production
------------------------

Most applications need more than one configuration.  There should be at
least separate configurations for the production server and the one used
during development.  The easiest way to handle this is to use a default
configuration that is always loaded and part of the version control, and a
separate configuration that overrides the values as necessary as mentioned
in the example above::

    app = Flask(__name__)
    app.config.from_object('yourapplication.default_settings')
    app.config.from_envvar('YOURAPPLICATION_SETTINGS')

Then you just have to add a separate :file:`config.py` file and export
``YOURAPPLICATION_SETTINGS=/path/to/config.py`` and you are done.  However
there are alternative ways as well.  For example you could use imports or
subclassing.

What is very popular in the Django world is to make the import explicit in
the config file by adding ``from yourapplication.default_settings
import *`` to the top of the file and then overriding the changes by hand.
You could also inspect an environment variable like
``YOURAPPLICATION_MODE`` and set that to `production`, `development` etc
and import different hard-coded files based on that.

An interesting pattern is also to use classes and inheritance for
configuration::

    class Config(object):
        TESTING = False

    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'

    class DevelopmentConfig(Config):
        DATABASE_URI = "sqlite:////tmp/foo.db"

    class TestingConfig(Config):
        DATABASE_URI = 'sqlite:///:memory:'
        TESTING = True

To enable such a config you just have to call into
:meth:`~flask.Config.from_object`::

    app.config.from_object('configmodule.ProductionConfig')

Note that :meth:`~flask.Config.from_object` does not instantiate the class
object. If you need to instantiate the class, such as to access a property,
then you must do so before calling :meth:`~flask.Config.from_object`::

    from configmodule import ProductionConfig
    app.config.from_object(ProductionConfig())

    # Alternatively, import via string:
    from werkzeug.utils import import_string
    cfg = import_string('configmodule.ProductionConfig')()
    app.config.from_object(cfg)

Instantiating the configuration object allows you to use ``@property`` in
your configuration classes::

    class Config(object):
        """Base config, uses staging database server."""
        TESTING = False
        DB_SERVER = '192.168.1.56'

        @property
        def DATABASE_URI(self):  # Note: all caps
            return f"mysql://user@{self.DB_SERVER}/foo"

    class ProductionConfig(Config):
        """Uses production database server."""
        DB_SERVER = '192.168.19.32'

    class DevelopmentConfig(Config):
        DB_SERVER = 'localhost'

    class TestingConfig(Config):
        DB_SERVER = 'localhost'
        DATABASE_URI = 'sqlite:///:memory:'

There are many different ways and it's up to you how you want to manage
your configuration files.  However here a list of good recommendations:

-   Keep a default configuration in version control.  Either populate the
    config with this default configuration or import it in your own
    configuration files before overriding values.
-   Use an environment variable to switch between the configurations.
    This can be done from outside the Python interpreter and makes
    development and deployment much easier because you can quickly and
    easily switch between different configs without having to touch the
    code at all.  If you are working often on different projects you can
    even create your own script for sourcing that activates a virtualenv
    and exports the development configuration for you.
-   Use a tool like `fabric`_ to push code and configuration separately
    to the production server(s).

.. _fabric: https://www.fabfile.org/


.. _instance-folders:

Instance Folders
----------------

.. versionadded:: 0.8

Flask 0.8 introduces instance folders.  Flask for a long time made it
possible to refer to paths relative to the application's folder directly
(via :attr:`Flask.root_path`).  This was also how many developers loaded
configurations stored next to the application.  Unfortunately however this
only works well if applications are not packages in which case the root
path refers to the contents of the package.

With Flask 0.8 a new attribute was introduced:
:attr:`Flask.instance_path`.  It refers to a new concept called the
“instance folder”.  The instance folder is designed to not be under
version control and be deployment specific.  It's the perfect place to
drop things that either change at runtime or configuration files.

You can either explicitly provide the path of the instance folder when
creating the Flask application or you can let Flask autodetect the
instance folder.  For explicit configuration use the `instance_path`
parameter::

    app = Flask(__name__, instance_path='/path/to/instance/folder')

Please keep in mind that this path *must* be absolute when provided.

If the `instance_path` parameter is not provided the following default
locations are used:

-   Uninstalled module::

        /myapp.py
        /instance

-   Uninstalled package::

        /myapp
            /__init__.py
        /instance

-   Installed module or package::

        $PREFIX/lib/pythonX.Y/site-packages/myapp
        $PREFIX/var/myapp-instance

    ``$PREFIX`` is the prefix of your Python installation.  This can be
    ``/usr`` or the path to your virtualenv.  You can print the value of
    ``sys.prefix`` to see what the prefix is set to.

Since the config object provided loading of configuration files from
relative filenames we made it possible to change the loading via filenames
to be relative to the instance path if wanted.  The behavior of relative
paths in config files can be flipped between “relative to the application
root” (the default) to “relative to instance folder” via the
`instance_relative_config` switch to the application constructor::

    app = Flask(__name__, instance_relative_config=True)

Here is a full example of how to configure Flask to preload the config
from a module and then override the config from a file in the instance
folder if it exists::

    app = Flask(__name__, instance_relative_config=True)
    app.config.from_object('yourapplication.default_settings')
    app.config.from_pyfile('application.cfg', silent=True)

The path to the instance folder can be found via the
:attr:`Flask.instance_path`.  Flask also provides a shortcut to open a
file from the instance folder with :meth:`Flask.open_instance_resource`.

Example usage for both::

    filename = os.path.join(app.instance_path, 'application.cfg')
    with open(filename) as f:
        config = f.read()

    # or via open_instance_resource:
    with app.open_instance_resource('application.cfg') as f:
        config = f.read()


================================================
FILE: docs/contributing.rst
================================================
Contributing
============

See the Pallets `detailed contributing documentation <contrib_>`_ for many ways
to contribute, including reporting issues, requesting features, asking or
answering questions, and making PRs.

.. _contrib: https://palletsprojects.com/contributing/


================================================
FILE: docs/debugging.rst
================================================
Debugging Application Errors
============================


In Production
-------------

**Do not run the development server, or enable the built-in debugger, in
a production environment.** The debugger allows executing arbitrary
Python code from the browser. It's protected by a pin, but that should
not be relied on for security.

Use an error logging tool, such as Sentry, as described in
:ref:`error-logging-tools`, or enable logging and notifications as
described in :doc:`/logging`.

If you have access to the server, you could add some code to start an
external debugger if ``request.remote_addr`` matches your IP. Some IDE
debuggers also have a remote mode so breakpoints on the server can be
interacted with locally. Only enable a debugger temporarily.


The Built-In Debugger
---------------------

The built-in Werkzeug development server provides a debugger which shows
an interactive traceback in the browser when an unhandled error occurs
during a request. This debugger should only be used during development.

.. image:: _static/debugger.png
   :align: center
   :class: screenshot
   :alt: screenshot of debugger in action

.. warning::

    The debugger allows executing arbitrary Python code from the
    browser. It is protected by a pin, but still represents a major
    security risk. Do not run the development server or debugger in a
    production environment.

The debugger is enabled by default when the development server is run in debug mode.

.. code-block:: text

    $ flask --app hello run --debug

When running from Python code, passing ``debug=True`` enables debug mode, which is
mostly equivalent.

.. code-block:: python

    app.run(debug=True)

:doc:`/server` and :doc:`/cli` have more information about running the debugger and
debug mode. More information about the debugger can be found in the `Werkzeug
documentation <https://werkzeug.palletsprojects.com/debug/>`__.


External Debuggers
------------------

External debuggers, such as those provided by IDEs, can offer a more
powerful debugging experience than the built-in debugger. They can also
be used to step through code during a request before an error is raised,
or if no error is raised. Some even have a remote mode so you can debug
code running on another machine.

When using an external debugger, the app should still be in debug mode, otherwise Flask
turns unhandled errors into generic 500 error pages. However, the built-in debugger and
reloader should be disabled so they don't interfere with the external debugger.

.. code-block:: text

    $ flask --app hello run --debug --no-debugger --no-reload

When running from Python:

.. code-block:: python

    app.run(debug=True, use_debugger=False, use_reloader=False)

Disabling these isn't required, an external debugger will continue to work with the
following caveats.

-   If the built-in debugger is not disabled, it will catch unhandled exceptions before
    the external debugger can.
-   If the reloader is not disabled, it could cause an unexpected reload if code changes
    during a breakpoint.
-   The development server will still catch unhandled exceptions if the built-in
    debugger is disabled, otherwise it would crash on any error. If you want that (and
    usually you don't) pass ``passthrough_errors=True`` to ``app.run``.

    .. code-block:: python

        app.run(
            debug=True, passthrough_errors=True,
            use_debugger=False, use_reloader=False
        )


================================================
FILE: docs/deploying/apache-httpd.rst
================================================
Apache httpd
============

`Apache httpd`_ is a fast, production level HTTP server. When serving
your application with one of the WSGI servers listed in :doc:`index`, it
is often good or necessary to put a dedicated HTTP server in front of
it. This "reverse proxy" can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.

httpd can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running httpd itself is outside
the scope of this doc. This page outlines the basics of configuring
httpd to proxy your application. Be sure to read its documentation to
understand what features are available.

.. _Apache httpd: https://httpd.apache.org/


Domain Name
-----------

Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting provider's name servers.

To simulate this, you can also edit your ``hosts`` file, located at
``/etc/hosts`` on Linux. Add a line that associates a name with the
local IP.

Modern Linux systems may be configured to treat any domain name that
ends with ``.localhost`` like this without adding it to the ``hosts``
file.

.. code-block:: python
    :caption: ``/etc/hosts``

    127.0.0.1 hello.localhost


Configuration
-------------

The httpd configuration is located at ``/etc/httpd/conf/httpd.conf`` on
Linux. It may be different depending on your operating system. Check the
docs and look for ``httpd.conf``.

Remove or comment out any existing ``DocumentRoot`` directive. Add the
config lines below. We'll assume the WSGI server is listening locally at
``http://127.0.0.1:8000``.

.. code-block:: apache
    :caption: ``/etc/httpd/conf/httpd.conf``

    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module modules/mod_proxy_http.so
    ProxyPass / http://127.0.0.1:8000/
    RequestHeader set X-Forwarded-Proto http
    RequestHeader set X-Forwarded-Prefix /

The ``LoadModule`` lines might already exist. If so, make sure they are
uncommented instead of adding them manually.

Then :doc:`proxy_fix` so that your application uses the ``X-Forwarded``
headers. ``X-Forwarded-For`` and ``X-Forwarded-Host`` are automatically
set by ``ProxyPass``.


================================================
FILE: docs/deploying/asgi.rst
================================================
ASGI
====

If you'd like to use an ASGI server you will need to utilise WSGI to
ASGI middleware. The asgiref
`WsgiToAsgi <https://github.com/django/asgiref#wsgi-to-asgi-adapter>`_
adapter is recommended as it integrates with the event loop used for
Flask's :ref:`async_await` support. You can use the adapter by
wrapping the Flask app,

.. code-block:: python

    from asgiref.wsgi import WsgiToAsgi
    from flask import Flask

    app = Flask(__name__)

    ...

    asgi_app = WsgiToAsgi(app)

and then serving the ``asgi_app`` with the ASGI server, e.g. using
`Hypercorn <https://github.com/pgjones/hypercorn>`_,

.. sourcecode:: text

    $ hypercorn module:asgi_app


================================================
FILE: docs/deploying/eventlet.rst
================================================
:orphan:

eventlet
========

`Eventlet is no longer maintained.`__ Use :doc:`/deploying/gevent` instead.

__ https://eventlet.readthedocs.io


================================================
FILE: docs/deploying/gevent.rst
================================================
gevent
======

Prefer using :doc:`gunicorn` or :doc:`uwsgi` with gevent workers rather
than using `gevent`_ directly. Gunicorn and uWSGI provide much more
configurable and production-tested servers.

`gevent`_ allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses `greenlet`_ to enable task
switching without writing ``async/await`` or using ``asyncio``. This is
not the same as Python's ``async/await``, or the ASGI server spec.

gevent provides a WSGI server that can handle many connections at once
instead of one per worker process. See :doc:`/gevent` for more
information about enabling it in your application.

.. _gevent: https://www.gevent.org/
.. _greenlet: https://greenlet.readthedocs.io/en/latest/


Installing
----------

When using gevent, greenlet>=1.0 is required. When using PyPy,
PyPy>=7.3.7 is required.

Create a virtualenv, install your application, then install ``gevent``.

.. code-block:: text

    $ cd hello-app
    $ python -m venv .venv
    $ . .venv/bin/activate
    $ pip install .  # install your application
    $ pip install gevent


Running
-------

To use gevent to serve your application, write a script that imports its
``WSGIServer``, as well as your app or app factory.

.. code-block:: python
    :caption: ``wsgi.py``

    from gevent.pywsgi import WSGIServer
    from hello import create_app

    app = create_app()
    http_server = WSGIServer(("127.0.0.1", 8000), app)
    http_server.serve_forever()

.. code-block:: text

    $ python wsgi.py

No output is shown when the server starts.


Binding Externally
------------------

gevent should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
in front of gevent.

You can bind to all external IPs on a non-privileged port by using
``0.0.0.0`` in the server arguments shown in the previous section. Don't
do this when using a reverse proxy setup, otherwise it will be possible
to bypass the proxy.

``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
IP address in your browser.


================================================
FILE: docs/deploying/gunicorn.rst
================================================
Gunicorn
========

`Gunicorn`_ is a pure Python WSGI server with simple configuration and
multiple worker implementations for performance tuning.

*   It tends to integrate easily with hosting platforms.
*   It does not support Windows (but does run on WSL).
*   It is easy to install as it does not require additional dependencies
    or compilation.
*   It has built-in async worker support using gevent.

This page outlines the basics of running Gunicorn. Be sure to read its
`documentation`_ and use ``gunicorn --help`` to understand what features
are available.

.. _Gunicorn: https://gunicorn.org/
.. _documentation: https://docs.gunicorn.org/


Installing
----------

Gunicorn is easy to install, as it does not require external
dependencies or compilation. It runs on Windows only under WSL.

Create a virtualenv, install your application, then install
``gunicorn``.

.. code-block:: text

    $ cd hello-app
    $ python -m venv .venv
    $ . .venv/bin/activate
    $ pip install .  # install your application
    $ pip install gunicorn


Running
-------

The only required argument to Gunicorn tells it how to load your Flask
application. The syntax is ``{module_import}:{app_variable}``.
``module_import`` is the dotted import name to the module with your
application. ``app_variable`` is the variable with the application. It
can also be a function call (with any arguments) if you're using the
app factory pattern.

.. code-block:: text

    # equivalent to 'from hello import app'
    $ gunicorn -w 4 'hello:app'

    # equivalent to 'from hello import create_app; create_app()'
    $ gunicorn -w 4 'hello:create_app()'

    Starting gunicorn 20.1.0
    Listening at: http://127.0.0.1:8000 (x)
    Using worker: sync
    Booting worker with pid: x
    Booting worker with pid: x
    Booting worker with pid: x
    Booting worker with pid: x

The ``-w`` option specifies the number of processes to run; a starting
value could be ``CPU * 2``. The default is only 1 worker, which is
probably not what you want for the default worker type.

Logs for each request aren't shown by default, only worker info and
errors are shown. To show access logs on stdout, use the
``--access-logfile=-`` option.


Binding Externally
------------------

Gunicorn should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
in front of Gunicorn.

You can bind to all external IPs on a non-privileged port using the
``-b 0.0.0.0`` option. Don't do this when using a reverse proxy setup,
otherwise it will be possible to bypass the proxy.

.. code-block:: text

    $ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'
    Listening at: http://0.0.0.0:8000 (x)

``0.0.0.0`` is not a valid address to navigate to, you'd use a specif
Download .txt
gitextract_e1znr51w/

├── .devcontainer/
│   ├── devcontainer.json
│   └── on-create-command.sh
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   └── feature-request.md
│   ├── pull_request_template.md
│   └── workflows/
│       ├── lock.yaml
│       ├── pre-commit.yaml
│       ├── publish.yaml
│       ├── tests.yaml
│       └── zizmor.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── CHANGES.rst
├── LICENSE.txt
├── README.md
├── docs/
│   ├── Makefile
│   ├── api.rst
│   ├── appcontext.rst
│   ├── async-await.rst
│   ├── blueprints.rst
│   ├── changes.rst
│   ├── cli.rst
│   ├── conf.py
│   ├── config.rst
│   ├── contributing.rst
│   ├── debugging.rst
│   ├── deploying/
│   │   ├── apache-httpd.rst
│   │   ├── asgi.rst
│   │   ├── eventlet.rst
│   │   ├── gevent.rst
│   │   ├── gunicorn.rst
│   │   ├── index.rst
│   │   ├── mod_wsgi.rst
│   │   ├── nginx.rst
│   │   ├── proxy_fix.rst
│   │   ├── uwsgi.rst
│   │   └── waitress.rst
│   ├── design.rst
│   ├── errorhandling.rst
│   ├── extensiondev.rst
│   ├── extensions.rst
│   ├── gevent.rst
│   ├── index.rst
│   ├── installation.rst
│   ├── license.rst
│   ├── lifecycle.rst
│   ├── logging.rst
│   ├── make.bat
│   ├── patterns/
│   │   ├── appdispatch.rst
│   │   ├── appfactories.rst
│   │   ├── caching.rst
│   │   ├── celery.rst
│   │   ├── deferredcallbacks.rst
│   │   ├── favicon.rst
│   │   ├── fileuploads.rst
│   │   ├── flashing.rst
│   │   ├── index.rst
│   │   ├── javascript.rst
│   │   ├── jquery.rst
│   │   ├── lazyloading.rst
│   │   ├── methodoverrides.rst
│   │   ├── mongoengine.rst
│   │   ├── packages.rst
│   │   ├── requestchecksum.rst
│   │   ├── singlepageapplications.rst
│   │   ├── sqlalchemy.rst
│   │   ├── sqlite3.rst
│   │   ├── streaming.rst
│   │   ├── subclassing.rst
│   │   ├── templateinheritance.rst
│   │   ├── urlprocessors.rst
│   │   ├── viewdecorators.rst
│   │   └── wtforms.rst
│   ├── quickstart.rst
│   ├── reqcontext.rst
│   ├── server.rst
│   ├── shell.rst
│   ├── signals.rst
│   ├── templating.rst
│   ├── testing.rst
│   ├── tutorial/
│   │   ├── blog.rst
│   │   ├── database.rst
│   │   ├── deploy.rst
│   │   ├── factory.rst
│   │   ├── index.rst
│   │   ├── install.rst
│   │   ├── layout.rst
│   │   ├── next.rst
│   │   ├── static.rst
│   │   ├── templates.rst
│   │   ├── tests.rst
│   │   └── views.rst
│   ├── views.rst
│   └── web-security.rst
├── examples/
│   ├── celery/
│   │   ├── README.md
│   │   ├── make_celery.py
│   │   ├── pyproject.toml
│   │   ├── requirements.txt
│   │   └── src/
│   │       └── task_app/
│   │           ├── __init__.py
│   │           ├── tasks.py
│   │           ├── templates/
│   │           │   └── index.html
│   │           └── views.py
│   ├── javascript/
│   │   ├── .gitignore
│   │   ├── LICENSE.txt
│   │   ├── README.rst
│   │   ├── js_example/
│   │   │   ├── __init__.py
│   │   │   ├── templates/
│   │   │   │   ├── base.html
│   │   │   │   ├── fetch.html
│   │   │   │   ├── jquery.html
│   │   │   │   └── xhr.html
│   │   │   └── views.py
│   │   ├── pyproject.toml
│   │   └── tests/
│   │       ├── conftest.py
│   │       └── test_js_example.py
│   └── tutorial/
│       ├── .gitignore
│       ├── LICENSE.txt
│       ├── README.rst
│       ├── flaskr/
│       │   ├── __init__.py
│       │   ├── auth.py
│       │   ├── blog.py
│       │   ├── db.py
│       │   ├── schema.sql
│       │   ├── static/
│       │   │   └── style.css
│       │   └── templates/
│       │       ├── auth/
│       │       │   ├── login.html
│       │       │   └── register.html
│       │       ├── base.html
│       │       └── blog/
│       │           ├── create.html
│       │           ├── index.html
│       │           └── update.html
│       ├── pyproject.toml
│       └── tests/
│           ├── conftest.py
│           ├── data.sql
│           ├── test_auth.py
│           ├── test_blog.py
│           ├── test_db.py
│           └── test_factory.py
├── pyproject.toml
├── src/
│   └── flask/
│       ├── __init__.py
│       ├── __main__.py
│       ├── app.py
│       ├── blueprints.py
│       ├── cli.py
│       ├── config.py
│       ├── ctx.py
│       ├── debughelpers.py
│       ├── globals.py
│       ├── helpers.py
│       ├── json/
│       │   ├── __init__.py
│       │   ├── provider.py
│       │   └── tag.py
│       ├── logging.py
│       ├── py.typed
│       ├── sansio/
│       │   ├── README.md
│       │   ├── app.py
│       │   ├── blueprints.py
│       │   └── scaffold.py
│       ├── sessions.py
│       ├── signals.py
│       ├── templating.py
│       ├── testing.py
│       ├── typing.py
│       ├── views.py
│       └── wrappers.py
└── tests/
    ├── conftest.py
    ├── static/
    │   ├── config.json
    │   ├── config.toml
    │   └── index.html
    ├── templates/
    │   ├── _macro.html
    │   ├── context_template.html
    │   ├── escaping_template.html
    │   ├── mail.txt
    │   ├── nested/
    │   │   └── nested.txt
    │   ├── non_escaping_template.txt
    │   ├── simple_template.html
    │   ├── template_filter.html
    │   └── template_test.html
    ├── test_appctx.py
    ├── test_apps/
    │   ├── .flaskenv
    │   ├── blueprintapp/
    │   │   ├── __init__.py
    │   │   └── apps/
    │   │       ├── __init__.py
    │   │       ├── admin/
    │   │       │   ├── __init__.py
    │   │       │   ├── static/
    │   │       │   │   ├── css/
    │   │       │   │   │   └── test.css
    │   │       │   │   └── test.txt
    │   │       │   └── templates/
    │   │       │       └── admin/
    │   │       │           └── index.html
    │   │       └── frontend/
    │   │           ├── __init__.py
    │   │           └── templates/
    │   │               └── frontend/
    │   │                   └── index.html
    │   ├── cliapp/
    │   │   ├── __init__.py
    │   │   ├── app.py
    │   │   ├── factory.py
    │   │   ├── importerrorapp.py
    │   │   ├── inner1/
    │   │   │   ├── __init__.py
    │   │   │   └── inner2/
    │   │   │       ├── __init__.py
    │   │   │       └── flask.py
    │   │   ├── message.txt
    │   │   └── multiapp.py
    │   ├── helloworld/
    │   │   ├── hello.py
    │   │   └── wsgi.py
    │   └── subdomaintestmodule/
    │       ├── __init__.py
    │       └── static/
    │           └── hello.txt
    ├── test_async.py
    ├── test_basic.py
    ├── test_blueprints.py
    ├── test_cli.py
    ├── test_config.py
    ├── test_converters.py
    ├── test_helpers.py
    ├── test_instance_config.py
    ├── test_json.py
    ├── test_json_tag.py
    ├── test_logging.py
    ├── test_regression.py
    ├── test_reqctx.py
    ├── test_request.py
    ├── test_session_interface.py
    ├── test_signals.py
    ├── test_subclassing.py
    ├── test_templating.py
    ├── test_testing.py
    ├── test_user_error_handler.py
    ├── test_views.py
    └── type_check/
        ├── typing_app_decorators.py
        ├── typing_error_handler.py
        └── typing_route.py
Download .txt
SYMBOL INDEX (933 symbols across 67 files)

FILE: docs/conf.py
  function github_link (line 72) | def github_link(name, rawtext, text, lineno, inliner, options=None, cont...
  function setup (line 100) | def setup(app):

FILE: examples/celery/src/task_app/__init__.py
  function create_app (line 7) | def create_app() -> Flask:
  function celery_init_app (line 29) | def celery_init_app(app: Flask) -> Celery:

FILE: examples/celery/src/task_app/tasks.py
  function add (line 8) | def add(a: int, b: int) -> int:
  function block (line 13) | def block() -> None:
  function process (line 18) | def process(self: Task, total: int) -> object:

FILE: examples/celery/src/task_app/views.py
  function result (line 11) | def result(id: str) -> dict[str, object]:
  function add (line 22) | def add() -> dict[str, object]:
  function block (line 30) | def block() -> dict[str, object]:
  function process (line 36) | def process() -> dict[str, object]:

FILE: examples/javascript/js_example/views.py
  function index (line 10) | def index(js):
  function add (line 15) | def add():

FILE: examples/javascript/tests/conftest.py
  function fixture_app (line 7) | def fixture_app():
  function client (line 14) | def client(app):

FILE: examples/javascript/tests/test_js_example.py
  function test_index (line 14) | def test_index(app, client, path, template_name):
  function test_add (line 25) | def test_add(client, a, b, result):

FILE: examples/tutorial/flaskr/__init__.py
  function create_app (line 6) | def create_app(test_config=None):

FILE: examples/tutorial/flaskr/auth.py
  function login_required (line 19) | def login_required(view):
  function load_logged_in_user (line 33) | def load_logged_in_user():
  function register (line 47) | def register():
  function login (line 85) | def login():
  function logout (line 113) | def logout():

FILE: examples/tutorial/flaskr/blog.py
  function index (line 17) | def index():
  function get_post (line 28) | def get_post(id, check_author=True):
  function create (line 62) | def create():
  function update (line 88) | def update(id):
  function delete (line 115) | def delete(id):

FILE: examples/tutorial/flaskr/db.py
  function get_db (line 9) | def get_db():
  function close_db (line 23) | def close_db(e=None):
  function init_db (line 33) | def init_db():
  function init_db_command (line 42) | def init_db_command():
  function init_app (line 51) | def init_app(app):

FILE: examples/tutorial/flaskr/schema.sql
  type user (line 7) | CREATE TABLE user (
  type post (line 13) | CREATE TABLE post (

FILE: examples/tutorial/tests/conftest.py
  function app (line 16) | def app():
  function client (line 36) | def client(app):
  function runner (line 42) | def runner(app):
  class AuthActions (line 47) | class AuthActions:
    method __init__ (line 48) | def __init__(self, client):
    method login (line 51) | def login(self, username="test", password="test"):
    method logout (line 56) | def logout(self):
  function auth (line 61) | def auth(client):

FILE: examples/tutorial/tests/test_auth.py
  function test_register (line 8) | def test_register(client, app):
  function test_register_validate_input (line 32) | def test_register_validate_input(client, username, password, message):
  function test_login (line 39) | def test_login(client, auth):
  function test_login_validate_input (line 59) | def test_login_validate_input(auth, username, password, message):
  function test_logout (line 64) | def test_logout(client, auth):

FILE: examples/tutorial/tests/test_blog.py
  function test_index (line 6) | def test_index(client, auth):
  function test_login_required (line 20) | def test_login_required(client, path):
  function test_author_required (line 25) | def test_author_required(app, client, auth):
  function test_exists_required (line 41) | def test_exists_required(client, auth, path):
  function test_create (line 46) | def test_create(client, auth, app):
  function test_update (line 57) | def test_update(client, auth, app):
  function test_create_update_validate (line 69) | def test_create_update_validate(client, auth, path):
  function test_delete (line 75) | def test_delete(client, auth, app):

FILE: examples/tutorial/tests/test_db.py
  function test_get_close_db (line 8) | def test_get_close_db(app):
  function test_init_db_command (line 19) | def test_init_db_command(runner, monkeypatch):

FILE: examples/tutorial/tests/test_factory.py
  function test_config (line 4) | def test_config():
  function test_hello (line 10) | def test_hello(client):

FILE: src/flask/app.py
  function _make_timedelta (line 73) | def _make_timedelta(value: timedelta | int | None) -> timedelta | None:
  function remove_ctx (line 85) | def remove_ctx(f: F) -> F:
  function add_ctx (line 97) | def add_ctx(f: F) -> F:
  class Flask (line 109) | class Flask(App):
    method __init_subclass__ (line 254) | def __init_subclass__(cls, **kwargs: t.Any) -> None:
    method __init__ (line 310) | def __init__(
    method get_send_file_max_age (line 365) | def get_send_file_max_age(self, filename: str | None) -> int | None:
    method send_static_file (line 392) | def send_static_file(self, filename: str) -> Response:
    method open_resource (line 414) | def open_resource(
    method open_instance_resource (line 447) | def open_instance_resource(
    method create_jinja_environment (line 469) | def create_jinja_environment(self) -> Environment:
    method create_url_adapter (line 509) | def create_url_adapter(self, request: Request | None) -> MapAdapter | ...
    method raise_routing_exception (line 562) | def raise_routing_exception(self, request: Request) -> t.NoReturn:
    method update_template_context (line 590) | def update_template_context(
    method make_shell_context (line 620) | def make_shell_context(self) -> dict[str, t.Any]:
    method run (line 632) | def run(
    method test_client (line 755) | def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> Fl...
    method test_cli_runner (line 813) | def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner:
    method handle_http_exception (line 830) | def handle_http_exception(
    method handle_user_exception (line 865) | def handle_user_exception(
    method handle_exception (line 897) | def handle_exception(self, ctx: AppContext, e: Exception) -> Response:
    method log_exception (line 950) | def log_exception(
    method dispatch_request (line 966) | def dispatch_request(self, ctx: AppContext) -> ft.ResponseReturnValue:
    method full_dispatch_request (line 992) | def full_dispatch_request(self, ctx: AppContext) -> Response:
    method finalize_request (line 1021) | def finalize_request(
    method make_default_options_response (line 1053) | def make_default_options_response(self, ctx: AppContext) -> Response:
    method ensure_sync (line 1065) | def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[...,...
    method async_to_sync (line 1079) | def async_to_sync(
    method url_for (line 1102) | def url_for(
    method make_response (line 1224) | def make_response(self, rv: ft.ResponseReturnValue) -> Response:
    method preprocess_request (line 1366) | def preprocess_request(self, ctx: AppContext) -> ft.ResponseReturnValu...
    method process_response (line 1394) | def process_response(self, ctx: AppContext, response: Response) -> Res...
    method do_teardown_request (line 1420) | def do_teardown_request(
    method do_teardown_appcontext (line 1453) | def do_teardown_appcontext(
    method app_context (line 1481) | def app_context(self) -> AppContext:
    method request_context (line 1501) | def request_context(self, environ: WSGIEnvironment) -> AppContext:
    method test_request_context (line 1517) | def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> AppCo...
    method wsgi_app (line 1566) | def wsgi_app(
    method __call__ (line 1618) | def __call__(

FILE: src/flask/blueprints.py
  class Blueprint (line 18) | class Blueprint(SansioBlueprint):
    method __init__ (line 19) | def __init__(
    method get_send_file_max_age (line 55) | def get_send_file_max_age(self, filename: str | None) -> int | None:
    method send_static_file (line 82) | def send_static_file(self, filename: str) -> Response:
    method open_resource (line 104) | def open_resource(

FILE: src/flask/cli.py
  class NoAppException (line 37) | class NoAppException(click.UsageError):
  function find_best_app (line 41) | def find_best_app(module: ModuleType) -> Flask:
  function _called_with_wrong_args (line 94) | def _called_with_wrong_args(f: t.Callable[..., Flask]) -> bool:
  function find_app_by_string (line 120) | def find_app_by_string(module: ModuleType, app_name: str) -> Flask:
  function prepare_import (line 200) | def prepare_import(path: str) -> str:
  function locate_app (line 230) | def locate_app(
  function locate_app (line 236) | def locate_app(
  function locate_app (line 241) | def locate_app(
  function get_version (line 267) | def get_version(ctx: click.Context, param: click.Parameter, value: t.Any...
  class ScriptInfo (line 293) | class ScriptInfo:
    method __init__ (line 305) | def __init__(
    method load_app (line 333) | def load_app(self) -> Flask:
  function with_appcontext (line 380) | def with_appcontext(f: F) -> F:
  class AppGroup (line 405) | class AppGroup(click.Group):
    method command (line 413) | def command(  # type: ignore[override]
    method group (line 429) | def group(  # type: ignore[override]
  function _set_app (line 440) | def _set_app(ctx: click.Context, param: click.Option, value: str | None)...
  function _set_debug (line 468) | def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> ...
  function _env_file_callback (line 493) | def _env_file_callback(
  class FlaskGroup (line 531) | class FlaskGroup(AppGroup):
    method __init__ (line 563) | def __init__(
    method _load_plugin_commands (line 600) | def _load_plugin_commands(self) -> None:
    method get_command (line 609) | def get_command(self, ctx: click.Context, name: str) -> click.Command ...
    method list_commands (line 636) | def list_commands(self, ctx: click.Context) -> list[str]:
    method make_context (line 657) | def make_context(
    method parse_args (line 678) | def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
  function _path_is_ancestor (line 691) | def _path_is_ancestor(path: str, other: str) -> bool:
  function load_dotenv (line 698) | def load_dotenv(
  function show_server_banner (line 766) | def show_server_banner(debug: bool, app_import_path: str | None) -> None:
  class CertParamType (line 780) | class CertParamType(click.ParamType):
    method __init__ (line 788) | def __init__(self) -> None:
    method convert (line 791) | def convert(
  function _validate_key (line 828) | def _validate_key(ctx: click.Context, param: click.Parameter, value: t.A...
  class SeparatedPathType (line 867) | class SeparatedPathType(click.Path):
    method convert (line 873) | def convert(
  function run_command (line 935) | def run_command(
  function shell_command (line 1001) | def shell_command() -> None:
  function routes_command (line 1061) | def routes_command(sort: str, all_methods: bool) -> None:
  function main (line 1122) | def main() -> None:

FILE: src/flask/config.py
  class ConfigAttribute (line 20) | class ConfigAttribute(t.Generic[T]):
    method __init__ (line 23) | def __init__(
    method __get__ (line 30) | def __get__(self, obj: None, owner: None) -> te.Self: ...
    method __get__ (line 33) | def __get__(self, obj: App, owner: type[App]) -> T: ...
    method __get__ (line 35) | def __get__(self, obj: App | None, owner: type[App] | None = None) -> ...
    method __set__ (line 46) | def __set__(self, obj: App, value: t.Any) -> None:
  class Config (line 50) | class Config(dict):  # type: ignore[type-arg]
    method __init__ (line 94) | def __init__(
    method from_envvar (line 102) | def from_envvar(self, variable_name: str, silent: bool = False) -> bool:
    method from_prefixed_env (line 126) | def from_prefixed_env(
    method from_pyfile (line 187) | def from_pyfile(
    method from_object (line 218) | def from_object(self, obj: object | str) -> None:
    method from_file (line 256) | def from_file(
    method from_mapping (line 304) | def from_mapping(
    method get_namespace (line 323) | def get_namespace(
    method __repr__ (line 366) | def __repr__(self) -> str:

FILE: src/flask/ctx.py
  class _AppCtxGlobals (line 30) | class _AppCtxGlobals:
    method __getattr__ (line 53) | def __getattr__(self, name: str) -> t.Any:
    method __setattr__ (line 59) | def __setattr__(self, name: str, value: t.Any) -> None:
    method __delattr__ (line 62) | def __delattr__(self, name: str) -> None:
    method get (line 68) | def get(self, name: str, default: t.Any | None = None) -> t.Any:
    method pop (line 79) | def pop(self, name: str, default: t.Any = _sentinel) -> t.Any:
    method setdefault (line 93) | def setdefault(self, name: str, default: t.Any = None) -> t.Any:
    method __contains__ (line 105) | def __contains__(self, item: str) -> bool:
    method __iter__ (line 108) | def __iter__(self) -> t.Iterator[str]:
    method __repr__ (line 111) | def __repr__(self) -> str:
  function after_this_request (line 118) | def after_this_request(
  function copy_current_request_context (line 154) | def copy_current_request_context(f: F) -> F:
  function has_request_context (line 209) | def has_request_context() -> bool:
  function has_app_context (line 235) | def has_app_context() -> bool:
  class AppContext (line 260) | class AppContext:
    method __init__ (line 300) | def __init__(
    method from_environ (line 340) | def from_environ(cls, app: Flask, environ: WSGIEnvironment, /) -> te.S...
    method has_request (line 351) | def has_request(self) -> bool:
    method copy (line 355) | def copy(self) -> te.Self:
    method request (line 371) | def request(self) -> Request:
    method _get_session (line 381) | def _get_session(self) -> SessionMixin:
    method session (line 396) | def session(self) -> SessionMixin:
    method match_request (line 405) | def match_request(self) -> None:
    method push (line 416) | def push(self) -> None:
    method pop (line 446) | def pop(self, exc: BaseException | None = None) -> None:
    method __enter__ (line 506) | def __enter__(self) -> te.Self:
    method __exit__ (line 510) | def __exit__(
    method __repr__ (line 518) | def __repr__(self) -> str:
  function __getattr__ (line 528) | def __getattr__(name: str) -> t.Any:

FILE: src/flask/debughelpers.py
  class UnexpectedUnicodeError (line 17) | class UnexpectedUnicodeError(AssertionError, UnicodeError):
  class DebugFilesKeyError (line 23) | class DebugFilesKeyError(KeyError, AssertionError):
    method __init__ (line 28) | def __init__(self, request: Request, key: str) -> None:
    method __str__ (line 46) | def __str__(self) -> str:
  class FormDataRoutingRedirect (line 50) | class FormDataRoutingRedirect(AssertionError):
    method __init__ (line 57) | def __init__(self, request: Request) -> None:
  function attach_enctype_error_multidict (line 81) | def attach_enctype_error_multidict(request: Request) -> None:
  function _dump_loader_info (line 107) | def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]:
  function explain_template_loading_attempts (line 124) | def explain_template_loading_attempts(

FILE: src/flask/globals.py
  class ProxyMixin (line 17) | class ProxyMixin(t.Protocol[T]):
    method _get_current_object (line 18) | def _get_current_object(self) -> T: ...
  class FlaskProxy (line 22) | class FlaskProxy(ProxyMixin[Flask], Flask): ...
  class AppContextProxy (line 24) | class AppContextProxy(ProxyMixin[AppContext], AppContext): ...
  class _AppCtxGlobalsProxy (line 26) | class _AppCtxGlobalsProxy(ProxyMixin[_AppCtxGlobals], _AppCtxGlobals): ...
  class RequestProxy (line 28) | class RequestProxy(ProxyMixin[Request], Request): ...
  class SessionMixinProxy (line 30) | class SessionMixinProxy(ProxyMixin[SessionMixin], SessionMixin): ...
  function __getattr__ (line 65) | def __getattr__(name: str) -> t.Any:

FILE: src/flask/helpers.py
  function get_debug_flag (line 28) | def get_debug_flag() -> bool:
  function get_load_dotenv (line 36) | def get_load_dotenv(default: bool = True) -> bool:
  function stream_with_context (line 52) | def stream_with_context(
  function stream_with_context (line 58) | def stream_with_context(
  function stream_with_context (line 63) | def stream_with_context(
  function make_response (line 151) | def make_response(*args: t.Any) -> Response:
  function url_for (line 200) | def url_for(
  function redirect (line 254) | def redirect(
  function abort (line 281) | def abort(code: int | BaseResponse, *args: t.Any, **kwargs: t.Any) -> t....
  function get_template_attribute (line 304) | def get_template_attribute(template_name: str, attribute: str) -> t.Any:
  function flash (line 326) | def flash(message: str, category: str = "message") -> None:
  function get_flashed_messages (line 360) | def get_flashed_messages(
  function _prepare_send_file_kwargs (line 402) | def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]:
  function send_file (line 417) | def send_file(
  function send_from_directory (line 543) | def send_from_directory(
  function get_root_path (line 587) | def get_root_path(import_name: str) -> str:
  function _split_blueprint_path (line 645) | def _split_blueprint_path(name: str) -> list[str]:
  class _CollectErrors (line 654) | class _CollectErrors:
    method __init__ (line 659) | def __init__(self) -> None:
    method __enter__ (line 662) | def __enter__(self) -> None:
    method __exit__ (line 665) | def __exit__(
    method raise_any (line 676) | def raise_any(self, message: str) -> None:

FILE: src/flask/json/__init__.py
  function dumps (line 13) | def dumps(obj: t.Any, **kwargs: t.Any) -> str:
  function dump (line 47) | def dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None:
  function loads (line 77) | def loads(s: str | bytes, **kwargs: t.Any) -> t.Any:
  function load (line 108) | def load(fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any:
  function jsonify (line 138) | def jsonify(*args: t.Any, **kwargs: t.Any) -> Response:

FILE: src/flask/json/provider.py
  class JSONProvider (line 19) | class JSONProvider:
    method __init__ (line 38) | def __init__(self, app: App) -> None:
    method dumps (line 41) | def dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
    method dump (line 49) | def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None:
    method loads (line 59) | def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:
    method load (line 67) | def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any:
    method _prepare_response_obj (line 75) | def _prepare_response_obj(
    method response (line 89) | def response(self, *args: t.Any, **kwargs: t.Any) -> Response:
  function _default (line 108) | def _default(o: t.Any) -> t.Any:
  class DefaultJSONProvider (line 124) | class DefaultJSONProvider(JSONProvider):
    method dumps (line 166) | def dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
    method loads (line 181) | def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:
    method response (line 189) | def response(self, *args: t.Any, **kwargs: t.Any) -> Response:

FILE: src/flask/json/tag.py
  class JSONTag (line 60) | class JSONTag:
    method __init__ (line 69) | def __init__(self, serializer: TaggedJSONSerializer) -> None:
    method check (line 73) | def check(self, value: t.Any) -> bool:
    method to_json (line 77) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 82) | def to_python(self, value: t.Any) -> t.Any:
    method tag (line 87) | def tag(self, value: t.Any) -> dict[str, t.Any]:
  class TagDict (line 93) | class TagDict(JSONTag):
    method check (line 103) | def check(self, value: t.Any) -> bool:
    method to_json (line 110) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 114) | def to_python(self, value: t.Any) -> t.Any:
  class PassDict (line 119) | class PassDict(JSONTag):
    method check (line 122) | def check(self, value: t.Any) -> bool:
    method to_json (line 125) | def to_json(self, value: t.Any) -> t.Any:
  class TagTuple (line 133) | class TagTuple(JSONTag):
    method check (line 137) | def check(self, value: t.Any) -> bool:
    method to_json (line 140) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 143) | def to_python(self, value: t.Any) -> t.Any:
  class PassList (line 147) | class PassList(JSONTag):
    method check (line 150) | def check(self, value: t.Any) -> bool:
    method to_json (line 153) | def to_json(self, value: t.Any) -> t.Any:
  class TagBytes (line 159) | class TagBytes(JSONTag):
    method check (line 163) | def check(self, value: t.Any) -> bool:
    method to_json (line 166) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 169) | def to_python(self, value: t.Any) -> t.Any:
  class TagMarkup (line 173) | class TagMarkup(JSONTag):
    method check (line 181) | def check(self, value: t.Any) -> bool:
    method to_json (line 184) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 187) | def to_python(self, value: t.Any) -> t.Any:
  class TagUUID (line 191) | class TagUUID(JSONTag):
    method check (line 195) | def check(self, value: t.Any) -> bool:
    method to_json (line 198) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 201) | def to_python(self, value: t.Any) -> t.Any:
  class TagDateTime (line 205) | class TagDateTime(JSONTag):
    method check (line 209) | def check(self, value: t.Any) -> bool:
    method to_json (line 212) | def to_json(self, value: t.Any) -> t.Any:
    method to_python (line 215) | def to_python(self, value: t.Any) -> t.Any:
  class TaggedJSONSerializer (line 219) | class TaggedJSONSerializer:
    method __init__ (line 249) | def __init__(self) -> None:
    method register (line 256) | def register(
    method tag (line 289) | def tag(self, value: t.Any) -> t.Any:
    method untag (line 297) | def untag(self, value: dict[str, t.Any]) -> t.Any:
    method _untag_scan (line 309) | def _untag_scan(self, value: t.Any) -> t.Any:
    method dumps (line 321) | def dumps(self, value: t.Any) -> str:
    method loads (line 325) | def loads(self, value: str) -> t.Any:

FILE: src/flask/logging.py
  function wsgi_errors_stream (line 16) | def wsgi_errors_stream() -> t.TextIO:
  function has_level_handler (line 31) | def has_level_handler(logger: logging.Logger) -> bool:
  function create_logger (line 58) | def create_logger(app: App) -> logging.Logger:

FILE: src/flask/sansio/app.py
  function _make_timedelta (line 52) | def _make_timedelta(value: timedelta | int | None) -> timedelta | None:
  class App (line 59) | class App(Scaffold):
    method __init__ (line 279) | def __init__(
    method _check_setup_finished (line 410) | def _check_setup_finished(self, f_name: str) -> None:
    method name (line 423) | def name(self) -> str:
    method logger (line 440) | def logger(self) -> logging.Logger:
    method jinja_env (line 467) | def jinja_env(self) -> Environment:
    method create_jinja_environment (line 476) | def create_jinja_environment(self) -> Environment:
    method make_config (line 479) | def make_config(self, instance_relative: bool = False) -> Config:
    method make_aborter (line 495) | def make_aborter(self) -> Aborter:
    method auto_find_instance_path (line 507) | def auto_find_instance_path(self) -> str:
    method create_global_jinja_loader (line 520) | def create_global_jinja_loader(self) -> DispatchingJinjaLoader:
    method select_jinja_autoescape (line 533) | def select_jinja_autoescape(self, filename: str | None) -> bool:
    method debug (line 547) | def debug(self) -> bool:
    method debug (line 560) | def debug(self, value: bool) -> None:
    method register_blueprint (line 567) | def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -...
    method iter_blueprints (line 594) | def iter_blueprints(self) -> t.ValuesView[Blueprint]:
    method add_url_rule (line 602) | def add_url_rule(
    method template_filter (line 661) | def template_filter(self, name: T_template_filter) -> T_template_filte...
    method template_filter (line 663) | def template_filter(
    method template_filter (line 667) | def template_filter(
    method add_template_filter (line 696) | def add_template_filter(
    method template_test (line 711) | def template_test(self, name: T_template_test) -> T_template_test: ...
    method template_test (line 713) | def template_test(
    method template_test (line 717) | def template_test(
    method add_template_test (line 753) | def add_template_test(
    method template_global (line 770) | def template_global(self, name: T_template_global) -> T_template_globa...
    method template_global (line 772) | def template_global(
    method template_global (line 776) | def template_global(
    method add_template_global (line 807) | def add_template_global(
    method teardown_appcontext (line 824) | def teardown_appcontext(self, f: T_teardown) -> T_teardown:
    method shell_context_processor (line 855) | def shell_context_processor(
    method _find_error_handler (line 865) | def _find_error_handler(
    method trap_http_exception (line 890) | def trap_http_exception(self, e: Exception) -> bool:
    method redirect (line 936) | def redirect(self, location: str, code: int = 303) -> BaseResponse:
    method inject_url_defaults (line 957) | def inject_url_defaults(self, endpoint: str, values: dict[str, t.Any])...
    method handle_url_build_error (line 978) | def handle_url_build_error(

FILE: src/flask/sansio/blueprints.py
  class BlueprintSetupState (line 34) | class BlueprintSetupState:
    method __init__ (line 41) | def __init__(
    method add_url_rule (line 87) | def add_url_rule(
  class Blueprint (line 119) | class Blueprint(Scaffold):
    method __init__ (line 174) | def __init__(
    method _check_setup_finished (line 213) | def _check_setup_finished(self, f_name: str) -> None:
    method record (line 224) | def record(self, func: DeferredSetupFunction) -> None:
    method record_once (line 233) | def record_once(self, func: DeferredSetupFunction) -> None:
    method make_setup_state (line 246) | def make_setup_state(
    method register_blueprint (line 256) | def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -...
    method register (line 273) | def register(self, app: App, options: dict[str, t.Any]) -> None:
    method _merge_blueprint_funcs (line 379) | def _merge_blueprint_funcs(self, app: App, name: str) -> None:
    method add_url_rule (line 413) | def add_url_rule(
    method app_template_filter (line 444) | def app_template_filter(self, name: T_template_filter) -> T_template_f...
    method app_template_filter (line 446) | def app_template_filter(
    method app_template_filter (line 450) | def app_template_filter(
    method add_app_template_filter (line 476) | def add_app_template_filter(
    method app_template_test (line 498) | def app_template_test(self, name: T_template_test) -> T_template_test:...
    method app_template_test (line 500) | def app_template_test(
    method app_template_test (line 504) | def app_template_test(
    method add_app_template_test (line 532) | def add_app_template_test(
    method app_template_global (line 556) | def app_template_global(self, name: T_template_global) -> T_template_g...
    method app_template_global (line 558) | def app_template_global(
    method app_template_global (line 562) | def app_template_global(
    method add_app_template_global (line 590) | def add_app_template_global(
    method before_app_request (line 614) | def before_app_request(self, f: T_before_request) -> T_before_request:
    method after_app_request (line 624) | def after_app_request(self, f: T_after_request) -> T_after_request:
    method teardown_app_request (line 634) | def teardown_app_request(self, f: T_teardown) -> T_teardown:
    method app_context_processor (line 644) | def app_context_processor(
    method app_errorhandler (line 656) | def app_errorhandler(
    method app_url_value_preprocessor (line 673) | def app_url_value_preprocessor(
    method app_url_defaults (line 685) | def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults:

FILE: src/flask/sansio/scaffold.py
  function setupmethod (line 42) | def setupmethod(f: F) -> F:
  class Scaffold (line 52) | class Scaffold:
    method __init__ (line 75) | def __init__(
    method __repr__ (line 217) | def __repr__(self) -> str:
    method _check_setup_finished (line 220) | def _check_setup_finished(self, f_name: str) -> None:
    method static_folder (line 224) | def static_folder(self) -> str | None:
    method static_folder (line 234) | def static_folder(self, value: str | os.PathLike[str] | None) -> None:
    method has_static_folder (line 241) | def has_static_folder(self) -> bool:
    method static_url_path (line 249) | def static_url_path(self) -> str | None:
    method static_url_path (line 265) | def static_url_path(self, value: str | None) -> None:
    method jinja_loader (line 272) | def jinja_loader(self) -> BaseLoader | None:
    method _method_route (line 284) | def _method_route(
    method get (line 296) | def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_...
    method post (line 304) | def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T...
    method put (line 312) | def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_...
    method delete (line 320) | def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route],...
    method patch (line 328) | def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], ...
    method route (line 336) | def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], ...
    method add_url_rule (line 368) | def add_url_rule(
    method endpoint (line 436) | def endpoint(self, endpoint: str) -> t.Callable[[F], F]:
    method before_request (line 460) | def before_request(self, f: T_before_request) -> T_before_request:
    method after_request (line 487) | def after_request(self, f: T_after_request) -> T_after_request:
    method teardown_request (line 508) | def teardown_request(self, f: T_teardown) -> T_teardown:
    method context_processor (line 542) | def context_processor(
    method url_value_preprocessor (line 559) | def url_value_preprocessor(
    method url_defaults (line 584) | def url_defaults(self, f: T_url_defaults) -> T_url_defaults:
    method errorhandler (line 598) | def errorhandler(
    method register_error_handler (line 642) | def register_error_handler(
    method _get_exc_class_and_code (line 657) | def _get_exc_class_and_code(
  function _endpoint_from_view_func (line 701) | def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str:
  function _find_package_path (line 709) | def _find_package_path(import_name: str) -> str:
  function find_package (line 754) | def find_package(import_name: str) -> tuple[str | None, str]:

FILE: src/flask/sessions.py
  class SessionMixin (line 24) | class SessionMixin(MutableMapping[str, t.Any]):
    method permanent (line 28) | def permanent(self) -> bool:
    method permanent (line 33) | def permanent(self, value: bool) -> None:
  class SecureCookieSession (line 57) | class SecureCookieSession(CallbackDict[str, t.Any], SessionMixin):
    method __init__ (line 73) | def __init__(
  class NullSession (line 83) | class NullSession(SecureCookieSession):
    method _fail (line 89) | def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn:
  class SessionInterface (line 100) | class SessionInterface:
    method make_null_session (line 150) | def make_null_session(self, app: Flask) -> NullSession:
    method is_null_session (line 162) | def is_null_session(self, obj: object) -> bool:
    method get_cookie_name (line 171) | def get_cookie_name(self, app: Flask) -> str:
    method get_cookie_domain (line 175) | def get_cookie_domain(self, app: Flask) -> str | None:
    method get_cookie_path (line 187) | def get_cookie_path(self, app: Flask) -> str:
    method get_cookie_httponly (line 195) | def get_cookie_httponly(self, app: Flask) -> bool:
    method get_cookie_secure (line 202) | def get_cookie_secure(self, app: Flask) -> bool:
    method get_cookie_samesite (line 208) | def get_cookie_samesite(self, app: Flask) -> str | None:
    method get_cookie_partitioned (line 215) | def get_cookie_partitioned(self, app: Flask) -> bool:
    method get_expiration_time (line 223) | def get_expiration_time(self, app: Flask, session: SessionMixin) -> da...
    method should_set_cookie (line 233) | def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool:
    method open_session (line 249) | def open_session(self, app: Flask, request: Request) -> SessionMixin |...
    method save_session (line 263) | def save_session(
  function _lazy_sha1 (line 276) | def _lazy_sha1(string: bytes = b"") -> t.Any:
  class SecureCookieSessionInterface (line 284) | class SecureCookieSessionInterface(SessionInterface):
    method get_signing_serializer (line 303) | def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer...
    method open_session (line 323) | def open_session(self, app: Flask, request: Request) -> SecureCookieSe...
    method save_session (line 337) | def save_session(

FILE: src/flask/templating.py
  function _default_template_ctx_processor (line 21) | def _default_template_ctx_processor() -> dict[str, t.Any]:
  class Environment (line 36) | class Environment(BaseEnvironment):
    method __init__ (line 42) | def __init__(self, app: App, **options: t.Any) -> None:
  class DispatchingJinjaLoader (line 49) | class DispatchingJinjaLoader(BaseLoader):
    method __init__ (line 54) | def __init__(self, app: App) -> None:
    method get_source (line 57) | def get_source(
    method _get_source_explained (line 64) | def _get_source_explained(
    method _get_source_fast (line 88) | def _get_source_fast(
    method _iter_loaders (line 98) | def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, B...
    method list_templates (line 108) | def list_templates(self) -> list[str]:
  function _render (line 123) | def _render(ctx: AppContext, template: Template, context: dict[str, t.An...
  function render_template (line 136) | def render_template(
  function render_template_string (line 151) | def render_template_string(source: str, **context: t.Any) -> str:
  function _stream (line 163) | def _stream(
  function stream_template (line 181) | def stream_template(
  function stream_template_string (line 200) | def stream_template_string(source: str, **context: t.Any) -> t.Iterator[...

FILE: src/flask/testing.py
  class EnvironBuilder (line 27) | class EnvironBuilder(werkzeug.test.EnvironBuilder):
    method __init__ (line 49) | def __init__(
    method json_dumps (line 88) | def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
  function _get_werkzeug_version (line 100) | def _get_werkzeug_version() -> str:
  class FlaskClient (line 109) | class FlaskClient(Client):
    method __init__ (line 125) | def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
    method session_transaction (line 136) | def session_transaction(
    method _copy_environ (line 185) | def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment:
    method _request_from_builder_args (line 193) | def _request_from_builder_args(
    method open (line 204) | def open(
    method __enter__ (line 249) | def __enter__(self) -> FlaskClient:
    method __exit__ (line 255) | def __exit__(
  class FlaskCliRunner (line 265) | class FlaskCliRunner(CliRunner):
    method __init__ (line 271) | def __init__(self, app: Flask, **kwargs: t.Any) -> None:
    method invoke (line 275) | def invoke(  # type: ignore

FILE: src/flask/views.py
  class View (line 16) | class View:
    method dispatch_request (line 78) | def dispatch_request(self) -> ft.ResponseReturnValue:
    method as_view (line 86) | def as_view(
  class MethodView (line 138) | class MethodView(View):
    method __init_subclass__ (line 165) | def __init_subclass__(cls, **kwargs: t.Any) -> None:
    method dispatch_request (line 182) | def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:

FILE: src/flask/wrappers.py
  class Request (line 18) | class Request(RequestBase):
    method max_content_length (line 60) | def max_content_length(self) -> int | None:
    method max_content_length (line 89) | def max_content_length(self, value: int | None) -> None:
    method max_form_memory_size (line 93) | def max_form_memory_size(self) -> int | None:
    method max_form_memory_size (line 116) | def max_form_memory_size(self, value: int | None) -> None:
    method max_form_parts (line 120) | def max_form_parts(self) -> int | None:
    method max_form_parts (line 143) | def max_form_parts(self, value: int | None) -> None:
    method endpoint (line 147) | def endpoint(self) -> str | None:
    method blueprint (line 162) | def blueprint(self) -> str | None:
    method blueprints (line 181) | def blueprints(self) -> list[str]:
    method _load_form_data (line 197) | def _load_form_data(self) -> None:
    method on_json_loading_failed (line 212) | def on_json_loading_failed(self, e: ValueError | None) -> t.Any:
  class Response (line 222) | class Response(ResponseBase):
    method max_cookie_size (line 247) | def max_cookie_size(self) -> int:  # type: ignore

FILE: tests/conftest.py
  function _standard_os_environ (line 12) | def _standard_os_environ():
  function _reset_os_environ (line 37) | def _reset_os_environ(monkeypatch, _standard_os_environ):
  function app (line 45) | def app():
  function app_ctx (line 55) | def app_ctx(app):
  function req_ctx (line 61) | def req_ctx(app):
  function client (line 67) | def client(app):
  function test_apps (line 72) | def test_apps(monkeypatch):
  function leak_detector (line 85) | def leak_detector():
  function modules_tmp_path (line 100) | def modules_tmp_path(tmp_path, monkeypatch):
  function modules_tmp_path_prefix (line 109) | def modules_tmp_path_prefix(modules_tmp_path, monkeypatch):
  function site_packages (line 115) | def site_packages(modules_tmp_path, monkeypatch):
  function purge_module (line 125) | def purge_module(request):

FILE: tests/test_appctx.py
  function test_basic_url_generation (line 10) | def test_basic_url_generation(app):
  function test_url_generation_requires_server_name (line 23) | def test_url_generation_requires_server_name(app):
  function test_url_generation_without_context_fails (line 29) | def test_url_generation_without_context_fails():
  function test_request_context_means_app_context (line 34) | def test_request_context_means_app_context(app):
  function test_app_context_provides_current_app (line 40) | def test_app_context_provides_current_app(app):
  function test_app_tearing_down (line 46) | def test_app_tearing_down(app):
  function test_app_tearing_down_with_previous_exception (line 59) | def test_app_tearing_down_with_previous_exception(app):
  function test_app_tearing_down_with_handled_exception_by_except_block (line 77) | def test_app_tearing_down_with_handled_exception_by_except_block(app):
  function test_app_tearing_down_with_handled_exception_by_app_handler (line 93) | def test_app_tearing_down_with_handled_exception_by_app_handler(app, cli...
  function test_app_tearing_down_with_unhandled_exception (line 116) | def test_app_tearing_down_with_unhandled_exception(app, client):
  function test_app_ctx_globals_methods (line 139) | def test_app_ctx_globals_methods(app, app_ctx):
  function test_custom_app_ctx_globals_class (line 162) | def test_custom_app_ctx_globals_class(app):
  function test_context_refcounts (line 172) | def test_context_refcounts(app, client):
  function test_clean_pop (line 197) | def test_clean_pop(app):
  function test_robust_teardown (line 216) | def test_robust_teardown(app: flask.Flask, client: FlaskClient) -> None:

FILE: tests/test_apps/blueprintapp/apps/admin/__init__.py
  function index (line 14) | def index():
  function index2 (line 19) | def index2():

FILE: tests/test_apps/blueprintapp/apps/frontend/__init__.py
  function index (line 8) | def index():
  function missing_template (line 13) | def missing_template():

FILE: tests/test_apps/cliapp/factory.py
  function create_app (line 4) | def create_app():
  function create_app2 (line 8) | def create_app2(foo, bar):
  function no_app (line 12) | def no_app():

FILE: tests/test_apps/helloworld/hello.py
  function hello (line 7) | def hello():

FILE: tests/test_async.py
  class AppError (line 14) | class AppError(Exception):
  class BlueprintError (line 18) | class BlueprintError(Exception):
  class AsyncView (line 22) | class AsyncView(View):
    method dispatch_request (line 25) | async def dispatch_request(self):
  class AsyncMethodView (line 30) | class AsyncMethodView(MethodView):
    method get (line 31) | async def get(self):
    method post (line 35) | async def post(self):
  function _async_app (line 41) | def _async_app():
  function test_async_route (line 82) | def test_async_route(path, async_app):
  function test_async_error_handler (line 91) | def test_async_error_handler(path, async_app):
  function test_async_before_after_request (line 97) | def test_async_before_after_request():

FILE: tests/test_basic.py
  function test_options_work (line 32) | def test_options_work(app, client):
  function test_options_on_multiple_rules (line 42) | def test_options_on_multiple_rules(app, client):
  function test_method_route (line 56) | def test_method_route(app, client, method):
  function test_method_route_no_methods (line 67) | def test_method_route_no_methods(app):
  function test_provide_automatic_options_attr_disable (line 72) | def test_provide_automatic_options_attr_disable(
  function test_provide_automatic_options_attr_enable (line 86) | def test_provide_automatic_options_attr_enable(
  function test_provide_automatic_options_arg_disable (line 103) | def test_provide_automatic_options_arg_disable(
  function test_provide_automatic_options_method_disable (line 116) | def test_provide_automatic_options_method_disable(
  function test_request_dispatching (line 129) | def test_request_dispatching(app, client):
  function test_disallow_string_for_allowed_methods (line 152) | def test_disallow_string_for_allowed_methods(app):
  function test_url_mapping (line 157) | def test_url_mapping(app, client):
  function test_werkzeug_routing (line 193) | def test_werkzeug_routing(app, client):
  function test_endpoint_decorator (line 214) | def test_endpoint_decorator(app, client):
  function test_session_accessed (line 234) | def test_session_accessed(app: flask.Flask, client: FlaskClient) -> None:
  function test_session_path (line 276) | def test_session_path(app, client):
  function test_session_using_application_root (line 288) | def test_session_using_application_root(app, client):
  function test_session_using_session_settings (line 310) | def test_session_using_session_settings(app, client):
  function test_session_using_samesite_attribute (line 353) | def test_session_using_samesite_attribute(app, client):
  function test_missing_session (line 380) | def test_missing_session(app):
  function test_session_secret_key_fallbacks (line 393) | def test_session_secret_key_fallbacks(app, client) -> None:
  function test_session_expiration (line 421) | def test_session_expiration(app, client):
  function test_session_stored_last (line 453) | def test_session_stored_last(app, client):
  function test_session_special_types (line 467) | def test_session_special_types(app, client):
  function test_session_cookie_setting (line 498) | def test_session_cookie_setting(app):
  function test_session_vary_cookie (line 539) | def test_session_vary_cookie(app, client):
  function test_session_refresh_vary (line 600) | def test_session_refresh_vary(app, client):
  function test_flashes (line 617) | def test_flashes(app, req_ctx):
  function test_extended_flashing (line 626) | def test_extended_flashing(app):
  function test_request_processing (line 707) | def test_request_processing(app, client):
  function test_request_preprocessing_early_return (line 732) | def test_request_preprocessing_early_return(app, client):
  function test_after_request_processing (line 759) | def test_after_request_processing(app, client):
  function test_teardown_request_handler (line 774) | def test_teardown_request_handler(app, client):
  function test_teardown_request_handler_debug_mode (line 792) | def test_teardown_request_handler_debug_mode(app, client):
  function test_teardown_request_handler_error (line 810) | def test_teardown_request_handler_error(app, client):
  function test_before_after_request_order (line 848) | def test_before_after_request_order(app, client):
  function test_error_handling (line 886) | def test_error_handling(app, client):
  function test_error_handling_processing (line 924) | def test_error_handling_processing(app, client):
  function test_baseexception_error_handling (line 945) | def test_baseexception_error_handling(app, client):
  function test_before_request_and_routing_errors (line 956) | def test_before_request_and_routing_errors(app, client):
  function test_user_error_handling (line 970) | def test_user_error_handling(app, client):
  function test_http_error_subclass_handling (line 986) | def test_http_error_subclass_handling(app, client):
  function test_errorhandler_precedence (line 1018) | def test_errorhandler_precedence(app, client):
  function test_trap_bad_request_key_error (line 1055) | def test_trap_bad_request_key_error(app, client, debug, trap, expect_key...
  function test_trapping_of_all_http_exceptions (line 1086) | def test_trapping_of_all_http_exceptions(app, client):
  function test_error_handler_after_processor_error (line 1097) | def test_error_handler_after_processor_error(app, client):
  function test_enctype_debug_helper (line 1126) | def test_enctype_debug_helper(app, client):
  function test_response_types (line 1141) | def test_response_types(app, client):
  function test_response_type_errors (line 1235) | def test_response_type_errors():
  function test_make_response (line 1284) | def test_make_response(app, req_ctx):
  function test_make_response_with_response_instance (line 1306) | def test_make_response_with_response_instance(app, req_ctx):
  function test_jsonify_no_prettyprint (line 1328) | def test_jsonify_no_prettyprint(app, compact):
  function test_jsonify_mimetype (line 1336) | def test_jsonify_mimetype(app, req_ctx):
  function test_json_dump_dataclass (line 1343) | def test_json_dump_dataclass(app, req_ctx):
  function test_jsonify_args_and_kwargs_check (line 1352) | def test_jsonify_args_and_kwargs_check(app, req_ctx):
  function test_url_generation (line 1358) | def test_url_generation(app, req_ctx):
  function test_build_error_handler (line 1370) | def test_build_error_handler(app):
  function test_build_error_handler_reraise (line 1396) | def test_build_error_handler_reraise(app):
  function test_url_for_passes_special_values_to_build_error_handler (line 1407) | def test_url_for_passes_special_values_to_build_error_handler(app):
  function test_static_files (line 1422) | def test_static_files(app, client):
  function test_static_url_path (line 1432) | def test_static_url_path():
  function test_static_url_path_with_ending_slash (line 1443) | def test_static_url_path_with_ending_slash():
  function test_static_url_empty_path (line 1454) | def test_static_url_empty_path(app):
  function test_static_url_empty_path_default (line 1461) | def test_static_url_empty_path_default(app):
  function test_static_folder_with_pathlib_path (line 1468) | def test_static_folder_with_pathlib_path(app):
  function test_static_folder_with_ending_slash (line 1477) | def test_static_folder_with_ending_slash():
  function test_static_route_with_host_matching (line 1488) | def test_static_route_with_host_matching():
  function test_request_locals (line 1510) | def test_request_locals():
  function test_server_name_matching (line 1526) | def test_server_name_matching(
  function test_server_name_subdomain (line 1562) | def test_server_name_subdomain():
  function test_exception_propagation (line 1608) | def test_exception_propagation(app, client, key):
  function test_werkzeug_passthrough_errors (line 1628) | def test_werkzeug_passthrough_errors(
  function test_url_processors (line 1642) | def test_url_processors(app, client):
  function test_inject_blueprint_url_defaults (line 1671) | def test_inject_blueprint_url_defaults(app):
  function test_nonascii_pathinfo (line 1695) | def test_nonascii_pathinfo(app, client):
  function test_no_setup_after_first_request (line 1704) | def test_no_setup_after_first_request(app, client):
  function test_routing_redirect_debugging (line 1719) | def test_routing_redirect_debugging(monkeypatch, app, client):
  function test_route_decorator_custom_endpoint (line 1739) | def test_route_decorator_custom_endpoint(app, client):
  function test_get_method_on_g (line 1764) | def test_get_method_on_g(app_ctx):
  function test_g_iteration_protocol (line 1772) | def test_g_iteration_protocol(app_ctx):
  function test_subdomain_basic_support (line 1780) | def test_subdomain_basic_support():
  function test_subdomain_matching (line 1800) | def test_subdomain_matching():
  function test_subdomain_matching_with_ports (line 1813) | def test_subdomain_matching_with_ports():
  function test_subdomain_matching_other_name (line 1827) | def test_subdomain_matching_other_name(matching):
  function test_multi_route_rules (line 1850) | def test_multi_route_rules(app, client):
  function test_multi_route_class_views (line 1862) | def test_multi_route_class_views(app, client):
  function test_run_defaults (line 1878) | def test_run_defaults(monkeypatch, app):
  function test_run_server_port (line 1890) | def test_run_server_port(monkeypatch, app):
  function test_run_from_config (line 1915) | def test_run_from_config(
  function test_max_cookie_size (line 1927) | def test_max_cookie_size(app, client, recwarn):
  function test_app_freed_on_zero_refcount (line 1958) | def test_app_freed_on_zero_refcount():

FILE: tests/test_blueprints.py
  function test_blueprint_specific_error_handling (line 8) | def test_blueprint_specific_error_handling(app, client):
  function test_blueprint_specific_user_error_handling (line 46) | def test_blueprint_specific_user_error_handling(app, client):
  function test_blueprint_app_error_handling (line 80) | def test_blueprint_app_error_handling(app, client):
  function test_blueprint_prefix_slash (line 120) | def test_blueprint_prefix_slash(app, client, prefix, rule, url):
  function test_blueprint_url_defaults (line 131) | def test_blueprint_url_defaults(app, client):
  function test_blueprint_url_processors (line 151) | def test_blueprint_url_processors(app, client):
  function test_templates_and_static (line 176) | def test_templates_and_static(test_apps):
  function test_default_static_max_age (line 223) | def test_default_static_max_age(app: flask.Flask) -> None:
  function test_templates_list (line 238) | def test_templates_list(test_apps):
  function test_dotted_name_not_allowed (line 245) | def test_dotted_name_not_allowed(app, client):
  function test_empty_name_not_allowed (line 250) | def test_empty_name_not_allowed(app, client):
  function test_dotted_names_from_app (line 255) | def test_dotted_names_from_app(app, client):
  function test_empty_url_defaults (line 272) | def test_empty_url_defaults(app, client):
  function test_route_decorator_custom_endpoint (line 286) | def test_route_decorator_custom_endpoint(app, client):
  function test_route_decorator_custom_endpoint_with_dots (line 318) | def test_route_decorator_custom_endpoint_with_dots(app, client):
  function test_endpoint_decorator (line 336) | def test_endpoint_decorator(app, client):
  function test_template_filter (line 353) | def test_template_filter(app):
  function test_add_template_filter (line 390) | def test_add_template_filter(app):
  function test_template_filter_with_name (line 403) | def test_template_filter_with_name(app):
  function test_add_template_filter_with_name (line 416) | def test_add_template_filter_with_name(app):
  function test_template_filter_with_template (line 429) | def test_template_filter_with_template(app, client):
  function test_template_filter_after_route_with_template (line 446) | def test_template_filter_after_route_with_template(app, client):
  function test_add_template_filter_with_template (line 462) | def test_add_template_filter_with_template(app, client):
  function test_template_filter_with_name_and_template (line 479) | def test_template_filter_with_name_and_template(app, client):
  function test_add_template_filter_with_name_and_template (line 496) | def test_add_template_filter_with_name_and_template(app, client):
  function test_template_test (line 513) | def test_template_test(app):
  function test_add_template_test (line 550) | def test_add_template_test(app):
  function test_template_test_with_name (line 563) | def test_template_test_with_name(app):
  function test_add_template_test_with_name (line 576) | def test_add_template_test_with_name(app):
  function test_template_test_with_template (line 589) | def test_template_test_with_template(app, client):
  function test_template_test_after_route_with_template (line 606) | def test_template_test_after_route_with_template(app, client):
  function test_add_template_test_with_template (line 622) | def test_add_template_test_with_template(app, client):
  function test_template_test_with_name_and_template (line 639) | def test_template_test_with_name_and_template(app, client):
  function test_add_template_test_with_name_and_template (line 656) | def test_add_template_test_with_name_and_template(app, client):
  function test_context_processing (line 673) | def test_context_processing(app, client):
  function test_template_global (line 714) | def test_template_global(app):
  function test_request_processing (line 768) | def test_request_processing(app, client):
  function test_app_request_processing (line 799) | def test_app_request_processing(app, client):
  function test_app_url_processors (line 838) | def test_app_url_processors(app, client):
  function test_nested_blueprint (line 865) | def test_nested_blueprint(app, client):
  function test_nested_callback_order (line 914) | def test_nested_callback_order(app, client):
  function test_nesting_url_prefixes (line 1003) | def test_nesting_url_prefixes(
  function test_nesting_subdomains (line 1025) | def test_nesting_subdomains(app, client) -> None:
  function test_child_and_parent_subdomain (line 1044) | def test_child_and_parent_subdomain(app, client) -> None:
  function test_unique_blueprint_names (line 1066) | def test_unique_blueprint_names(app, client) -> None:
  function test_self_registration (line 1083) | def test_self_registration(app, client) -> None:
  function test_blueprint_renaming (line 1089) | def test_blueprint_renaming(app, client) -> None:

FILE: tests/test_cli.py
  function runner (line 37) | def runner():
  function test_cli_name (line 41) | def test_cli_name(test_apps):
  function test_find_best_app (line 48) | def test_find_best_app(test_apps):
  function test_prepare_import (line 161) | def test_prepare_import(request, value, path, result):
  function test_locate_app (line 195) | def test_locate_app(test_apps, iname, aname, result):
  function test_locate_app_raises (line 217) | def test_locate_app_raises(test_apps, iname, aname):
  function test_locate_app_suppress_raise (line 222) | def test_locate_app_suppress_raise(test_apps):
  function test_get_version (line 231) | def test_get_version(test_apps, capsys):
  function test_scriptinfo (line 247) | def test_scriptinfo(test_apps, monkeypatch):
  function test_app_cli_has_app_context (line 289) | def test_app_cli_has_app_context(app, runner):
  function test_with_appcontext (line 307) | def test_with_appcontext(runner):
  function test_appgroup_app_context (line 320) | def test_appgroup_app_context(runner):
  function test_flaskgroup_app_context (line 348) | def test_flaskgroup_app_context(runner):
  function test_flaskgroup_debug (line 366) | def test_flaskgroup_debug(runner, set_debug_flag):
  function test_flaskgroup_nested (line 385) | def test_flaskgroup_nested(app, runner):
  function test_no_command_echo_loading_error (line 398) | def test_no_command_echo_loading_error():
  function test_help_echo_loading_error (line 413) | def test_help_echo_loading_error():
  function test_help_echo_exception (line 428) | def test_help_echo_exception():
  class TestRoutes (line 446) | class TestRoutes:
    method app (line 448) | def app(self):
    method invoke (line 459) | def invoke(self, app, runner):
    method expect_order (line 463) | def expect_order(self, order, output):
    method test_simple (line 469) | def test_simple(self, invoke):
    method test_sort (line 474) | def test_sort(self, app, invoke):
    method test_all_methods (line 489) | def test_all_methods(self, invoke):
    method test_no_routes (line 496) | def test_no_routes(self, runner):
    method test_subdomain (line 503) | def test_subdomain(self, runner):
    method test_host (line 512) | def test_host(self, runner):
  function dotenv_not_available (line 522) | def dotenv_not_available():
  function test_load_dotenv (line 537) | def test_load_dotenv(monkeypatch):
  function test_dotenv_path (line 561) | def test_dotenv_path(monkeypatch):
  function test_dotenv_optional (line 570) | def test_dotenv_optional(monkeypatch):
  function test_disable_dotenv_from_env (line 578) | def test_disable_dotenv_from_env(monkeypatch, runner):
  function test_run_cert_path (line 585) | def test_run_cert_path():
  function test_run_cert_adhoc (line 603) | def test_run_cert_adhoc(monkeypatch):
  function test_run_cert_import (line 620) | def test_run_cert_import(monkeypatch):
  function test_run_cert_no_ssl (line 642) | def test_run_cert_no_ssl(monkeypatch):
  function test_cli_blueprints (line 649) | def test_cli_blueprints(app):
  function test_cli_empty (line 692) | def test_cli_empty(app):
  function test_run_exclude_patterns (line 701) | def test_run_exclude_patterns():

FILE: tests/test_config.py
  function common_object_test (line 13) | def common_object_test(app):
  function test_config_from_pyfile (line 19) | def test_config_from_pyfile():
  function test_config_from_object (line 25) | def test_config_from_object():
  function test_config_from_file_json (line 31) | def test_config_from_file_json():
  function test_config_from_file_toml (line 38) | def test_config_from_file_toml():
  function test_from_prefixed_env (line 48) | def test_from_prefixed_env(monkeypatch):
  function test_from_prefixed_env_custom_prefix (line 69) | def test_from_prefixed_env_custom_prefix(monkeypatch):
  function test_from_prefixed_env_nested (line 79) | def test_from_prefixed_env_nested(monkeypatch):
  function test_config_from_mapping (line 110) | def test_config_from_mapping():
  function test_config_from_class (line 132) | def test_config_from_class():
  function test_config_from_envvar (line 144) | def test_config_from_envvar(monkeypatch):
  function test_config_from_envvar_missing (line 161) | def test_config_from_envvar_missing(monkeypatch):
  function test_config_missing (line 174) | def test_config_missing():
  function test_config_missing_file (line 186) | def test_config_missing_file():
  function test_custom_config_class (line 198) | def test_custom_config_class():
  function test_session_lifetime (line 211) | def test_session_lifetime():
  function test_get_namespace (line 217) | def test_get_namespace():
  function test_from_pyfile_weird_encoding (line 244) | def test_from_pyfile_weird_encoding(tmp_path, encoding):

FILE: tests/test_converters.py
  function test_custom_converters (line 8) | def test_custom_converters(app, client):
  function test_context_available (line 29) | def test_context_available(app, client):

FILE: tests/test_helpers.py
  class FakePath (line 11) | class FakePath:
    method __init__ (line 18) | def __init__(self, path):
    method __fspath__ (line 21) | def __fspath__(self):
  class PyBytesIO (line 25) | class PyBytesIO:
    method __init__ (line 26) | def __init__(self, *args, **kwargs):
    method __getattr__ (line 29) | def __getattr__(self, name):
  class TestSendfile (line 33) | class TestSendfile:
    method test_send_file (line 34) | def test_send_file(self, app, req_ctx):
    method test_static_file (line 44) | def test_static_file(self, app, req_ctx):
    method test_send_from_directory (line 84) | def test_send_from_directory(self, app, req_ctx):
  class TestUrlFor (line 94) | class TestUrlFor:
    method test_url_for_with_anchor (line 95) | def test_url_for_with_anchor(self, app, req_ctx):
    method test_url_for_with_scheme (line 102) | def test_url_for_with_scheme(self, app, req_ctx):
    method test_url_for_with_scheme_not_external (line 112) | def test_url_for_with_scheme_not_external(self, app, req_ctx):
    method test_url_for_with_alternating_schemes (line 123) | def test_url_for_with_alternating_schemes(self, app, req_ctx):
    method test_url_with_method (line 135) | def test_url_with_method(self, app, req_ctx):
    method test_url_for_with_self (line 156) | def test_url_for_with_self(self, app, req_ctx):
  function test_redirect_no_app (line 164) | def test_redirect_no_app():
  function test_redirect_with_app (line 170) | def test_redirect_with_app(app):
  function test_abort_no_app (line 180) | def test_abort_no_app():
  function test_app_aborter_class (line 188) | def test_app_aborter_class():
  function test_abort_with_app (line 199) | def test_abort_with_app(app):
  class TestNoImports (line 209) | class TestNoImports:
    method test_name_with_import_error (line 220) | def test_name_with_import_error(self, modules_tmp_path):
  class TestStreaming (line 228) | class TestStreaming:
    method test_streaming_with_context (line 229) | def test_streaming_with_context(self, app, client):
    method test_streaming_with_context_as_decorator (line 242) | def test_streaming_with_context_as_decorator(self, app, client):
    method test_streaming_with_context_and_custom_close (line 256) | def test_streaming_with_context_and_custom_close(self, app, client):
    method test_stream_keeps_session (line 287) | def test_stream_keeps_session(self, app, client):
    method test_async_view (line 301) | def test_async_view(self, app, client):
  class TestHelpers (line 327) | class TestHelpers:
    method test_get_debug_flag (line 338) | def test_get_debug_flag(self, monkeypatch, debug, expect):
    method test_make_response (line 342) | def test_make_response(self):
  function test_open_resource (line 356) | def test_open_resource(mode):
  function test_open_resource_exceptions (line 364) | def test_open_resource_exceptions(mode):
  function test_open_resource_with_encoding (line 372) | def test_open_resource_with_encoding(tmp_path, encoding):

FILE: tests/test_instance_config.py
  function test_explicit_instance_paths (line 8) | def test_explicit_instance_paths(modules_tmp_path):
  function test_uninstalled_module_paths (line 16) | def test_uninstalled_module_paths(modules_tmp_path, purge_module):
  function test_uninstalled_package_paths (line 30) | def test_uninstalled_package_paths(modules_tmp_path, purge_module):
  function test_uninstalled_namespace_paths (line 46) | def test_uninstalled_namespace_paths(tmp_path, monkeypatch, purge_module):
  function test_installed_module_paths (line 65) | def test_installed_module_paths(
  function test_installed_package_paths (line 80) | def test_installed_package_paths(
  function test_prefix_package_paths (line 99) | def test_prefix_package_paths(

FILE: tests/test_json.py
  function test_bad_request_debug_message (line 15) | def test_bad_request_debug_message(app, client, debug):
  function test_json_bad_requests (line 30) | def test_json_bad_requests(app, client):
  function test_json_custom_mimetypes (line 39) | def test_json_custom_mimetypes(app, client):
  function test_json_as_unicode (line 51) | def test_json_as_unicode(test_value, expected, app, app_ctx):
  function test_json_dump_to_file (line 57) | def test_json_dump_to_file(app, app_ctx):
  function test_jsonify_basic_types (line 70) | def test_jsonify_basic_types(test_value, app, client):
  function test_jsonify_dicts (line 78) | def test_jsonify_dicts(app, client):
  function test_jsonify_arrays (line 105) | def test_jsonify_arrays(app, client):
  function test_jsonify_datetime (line 136) | def test_jsonify_datetime(app, client, value):
  class FixedOffset (line 145) | class FixedOffset(datetime.tzinfo):
    method __init__ (line 152) | def __init__(self, hours, name):
    method utcoffset (line 156) | def utcoffset(self, dt):
    method tzname (line 159) | def tzname(self, dt):
    method dst (line 162) | def dst(self, dt):
  function test_jsonify_aware_datetimes (line 167) | def test_jsonify_aware_datetimes(tz):
  function test_jsonify_uuid_types (line 176) | def test_jsonify_uuid_types(app, client):
  function test_json_decimal (line 191) | def test_json_decimal():
  function test_json_attr (line 196) | def test_json_attr(app, client):
  function test_tojson_filter (line 210) | def test_tojson_filter(app, req_ctx):
  function test_json_customization (line 223) | def test_json_customization(app, client):
  function _has_encoding (line 260) | def _has_encoding(name):
  function test_json_key_sorting (line 270) | def test_json_key_sorting(app, client):
  function test_html_method (line 340) | def test_html_method():

FILE: tests/test_json_tag.py
  function test_dump_load_unchanged (line 27) | def test_dump_load_unchanged(data):
  function test_duplicate_tag (line 32) | def test_duplicate_tag():
  function test_custom_tag (line 43) | def test_custom_tag():
  function test_tag_interface (line 66) | def test_tag_interface():
  function test_tag_order (line 73) | def test_tag_order():

FILE: tests/test_logging.py
  function reset_logging (line 13) | def reset_logging(pytestconfig):
  function test_logger (line 36) | def test_logger(app):
  function test_logger_debug (line 42) | def test_logger_debug(app):
  function test_existing_handler (line 48) | def test_existing_handler(app):
  function test_wsgi_errors_stream (line 54) | def test_wsgi_errors_stream(app, client):
  function test_has_level_handler (line 70) | def test_has_level_handler():
  function test_log_view_exception (line 86) | def test_log_view_exception(app, client):

FILE: tests/test_regression.py
  function test_aborting (line 4) | def test_aborting(app):

FILE: tests/test_reqctx.py
  function test_teardown_on_pop (line 16) | def test_teardown_on_pop(app):
  function test_teardown_with_previous_exception (line 30) | def test_teardown_with_previous_exception(app):
  function test_teardown_with_handled_exception (line 47) | def test_teardown_with_handled_exception(app):
  function test_proper_test_request_context (line 63) | def test_proper_test_request_context(app):
  function test_context_binding (line 107) | def test_context_binding(app):
  function test_context_test (line 123) | def test_context_test(app):
  function test_manual_context_binding (line 135) | def test_manual_context_binding(app):
  class TestGreenletContextCopying (line 149) | class TestGreenletContextCopying:
    method test_greenlet_context_copying (line 150) | def test_greenlet_context_copying(self, app, client):
    method test_greenlet_context_copying_api (line 179) | def test_greenlet_context_copying_api(self, app, client):
  function test_session_error_pops_context (line 205) | def test_session_error_pops_context():
  function test_session_dynamic_cookie_name (line 229) | def test_session_dynamic_cookie_name():
  function test_bad_environ_raises_bad_request (line 280) | def test_bad_environ_raises_bad_request():
  function test_environ_for_valid_idna_completes (line 297) | def test_environ_for_valid_idna_completes():
  function test_normal_environ_completes (line 318) | def test_normal_environ_completes():

FILE: tests/test_request.py
  function test_max_content_length (line 9) | def test_max_content_length(app: Flask, client: FlaskClient) -> None:
  function test_limit_config (line 25) | def test_limit_config(app: Flask):
  function test_trusted_hosts_config (line 57) | def test_trusted_hosts_config(app: Flask) -> None:

FILE: tests/test_session_interface.py
  function test_open_session_with_endpoint (line 6) | def test_open_session_with_endpoint():

FILE: tests/test_signals.py
  function test_template_rendered (line 4) | def test_template_rendered(app, client):
  function test_before_render_template (line 25) | def test_before_render_template():
  function test_request_signals (line 50) | def test_request_signals():
  function test_request_exception_signal (line 95) | def test_request_exception_signal():
  function test_appcontext_signals (line 115) | def test_appcontext_signals(app, client):
  function test_flash_signal (line 139) | def test_flash_signal(app):
  function test_appcontext_tearing_down_signal (line 163) | def test_appcontext_tearing_down_signal(app, client):

FILE: tests/test_subclassing.py
  function test_suppressed_exception_logging (line 6) | def test_suppressed_exception_logging():

FILE: tests/test_templating.py
  function test_context_processing (line 11) | def test_context_processing(app, client):
  function test_original_win (line 24) | def test_original_win(app, client):
  function test_simple_stream (line 33) | def test_simple_stream(app, client):
  function test_request_less_rendering (line 42) | def test_request_less_rendering(app, app_ctx):
  function test_standard_context (line 53) | def test_standard_context(app, client):
  function test_escaping (line 71) | def test_escaping(app, client):
  function test_no_escaping (line 91) | def test_no_escaping(app, client):
  function test_escaping_without_template_filename (line 113) | def test_escaping_without_template_filename(app, client, req_ctx):
  function test_macros (line 118) | def test_macros(app, req_ctx):
  function test_template_filter (line 123) | def test_template_filter(app):
  function test_add_template_filter (line 157) | def test_add_template_filter(app):
  function test_template_filter_with_name (line 167) | def test_template_filter_with_name(app):
  function test_add_template_filter_with_name (line 177) | def test_add_template_filter_with_name(app):
  function test_template_filter_with_template (line 187) | def test_template_filter_with_template(app, client):
  function test_add_template_filter_with_template (line 200) | def test_add_template_filter_with_template(app, client):
  function test_template_filter_with_name_and_template (line 214) | def test_template_filter_with_name_and_template(app, client):
  function test_add_template_filter_with_name_and_template (line 227) | def test_add_template_filter_with_name_and_template(app, client):
  function test_template_test (line 241) | def test_template_test(app):
  function test_add_template_test (line 275) | def test_add_template_test(app):
  function test_template_test_with_name (line 285) | def test_template_test_with_name(app):
  function test_add_template_test_with_name (line 295) | def test_add_template_test_with_name(app):
  function test_template_test_with_template (line 305) | def test_template_test_with_template(app, client):
  function test_add_template_test_with_template (line 318) | def test_add_template_test_with_template(app, client):
  function test_template_test_with_name_and_template (line 332) | def test_template_test_with_name_and_template(app, client):
  function test_add_template_test_with_name_and_template (line 345) | def test_add_template_test_with_name_and_template(app, client):
  function test_add_template_global (line 359) | def test_add_template_global(app, app_ctx):
  function test_custom_template_loader (line 405) | def test_custom_template_loader(client):
  function test_iterable_loader (line 423) | def test_iterable_loader(app, client):
  function test_templates_auto_reload (line 443) | def test_templates_auto_reload(app):
  function test_templates_auto_reload_debug_run (line 475) | def test_templates_auto_reload_debug_run(app, monkeypatch):
  function test_template_loader_debugging (line 488) | def test_template_loader_debugging(test_apps, monkeypatch):
  function test_custom_jinja_env (line 524) | def test_custom_jinja_env():

FILE: tests/test_testing.py
  function test_environ_defaults_from_config (line 15) | def test_environ_defaults_from_config(app, client):
  function test_environ_defaults (line 30) | def test_environ_defaults(app, client, app_ctx, req_ctx):
  function test_environ_base_default (line 42) | def test_environ_base_default(app, client):
  function test_environ_base_modified (line 57) | def test_environ_base_modified(app, client):
  function test_client_open_environ (line 73) | def test_client_open_environ(app, client, request):
  function test_specify_url_scheme (line 89) | def test_specify_url_scheme(app, client):
  function test_path_is_url (line 101) | def test_path_is_url(app):
  function test_environbuilder_json_dumps (line 109) | def test_environbuilder_json_dumps(app):
  function test_blueprint_with_subdomain (line 116) | def test_blueprint_with_subdomain():
  function test_redirect_session (line 140) | def test_redirect_session(app, client, app_ctx):
  function test_session_transactions (line 157) | def test_session_transactions(app, client):
  function test_session_transactions_no_null_sessions (line 174) | def test_session_transactions_no_null_sessions():
  function test_session_transactions_keep_context (line 184) | def test_session_transactions_keep_context(app, client, req_ctx):
  function test_session_transaction_needs_cookies (line 192) | def test_session_transaction_needs_cookies(app):
  function test_test_client_context_binding (line 200) | def test_test_client_context_binding(app, client):
  function test_reuse_client (line 229) | def test_reuse_client(client):
  function test_full_url_request (line 239) | def test_full_url_request(app, client):
  function test_json_request_and_response (line 251) | def test_json_request_and_response(app, client):
  function test_client_json_no_app_context (line 270) | def test_client_json_no_app_context(app, client):
  function test_subdomain (line 290) | def test_subdomain():
  function test_nosubdomain (line 309) | def test_nosubdomain(app, client):
  function test_cli_runner_class (line 326) | def test_cli_runner_class(app):
  function test_cli_invoke (line 338) | def test_cli_invoke(app):
  function test_cli_custom_obj (line 352) | def test_cli_custom_obj(app):
  function test_client_pop_all_preserved (line 370) | def test_client_pop_all_preserved(app, req_ctx, client):

FILE: tests/test_user_error_handler.py
  function test_error_handler_no_match (line 10) | def test_error_handler_no_match(app, client):
  function test_error_handler_subclass (line 61) | def test_error_handler_subclass(app):
  function test_error_handler_http_subclass (line 100) | def test_error_handler_http_subclass(app):
  function test_error_handler_blueprint (line 136) | def test_error_handler_blueprint(app):
  function test_default_error_handler (line 163) | def test_default_error_handler():
  class TestGenericHandlers (line 217) | class TestGenericHandlers:
    class Custom (line 220) | class Custom(Exception):
    method app (line 224) | def app(self, app):
    method report_error (line 244) | def report_error(self, e):
    method test_handle_class_or_code (line 253) | def test_handle_class_or_code(self, app, client, to_handle):
    method test_handle_generic_http (line 269) | def test_handle_generic_http(self, app, client):
    method test_handle_generic (line 283) | def test_handle_generic(self, app, client):

FILE: tests/test_views.py
  function common_test (line 8) | def common_test(app):
  function test_basic_view (line 18) | def test_basic_view(app):
  function test_method_based_view (line 29) | def test_method_based_view(app):
  function test_view_patching (line 42) | def test_view_patching(app):
  function test_view_inheritance (line 63) | def test_view_inheritance(app, client):
  function test_view_decorators (line 81) | def test_view_decorators(app, client):
  function test_view_provide_automatic_options_attr_disable (line 102) | def test_view_provide_automatic_options_attr_disable(
  function test_view_provide_automatic_options_attr_enable (line 118) | def test_view_provide_automatic_options_attr_enable(
  function test_provide_automatic_options_method_disable (line 137) | def test_provide_automatic_options_method_disable(
  function test_implicit_head (line 153) | def test_implicit_head(app, client):
  function test_explicit_head (line 167) | def test_explicit_head(app, client):
  function test_endpoint_override (line 183) | def test_endpoint_override(app):
  function test_methods_var_inheritance (line 201) | def test_methods_var_inheritance(app, client):
  function test_multiple_inheritance (line 219) | def test_multiple_inheritance(app, client):
  function test_remove_method_from_parent (line 238) | def test_remove_method_from_parent(app, client):
  function test_init_once (line 257) | def test_init_once(app, client):

FILE: tests/type_check/typing_app_decorators.py
  function after_sync (line 10) | def after_sync(response: Response) -> Response:
  function after_async (line 15) | async def after_async(response: Response) -> Response:
  function before_sync (line 20) | def before_sync() -> None: ...
  function before_async (line 24) | async def before_async() -> None: ...
  function teardown_sync (line 28) | def teardown_sync(exc: BaseException | None) -> None: ...
  function teardown_async (line 32) | async def teardown_async(exc: BaseException | None) -> None: ...

FILE: tests/type_check/typing_error_handler.py
  function handle_400 (line 16) | def handle_400(e: BadRequest) -> str:
  function handle_custom (line 21) | def handle_custom(e: ValueError) -> str:
  function handle_accept_base (line 26) | def handle_accept_base(e: Exception) -> str:
  function handle_multiple (line 32) | def handle_multiple(e: BadRequest | NotFound) -> str:

FILE: tests/type_check/typing_route.py
  function hello_str (line 17) | def hello_str() -> str:
  function hello_bytes (line 22) | def hello_bytes() -> bytes:
  function hello_json (line 27) | def hello_json() -> Response:
  function hello_json_dict (line 32) | def hello_json_dict() -> dict[str, t.Any]:
  function hello_json_list (line 37) | def hello_json_list() -> list[t.Any]:
  class StatusJSON (line 41) | class StatusJSON(t.TypedDict):
  function typed_dict (line 46) | def typed_dict() -> StatusJSON:
  function hello_generator (line 51) | def hello_generator() -> t.Generator[str, None, None]:
  function hello_generator_expression (line 60) | def hello_generator_expression() -> t.Iterator[bytes]:
  function hello_iterator (line 65) | def hello_iterator() -> t.Iterator[str]:
  function tuple_status (line 71) | def tuple_status(code: int = 200) -> tuple[str, int]:
  function tuple_status_enum (line 76) | def tuple_status_enum() -> tuple[str, int]:
  function tuple_headers (line 81) | def tuple_headers() -> tuple[str, dict[str, str]]:
  function return_template (line 87) | def return_template(name: str | None = None) -> str:
  function return_template_stream (line 92) | def return_template_stream() -> t.Iterator[str]:
  function async_route (line 97) | async def async_route() -> str:
  class RenderTemplateView (line 101) | class RenderTemplateView(View):
    method __init__ (line 102) | def __init__(self: RenderTemplateView, template_name: str) -> None:
    method dispatch_request (line 105) | def dispatch_request(self: RenderTemplateView) -> str:
Condensed preview — 226 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,217K chars).
[
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 434,
    "preview": "{\n  \"name\": \"pallets/flask\",\n  \"image\": \"mcr.microsoft.com/devcontainers/python:3\",\n  \"customizations\": {\n    \"vscode\": "
  },
  {
    "path": ".devcontainer/on-create-command.sh",
    "chars": 165,
    "preview": "#!/bin/bash\nset -e\npython3 -m venv --upgrade-deps .venv\n. .venv/bin/activate\npip install -r requirements/dev.txt\npip ins"
  },
  {
    "path": ".editorconfig",
    "chars": 233,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nend_of"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 615,
    "preview": "---\nname: Bug report\nabout: Report a bug in Flask (not other projects which depend on Flask)\n---\n\n<!--\nThis issue tracke"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 511,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Security issue\n    url: https://github.com/pallets/flask/security/a"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 416,
    "preview": "---\nname: Feature request\nabout: Suggest a new feature for Flask\n---\n\n<!--\nReplace this comment with a description of wh"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 822,
    "preview": "<!--\nBefore opening a PR, open a ticket describing the issue or feature the\nPR will address. An issue is not required fo"
  },
  {
    "path": ".github/workflows/lock.yaml",
    "chars": 741,
    "preview": "name: Lock inactive closed issues\n# Lock closed issues that have not received any further activity for two weeks.\n# This"
  },
  {
    "path": ".github/workflows/pre-commit.yaml",
    "chars": 1054,
    "preview": "name: pre-commit\non:\n  pull_request:\n  push:\n    branches: [main, stable]\npermissions: {}\nconcurrency:\n  group: ${{ gith"
  },
  {
    "path": ".github/workflows/publish.yaml",
    "chars": 2041,
    "preview": "name: Publish\non:\n  push:\n    tags: ['*']\npermissions: {}\nconcurrency:\n  group: publish-${{ github.event.push.ref }}\n  c"
  },
  {
    "path": ".github/workflows/tests.yaml",
    "chars": 2269,
    "preview": "name: Tests\non:\n  pull_request:\n    paths-ignore: ['docs/**', 'README.md']\n  push:\n    branches: [main, stable]\n    path"
  },
  {
    "path": ".github/workflows/zizmor.yaml",
    "chars": 654,
    "preview": "name: GitHub Actions security analysis with zizmor\non:\n  pull_request:\n    paths: [\"**/*.yaml?\"]\n  push:\n    branches: ["
  },
  {
    "path": ".gitignore",
    "chars": 74,
    "preview": ".idea/\n.vscode/\n__pycache__/\ndist/\n.coverage*\nhtmlcov/\n.tox/\ndocs/_build/\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 827,
    "preview": "repos:\n  - repo: https://github.com/astral-sh/ruff-pre-commit\n    rev: b969e2851312ca2b24bbec879ba4954341d1bd12  # froze"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 242,
    "preview": "version: 2\nbuild:\n  os: ubuntu-24.04\n  tools:\n    python: '3.13'\n  commands:\n    - asdf plugin add uv\n    - asdf install"
  },
  {
    "path": "CHANGES.rst",
    "chars": 73377,
    "preview": "Version 3.2.0\n-------------\n\nUnreleased\n\n-   Drop support for Python 3.9. :pr:`5730`\n-   Remove previously deprecated co"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1475,
    "preview": "Copyright 2010 Pallets\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted p"
  },
  {
    "path": "README.md",
    "chars": 1639,
    "preview": "<div align=\"center\"><img src=\"https://raw.githubusercontent.com/pallets/flask/refs/heads/stable/docs/_static/flask-name."
  },
  {
    "path": "docs/Makefile",
    "chars": 634,
    "preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the "
  },
  {
    "path": "docs/api.rst",
    "chars": 21212,
    "preview": "API\n===\n\n.. module:: flask\n\nThis part of the documentation covers all the interfaces of Flask. For\nparts where Flask dep"
  },
  {
    "path": "docs/appcontext.rst",
    "chars": 7691,
    "preview": "The App and Request Context\n===========================\n\nThe context keeps track of data and objects during a request, C"
  },
  {
    "path": "docs/async-await.rst",
    "chars": 4709,
    "preview": ".. _async_await:\n\nUsing ``async`` and ``await``\n=============================\n\n.. versionadded:: 2.0\n\nRoutes, error hand"
  },
  {
    "path": "docs/blueprints.rst",
    "chars": 12559,
    "preview": "Modular Applications with Blueprints\n====================================\n\n.. currentmodule:: flask\n\n.. versionadded:: 0"
  },
  {
    "path": "docs/changes.rst",
    "chars": 45,
    "preview": "Changes\n=======\n\n.. include:: ../CHANGES.rst\n"
  },
  {
    "path": "docs/cli.rst",
    "chars": 16701,
    "preview": ".. currentmodule:: flask\n\nCommand Line Interface\n======================\n\nInstalling Flask installs the ``flask`` script,"
  },
  {
    "path": "docs/conf.py",
    "chars": 3386,
    "preview": "import packaging.version\nfrom pallets_sphinx_themes import get_version\nfrom pallets_sphinx_themes import ProjectLink\n\n# "
  },
  {
    "path": "docs/config.rst",
    "chars": 28998,
    "preview": "Configuration Handling\n======================\n\nApplications need some kind of configuration.  There are different settin"
  },
  {
    "path": "docs/contributing.rst",
    "chars": 274,
    "preview": "Contributing\n============\n\nSee the Pallets `detailed contributing documentation <contrib_>`_ for many ways\nto contribute"
  },
  {
    "path": "docs/debugging.rst",
    "chars": 3462,
    "preview": "Debugging Application Errors\n============================\n\n\nIn Production\n-------------\n\n**Do not run the development se"
  },
  {
    "path": "docs/deploying/apache-httpd.rst",
    "chars": 2364,
    "preview": "Apache httpd\n============\n\n`Apache httpd`_ is a fast, production level HTTP server. When serving\nyour application with o"
  },
  {
    "path": "docs/deploying/asgi.rst",
    "chars": 673,
    "preview": "ASGI\n====\n\nIf you'd like to use an ASGI server you will need to utilise WSGI to\nASGI middleware. The asgiref\n`WsgiToAsgi"
  },
  {
    "path": "docs/deploying/eventlet.rst",
    "chars": 141,
    "preview": ":orphan:\n\neventlet\n========\n\n`Eventlet is no longer maintained.`__ Use :doc:`/deploying/gevent` instead.\n\n__ https://eve"
  },
  {
    "path": "docs/deploying/gevent.rst",
    "chars": 2248,
    "preview": "gevent\n======\n\nPrefer using :doc:`gunicorn` or :doc:`uwsgi` with gevent workers rather\nthan using `gevent`_ directly. Gu"
  },
  {
    "path": "docs/deploying/gunicorn.rst",
    "chars": 3645,
    "preview": "Gunicorn\n========\n\n`Gunicorn`_ is a pure Python WSGI server with simple configuration and\nmultiple worker implementation"
  },
  {
    "path": "docs/deploying/index.rst",
    "chars": 3173,
    "preview": "Deploying to Production\n=======================\n\nAfter developing your application, you'll want to make it available\npub"
  },
  {
    "path": "docs/deploying/mod_wsgi.rst",
    "chars": 2813,
    "preview": "mod_wsgi\n========\n\n`mod_wsgi`_ is a WSGI server integrated with the `Apache httpd`_ server.\nThe modern `mod_wsgi-express"
  },
  {
    "path": "docs/deploying/nginx.rst",
    "chars": 2316,
    "preview": "nginx\n=====\n\n`nginx`_ is a fast, production level HTTP server. When serving your\napplication with one of the WSGI server"
  },
  {
    "path": "docs/deploying/proxy_fix.rst",
    "chars": 1365,
    "preview": "Tell Flask it is Behind a Proxy\n===============================\n\nWhen using a reverse proxy, or many Python hosting plat"
  },
  {
    "path": "docs/deploying/uwsgi.rst",
    "chars": 4734,
    "preview": "uWSGI\n=====\n\n`uWSGI`_ is a fast, compiled server suite with extensive configuration\nand capabilities beyond a basic serv"
  },
  {
    "path": "docs/deploying/waitress.rst",
    "chars": 2337,
    "preview": "Waitress\n========\n\n`Waitress`_ is a pure Python WSGI server.\n\n*   It is easy to configure.\n*   It supports Windows direc"
  },
  {
    "path": "docs/design.rst",
    "chars": 11211,
    "preview": "Design Decisions in Flask\n=========================\n\nIf you are curious why Flask does certain things the way it does an"
  },
  {
    "path": "docs/errorhandling.rst",
    "chars": 18373,
    "preview": "Handling Application Errors\n===========================\n\nApplications fail, servers fail. Sooner or later you will see a"
  },
  {
    "path": "docs/extensiondev.rst",
    "chars": 12918,
    "preview": "Flask Extension Development\n===========================\n\n.. currentmodule:: flask\n\nExtensions are extra packages that ad"
  },
  {
    "path": "docs/extensions.rst",
    "chars": 1372,
    "preview": "Extensions\n==========\n\nExtensions are extra packages that add functionality to a Flask\napplication. For example, an exte"
  },
  {
    "path": "docs/gevent.rst",
    "chars": 4075,
    "preview": "Async with Gevent\n=================\n\n`Gevent`_ patches Python's standard library to run within special async workers\ncal"
  },
  {
    "path": "docs/index.rst",
    "chars": 2065,
    "preview": ".. rst-class:: hide-header\n\nWelcome to Flask\n================\n\n.. image:: _static/flask-name.svg\n    :align: center\n    "
  },
  {
    "path": "docs/installation.rst",
    "chars": 3768,
    "preview": "Installation\n============\n\n\nPython Version\n--------------\n\nWe recommend using the latest version of Python. Flask suppor"
  },
  {
    "path": "docs/license.rst",
    "chars": 98,
    "preview": "BSD-3-Clause License\n====================\n\n.. literalinclude:: ../LICENSE.txt\n    :language: text\n"
  },
  {
    "path": "docs/lifecycle.rst",
    "chars": 8987,
    "preview": "Application Structure and Lifecycle\n===================================\n\nFlask makes it pretty easy to write a web appli"
  },
  {
    "path": "docs/logging.rst",
    "chars": 5927,
    "preview": "Logging\n=======\n\nFlask uses standard Python :mod:`logging`. Messages about your Flask\napplication are logged with :meth:"
  },
  {
    "path": "docs/make.bat",
    "chars": 760,
    "preview": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-bu"
  },
  {
    "path": "docs/patterns/appdispatch.rst",
    "chars": 6507,
    "preview": "Application Dispatching\n=======================\n\nApplication dispatching is the process of combining multiple Flask\nappl"
  },
  {
    "path": "docs/patterns/appfactories.rst",
    "chars": 4098,
    "preview": "Application Factories\n=====================\n\nIf you are already using packages and blueprints for your application\n(:doc"
  },
  {
    "path": "docs/patterns/caching.rst",
    "chars": 653,
    "preview": "Caching\n=======\n\nWhen your application runs slow, throw some caches in.  Well, at least\nit's the easiest way to speed up"
  },
  {
    "path": "docs/patterns/celery.rst",
    "chars": 8670,
    "preview": "Background Tasks with Celery\n============================\n\nIf your application has a long running task, such as processi"
  },
  {
    "path": "docs/patterns/deferredcallbacks.rst",
    "chars": 1848,
    "preview": "Deferred Request Callbacks\n==========================\n\nOne of the design principles of Flask is that response objects ar"
  },
  {
    "path": "docs/patterns/favicon.rst",
    "chars": 2100,
    "preview": "Adding a favicon\n================\n\nA \"favicon\" is an icon used by browsers for tabs and bookmarks. This helps\nto disting"
  },
  {
    "path": "docs/patterns/fileuploads.rst",
    "chars": 7297,
    "preview": "Uploading Files\n===============\n\nAh yes, the good old problem of file uploads.  The basic idea of file\nuploads is actual"
  },
  {
    "path": "docs/patterns/flashing.rst",
    "chars": 4535,
    "preview": "Message Flashing\n================\n\nGood applications and user interfaces are all about feedback.  If the user\ndoes not g"
  },
  {
    "path": "docs/patterns/index.rst",
    "chars": 961,
    "preview": "Patterns for Flask\n==================\n\nCertain features and interactions are common enough that you will find\nthem in mo"
  },
  {
    "path": "docs/patterns/javascript.rst",
    "chars": 9038,
    "preview": "JavaScript, ``fetch``, and JSON\n===============================\n\nYou may want to make your HTML page dynamic, by changin"
  },
  {
    "path": "docs/patterns/jquery.rst",
    "chars": 96,
    "preview": ":orphan:\n\nAJAX with jQuery\n================\n\nObsolete, see :doc:`/patterns/javascript` instead.\n"
  },
  {
    "path": "docs/patterns/lazyloading.rst",
    "chars": 3847,
    "preview": "Lazily Loading Views\n====================\n\nFlask is usually used with the decorators.  Decorators are simple and you\nhav"
  },
  {
    "path": "docs/patterns/methodoverrides.rst",
    "chars": 1456,
    "preview": "Adding HTTP Method Overrides\n============================\n\nSome HTTP proxies do not support arbitrary HTTP methods or ne"
  },
  {
    "path": "docs/patterns/mongoengine.rst",
    "chars": 2857,
    "preview": "MongoDB with MongoEngine\n========================\n\nUsing a document database like MongoDB is a common alternative to\nrel"
  },
  {
    "path": "docs/patterns/packages.rst",
    "chars": 4105,
    "preview": "Large Applications as Packages\n==============================\n\nImagine a simple flask application structure that looks l"
  },
  {
    "path": "docs/patterns/requestchecksum.rst",
    "chars": 1861,
    "preview": "Request Content Checksums\n=========================\n\nVarious pieces of code can consume the request data and preprocess "
  },
  {
    "path": "docs/patterns/singlepageapplications.rst",
    "chars": 731,
    "preview": "Single-Page Applications\n========================\n\nFlask can be used to serve Single-Page Applications (SPA) by placing "
  },
  {
    "path": "docs/patterns/sqlalchemy.rst",
    "chars": 7265,
    "preview": "SQLAlchemy in Flask\n===================\n\nMany people prefer `SQLAlchemy`_ for database access.  In this case it's\nencour"
  },
  {
    "path": "docs/patterns/sqlite3.rst",
    "chars": 5028,
    "preview": "Using SQLite 3 with Flask\n=========================\n\nYou can implement a few functions to work with a SQLite connection "
  },
  {
    "path": "docs/patterns/streaming.rst",
    "chars": 3307,
    "preview": "Streaming Contents\n==================\n\nSometimes you want to send an enormous amount of data to the client, much\nmore th"
  },
  {
    "path": "docs/patterns/subclassing.rst",
    "chars": 676,
    "preview": "Subclassing Flask\n=================\n\nThe :class:`~flask.Flask` class is designed for subclassing.\n\nFor example, you may "
  },
  {
    "path": "docs/patterns/templateinheritance.rst",
    "chars": 2197,
    "preview": "Template Inheritance\n====================\n\nThe most powerful part of Jinja is template inheritance. Template inheritance"
  },
  {
    "path": "docs/patterns/urlprocessors.rst",
    "chars": 4306,
    "preview": "Using URL Processors\n====================\n\n.. versionadded:: 0.7\n\nFlask 0.7 introduces the concept of URL processors.  T"
  },
  {
    "path": "docs/patterns/viewdecorators.rst",
    "chars": 6318,
    "preview": "View Decorators\n===============\n\nPython has a really interesting feature called function decorators.  This\nallows some r"
  },
  {
    "path": "docs/patterns/wtforms.rst",
    "chars": 4708,
    "preview": "Form Validation with WTForms\n============================\n\nWhen you have to work with form data submitted by a browser v"
  },
  {
    "path": "docs/quickstart.rst",
    "chars": 30054,
    "preview": "Quickstart\n==========\n\nEager to get started? This page gives a good introduction to Flask.\nFollow :doc:`installation` to"
  },
  {
    "path": "docs/reqcontext.rst",
    "chars": 93,
    "preview": ":orphan:\n\nThe Request Context\n===================\n\nObsolete, see :doc:`/appcontext` instead.\n"
  },
  {
    "path": "docs/server.rst",
    "chars": 3712,
    "preview": ".. currentmodule:: flask\n\nDevelopment Server\n==================\n\nFlask provides a ``run`` command to run the application"
  },
  {
    "path": "docs/shell.rst",
    "chars": 2853,
    "preview": "Working with the Shell\n======================\n\nOne of the reasons everybody loves Python is the interactive shell. It al"
  },
  {
    "path": "docs/signals.rst",
    "chars": 6107,
    "preview": "Signals\n=======\n\nSignals are a lightweight way to notify subscribers of certain events during the\nlifecycle of the appli"
  },
  {
    "path": "docs/templating.rst",
    "chars": 8933,
    "preview": "Templates\n=========\n\nFlask leverages Jinja as its template engine.  You are obviously free to use\na different template e"
  },
  {
    "path": "docs/testing.rst",
    "chars": 10426,
    "preview": "Testing Flask Applications\n==========================\n\nFlask provides utilities for testing an application. This documen"
  },
  {
    "path": "docs/tutorial/blog.rst",
    "chars": 11388,
    "preview": ".. currentmodule:: flask\n\nBlog Blueprint\n==============\n\nYou'll use the same techniques you learned about when writing t"
  },
  {
    "path": "docs/tutorial/database.rst",
    "chars": 7028,
    "preview": ".. currentmodule:: flask\n\nDefine and Access the Database\n==============================\n\nThe application will use a `SQL"
  },
  {
    "path": "docs/tutorial/deploy.rst",
    "chars": 3699,
    "preview": "Deploy to Production\n====================\n\nThis part of the tutorial assumes you have a server that you want to\ndeploy y"
  },
  {
    "path": "docs/tutorial/factory.rst",
    "chars": 5878,
    "preview": ".. currentmodule:: flask\n\nApplication Setup\n=================\n\nA Flask application is an instance of the :class:`Flask` "
  },
  {
    "path": "docs/tutorial/index.rst",
    "chars": 2061,
    "preview": "Tutorial\n========\n\n.. toctree::\n    :caption: Contents:\n    :maxdepth: 1\n\n    layout\n    factory\n    database\n    views\n"
  },
  {
    "path": "docs/tutorial/install.rst",
    "chars": 2838,
    "preview": "Make the Project Installable\n============================\n\nMaking your project installable means that you can build a *w"
  },
  {
    "path": "docs/tutorial/layout.rst",
    "chars": 2716,
    "preview": "Project Layout\n==============\n\nCreate a project directory and enter it:\n\n.. code-block:: none\n\n    $ mkdir flask-tutoria"
  },
  {
    "path": "docs/tutorial/next.rst",
    "chars": 1631,
    "preview": "Keep Developing!\n================\n\nYou've learned about quite a few Flask and Python concepts throughout\nthe tutorial. G"
  },
  {
    "path": "docs/tutorial/static.rst",
    "chars": 3170,
    "preview": "Static Files\n============\n\nThe authentication views and templates work, but they look very plain\nright now. Some `CSS`_ "
  },
  {
    "path": "docs/tutorial/templates.rst",
    "chars": 6962,
    "preview": ".. currentmodule:: flask\n\nTemplates\n=========\n\nYou've written the authentication views for your application, but if\nyou'"
  },
  {
    "path": "docs/tutorial/tests.rst",
    "chars": 18268,
    "preview": ".. currentmodule:: flask\n\nTest Coverage\n=============\n\nWriting unit tests for your application lets you check that the c"
  },
  {
    "path": "docs/tutorial/views.rst",
    "chars": 10924,
    "preview": ".. currentmodule:: flask\n\nBlueprints and Views\n====================\n\nA view function is the code you write to respond to"
  },
  {
    "path": "docs/views.rst",
    "chars": 10270,
    "preview": "Class-based Views\n=================\n\n.. currentmodule:: flask.views\n\nThis page introduces using the :class:`View` and :c"
  },
  {
    "path": "docs/web-security.rst",
    "chars": 13085,
    "preview": "Security Considerations\n=======================\n\nWeb applications face many types of potential security problems, and it"
  },
  {
    "path": "examples/celery/README.md",
    "chars": 950,
    "preview": "Background Tasks with Celery\n============================\n\nThis example shows how to configure Celery with Flask, how to"
  },
  {
    "path": "examples/celery/make_celery.py",
    "chars": 102,
    "preview": "from task_app import create_app\n\nflask_app = create_app()\ncelery_app = flask_app.extensions[\"celery\"]\n"
  },
  {
    "path": "examples/celery/pyproject.toml",
    "chars": 381,
    "preview": "[project]\nname = \"flask-example-celery\"\nversion = \"1.0.0\"\ndescription = \"Example Flask application with Celery backgroun"
  },
  {
    "path": "examples/celery/requirements.txt",
    "chars": 1073,
    "preview": "#\n# This file is autogenerated by pip-compile with Python 3.11\n# by the following command:\n#\n#    pip-compile --resolver"
  },
  {
    "path": "examples/celery/src/task_app/__init__.py",
    "chars": 1019,
    "preview": "from celery import Celery\nfrom celery import Task\nfrom flask import Flask\nfrom flask import render_template\n\n\ndef create"
  },
  {
    "path": "examples/celery/src/task_app/tasks.py",
    "chars": 484,
    "preview": "import time\n\nfrom celery import shared_task\nfrom celery import Task\n\n\n@shared_task(ignore_result=False)\ndef add(a: int, "
  },
  {
    "path": "examples/celery/src/task_app/templates/index.html",
    "chars": 2907,
    "preview": "<!doctype html>\n<html>\n<head>\n  <meta charset=UTF-8>\n  <title>Celery Example</title>\n</head>\n<body>\n<h2>Celery Example</"
  },
  {
    "path": "examples/celery/src/task_app/views.py",
    "chars": 954,
    "preview": "from celery.result import AsyncResult\nfrom flask import Blueprint\nfrom flask import request\n\nfrom . import tasks\n\nbp = B"
  },
  {
    "path": "examples/javascript/.gitignore",
    "chars": 119,
    "preview": ".venv/\n*.pyc\n__pycache__/\ninstance/\n.cache/\n.pytest_cache/\n.coverage\nhtmlcov/\ndist/\nbuild/\n*.egg-info/\n.idea/\n*.swp\n*~\n"
  },
  {
    "path": "examples/javascript/LICENSE.txt",
    "chars": 1475,
    "preview": "Copyright 2010 Pallets\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted p"
  },
  {
    "path": "examples/javascript/README.rst",
    "chars": 1086,
    "preview": "JavaScript Ajax Example\n=======================\n\nDemonstrates how to post form data and process a JSON response using\nJa"
  },
  {
    "path": "examples/javascript/js_example/__init__.py",
    "chars": 97,
    "preview": "from flask import Flask\n\napp = Flask(__name__)\n\nfrom js_example import views  # noqa: E402, F401\n"
  },
  {
    "path": "examples/javascript/js_example/templates/base.html",
    "chars": 1178,
    "preview": "<!doctype html>\n<title>JavaScript Example</title>\n<link rel=\"stylesheet\" href=\"https://unpkg.com/normalize.css@8.0.1/nor"
  },
  {
    "path": "examples/javascript/js_example/templates/fetch.html",
    "chars": 852,
    "preview": "{% extends 'base.html' %}\n\n{% block intro %}\n  <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerG"
  },
  {
    "path": "examples/javascript/js_example/templates/jquery.html",
    "chars": 666,
    "preview": "{% extends 'base.html' %}\n\n{% block intro %}\n  <a href=\"https://jquery.com/\">jQuery</a> is a popular library that\n  adds"
  },
  {
    "path": "examples/javascript/js_example/templates/xhr.html",
    "chars": 933,
    "preview": "{% extends 'base.html' %}\n\n{% block intro %}\n  <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\""
  },
  {
    "path": "examples/javascript/js_example/views.py",
    "chars": 429,
    "preview": "from flask import jsonify\nfrom flask import render_template\nfrom flask import request\n\nfrom . import app\n\n\n@app.route(\"/"
  },
  {
    "path": "examples/javascript/pyproject.toml",
    "chars": 736,
    "preview": "[project]\nname = \"js_example\"\nversion = \"1.1.0\"\ndescription = \"Demonstrates making AJAX requests to Flask.\"\nreadme = \"RE"
  },
  {
    "path": "examples/javascript/tests/conftest.py",
    "chars": 216,
    "preview": "import pytest\n\nfrom js_example import app\n\n\n@pytest.fixture(name=\"app\")\ndef fixture_app():\n    app.testing = True\n    yi"
  },
  {
    "path": "examples/javascript/tests/test_js_example.py",
    "chars": 727,
    "preview": "import pytest\nfrom flask import template_rendered\n\n\n@pytest.mark.parametrize(\n    (\"path\", \"template_name\"),\n    (\n     "
  },
  {
    "path": "examples/tutorial/.gitignore",
    "chars": 119,
    "preview": ".venv/\n*.pyc\n__pycache__/\ninstance/\n.cache/\n.pytest_cache/\n.coverage\nhtmlcov/\ndist/\nbuild/\n*.egg-info/\n.idea/\n*.swp\n*~\n"
  },
  {
    "path": "examples/tutorial/LICENSE.txt",
    "chars": 1475,
    "preview": "Copyright 2010 Pallets\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted p"
  },
  {
    "path": "examples/tutorial/README.rst",
    "chars": 1273,
    "preview": "Flaskr\n======\n\nThe basic blog app built in the Flask `tutorial`_.\n\n.. _tutorial: https://flask.palletsprojects.com/tutor"
  },
  {
    "path": "examples/tutorial/flaskr/__init__.py",
    "chars": 1406,
    "preview": "import os\n\nfrom flask import Flask\n\n\ndef create_app(test_config=None):\n    \"\"\"Create and configure an instance of the Fl"
  },
  {
    "path": "examples/tutorial/flaskr/auth.py",
    "chars": 3296,
    "preview": "import functools\n\nfrom flask import Blueprint\nfrom flask import flash\nfrom flask import g\nfrom flask import redirect\nfro"
  },
  {
    "path": "examples/tutorial/flaskr/blog.py",
    "chars": 3305,
    "preview": "from flask import Blueprint\nfrom flask import flash\nfrom flask import g\nfrom flask import redirect\nfrom flask import ren"
  },
  {
    "path": "examples/tutorial/flaskr/db.py",
    "chars": 1317,
    "preview": "import sqlite3\nfrom datetime import datetime\n\nimport click\nfrom flask import current_app\nfrom flask import g\n\n\ndef get_d"
  },
  {
    "path": "examples/tutorial/flaskr/schema.sql",
    "chars": 498,
    "preview": "-- Initialize the database.\n-- Drop any existing data and create empty tables.\n\nDROP TABLE IF EXISTS user;\nDROP TABLE IF"
  },
  {
    "path": "examples/tutorial/flaskr/static/style.css",
    "chars": 1696,
    "preview": "html {\n  font-family: sans-serif;\n  background: #eee;\n  padding: 1rem;\n}\n\nbody {\n  max-width: 960px;\n  margin: 0 auto;\n "
  },
  {
    "path": "examples/tutorial/flaskr/templates/auth/login.html",
    "chars": 424,
    "preview": "{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Log In{% endblock %}</h1>\n{% endblock %}\n\n{% block "
  },
  {
    "path": "examples/tutorial/flaskr/templates/auth/register.html",
    "chars": 428,
    "preview": "{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Register{% endblock %}</h1>\n{% endblock %}\n\n{% bloc"
  },
  {
    "path": "examples/tutorial/flaskr/templates/base.html",
    "chars": 752,
    "preview": "<!doctype html>\n<title>{% block title %}{% endblock %} - Flaskr</title>\n<link rel=\"stylesheet\" href=\"{{ url_for('static'"
  },
  {
    "path": "examples/tutorial/flaskr/templates/blog/create.html",
    "chars": 447,
    "preview": "{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}New Post{% endblock %}</h1>\n{% endblock %}\n\n{% bloc"
  },
  {
    "path": "examples/tutorial/flaskr/templates/blog/index.html",
    "chars": 790,
    "preview": "{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Posts{% endblock %}</h1>\n  {% if g.user %}\n    <a c"
  },
  {
    "path": "examples/tutorial/flaskr/templates/blog/update.html",
    "chars": 690,
    "preview": "{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Edit \"{{ post['title'] }}\"{% endblock %}</h1>\n{% en"
  },
  {
    "path": "examples/tutorial/pyproject.toml",
    "chars": 771,
    "preview": "[project]\nname = \"flaskr\"\nversion = \"1.0.0\"\ndescription = \"The basic blog app built in the Flask tutorial.\"\nreadme = \"RE"
  },
  {
    "path": "examples/tutorial/tests/conftest.py",
    "chars": 1454,
    "preview": "import os\nimport tempfile\n\nimport pytest\n\nfrom flaskr import create_app\nfrom flaskr.db import get_db\nfrom flaskr.db impo"
  },
  {
    "path": "examples/tutorial/tests/data.sql",
    "chars": 394,
    "preview": "INSERT INTO user (username, password)\nVALUES\n  ('test', 'pbkdf2:sha256:50000$TCI4GzcX$0de171a4f4dac32e3364c7ddc7c14f3e2f"
  },
  {
    "path": "examples/tutorial/tests/test_auth.py",
    "chars": 2070,
    "preview": "import pytest\nfrom flask import g\nfrom flask import session\n\nfrom flaskr.db import get_db\n\n\ndef test_register(client, ap"
  },
  {
    "path": "examples/tutorial/tests/test_blog.py",
    "chars": 2503,
    "preview": "import pytest\n\nfrom flaskr.db import get_db\n\n\ndef test_index(client, auth):\n    response = client.get(\"/\")\n    assert b\""
  },
  {
    "path": "examples/tutorial/tests/test_db.py",
    "chars": 616,
    "preview": "import sqlite3\n\nimport pytest\n\nfrom flaskr.db import get_db\n\n\ndef test_get_close_db(app):\n    with app.app_context():\n  "
  },
  {
    "path": "examples/tutorial/tests/test_factory.py",
    "chars": 298,
    "preview": "from flaskr import create_app\n\n\ndef test_config():\n    \"\"\"Test create_app without passing test config.\"\"\"\n    assert not"
  },
  {
    "path": "pyproject.toml",
    "chars": 6557,
    "preview": "[project]\nname = \"Flask\"\nversion = \"3.2.0.dev\"\ndescription = \"A simple framework for building complex web applications.\""
  },
  {
    "path": "src/flask/__init__.py",
    "chars": 2072,
    "preview": "from . import json as json\nfrom .app import Flask as Flask\nfrom .blueprints import Blueprint as Blueprint\nfrom .config i"
  },
  {
    "path": "src/flask/__main__.py",
    "chars": 30,
    "preview": "from .cli import main\n\nmain()\n"
  },
  {
    "path": "src/flask/app.py",
    "chars": 65423,
    "preview": "from __future__ import annotations\n\nimport collections.abc as cabc\nimport inspect\nimport os\nimport sys\nimport typing as "
  },
  {
    "path": "src/flask/blueprints.py",
    "chars": 4541,
    "preview": "from __future__ import annotations\n\nimport os\nimport typing as t\nfrom datetime import timedelta\n\nfrom .cli import AppGro"
  },
  {
    "path": "src/flask/cli.py",
    "chars": 36808,
    "preview": "from __future__ import annotations\n\nimport ast\nimport collections.abc as cabc\nimport importlib.metadata\nimport inspect\ni"
  },
  {
    "path": "src/flask/config.py",
    "chars": 13219,
    "preview": "from __future__ import annotations\n\nimport errno\nimport json\nimport os\nimport types\nimport typing as t\n\nfrom werkzeug.ut"
  },
  {
    "path": "src/flask/ctx.py",
    "chars": 18104,
    "preview": "from __future__ import annotations\n\nimport contextvars\nimport typing as t\nfrom functools import update_wrapper\nfrom type"
  },
  {
    "path": "src/flask/debughelpers.py",
    "chars": 6070,
    "preview": "from __future__ import annotations\n\nimport typing as t\n\nfrom jinja2.loaders import BaseLoader\nfrom werkzeug.routing impo"
  },
  {
    "path": "src/flask/globals.py",
    "chars": 2414,
    "preview": "from __future__ import annotations\n\nimport typing as t\nfrom contextvars import ContextVar\n\nfrom werkzeug.local import Lo"
  },
  {
    "path": "src/flask/helpers.py",
    "chars": 24637,
    "preview": "from __future__ import annotations\n\nimport importlib.util\nimport os\nimport sys\nimport typing as t\nfrom datetime import d"
  },
  {
    "path": "src/flask/json/__init__.py",
    "chars": 5583,
    "preview": "from __future__ import annotations\n\nimport json as _json\nimport typing as t\n\nfrom ..globals import current_app\nfrom .pro"
  },
  {
    "path": "src/flask/json/provider.py",
    "chars": 7644,
    "preview": "from __future__ import annotations\n\nimport dataclasses\nimport decimal\nimport json\nimport typing as t\nimport uuid\nimport "
  },
  {
    "path": "src/flask/json/tag.py",
    "chars": 9281,
    "preview": "\"\"\"\nTagged JSON\n~~~~~~~~~~~\n\nA compact representation for lossless serialization of non-standard JSON\ntypes. :class:`~fl"
  },
  {
    "path": "src/flask/logging.py",
    "chars": 2377,
    "preview": "from __future__ import annotations\n\nimport logging\nimport sys\nimport typing as t\n\nfrom werkzeug.local import LocalProxy\n"
  },
  {
    "path": "src/flask/py.typed",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/flask/sansio/README.md",
    "chars": 228,
    "preview": "# Sansio\n\nThis folder contains code that can be used by alternative Flask\nimplementations, for example Quart. The code t"
  },
  {
    "path": "src/flask/sansio/app.py",
    "chars": 39382,
    "preview": "from __future__ import annotations\n\nimport logging\nimport os\nimport sys\nimport typing as t\nfrom datetime import timedelt"
  },
  {
    "path": "src/flask/sansio/blueprints.py",
    "chars": 27017,
    "preview": "from __future__ import annotations\n\nimport os\nimport typing as t\nfrom collections import defaultdict\nfrom functools impo"
  },
  {
    "path": "src/flask/sansio/scaffold.py",
    "chars": 30364,
    "preview": "from __future__ import annotations\n\nimport importlib.util\nimport os\nimport pathlib\nimport sys\nimport typing as t\nfrom co"
  },
  {
    "path": "src/flask/sessions.py",
    "chars": 14969,
    "preview": "from __future__ import annotations\n\nimport collections.abc as c\nimport hashlib\nimport typing as t\nfrom collections.abc i"
  },
  {
    "path": "src/flask/signals.py",
    "chars": 750,
    "preview": "from __future__ import annotations\n\nfrom blinker import Namespace\n\n# This namespace is only for signals provided by Flas"
  },
  {
    "path": "src/flask/templating.py",
    "chars": 7336,
    "preview": "from __future__ import annotations\n\nimport typing as t\n\nfrom jinja2 import BaseLoader\nfrom jinja2 import Environment as "
  },
  {
    "path": "src/flask/testing.py",
    "chars": 10114,
    "preview": "from __future__ import annotations\n\nimport importlib.metadata\nimport typing as t\nfrom contextlib import contextmanager\nf"
  },
  {
    "path": "src/flask/typing.py",
    "chars": 3114,
    "preview": "from __future__ import annotations\n\nimport collections.abc as cabc\nimport typing as t\n\nif t.TYPE_CHECKING:  # pragma: no"
  },
  {
    "path": "src/flask/views.py",
    "chars": 6962,
    "preview": "from __future__ import annotations\n\nimport typing as t\n\nfrom . import typing as ft\nfrom .globals import current_app\nfrom"
  },
  {
    "path": "src/flask/wrappers.py",
    "chars": 9406,
    "preview": "from __future__ import annotations\n\nimport typing as t\n\nfrom werkzeug.exceptions import BadRequest\nfrom werkzeug.excepti"
  },
  {
    "path": "tests/conftest.py",
    "chars": 3293,
    "preview": "import os\nimport sys\n\nimport pytest\nfrom _pytest import monkeypatch\n\nfrom flask import Flask\nfrom flask.globals import a"
  },
  {
    "path": "tests/static/config.json",
    "chars": 54,
    "preview": "{\n    \"TEST_KEY\": \"foo\",\n    \"SECRET_KEY\": \"config\"\n}\n"
  },
  {
    "path": "tests/static/config.toml",
    "chars": 35,
    "preview": "TEST_KEY=\"foo\"\nSECRET_KEY=\"config\"\n"
  },
  {
    "path": "tests/static/index.html",
    "chars": 22,
    "preview": "<h1>Hello World!</h1>\n"
  },
  {
    "path": "tests/templates/_macro.html",
    "chars": 55,
    "preview": "{% macro hello(name) %}Hello {{ name }}!{% endmacro %}\n"
  },
  {
    "path": "tests/templates/context_template.html",
    "chars": 36,
    "preview": "<p>{{ value }}|{{ injected_value }}\n"
  },
  {
    "path": "tests/templates/escaping_template.html",
    "chars": 147,
    "preview": "{{ text }}\n{{ html }}\n{% autoescape false %}{{ text }}\n{{ html }}{% endautoescape %}\n{% autoescape true %}{{ text }}\n{{ "
  },
  {
    "path": "tests/templates/mail.txt",
    "chars": 14,
    "preview": "{{ foo}} Mail\n"
  },
  {
    "path": "tests/templates/nested/nested.txt",
    "chars": 11,
    "preview": "I'm nested\n"
  },
  {
    "path": "tests/templates/non_escaping_template.txt",
    "chars": 169,
    "preview": "{{ text }}\n{{ html }}\n{% autoescape false %}{{ text }}\n{{ html }}{% endautoescape %}\n{% autoescape true %}{{ text }}\n{{ "
  },
  {
    "path": "tests/templates/simple_template.html",
    "chars": 23,
    "preview": "<h1>{{ whiskey }}</h1>\n"
  },
  {
    "path": "tests/templates/template_filter.html",
    "chars": 26,
    "preview": "{{ value|super_reverse }}\n"
  },
  {
    "path": "tests/templates/template_test.html",
    "chars": 51,
    "preview": "{% if value is boolean %}\n    Success!\n{% endif %}\n"
  },
  {
    "path": "tests/test_appctx.py",
    "chars": 6827,
    "preview": "import sys\n\nimport pytest\n\nimport flask\nfrom flask.globals import app_ctx\nfrom flask.testing import FlaskClient\n\n\ndef te"
  },
  {
    "path": "tests/test_apps/.flaskenv",
    "chars": 28,
    "preview": "FOO=flaskenv\nBAR=bar\nEGGS=0\n"
  },
  {
    "path": "tests/test_apps/blueprintapp/__init__.py",
    "chars": 256,
    "preview": "from flask import Flask\n\napp = Flask(__name__)\napp.config[\"DEBUG\"] = True\nfrom blueprintapp.apps.admin import admin  # n"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/admin/__init__.py",
    "chars": 366,
    "preview": "from flask import Blueprint\nfrom flask import render_template\n\nadmin = Blueprint(\n    \"admin\",\n    __name__,\n    url_pre"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/admin/static/css/test.css",
    "chars": 18,
    "preview": "/* nested file */\n"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/admin/static/test.txt",
    "chars": 11,
    "preview": "Admin File\n"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/admin/templates/admin/index.html",
    "chars": 21,
    "preview": "Hello from the Admin\n"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/frontend/__init__.py",
    "chars": 327,
    "preview": "from flask import Blueprint\nfrom flask import render_template\n\nfrontend = Blueprint(\"frontend\", __name__, template_folde"
  },
  {
    "path": "tests/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html",
    "chars": 24,
    "preview": "Hello from the Frontend\n"
  },
  {
    "path": "tests/test_apps/cliapp/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_apps/cliapp/app.py",
    "chars": 52,
    "preview": "from flask import Flask\n\ntestapp = Flask(\"testapp\")\n"
  },
  {
    "path": "tests/test_apps/cliapp/factory.py",
    "chars": 169,
    "preview": "from flask import Flask\n\n\ndef create_app():\n    return Flask(\"app\")\n\n\ndef create_app2(foo, bar):\n    return Flask(\"_\".jo"
  },
  {
    "path": "tests/test_apps/cliapp/importerrorapp.py",
    "chars": 73,
    "preview": "from flask import Flask\n\nraise ImportError()\n\ntestapp = Flask(\"testapp\")\n"
  },
  {
    "path": "tests/test_apps/cliapp/inner1/__init__.py",
    "chars": 55,
    "preview": "from flask import Flask\n\napplication = Flask(__name__)\n"
  },
  {
    "path": "tests/test_apps/cliapp/inner1/inner2/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_apps/cliapp/inner1/inner2/flask.py",
    "chars": 47,
    "preview": "from flask import Flask\n\napp = Flask(__name__)\n"
  },
  {
    "path": "tests/test_apps/cliapp/message.txt",
    "chars": 38,
    "preview": "So long, and thanks for all the fish.\n"
  },
  {
    "path": "tests/test_apps/cliapp/multiapp.py",
    "chars": 67,
    "preview": "from flask import Flask\n\napp1 = Flask(\"app1\")\napp2 = Flask(\"app2\")\n"
  },
  {
    "path": "tests/test_apps/helloworld/hello.py",
    "chars": 104,
    "preview": "from flask import Flask\n\napp = Flask(__name__)\n\n\n@app.route(\"/\")\ndef hello():\n    return \"Hello World!\"\n"
  },
  {
    "path": "tests/test_apps/helloworld/wsgi.py",
    "chars": 36,
    "preview": "from hello import app  # noqa: F401\n"
  }
]

// ... and 26 more files (download for full content)

About this extraction

This page contains the full source code of the pallets/flask GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 226 files (1.1 MB), approximately 274.7k tokens, and a symbol index with 933 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!