commit
d2cb6a8a67
51 changed files with 367 additions and 289 deletions
25
.flake8
25
.flake8
|
|
@ -1,25 +0,0 @@
|
||||||
[flake8]
|
|
||||||
extend-select =
|
|
||||||
# bugbear
|
|
||||||
B
|
|
||||||
# bugbear opinions
|
|
||||||
B9
|
|
||||||
# implicit str concat
|
|
||||||
ISC
|
|
||||||
extend-ignore =
|
|
||||||
# slice notation whitespace, invalid
|
|
||||||
E203
|
|
||||||
# line length, handled by bugbear B950
|
|
||||||
E501
|
|
||||||
# bare except, handled by bugbear B001
|
|
||||||
E722
|
|
||||||
# zip with strict=, requires python >= 3.10
|
|
||||||
B905
|
|
||||||
# string formatting opinion, B028 renamed to B907
|
|
||||||
B028
|
|
||||||
B907
|
|
||||||
# up to 88 allowed by bugbear B950
|
|
||||||
max-line-length = 80
|
|
||||||
per-file-ignores =
|
|
||||||
# __init__ exports names
|
|
||||||
src/flask/__init__.py: F401
|
|
||||||
23
.github/dependabot.yml
vendored
23
.github/dependabot.yml
vendored
|
|
@ -1,9 +1,18 @@
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: github-actions
|
||||||
directory: "/"
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: "monthly"
|
interval: monthly
|
||||||
day: "monday"
|
groups:
|
||||||
time: "16:00"
|
github-actions:
|
||||||
timezone: "UTC"
|
patterns:
|
||||||
|
- '*'
|
||||||
|
- package-ecosystem: pip
|
||||||
|
directory: /requirements/
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
||||||
|
groups:
|
||||||
|
python-requirements:
|
||||||
|
patterns:
|
||||||
|
- '*'
|
||||||
|
|
|
||||||
10
.github/workflows/lock.yaml
vendored
10
.github/workflows/lock.yaml
vendored
|
|
@ -1,8 +1,8 @@
|
||||||
name: 'Lock threads'
|
name: 'Lock inactive closed issues'
|
||||||
# Lock closed issues that have not received any further activity for
|
# Lock closed issues that have not received any further activity for two weeks.
|
||||||
# two weeks. This does not close open issues, only humans may do that.
|
# This does not close open issues, only humans may do that. We find that it is
|
||||||
# We find that it is easier to respond to new issues with fresh examples
|
# easier to respond to new issues with fresh examples rather than continuing
|
||||||
# rather than continuing discussions on old issues.
|
# discussions on old issues.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
|
|
|
||||||
19
.github/workflows/publish.yaml
vendored
19
.github/workflows/publish.yaml
vendored
|
|
@ -9,12 +9,12 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
hash: ${{ steps.hash.outputs.hash }}
|
hash: ${{ steps.hash.outputs.hash }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||||
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
|
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
cache: 'pip'
|
cache: pip
|
||||||
cache-dependency-path: 'requirements/*.txt'
|
cache-dependency-path: requirements*/*.txt
|
||||||
- run: pip install -r requirements/build.txt
|
- run: pip install -r requirements/build.txt
|
||||||
# Use the commit date instead of the current date during the build.
|
# Use the commit date instead of the current date during the build.
|
||||||
- run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
|
- run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
|
||||||
|
|
@ -23,11 +23,11 @@ jobs:
|
||||||
- name: generate hash
|
- name: generate hash
|
||||||
id: hash
|
id: hash
|
||||||
run: cd dist && echo "hash=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT
|
run: cd dist && echo "hash=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT
|
||||||
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
|
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32
|
||||||
with:
|
with:
|
||||||
path: ./dist
|
path: ./dist
|
||||||
provenance:
|
provenance:
|
||||||
needs: ['build']
|
needs: [build]
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
id-token: write
|
id-token: write
|
||||||
|
|
@ -39,7 +39,7 @@ jobs:
|
||||||
create-release:
|
create-release:
|
||||||
# Upload the sdist, wheels, and provenance to a GitHub release. They remain
|
# Upload the sdist, wheels, and provenance to a GitHub release. They remain
|
||||||
# available as build artifacts for a while as well.
|
# available as build artifacts for a while as well.
|
||||||
needs: ['provenance']
|
needs: [provenance]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
@ -53,16 +53,15 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
publish-pypi:
|
publish-pypi:
|
||||||
needs: ['provenance']
|
needs: [provenance]
|
||||||
# Wait for approval before attempting to upload to PyPI. This allows reviewing the
|
# Wait for approval before attempting to upload to PyPI. This allows reviewing the
|
||||||
# files in the draft release.
|
# files in the draft release.
|
||||||
environment: 'publish'
|
environment: publish
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
||||||
# Try uploading to Test PyPI first, in case something fails.
|
|
||||||
- uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e
|
- uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e
|
||||||
with:
|
with:
|
||||||
repository-url: https://test.pypi.org/legacy/
|
repository-url: https://test.pypi.org/legacy/
|
||||||
|
|
|
||||||
23
.github/workflows/tests.yaml
vendored
23
.github/workflows/tests.yaml
vendored
|
|
@ -9,9 +9,6 @@ on:
|
||||||
- '*.md'
|
- '*.md'
|
||||||
- '*.rst'
|
- '*.rst'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- '*.x'
|
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- '*.md'
|
- '*.md'
|
||||||
|
|
@ -24,26 +21,26 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- {name: Linux, python: '3.11', os: ubuntu-latest, tox: py311}
|
- {name: Linux, python: '3.12', os: ubuntu-latest, tox: py312}
|
||||||
- {name: Windows, python: '3.11', os: windows-latest, tox: py311}
|
- {name: Windows, python: '3.12', os: windows-latest, tox: py312}
|
||||||
- {name: Mac, python: '3.11', os: macos-latest, tox: py311}
|
- {name: Mac, python: '3.12', os: macos-latest, tox: py312}
|
||||||
- {name: '3.12-dev', python: '3.12-dev', os: ubuntu-latest, tox: py312}
|
- {name: '3.11', python: '3.11', os: ubuntu-latest, tox: py311}
|
||||||
- {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310}
|
- {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310}
|
||||||
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
|
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
|
||||||
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
|
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
|
||||||
- {name: 'PyPy', python: 'pypy-3.10', os: ubuntu-latest, tox: pypy310}
|
- {name: 'PyPy', python: 'pypy-3.10', os: ubuntu-latest, tox: pypy310}
|
||||||
- {name: 'Minimum Versions', python: '3.11', os: ubuntu-latest, tox: py311-min}
|
- {name: 'Minimum Versions', python: '3.12', os: ubuntu-latest, tox: py312-min}
|
||||||
- {name: 'Development Versions', python: '3.8', os: ubuntu-latest, tox: py38-dev}
|
- {name: 'Development Versions', python: '3.8', os: ubuntu-latest, tox: py38-dev}
|
||||||
- {name: Typing, python: '3.11', os: ubuntu-latest, tox: typing}
|
- {name: Typing, python: '3.12', os: ubuntu-latest, tox: typing}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||||
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1
|
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
cache-dependency-path: 'requirements/*.txt'
|
cache-dependency-path: requirements*/*.txt
|
||||||
- name: cache mypy
|
- name: cache mypy
|
||||||
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8
|
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84
|
||||||
with:
|
with:
|
||||||
path: ./.mypy_cache
|
path: ./.mypy_cache
|
||||||
key: mypy|${{ matrix.python }}|${{ hashFiles('pyproject.toml') }}
|
key: mypy|${{ matrix.python }}|${{ hashFiles('pyproject.toml') }}
|
||||||
|
|
|
||||||
29
.gitignore
vendored
29
.gitignore
vendored
|
|
@ -1,25 +1,10 @@
|
||||||
.DS_Store
|
|
||||||
.env
|
|
||||||
.flaskenv
|
|
||||||
*.pyc
|
|
||||||
*.pyo
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
.venv/
|
|
||||||
env*
|
|
||||||
dist/
|
|
||||||
build/
|
|
||||||
*.egg
|
|
||||||
*.egg-info/
|
|
||||||
.tox/
|
|
||||||
.cache/
|
|
||||||
.pytest_cache/
|
|
||||||
.idea/
|
.idea/
|
||||||
docs/_build/
|
.vscode/
|
||||||
.vscode
|
__pycache__/
|
||||||
|
.tox/
|
||||||
# Coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.coverage
|
.coverage
|
||||||
.coverage.*
|
.coverage.*
|
||||||
*,cover
|
htmlcov/
|
||||||
|
docs/_build/
|
||||||
|
dist/
|
||||||
|
venv/
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,16 @@
|
||||||
ci:
|
ci:
|
||||||
autoupdate_branch: "2.3.x"
|
|
||||||
autoupdate_schedule: monthly
|
autoupdate_schedule: monthly
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v3.10.1
|
rev: v0.1.5
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: ruff
|
||||||
args: ["--py38-plus"]
|
- id: ruff-format
|
||||||
- repo: https://github.com/asottile/reorder-python-imports
|
|
||||||
rev: v3.10.0
|
|
||||||
hooks:
|
|
||||||
- id: reorder-python-imports
|
|
||||||
name: Reorder Python imports (src, tests)
|
|
||||||
files: "^(?!examples/)"
|
|
||||||
args: ["--application-directories", "src"]
|
|
||||||
- repo: https://github.com/psf/black
|
|
||||||
rev: 23.7.0
|
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
|
||||||
rev: 6.1.0
|
|
||||||
hooks:
|
|
||||||
- id: flake8
|
|
||||||
additional_dependencies:
|
|
||||||
- flake8-bugbear
|
|
||||||
- flake8-implicit-str-concat
|
|
||||||
- repo: https://github.com/peterdemin/pip-compile-multi
|
|
||||||
rev: v2.6.3
|
|
||||||
hooks:
|
|
||||||
- id: pip-compile-multi-verify
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.4.0
|
rev: v4.5.0
|
||||||
hooks:
|
hooks:
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: debug-statements
|
||||||
- id: fix-byte-order-marker
|
- id: fix-byte-order-marker
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
version: 2
|
version: 2
|
||||||
build:
|
build:
|
||||||
os: ubuntu-20.04
|
os: ubuntu-22.04
|
||||||
tools:
|
tools:
|
||||||
python: "3.10"
|
python: "3.12"
|
||||||
python:
|
python:
|
||||||
install:
|
install:
|
||||||
- requirements: requirements/docs.txt
|
- requirements: requirements/docs.txt
|
||||||
|
|
|
||||||
12
CHANGES.rst
12
CHANGES.rst
|
|
@ -1,13 +1,23 @@
|
||||||
Version 3.0.0
|
Version 3.0.1
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Unreleased
|
Unreleased
|
||||||
|
|
||||||
|
- Correct type for ``path`` argument to ``send_file``. :issue:`5230`
|
||||||
|
|
||||||
|
|
||||||
|
Version 3.0.0
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Released 2023-09-30
|
||||||
|
|
||||||
- Remove previously deprecated code. :pr:`5223`
|
- Remove previously deprecated code. :pr:`5223`
|
||||||
- Deprecate the ``__version__`` attribute. Use feature detection, or
|
- Deprecate the ``__version__`` attribute. Use feature detection, or
|
||||||
``importlib.metadata.version("flask")``, instead. :issue:`5230`
|
``importlib.metadata.version("flask")``, instead. :issue:`5230`
|
||||||
- Restructure the code such that the Flask (app) and Blueprint
|
- Restructure the code such that the Flask (app) and Blueprint
|
||||||
classes have Sans-IO bases. :pr:`5127`
|
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
|
Version 2.3.3
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ wrapping the Flask app,
|
||||||
asgi_app = WsgiToAsgi(app)
|
asgi_app = WsgiToAsgi(app)
|
||||||
|
|
||||||
and then serving the ``asgi_app`` with the ASGI server, e.g. using
|
and then serving the ``asgi_app`` with the ASGI server, e.g. using
|
||||||
`Hypercorn <https://gitlab.com/pgjones/hypercorn>`_,
|
`Hypercorn <https://github.com/pgjones/hypercorn>`_,
|
||||||
|
|
||||||
.. sourcecode:: text
|
.. sourcecode:: text
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,11 @@ Welcome to Flask
|
||||||
.. image:: _static/flask-horizontal.png
|
.. image:: _static/flask-horizontal.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Welcome to Flask's documentation. Get started with :doc:`installation`
|
Welcome to Flask's documentation. 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.
|
||||||
|
|
||||||
|
Get started with :doc:`installation`
|
||||||
and then get an overview with the :doc:`quickstart`. There is also a
|
and then get an overview with the :doc:`quickstart`. There is also a
|
||||||
more detailed :doc:`tutorial/index` that shows how to create a small but
|
more detailed :doc:`tutorial/index` that shows how to create a small but
|
||||||
complete application with Flask. Common patterns are described in the
|
complete application with Flask. Common patterns are described in the
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ in the previous section. The following example shows how to replace a
|
||||||
const geology_div = getElementById("geology-fact")
|
const geology_div = getElementById("geology-fact")
|
||||||
fetch(geology_url)
|
fetch(geology_url)
|
||||||
.then(response => response.text)
|
.then(response => response.text)
|
||||||
.then(text => geology_div.innerHtml = text)
|
.then(text => geology_div.innerHTML = text)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ which records the request that produced that response.
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_logout_redirect(client):
|
def test_logout_redirect(client):
|
||||||
response = client.get("/logout")
|
response = client.get("/logout", follow_redirects=True)
|
||||||
# Check that there was one redirect response.
|
# Check that there was one redirect response.
|
||||||
assert len(response.history) == 1
|
assert len(response.history) == 1
|
||||||
# Check that the second request was to the index page.
|
# Check that the second request was to the index page.
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,6 @@ build-backend = "flit_core.buildapi"
|
||||||
|
|
||||||
[tool.flit.module]
|
[tool.flit.module]
|
||||||
name = "task_app"
|
name = "task_app"
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
src = ["src"]
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ page. Demonstrates using |fetch|_, |XMLHttpRequest|_, and
|
||||||
.. |jQuery.ajax| replace:: ``jQuery.ajax``
|
.. |jQuery.ajax| replace:: ``jQuery.ajax``
|
||||||
.. _jQuery.ajax: https://api.jquery.com/jQuery.ajax/
|
.. _jQuery.ajax: https://api.jquery.com/jQuery.ajax/
|
||||||
|
|
||||||
.. _Flask docs: https://flask.palletsprojects.com/patterns/jquery/
|
.. _Flask docs: https://flask.palletsprojects.com/patterns/javascript/
|
||||||
|
|
||||||
|
|
||||||
Install
|
Install
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from flask import jsonify
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from js_example import app
|
from . import app
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", defaults={"js": "fetch"})
|
@app.route("/", defaults={"js": "fetch"})
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,6 @@ filterwarnings = ["error"]
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
branch = true
|
branch = true
|
||||||
source = ["js_example", "tests"]
|
source = ["js_example", "tests"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
src = ["src"]
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ def create_app(test_config=None):
|
||||||
return "Hello, World!"
|
return "Hello, World!"
|
||||||
|
|
||||||
# register the database commands
|
# register the database commands
|
||||||
from flaskr import db
|
from . import db
|
||||||
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
|
|
||||||
# apply the blueprints to the app
|
# apply the blueprints to the app
|
||||||
from flaskr import auth, blog
|
from . import auth
|
||||||
|
from . import blog
|
||||||
|
|
||||||
app.register_blueprint(auth.bp)
|
app.register_blueprint(auth.bp)
|
||||||
app.register_blueprint(blog.bp)
|
app.register_blueprint(blog.bp)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from flask import url_for
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
|
|
||||||
from flaskr.db import get_db
|
from .db import get_db
|
||||||
|
|
||||||
bp = Blueprint("auth", __name__, url_prefix="/auth")
|
bp = Blueprint("auth", __name__, url_prefix="/auth")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ from flask import request
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
from werkzeug.exceptions import abort
|
from werkzeug.exceptions import abort
|
||||||
|
|
||||||
from flaskr.auth import login_required
|
from .auth import login_required
|
||||||
from flaskr.db import get_db
|
from .db import get_db
|
||||||
|
|
||||||
bp = Blueprint("blog", __name__)
|
bp = Blueprint("blog", __name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,3 +34,6 @@ filterwarnings = ["error"]
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
branch = true
|
branch = true
|
||||||
source = ["flaskr", "tests"]
|
source = ["flaskr", "tests"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
src = ["src"]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "Flask"
|
name = "Flask"
|
||||||
version = "3.0.0.dev"
|
version = "3.0.1.dev"
|
||||||
description = "A simple framework for building complex web applications."
|
description = "A simple framework for building complex web applications."
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
license = {file = "LICENSE.rst"}
|
license = {file = "LICENSE.rst"}
|
||||||
|
|
@ -20,7 +20,7 @@ classifiers = [
|
||||||
]
|
]
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Werkzeug>=2.3.7",
|
"Werkzeug>=3.0.0",
|
||||||
"Jinja2>=3.1.2",
|
"Jinja2>=3.1.2",
|
||||||
"itsdangerous>=2.1.2",
|
"itsdangerous>=2.1.2",
|
||||||
"click>=8.1.3",
|
"click>=8.1.3",
|
||||||
|
|
@ -106,3 +106,24 @@ module = [
|
||||||
"importlib_metadata",
|
"importlib_metadata",
|
||||||
]
|
]
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
src = ["src"]
|
||||||
|
fix = true
|
||||||
|
show-fixes = true
|
||||||
|
show-source = true
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"B", # flake8-bugbear
|
||||||
|
"E", # pycodestyle error
|
||||||
|
"F", # pyflakes
|
||||||
|
"I", # isort
|
||||||
|
"UP", # pyupgrade
|
||||||
|
"W", # pycodestyle warning
|
||||||
|
]
|
||||||
|
ignore-init-module-imports = true
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-single-line = true
|
||||||
|
order-by-type = false
|
||||||
|
|
|
||||||
2
requirements-skip/README.md
Normal file
2
requirements-skip/README.md
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Dependabot will only update files in the `requirements` directory. This directory is
|
||||||
|
separate because the pins in here should not be updated automatically.
|
||||||
6
requirements-skip/tests-dev.txt
Normal file
6
requirements-skip/tests-dev.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
https://github.com/pallets/werkzeug/archive/refs/heads/main.tar.gz
|
||||||
|
https://github.com/pallets/jinja/archive/refs/heads/main.tar.gz
|
||||||
|
https://github.com/pallets/markupsafe/archive/refs/heads/main.tar.gz
|
||||||
|
https://github.com/pallets/itsdangerous/archive/refs/heads/main.tar.gz
|
||||||
|
https://github.com/pallets/click/archive/refs/heads/main.tar.gz
|
||||||
|
https://github.com/pallets-eco/blinker/archive/refs/heads/main.tar.gz
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Werkzeug==2.3.7
|
werkzeug==3.0.0
|
||||||
Jinja2==3.1.2
|
jinja2==3.1.2
|
||||||
MarkupSafe==2.1.1
|
markupsafe==2.1.1
|
||||||
itsdangerous==2.1.2
|
itsdangerous==2.1.2
|
||||||
click==8.1.3
|
click==8.1.3
|
||||||
blinker==1.6.2
|
blinker==1.6.2
|
||||||
21
requirements-skip/tests-min.txt
Normal file
21
requirements-skip/tests-min.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
|
# by the following command:
|
||||||
|
#
|
||||||
|
# pip-compile tests-min.in
|
||||||
|
#
|
||||||
|
blinker==1.6.2
|
||||||
|
# via -r tests-min.in
|
||||||
|
click==8.1.3
|
||||||
|
# via -r tests-min.in
|
||||||
|
itsdangerous==2.1.2
|
||||||
|
# via -r tests-min.in
|
||||||
|
jinja2==3.1.2
|
||||||
|
# via -r tests-min.in
|
||||||
|
markupsafe==2.1.1
|
||||||
|
# via
|
||||||
|
# -r tests-min.in
|
||||||
|
# jinja2
|
||||||
|
# werkzeug
|
||||||
|
werkzeug==3.0.0
|
||||||
|
# via -r tests-min.in
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
# SHA1:80754af91bfb6d1073585b046fe0a474ce868509
|
|
||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile-multi
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile-multi
|
# pip-compile build.in
|
||||||
#
|
#
|
||||||
build==0.10.0
|
build==1.0.3
|
||||||
# via -r requirements/build.in
|
# via -r build.in
|
||||||
packaging==23.1
|
packaging==23.2
|
||||||
# via build
|
# via build
|
||||||
pyproject-hooks==1.0.0
|
pyproject-hooks==1.0.0
|
||||||
# via build
|
# via build
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
-r docs.in
|
-r docs.in
|
||||||
-r tests.in
|
-r tests.in
|
||||||
-r typing.in
|
-r typing.in
|
||||||
pip-compile-multi
|
pip-tools
|
||||||
pre-commit
|
pre-commit
|
||||||
tox
|
tox
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,150 @@
|
||||||
# SHA1:54b5b77ec8c7a0064ffa93b2fd16cb0130ba177c
|
|
||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile-multi
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile-multi
|
# pip-compile dev.in
|
||||||
#
|
#
|
||||||
-r docs.txt
|
alabaster==0.7.13
|
||||||
-r tests.txt
|
# via sphinx
|
||||||
-r typing.txt
|
asgiref==3.7.2
|
||||||
build==0.10.0
|
# via -r tests.in
|
||||||
|
babel==2.13.1
|
||||||
|
# via sphinx
|
||||||
|
build==1.0.3
|
||||||
# via pip-tools
|
# via pip-tools
|
||||||
cachetools==5.3.1
|
cachetools==5.3.2
|
||||||
# via tox
|
# via tox
|
||||||
|
certifi==2023.7.22
|
||||||
|
# via requests
|
||||||
|
cffi==1.16.0
|
||||||
|
# via cryptography
|
||||||
cfgv==3.4.0
|
cfgv==3.4.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
chardet==5.2.0
|
chardet==5.2.0
|
||||||
# via tox
|
# via tox
|
||||||
click==8.1.6
|
charset-normalizer==3.3.2
|
||||||
# via
|
# via requests
|
||||||
# pip-compile-multi
|
click==8.1.7
|
||||||
# pip-tools
|
# via pip-tools
|
||||||
colorama==0.4.6
|
colorama==0.4.6
|
||||||
# via tox
|
# via tox
|
||||||
|
cryptography==41.0.5
|
||||||
|
# via -r typing.in
|
||||||
distlib==0.3.7
|
distlib==0.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.12.2
|
docutils==0.18.1
|
||||||
|
# via
|
||||||
|
# sphinx
|
||||||
|
# sphinx-tabs
|
||||||
|
filelock==3.13.1
|
||||||
# via
|
# via
|
||||||
# tox
|
# tox
|
||||||
# virtualenv
|
# virtualenv
|
||||||
identify==2.5.26
|
identify==2.5.31
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
|
idna==3.4
|
||||||
|
# via requests
|
||||||
|
imagesize==1.4.1
|
||||||
|
# via sphinx
|
||||||
|
iniconfig==2.0.0
|
||||||
|
# via pytest
|
||||||
|
jinja2==3.1.2
|
||||||
|
# via sphinx
|
||||||
|
markupsafe==2.1.3
|
||||||
|
# via jinja2
|
||||||
|
mypy==1.6.1
|
||||||
|
# via -r typing.in
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
# via mypy
|
||||||
nodeenv==1.8.0
|
nodeenv==1.8.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
pip-compile-multi==2.6.3
|
packaging==23.2
|
||||||
# via -r requirements/dev.in
|
# via
|
||||||
|
# build
|
||||||
|
# pallets-sphinx-themes
|
||||||
|
# pyproject-api
|
||||||
|
# pytest
|
||||||
|
# sphinx
|
||||||
|
# tox
|
||||||
|
pallets-sphinx-themes==2.1.1
|
||||||
|
# via -r docs.in
|
||||||
pip-tools==7.3.0
|
pip-tools==7.3.0
|
||||||
# via pip-compile-multi
|
# via -r dev.in
|
||||||
platformdirs==3.10.0
|
platformdirs==3.11.0
|
||||||
# via
|
# via
|
||||||
# tox
|
# tox
|
||||||
# virtualenv
|
# virtualenv
|
||||||
pre-commit==3.3.3
|
pluggy==1.3.0
|
||||||
# via -r requirements/dev.in
|
# via
|
||||||
pyproject-api==1.5.3
|
# pytest
|
||||||
|
# tox
|
||||||
|
pre-commit==3.5.0
|
||||||
|
# via -r dev.in
|
||||||
|
pycparser==2.21
|
||||||
|
# via cffi
|
||||||
|
pygments==2.16.1
|
||||||
|
# via
|
||||||
|
# sphinx
|
||||||
|
# sphinx-tabs
|
||||||
|
pyproject-api==1.6.1
|
||||||
# via tox
|
# via tox
|
||||||
pyproject-hooks==1.0.0
|
pyproject-hooks==1.0.0
|
||||||
# via build
|
# via build
|
||||||
|
pytest==7.4.3
|
||||||
|
# via -r tests.in
|
||||||
|
python-dotenv==1.0.0
|
||||||
|
# via -r tests.in
|
||||||
pyyaml==6.0.1
|
pyyaml==6.0.1
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
toposort==1.10
|
requests==2.31.0
|
||||||
# via pip-compile-multi
|
# via sphinx
|
||||||
tox==4.9.0
|
snowballstemmer==2.2.0
|
||||||
# via -r requirements/dev.in
|
# via sphinx
|
||||||
virtualenv==20.24.3
|
sphinx==7.2.6
|
||||||
|
# via
|
||||||
|
# -r docs.in
|
||||||
|
# pallets-sphinx-themes
|
||||||
|
# sphinx-issues
|
||||||
|
# sphinx-tabs
|
||||||
|
# sphinxcontrib-applehelp
|
||||||
|
# sphinxcontrib-devhelp
|
||||||
|
# sphinxcontrib-htmlhelp
|
||||||
|
# sphinxcontrib-log-cabinet
|
||||||
|
# sphinxcontrib-qthelp
|
||||||
|
# sphinxcontrib-serializinghtml
|
||||||
|
sphinx-issues==3.0.1
|
||||||
|
# via -r docs.in
|
||||||
|
sphinx-tabs==3.4.4
|
||||||
|
# via -r docs.in
|
||||||
|
sphinxcontrib-applehelp==1.0.7
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-devhelp==1.0.5
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-htmlhelp==2.0.4
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-jsmath==1.0.1
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-log-cabinet==1.0.1
|
||||||
|
# via -r docs.in
|
||||||
|
sphinxcontrib-qthelp==1.0.6
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-serializinghtml==1.1.9
|
||||||
|
# via sphinx
|
||||||
|
tox==4.11.3
|
||||||
|
# via -r dev.in
|
||||||
|
types-contextvars==2.4.7.3
|
||||||
|
# via -r typing.in
|
||||||
|
types-dataclasses==0.6.6
|
||||||
|
# via -r typing.in
|
||||||
|
typing-extensions==4.8.0
|
||||||
|
# via mypy
|
||||||
|
urllib3==2.0.7
|
||||||
|
# via requests
|
||||||
|
virtualenv==20.24.6
|
||||||
# via
|
# via
|
||||||
# pre-commit
|
# pre-commit
|
||||||
# tox
|
# tox
|
||||||
wheel==0.41.1
|
wheel==0.41.3
|
||||||
# via pip-tools
|
# via pip-tools
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Pallets-Sphinx-Themes
|
pallets-sphinx-themes
|
||||||
Sphinx
|
sphinx
|
||||||
sphinx-issues
|
sphinx-issues
|
||||||
sphinxcontrib-log-cabinet
|
sphinxcontrib-log-cabinet
|
||||||
sphinx-tabs
|
sphinx-tabs
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
# SHA1:34fd4ca6516e97c7348e6facdd9c4ebb68209d1c
|
|
||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile-multi
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile-multi
|
# pip-compile docs.in
|
||||||
#
|
#
|
||||||
alabaster==0.7.13
|
alabaster==0.7.13
|
||||||
# via sphinx
|
# via sphinx
|
||||||
babel==2.12.1
|
babel==2.13.1
|
||||||
# via sphinx
|
# via sphinx
|
||||||
certifi==2023.7.22
|
certifi==2023.7.22
|
||||||
# via requests
|
# via requests
|
||||||
charset-normalizer==3.2.0
|
charset-normalizer==3.3.2
|
||||||
# via requests
|
# via requests
|
||||||
docutils==0.18.1
|
docutils==0.18.1
|
||||||
# via
|
# via
|
||||||
|
|
@ -25,12 +24,12 @@ jinja2==3.1.2
|
||||||
# via sphinx
|
# via sphinx
|
||||||
markupsafe==2.1.3
|
markupsafe==2.1.3
|
||||||
# via jinja2
|
# via jinja2
|
||||||
packaging==23.1
|
packaging==23.2
|
||||||
# via
|
# via
|
||||||
# pallets-sphinx-themes
|
# pallets-sphinx-themes
|
||||||
# sphinx
|
# sphinx
|
||||||
pallets-sphinx-themes==2.1.1
|
pallets-sphinx-themes==2.1.1
|
||||||
# via -r requirements/docs.in
|
# via -r docs.in
|
||||||
pygments==2.16.1
|
pygments==2.16.1
|
||||||
# via
|
# via
|
||||||
# sphinx
|
# sphinx
|
||||||
|
|
@ -39,9 +38,9 @@ requests==2.31.0
|
||||||
# via sphinx
|
# via sphinx
|
||||||
snowballstemmer==2.2.0
|
snowballstemmer==2.2.0
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinx==7.1.2
|
sphinx==7.2.6
|
||||||
# via
|
# via
|
||||||
# -r requirements/docs.in
|
# -r docs.in
|
||||||
# pallets-sphinx-themes
|
# pallets-sphinx-themes
|
||||||
# sphinx-issues
|
# sphinx-issues
|
||||||
# sphinx-tabs
|
# sphinx-tabs
|
||||||
|
|
@ -52,9 +51,9 @@ sphinx==7.1.2
|
||||||
# sphinxcontrib-qthelp
|
# sphinxcontrib-qthelp
|
||||||
# sphinxcontrib-serializinghtml
|
# sphinxcontrib-serializinghtml
|
||||||
sphinx-issues==3.0.1
|
sphinx-issues==3.0.1
|
||||||
# via -r requirements/docs.in
|
# via -r docs.in
|
||||||
sphinx-tabs==3.4.1
|
sphinx-tabs==3.4.4
|
||||||
# via -r requirements/docs.in
|
# via -r docs.in
|
||||||
sphinxcontrib-applehelp==1.0.7
|
sphinxcontrib-applehelp==1.0.7
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-devhelp==1.0.5
|
sphinxcontrib-devhelp==1.0.5
|
||||||
|
|
@ -64,10 +63,10 @@ sphinxcontrib-htmlhelp==2.0.4
|
||||||
sphinxcontrib-jsmath==1.0.1
|
sphinxcontrib-jsmath==1.0.1
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-log-cabinet==1.0.1
|
sphinxcontrib-log-cabinet==1.0.1
|
||||||
# via -r requirements/docs.in
|
# via -r docs.in
|
||||||
sphinxcontrib-qthelp==1.0.6
|
sphinxcontrib-qthelp==1.0.6
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-serializinghtml==1.1.8
|
sphinxcontrib-serializinghtml==1.1.9
|
||||||
# via sphinx
|
# via sphinx
|
||||||
urllib3==2.0.4
|
urllib3==2.0.7
|
||||||
# via requests
|
# via requests
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
# SHA1:fe057f95a98251b053eec8fa27df0feb722c70e8
|
|
||||||
#
|
|
||||||
# This file is autogenerated by pip-compile-multi
|
|
||||||
# To update, run:
|
|
||||||
#
|
|
||||||
# pip-compile-multi
|
|
||||||
#
|
|
||||||
blinker==1.6.2
|
|
||||||
# via -r requirements/tests-pallets-min.in
|
|
||||||
click==8.1.3
|
|
||||||
# via -r requirements/tests-pallets-min.in
|
|
||||||
itsdangerous==2.1.2
|
|
||||||
# via -r requirements/tests-pallets-min.in
|
|
||||||
jinja2==3.1.2
|
|
||||||
# via -r requirements/tests-pallets-min.in
|
|
||||||
markupsafe==2.1.1
|
|
||||||
# via
|
|
||||||
# -r requirements/tests-pallets-min.in
|
|
||||||
# jinja2
|
|
||||||
# werkzeug
|
|
||||||
werkzeug==2.3.7
|
|
||||||
# via -r requirements/tests-pallets-min.in
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
# SHA1:42d37aff22e2f1fc447e20d483e13d6d4e066b10
|
|
||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile-multi
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile-multi
|
# pip-compile tests.in
|
||||||
#
|
#
|
||||||
asgiref==3.7.2
|
asgiref==3.7.2
|
||||||
# via -r requirements/tests.in
|
# via -r tests.in
|
||||||
iniconfig==2.0.0
|
iniconfig==2.0.0
|
||||||
# via pytest
|
# via pytest
|
||||||
packaging==23.1
|
packaging==23.2
|
||||||
# via pytest
|
# via pytest
|
||||||
pluggy==1.2.0
|
pluggy==1.3.0
|
||||||
# via pytest
|
# via pytest
|
||||||
pytest==7.4.0
|
pytest==7.4.3
|
||||||
# via -r requirements/tests.in
|
# via -r tests.in
|
||||||
python-dotenv==1.0.0
|
python-dotenv==1.0.0
|
||||||
# via -r requirements/tests.in
|
# via -r tests.in
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
# SHA1:6a354b832686fd3ec017455769a0270953a1e225
|
|
||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile-multi
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile-multi
|
# pip-compile typing.in
|
||||||
#
|
#
|
||||||
cffi==1.15.1
|
cffi==1.16.0
|
||||||
# via cryptography
|
# via cryptography
|
||||||
cryptography==41.0.3
|
cryptography==41.0.5
|
||||||
# via -r requirements/typing.in
|
# via -r typing.in
|
||||||
mypy==1.5.1
|
mypy==1.6.1
|
||||||
# via -r requirements/typing.in
|
# via -r typing.in
|
||||||
mypy-extensions==1.0.0
|
mypy-extensions==1.0.0
|
||||||
# via mypy
|
# via mypy
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
types-contextvars==2.4.7.3
|
types-contextvars==2.4.7.3
|
||||||
# via -r requirements/typing.in
|
# via -r typing.in
|
||||||
types-dataclasses==0.6.6
|
types-dataclasses==0.6.6
|
||||||
# via -r requirements/typing.in
|
# via -r typing.in
|
||||||
typing-extensions==4.7.1
|
typing-extensions==4.8.0
|
||||||
# via mypy
|
# via mypy
|
||||||
|
|
|
||||||
|
|
@ -952,6 +952,7 @@ class Flask(App):
|
||||||
|
|
||||||
def url_for(
|
def url_for(
|
||||||
self,
|
self,
|
||||||
|
/,
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
*,
|
*,
|
||||||
_anchor: str | None = None,
|
_anchor: str | None = None,
|
||||||
|
|
@ -1182,7 +1183,8 @@ class Flask(App):
|
||||||
# class to the correct type
|
# class to the correct type
|
||||||
try:
|
try:
|
||||||
rv = self.response_class.force_type(
|
rv = self.response_class.force_type(
|
||||||
rv, request.environ # type: ignore[arg-type]
|
rv, # type: ignore[arg-type]
|
||||||
|
request.environ,
|
||||||
)
|
)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
|
|
@ -1271,7 +1273,8 @@ class Flask(App):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def do_teardown_request(
|
def do_teardown_request(
|
||||||
self, exc: BaseException | None = _sentinel # type: ignore
|
self,
|
||||||
|
exc: BaseException | None = _sentinel, # type: ignore[assignment]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called after the request is dispatched and the response is
|
"""Called after the request is dispatched and the response is
|
||||||
returned, right before the request context is popped.
|
returned, right before the request context is popped.
|
||||||
|
|
@ -1304,7 +1307,8 @@ class Flask(App):
|
||||||
request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
|
request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
|
||||||
|
|
||||||
def do_teardown_appcontext(
|
def do_teardown_appcontext(
|
||||||
self, exc: BaseException | None = _sentinel # type: ignore
|
self,
|
||||||
|
exc: BaseException | None = _sentinel, # type: ignore[assignment]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called right before the application context is popped.
|
"""Called right before the application context is popped.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from .signals import message_flashed
|
||||||
|
|
||||||
if t.TYPE_CHECKING: # pragma: no cover
|
if t.TYPE_CHECKING: # pragma: no cover
|
||||||
from werkzeug.wrappers import Response as BaseResponse
|
from werkzeug.wrappers import Response as BaseResponse
|
||||||
|
|
||||||
from .wrappers import Response
|
from .wrappers import Response
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -48,9 +49,7 @@ def get_load_dotenv(default: bool = True) -> bool:
|
||||||
|
|
||||||
|
|
||||||
def stream_with_context(
|
def stream_with_context(
|
||||||
generator_or_function: (
|
generator_or_function: t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]]
|
||||||
t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]]
|
|
||||||
)
|
|
||||||
) -> t.Iterator[t.AnyStr]:
|
) -> t.Iterator[t.AnyStr]:
|
||||||
"""Request contexts disappear when the response is started on the server.
|
"""Request contexts disappear when the response is started on the server.
|
||||||
This is done for efficiency reasons and to make it less likely to encounter
|
This is done for efficiency reasons and to make it less likely to encounter
|
||||||
|
|
@ -388,7 +387,7 @@ def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]:
|
||||||
|
|
||||||
|
|
||||||
def send_file(
|
def send_file(
|
||||||
path_or_file: os.PathLike | str | t.BinaryIO,
|
path_or_file: os.PathLike[t.AnyStr] | str | t.BinaryIO,
|
||||||
mimetype: str | None = None,
|
mimetype: str | None = None,
|
||||||
as_attachment: bool = False,
|
as_attachment: bool = False,
|
||||||
download_name: str | None = None,
|
download_name: str | None = None,
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,7 @@ class DefaultJSONProvider(JSONProvider):
|
||||||
method) will call the ``__html__`` method to get a string.
|
method) will call the ``__html__`` method to get a string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
default: t.Callable[[t.Any], t.Any] = staticmethod(
|
default: t.Callable[[t.Any], t.Any] = staticmethod(_default) # type: ignore[assignment]
|
||||||
_default
|
|
||||||
) # type: ignore[assignment]
|
|
||||||
"""Apply this function to any object that :meth:`json.dumps` does
|
"""Apply this function to any object that :meth:`json.dumps` does
|
||||||
not know how to serialize. It should return a valid JSON type or
|
not know how to serialize. It should return a valid JSON type or
|
||||||
raise a ``TypeError``.
|
raise a ``TypeError``.
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,10 @@ from .scaffold import setupmethod
|
||||||
|
|
||||||
if t.TYPE_CHECKING: # pragma: no cover
|
if t.TYPE_CHECKING: # pragma: no cover
|
||||||
from werkzeug.wrappers import Response as BaseResponse
|
from werkzeug.wrappers import Response as BaseResponse
|
||||||
from .blueprints import Blueprint
|
|
||||||
from ..testing import FlaskClient
|
from ..testing import FlaskClient
|
||||||
from ..testing import FlaskCliRunner
|
from ..testing import FlaskCliRunner
|
||||||
|
from .blueprints import Blueprint
|
||||||
|
|
||||||
T_shell_context_processor = t.TypeVar(
|
T_shell_context_processor = t.TypeVar(
|
||||||
"T_shell_context_processor", bound=ft.ShellContextProcessorCallable
|
"T_shell_context_processor", bound=ft.ShellContextProcessorCallable
|
||||||
|
|
@ -905,7 +906,9 @@ class App(Scaffold):
|
||||||
Moved from ``flask.redirect``, which calls this method.
|
Moved from ``flask.redirect``, which calls this method.
|
||||||
"""
|
"""
|
||||||
return _wz_redirect(
|
return _wz_redirect(
|
||||||
location, code=code, Response=self.response_class # type: ignore[arg-type]
|
location,
|
||||||
|
code=code,
|
||||||
|
Response=self.response_class, # type: ignore[arg-type]
|
||||||
)
|
)
|
||||||
|
|
||||||
def inject_url_defaults(self, endpoint: str, values: dict) -> None:
|
def inject_url_defaults(self, endpoint: str, values: dict) -> None:
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ from .json.tag import TaggedJSONSerializer
|
||||||
|
|
||||||
if t.TYPE_CHECKING: # pragma: no cover
|
if t.TYPE_CHECKING: # pragma: no cover
|
||||||
from .app import Flask
|
from .app import Flask
|
||||||
from .wrappers import Request, Response
|
from .wrappers import Request
|
||||||
|
from .wrappers import Response
|
||||||
|
|
||||||
|
|
||||||
class SessionMixin(MutableMapping):
|
class SessionMixin(MutableMapping):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from . import typing as ft
|
||||||
from .globals import current_app
|
from .globals import current_app
|
||||||
from .globals import request
|
from .globals import request
|
||||||
|
|
||||||
|
|
||||||
http_method_funcs = frozenset(
|
http_method_funcs = frozenset(
|
||||||
["get", "post", "head", "options", "delete", "put", "trace", "patch"]
|
["get", "post", "head", "options", "delete", "put", "trace", "patch"]
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -196,17 +196,14 @@ def test_clean_pop(app):
|
||||||
|
|
||||||
@app.teardown_request
|
@app.teardown_request
|
||||||
def teardown_req(error=None):
|
def teardown_req(error=None):
|
||||||
1 / 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
@app.teardown_appcontext
|
@app.teardown_appcontext
|
||||||
def teardown_app(error=None):
|
def teardown_app(error=None):
|
||||||
called.append("TEARDOWN")
|
called.append("TEARDOWN")
|
||||||
|
|
||||||
try:
|
with app.app_context():
|
||||||
with app.test_request_context():
|
called.append(flask.current_app.name)
|
||||||
called.append(flask.current_app.name)
|
|
||||||
except ZeroDivisionError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
assert called == ["flask_test", "TEARDOWN"]
|
assert called == ["flask_test", "TEARDOWN"]
|
||||||
assert not flask.current_app
|
assert not flask.current_app
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
from flask import Module
|
from flask import Module
|
||||||
|
|
||||||
|
|
||||||
mod = Module(__name__, "foo", subdomain="foo")
|
mod = Module(__name__, "foo", subdomain="foo")
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ from werkzeug.routing import RequestRedirect
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
|
|
||||||
|
|
||||||
require_cpython_gc = pytest.mark.skipif(
|
require_cpython_gc = pytest.mark.skipif(
|
||||||
python_implementation() != "CPython",
|
python_implementation() != "CPython",
|
||||||
reason="Requires CPython GC behavior",
|
reason="Requires CPython GC behavior",
|
||||||
|
|
@ -190,7 +189,8 @@ def test_url_mapping(app, client):
|
||||||
|
|
||||||
|
|
||||||
def test_werkzeug_routing(app, client):
|
def test_werkzeug_routing(app, client):
|
||||||
from werkzeug.routing import Submount, Rule
|
from werkzeug.routing import Rule
|
||||||
|
from werkzeug.routing import Submount
|
||||||
|
|
||||||
app.url_map.add(
|
app.url_map.add(
|
||||||
Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
|
Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
|
||||||
|
|
@ -210,7 +210,8 @@ def test_werkzeug_routing(app, client):
|
||||||
|
|
||||||
|
|
||||||
def test_endpoint_decorator(app, client):
|
def test_endpoint_decorator(app, client):
|
||||||
from werkzeug.routing import Submount, Rule
|
from werkzeug.routing import Rule
|
||||||
|
from werkzeug.routing import Submount
|
||||||
|
|
||||||
app.url_map.add(
|
app.url_map.add(
|
||||||
Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
|
Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
|
||||||
|
|
@ -431,9 +432,9 @@ def test_session_special_types(app, client):
|
||||||
client.get("/")
|
client.get("/")
|
||||||
s = flask.session
|
s = flask.session
|
||||||
assert s["t"] == (1, 2, 3)
|
assert s["t"] == (1, 2, 3)
|
||||||
assert type(s["b"]) is bytes
|
assert type(s["b"]) is bytes # noqa: E721
|
||||||
assert s["b"] == b"\xff"
|
assert s["b"] == b"\xff"
|
||||||
assert type(s["m"]) is Markup
|
assert type(s["m"]) is Markup # noqa: E721
|
||||||
assert s["m"] == Markup("<html>")
|
assert s["m"] == Markup("<html>")
|
||||||
assert s["u"] == the_uuid
|
assert s["u"] == the_uuid
|
||||||
assert s["d"] == now
|
assert s["d"] == now
|
||||||
|
|
@ -784,7 +785,7 @@ def test_teardown_request_handler_error(app, client):
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def fails():
|
def fails():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
rv = client.get("/")
|
rv = client.get("/")
|
||||||
assert rv.status_code == 500
|
assert rv.status_code == 500
|
||||||
|
|
@ -851,7 +852,7 @@ def test_error_handling(app, client):
|
||||||
|
|
||||||
@app.route("/error")
|
@app.route("/error")
|
||||||
def error():
|
def error():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
@app.route("/forbidden")
|
@app.route("/forbidden")
|
||||||
def error2():
|
def error2():
|
||||||
|
|
@ -877,7 +878,7 @@ def test_error_handling_processing(app, client):
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def broken_func():
|
def broken_func():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def after_request(resp):
|
def after_request(resp):
|
||||||
|
|
@ -1047,12 +1048,13 @@ def test_error_handler_after_processor_error(app, client):
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def before_request():
|
def before_request():
|
||||||
if _trigger == "before":
|
if _trigger == "before":
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def after_request(response):
|
def after_request(response):
|
||||||
if _trigger == "after":
|
if _trigger == "after":
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
|
|
@ -1507,7 +1509,7 @@ def test_exception_propagation(app, client, key):
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
if key is not None:
|
if key is not None:
|
||||||
app.config[key] = True
|
app.config[key] = True
|
||||||
|
|
|
||||||
|
|
@ -634,10 +634,11 @@ def test_add_template_test_with_name_and_template(app, client):
|
||||||
def test_context_processing(app, client):
|
def test_context_processing(app, client):
|
||||||
answer_bp = flask.Blueprint("answer_bp", __name__)
|
answer_bp = flask.Blueprint("answer_bp", __name__)
|
||||||
|
|
||||||
template_string = lambda: flask.render_template_string( # noqa: E731
|
def template_string():
|
||||||
"{% if notanswer %}{{ notanswer }} is not the answer. {% endif %}"
|
return flask.render_template_string(
|
||||||
"{% if answer %}{{ answer }} is the answer.{% endif %}"
|
"{% if notanswer %}{{ notanswer }} is not the answer. {% endif %}"
|
||||||
)
|
"{% if answer %}{{ answer }} is the answer.{% endif %}"
|
||||||
|
)
|
||||||
|
|
||||||
# App global context processor
|
# App global context processor
|
||||||
@answer_bp.app_context_processor
|
@answer_bp.app_context_processor
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,13 @@ class TestUrlFor:
|
||||||
assert flask.url_for("myview", id=42, _method="GET") == "/myview/42"
|
assert flask.url_for("myview", id=42, _method="GET") == "/myview/42"
|
||||||
assert flask.url_for("myview", _method="POST") == "/myview/create"
|
assert flask.url_for("myview", _method="POST") == "/myview/create"
|
||||||
|
|
||||||
|
def test_url_for_with_self(self, app, req_ctx):
|
||||||
|
@app.route("/<self>")
|
||||||
|
def index(self):
|
||||||
|
return "42"
|
||||||
|
|
||||||
|
assert flask.url_for("index", self="2") == "/2"
|
||||||
|
|
||||||
|
|
||||||
def test_redirect_no_app():
|
def test_redirect_no_app():
|
||||||
response = flask.redirect("https://localhost", 307)
|
response = flask.redirect("https://localhost", 307)
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ def test_request_exception_signal():
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
def record(sender, exception):
|
def record(sender, exception):
|
||||||
recorded.append(exception)
|
recorded.append(exception)
|
||||||
|
|
@ -169,7 +169,7 @@ def test_appcontext_tearing_down_signal(app, client):
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
flask.appcontext_tearing_down.connect(record_teardown, app)
|
flask.appcontext_tearing_down.connect(record_teardown, app)
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ def test_test_client_context_binding(app, client):
|
||||||
|
|
||||||
@app.route("/other")
|
@app.route("/other")
|
||||||
def other():
|
def other():
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
with client:
|
with client:
|
||||||
resp = client.get("/")
|
resp = client.get("/")
|
||||||
|
|
@ -227,18 +227,15 @@ def test_test_client_context_binding(app, client):
|
||||||
assert resp.data == b"Hello World!"
|
assert resp.data == b"Hello World!"
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|
||||||
|
with client:
|
||||||
resp = client.get("/other")
|
resp = client.get("/other")
|
||||||
assert not hasattr(flask.g, "value")
|
assert not hasattr(flask.g, "value")
|
||||||
assert b"Internal Server Error" in resp.data
|
assert b"Internal Server Error" in resp.data
|
||||||
assert resp.status_code == 500
|
assert resp.status_code == 500
|
||||||
flask.g.value = 23
|
flask.g.value = 23
|
||||||
|
|
||||||
try:
|
with pytest.raises(RuntimeError):
|
||||||
flask.g.value
|
flask.g.value # noqa: B018
|
||||||
except (AttributeError, RuntimeError):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise AssertionError("some kind of exception expected")
|
|
||||||
|
|
||||||
|
|
||||||
def test_reuse_client(client):
|
def test_reuse_client(client):
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,10 @@ def test_method_based_view(app):
|
||||||
def test_view_patching(app):
|
def test_view_patching(app):
|
||||||
class Index(flask.views.MethodView):
|
class Index(flask.views.MethodView):
|
||||||
def get(self):
|
def get(self):
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
1 // 0
|
raise ZeroDivisionError
|
||||||
|
|
||||||
class Other(Index):
|
class Other(Index):
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import typing as t
|
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask import Response
|
from flask import Response
|
||||||
|
|
||||||
|
|
@ -29,10 +27,10 @@ async def before_async() -> None:
|
||||||
|
|
||||||
|
|
||||||
@app.teardown_appcontext
|
@app.teardown_appcontext
|
||||||
def teardown_sync(exc: t.Optional[BaseException]) -> None:
|
def teardown_sync(exc: BaseException | None) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
@app.teardown_appcontext
|
@app.teardown_appcontext
|
||||||
async def teardown_async(exc: t.Optional[BaseException]) -> None:
|
async def teardown_async(exc: BaseException | None) -> None:
|
||||||
...
|
...
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ def hello_json() -> Response:
|
||||||
|
|
||||||
|
|
||||||
@app.route("/json/dict")
|
@app.route("/json/dict")
|
||||||
def hello_json_dict() -> t.Dict[str, t.Any]:
|
def hello_json_dict() -> dict[str, t.Any]:
|
||||||
return {"response": "Hello, World!"}
|
return {"response": "Hello, World!"}
|
||||||
|
|
||||||
|
|
||||||
@app.route("/json/dict")
|
@app.route("/json/dict")
|
||||||
def hello_json_list() -> t.List[t.Any]:
|
def hello_json_list() -> list[t.Any]:
|
||||||
return [{"message": "Hello"}, {"message": "World"}]
|
return [{"message": "Hello"}, {"message": "World"}]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
11
tox.ini
11
tox.ini
|
|
@ -17,15 +17,8 @@ constrain_package_deps = true
|
||||||
use_frozen_constraints = true
|
use_frozen_constraints = true
|
||||||
deps =
|
deps =
|
||||||
-r requirements/tests.txt
|
-r requirements/tests.txt
|
||||||
min: -r requirements/tests-pallets-min.txt
|
min: -r requirements-skip/tests-min.txt
|
||||||
dev: https://github.com/pallets/werkzeug/archive/refs/heads/main.tar.gz
|
dev: -r requirements-skip/tests-dev.txt
|
||||||
dev: https://github.com/pallets/jinja/archive/refs/heads/main.tar.gz
|
|
||||||
dev: https://github.com/pallets/markupsafe/archive/refs/heads/main.tar.gz
|
|
||||||
dev: https://github.com/pallets/itsdangerous/archive/refs/heads/main.tar.gz
|
|
||||||
dev: https://github.com/pallets/click/archive/refs/heads/main.tar.gz
|
|
||||||
# examples/tutorial[test]
|
|
||||||
# examples/javascript[test]
|
|
||||||
# commands = pytest -v --tb=short --basetemp={envtmpdir} {posargs:tests examples}
|
|
||||||
commands = pytest -v --tb=short --basetemp={envtmpdir} {posargs:tests}
|
commands = pytest -v --tb=short --basetemp={envtmpdir} {posargs:tests}
|
||||||
|
|
||||||
[testenv:style]
|
[testenv:style]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue