deprecate markupsafe exports

This commit is contained in:
David Lord 2023-02-23 08:55:01 -08:00
parent 1ee22e1736
commit 9c02f07f9b
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
8 changed files with 41 additions and 20 deletions

View File

@ -21,6 +21,8 @@ Unreleased
corresponding ``json.JSONEncoder`` and ``JSONDecoder`` classes, are removed. corresponding ``json.JSONEncoder`` and ``JSONDecoder`` classes, are removed.
- The ``json.htmlsafe_dumps`` and ``htmlsafe_dump`` functions are removed. - The ``json.htmlsafe_dumps`` and ``htmlsafe_dump`` functions are removed.
- Importing ``escape`` and ``Markup`` from ``flask`` is deprecated. Import them
directly from ``markupsafe`` instead. :pr:`4996`
- Use modern packaging metadata with ``pyproject.toml`` instead of ``setup.cfg``. - Use modern packaging metadata with ``pyproject.toml`` instead of ``setup.cfg``.
:pr:`4947` :pr:`4947`
- Ensure subdomains are applied with nested blueprints. :issue:`4834` - Ensure subdomains are applied with nested blueprints. :issue:`4834`

View File

@ -217,10 +217,6 @@ Useful Functions and Classes
.. autofunction:: send_from_directory .. autofunction:: send_from_directory
.. autofunction:: escape
.. autoclass:: Markup
:members: escape, unescape, striptags
Message Flashing Message Flashing
---------------- ----------------

View File

@ -23,7 +23,7 @@ in templates, but there are still other places where you have to be
careful: careful:
- generating HTML without the help of Jinja2 - generating HTML without the help of Jinja2
- calling :class:`~flask.Markup` on data submitted by users - calling :class:`~markupsafe.Markup` on data submitted by users
- sending out HTML from uploaded files, never do that, use the - sending out HTML from uploaded files, never do that, use the
``Content-Disposition: attachment`` header to prevent that problem. ``Content-Disposition: attachment`` header to prevent that problem.
- sending out textfiles from uploaded files. Some browsers are using - sending out textfiles from uploaded files. Some browsers are using

View File

@ -115,7 +115,7 @@ markdown to HTML converter.
There are three ways to accomplish that: There are three ways to accomplish that:
- In the Python code, wrap the HTML string in a :class:`~flask.Markup` - In the Python code, wrap the HTML string in a :class:`~markupsafe.Markup`
object before passing it to the template. This is in general the object before passing it to the template. This is in general the
recommended way. recommended way.
- Inside the template, use the ``|safe`` filter to explicitly mark a - Inside the template, use the ``|safe`` filter to explicitly mark a

View File

@ -1,6 +1,3 @@
from markupsafe import escape
from markupsafe import Markup
from . import json as json from . import json as json
from .app import Flask as Flask from .app import Flask as Flask
from .app import Request as Request from .app import Request as Request
@ -68,4 +65,28 @@ def __getattr__(name):
) )
return __request_ctx_stack return __request_ctx_stack
if name == "escape":
import warnings
from markupsafe import escape
warnings.warn(
"'flask.escape' is deprecated and will be removed in Flask 2.4. Import"
" 'markupsafe.escape' instead.",
DeprecationWarning,
stacklevel=2,
)
return escape
if name == "escape":
import warnings
from markupsafe import Markup
warnings.warn(
"'flask.Markup' is deprecated and will be removed in Flask 2.4. Import"
" 'markupsafe.Markup' instead.",
DeprecationWarning,
stacklevel=2,
)
return Markup
raise AttributeError(name) raise AttributeError(name)

View File

@ -9,6 +9,7 @@ from platform import python_implementation
import pytest import pytest
import werkzeug.serving import werkzeug.serving
from markupsafe import Markup
from werkzeug.exceptions import BadRequest from werkzeug.exceptions import BadRequest
from werkzeug.exceptions import Forbidden from werkzeug.exceptions import Forbidden
from werkzeug.exceptions import NotFound from werkzeug.exceptions import NotFound
@ -472,7 +473,7 @@ def test_session_special_types(app, client):
def dump_session_contents(): def dump_session_contents():
flask.session["t"] = (1, 2, 3) flask.session["t"] = (1, 2, 3)
flask.session["b"] = b"\xff" flask.session["b"] = b"\xff"
flask.session["m"] = flask.Markup("<html>") flask.session["m"] = Markup("<html>")
flask.session["u"] = the_uuid flask.session["u"] = the_uuid
flask.session["d"] = now flask.session["d"] = now
flask.session["t_tag"] = {" t": "not-a-tuple"} flask.session["t_tag"] = {" t": "not-a-tuple"}
@ -486,8 +487,8 @@ def test_session_special_types(app, client):
assert s["t"] == (1, 2, 3) assert s["t"] == (1, 2, 3)
assert type(s["b"]) == bytes assert type(s["b"]) == bytes
assert s["b"] == b"\xff" assert s["b"] == b"\xff"
assert type(s["m"]) == flask.Markup assert type(s["m"]) == Markup
assert s["m"] == flask.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
assert s["t_tag"] == {" t": "not-a-tuple"} assert s["t_tag"] == {" t": "not-a-tuple"}
@ -611,7 +612,7 @@ def test_extended_flashing(app):
def index(): def index():
flask.flash("Hello World") flask.flash("Hello World")
flask.flash("Hello World", "error") flask.flash("Hello World", "error")
flask.flash(flask.Markup("<em>Testing</em>"), "warning") flask.flash(Markup("<em>Testing</em>"), "warning")
return "" return ""
@app.route("/test/") @app.route("/test/")
@ -620,7 +621,7 @@ def test_extended_flashing(app):
assert list(messages) == [ assert list(messages) == [
"Hello World", "Hello World",
"Hello World", "Hello World",
flask.Markup("<em>Testing</em>"), Markup("<em>Testing</em>"),
] ]
return "" return ""
@ -631,7 +632,7 @@ def test_extended_flashing(app):
assert list(messages) == [ assert list(messages) == [
("message", "Hello World"), ("message", "Hello World"),
("error", "Hello World"), ("error", "Hello World"),
("warning", flask.Markup("<em>Testing</em>")), ("warning", Markup("<em>Testing</em>")),
] ]
return "" return ""
@ -650,7 +651,7 @@ def test_extended_flashing(app):
) )
assert list(messages) == [ assert list(messages) == [
("message", "Hello World"), ("message", "Hello World"),
("warning", flask.Markup("<em>Testing</em>")), ("warning", Markup("<em>Testing</em>")),
] ]
return "" return ""
@ -659,7 +660,7 @@ def test_extended_flashing(app):
messages = flask.get_flashed_messages(category_filter=["message", "warning"]) messages = flask.get_flashed_messages(category_filter=["message", "warning"])
assert len(messages) == 2 assert len(messages) == 2
assert messages[0] == "Hello World" assert messages[0] == "Hello World"
assert messages[1] == flask.Markup("<em>Testing</em>") assert messages[1] == Markup("<em>Testing</em>")
return "" return ""
# Create new test client on each test to clean flashed messages. # Create new test client on each test to clean flashed messages.

View File

@ -3,8 +3,8 @@ from datetime import timezone
from uuid import uuid4 from uuid import uuid4
import pytest import pytest
from markupsafe import Markup
from flask import Markup
from flask.json.tag import JSONTag from flask.json.tag import JSONTag
from flask.json.tag import TaggedJSONSerializer from flask.json.tag import TaggedJSONSerializer

View File

@ -3,6 +3,7 @@ import logging
import pytest import pytest
import werkzeug.serving import werkzeug.serving
from jinja2 import TemplateNotFound from jinja2 import TemplateNotFound
from markupsafe import Markup
import flask import flask
@ -73,7 +74,7 @@ def test_escaping(app, client):
@app.route("/") @app.route("/")
def index(): def index():
return flask.render_template( return flask.render_template(
"escaping_template.html", text=text, html=flask.Markup(text) "escaping_template.html", text=text, html=Markup(text)
) )
lines = client.get("/").data.splitlines() lines = client.get("/").data.splitlines()
@ -93,7 +94,7 @@ def test_no_escaping(app, client):
@app.route("/") @app.route("/")
def index(): def index():
return flask.render_template( return flask.render_template(
"non_escaping_template.txt", text=text, html=flask.Markup(text) "non_escaping_template.txt", text=text, html=Markup(text)
) )
lines = client.get("/").data.splitlines() lines = client.get("/").data.splitlines()