Skip to content

Commit 3301232

Browse files
committed
Merge branch 'stable'
2 parents ed1c9e9 + 85793d6 commit 3301232

20 files changed

+560
-449
lines changed

.github/workflows/pre-commit.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ jobs:
77
main:
88
runs-on: ubuntu-latest
99
steps:
10-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
11-
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
10+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
11+
- uses: astral-sh/setup-uv@d9e0f98d3fc6adb07d1e3d37f3043649ddad06a1 # v6.5.0
1212
with:
1313
enable-cache: true
1414
prune-cache: false
1515
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
1616
id: setup-python
1717
with:
1818
python-version-file: pyproject.toml
19-
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
19+
- uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
2020
with:
2121
path: ~/.cache/pre-commit
2222
key: pre-commit|${{ hashFiles('pyproject.toml', '.pre-commit-config.yaml') }}

.github/workflows/publish.yaml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ on:
55
jobs:
66
build:
77
runs-on: ubuntu-latest
8+
outputs:
9+
artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }}
810
steps:
9-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
10-
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
11+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
12+
with:
13+
persist-credentials: false
14+
- uses: astral-sh/setup-uv@d9e0f98d3fc6adb07d1e3d37f3043649ddad06a1 # v6.5.0
1115
with:
1216
enable-cache: true
1317
prune-cache: false
@@ -17,17 +21,23 @@ jobs:
1721
- run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
1822
- run: uv build
1923
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
24+
id: upload-artifact
2025
with:
21-
path: ./dist
26+
name: dist
27+
path: dist/
28+
if-no-files-found: error
2229
create-release:
2330
needs: [build]
2431
runs-on: ubuntu-latest
2532
permissions:
2633
contents: write
2734
steps:
28-
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
35+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
36+
with:
37+
artifact-ids: ${{ needs.build.outputs.artifact-id }}
38+
path: dist/
2939
- name: create release
30-
run: gh release create --draft --repo ${{ github.repository }} ${{ github.ref_name }} artifact/*
40+
run: gh release create --draft --repo ${{ github.repository }} ${{ github.ref_name }} dist/*
3141
env:
3242
GH_TOKEN: ${{ github.token }}
3343
publish-pypi:
@@ -39,7 +49,10 @@ jobs:
3949
permissions:
4050
id-token: write
4151
steps:
42-
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
52+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
53+
with:
54+
artifact-ids: ${{ needs.build.outputs.artifact-id }}
55+
path: dist/
4356
- uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
4457
with:
45-
packages-dir: artifact/
58+
packages-dir: "dist/"

.github/workflows/tests.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ jobs:
2323
- {name: Minimum Versions, python: '3.13', tox: tests-min}
2424
- {name: Development Versions, python: '3.10', tox: tests-dev}
2525
steps:
26-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
27-
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
26+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
27+
- uses: astral-sh/setup-uv@d9e0f98d3fc6adb07d1e3d37f3043649ddad06a1 # v6.5.0
2828
with:
2929
enable-cache: true
3030
prune-cache: false
@@ -35,16 +35,16 @@ jobs:
3535
typing:
3636
runs-on: ubuntu-latest
3737
steps:
38-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
39-
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
38+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
39+
- uses: astral-sh/setup-uv@d9e0f98d3fc6adb07d1e3d37f3043649ddad06a1 # v6.5.0
4040
with:
4141
enable-cache: true
4242
prune-cache: false
4343
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
4444
with:
4545
python-version-file: pyproject.toml
4646
- name: cache mypy
47-
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
47+
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
4848
with:
4949
path: ./.mypy_cache
5050
key: mypy|${{ hashFiles('pyproject.toml') }}

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: 9aeda5d1f4bbd212c557da1ea78eca9e8c829e19 # frozen: v0.11.13
3+
rev: 54a455f7ce629598b7535ff828fd5fb796f4b83f # frozen: v0.12.9
44
hooks:
55
- id: ruff
66
- id: ruff-format
77
- repo: https://github.com/astral-sh/uv-pre-commit
8-
rev: a621b109bab2e7e832d98c88fd3e83399f4e6657 # frozen: 0.7.12
8+
rev: f9572a6b06237978e1d52fad0ae55bac5e36da26 # frozen: 0.8.12
99
hooks:
1010
- id: uv-lock
1111
- repo: https://github.com/pre-commit/pre-commit-hooks
12-
rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0
12+
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
1313
hooks:
1414
- id: check-merge-conflict
1515
- id: debug-statements

CHANGES.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ Unreleased
99
can be used without parentheses. :issue:`5729`
1010

1111

12+
Version 3.1.2
13+
-------------
14+
15+
Released 2025-08-19
16+
17+
- ``stream_with_context`` does not fail inside async views. :issue:`5774`
18+
- When using ``follow_redirects`` in the test client, the final state
19+
of ``session`` is correct. :issue:`5786`
20+
- Relax type hint for passing bytes IO to ``send_file``. :issue:`5776`
21+
22+
1223
Version 3.1.1
1324
-------------
1425

@@ -1376,7 +1387,7 @@ Released 2011-09-29, codename Rakija
13761387
of Flask itself and no longer of the test client. This cleaned up
13771388
some internal logic and lowers the odds of runaway request contexts
13781389
in unittests.
1379-
- Fixed the Jinja2 environment's ``list_templates`` method not
1390+
- Fixed the Jinja environment's ``list_templates`` method not
13801391
returning the correct names when blueprints or modules were
13811392
involved.
13821393

@@ -1462,7 +1473,7 @@ Released 2010-12-31
14621473

14631474
- Fixed an issue where the default ``OPTIONS`` response was not
14641475
exposing all valid methods in the ``Allow`` header.
1465-
- Jinja2 template loading syntax now allows "./" in front of a
1476+
- Jinja template loading syntax now allows "./" in front of a
14661477
template load path. Previously this caused issues with module
14671478
setups.
14681479
- Fixed an issue where the subdomain setting for modules was ignored

docs/design.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,18 @@ is ambiguous.
9696
One Template Engine
9797
-------------------
9898

99-
Flask decides on one template engine: Jinja2. Why doesn't Flask have a
99+
Flask decides on one template engine: Jinja. Why doesn't Flask have a
100100
pluggable template engine interface? You can obviously use a different
101-
template engine, but Flask will still configure Jinja2 for you. While
102-
that limitation that Jinja2 is *always* configured will probably go away,
101+
template engine, but Flask will still configure Jinja for you. While
102+
that limitation that Jinja is *always* configured will probably go away,
103103
the decision to bundle one template engine and use that will not.
104104

105105
Template engines are like programming languages and each of those engines
106106
has a certain understanding about how things work. On the surface they
107107
all work the same: you tell the engine to evaluate a template with a set
108108
of variables and take the return value as string.
109109

110-
But that's about where similarities end. Jinja2 for example has an
110+
But that's about where similarities end. Jinja for example has an
111111
extensive filter system, a certain way to do template inheritance,
112112
support for reusable blocks (macros) that can be used from inside
113113
templates and also from Python code, supports iterative template
@@ -118,8 +118,8 @@ other hand treats templates similar to Python modules.
118118

119119
When it comes to connecting a template engine with an application or
120120
framework there is more than just rendering templates. For instance,
121-
Flask uses Jinja2's extensive autoescaping support. Also it provides
122-
ways to access macros from Jinja2 templates.
121+
Flask uses Jinja's extensive autoescaping support. Also it provides
122+
ways to access macros from Jinja templates.
123123

124124
A template abstraction layer that would not take the unique features of
125125
the template engines away is a science on its own and a too large
@@ -150,7 +150,7 @@ authentication technologies, and more. Flask may be "micro", but it's ready for
150150
production use on a variety of needs.
151151

152152
Why does Flask call itself a microframework and yet it depends on two
153-
libraries (namely Werkzeug and Jinja2). Why shouldn't it? If we look
153+
libraries (namely Werkzeug and Jinja). Why shouldn't it? If we look
154154
over to the Ruby side of web development there we have a protocol very
155155
similar to WSGI. Just that it's called Rack there, but besides that it
156156
looks very much like a WSGI rendition for Ruby. But nearly all
@@ -208,7 +208,7 @@ What Flask is, What Flask is Not
208208

209209
Flask will never have a database layer. It will not have a form library
210210
or anything else in that direction. Flask itself just bridges to Werkzeug
211-
to implement a proper WSGI application and to Jinja2 to handle templating.
211+
to implement a proper WSGI application and to Jinja to handle templating.
212212
It also binds to a few common standard library packages such as logging.
213213
Everything else is up for extensions.
214214

docs/patterns/streaming.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ debug environments with profilers and other things you might have enabled.
2929
Streaming from Templates
3030
------------------------
3131

32-
The Jinja2 template engine supports rendering a template piece by
32+
The Jinja template engine supports rendering a template piece by
3333
piece, returning an iterator of strings. Flask provides the
3434
:func:`~flask.stream_template` and :func:`~flask.stream_template_string`
3535
functions to make this easier to use.

docs/patterns/wtforms.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ WTForm's field function, which renders the field for us. The keyword
9999
arguments will be inserted as HTML attributes. So, for example, you can
100100
call ``render_field(form.username, class='username')`` to add a class to
101101
the input element. Note that WTForms returns standard Python strings,
102-
so we have to tell Jinja2 that this data is already HTML-escaped with
102+
so we have to tell Jinja that this data is already HTML-escaped with
103103
the ``|safe`` filter.
104104

105105
Here is the :file:`register.html` template for the function we used above, which

docs/quickstart.rst

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,16 @@ how you're using untrusted data.
139139

140140
.. code-block:: python
141141
142+
from flask import request
142143
from markupsafe import escape
143144
144-
@app.route("/<name>")
145-
def hello(name):
145+
@app.route("/hello")
146+
def hello():
147+
name = request.args.get("name", "Flask")
146148
return f"Hello, {escape(name)}!"
147149
148-
If a user managed to submit the name ``<script>alert("bad")</script>``,
149-
escaping causes it to be rendered as text, rather than running the
150-
script in the user's browser.
151-
152-
``<name>`` in the route captures a value from the URL and passes it to
153-
the view function. These variable rules are explained below.
150+
If a user submits ``/hello?name=<script>alert("bad")</script>``, escaping causes
151+
it to be rendered as text, rather than running the script in the user's browser.
154152

155153

156154
Routing
@@ -354,7 +352,7 @@ Rendering Templates
354352

355353
Generating HTML from within Python is not fun, and actually pretty
356354
cumbersome because you have to do the HTML escaping on your own to keep
357-
the application secure. Because of that Flask configures the `Jinja2
355+
the application secure. Because of that Flask configures the `Jinja
358356
<https://palletsprojects.com/p/jinja/>`_ template engine for you automatically.
359357

360358
Templates can be used to generate any type of text file. For web applications, you'll
@@ -394,8 +392,8 @@ package it's actually inside your package:
394392
/templates
395393
/hello.html
396394

397-
For templates you can use the full power of Jinja2 templates. Head over
398-
to the official `Jinja2 Template Documentation
395+
For templates you can use the full power of Jinja templates. Head over
396+
to the official `Jinja Template Documentation
399397
<https://jinja.palletsprojects.com/templates/>`_ for more information.
400398

401399
Here is an example template:

docs/server.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ following example shows that process id 6847 is using port 5000.
7777
7878
macOS Monterey and later automatically starts a service that uses port
7979
5000. You can choose to disable this service instead of using a different port by
80-
searching for "AirPlay Receiver" in System Preferences and toggling it off.
80+
searching for "AirPlay Receiver" in System Settings and toggling it off.
8181

8282

8383
Deferred Errors on Reload

0 commit comments

Comments
 (0)