From 9c186ccfe8fa4156123e9252a6e8a9cc68bfecab Mon Sep 17 00:00:00 2001 From: Rafael Aviles Date: Fri, 14 May 2021 13:23:34 -0700 Subject: [PATCH 1/7] Use escape function in return statement for username and subpath. --- docs/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 9418835a..5cd59f41 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -246,7 +246,7 @@ of the argument like ````. :: @app.route('/user/') def show_user_profile(username): # show the user profile for that user - return f'User {username}' + return f'User {escape(username)}' @app.route('/post/') def show_post(post_id): @@ -256,7 +256,7 @@ of the argument like ````. :: @app.route('/path/') def show_subpath(subpath): # show the subpath after /path/ - return f'Subpath {subpath}' + return f'Subpath {escape(subpath)}' Converter types: From 6fbdeb80c76b8a698ab366d21ccd786731b17361 Mon Sep 17 00:00:00 2001 From: pgjones Date: Sun, 16 May 2021 19:32:29 +0100 Subject: [PATCH 2/7] Fix nested blueprint url_prefix This fixes the case where the blueprint is registered with a url_prefix but any child blueprints have no prefixes. --- src/flask/blueprints.py | 2 ++ tests/test_blueprints.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/flask/blueprints.py b/src/flask/blueprints.py index 7bfef84b..39396ce7 100644 --- a/src/flask/blueprints.py +++ b/src/flask/blueprints.py @@ -354,6 +354,8 @@ class Blueprint(Scaffold): bp_options["url_prefix"] = ( state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") ) + else: + bp_options["url_prefix"] = state.url_prefix bp_options["name_prefix"] = options.get("name_prefix", "") + self.name + "." blueprint.register(app, bp_options) diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index e7724519..0bae5333 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -868,3 +868,17 @@ def test_nested_blueprint_url_prefix(app, client): assert client.get("/parent/child/").data == b"Child" assert client.get("/parent/child/grandchild/").data == b"Grandchild" assert client.get("/parent/child/orange/").data == b"Apple" + + +def test_nested_blueprint_url_prefix_only_parent_prefix(app, client): + parent = flask.Blueprint("parent", __name__) + child = flask.Blueprint("child", __name__) + + @child.route("/child-endpoint") + def child_index(): + return "Child" + + parent.register_blueprint(child) + app.register_blueprint(parent, url_prefix="/parent") + + assert client.get("/parent/child-endpoint").data == b"Child" From 1b5f21e015e2c4f36fcdb34a09ce93787d59e181 Mon Sep 17 00:00:00 2001 From: Danny Sepler Date: Sun, 16 May 2021 22:34:32 -0400 Subject: [PATCH 3/7] Add pathlib in cli tests --- tests/test_cli.py | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index c3a00f17..ebf8d1f5 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -5,6 +5,7 @@ import ssl import sys import types from functools import partial +from pathlib import Path from unittest.mock import patch import click @@ -29,8 +30,8 @@ from flask.cli import run_command from flask.cli import ScriptInfo from flask.cli import with_appcontext -cwd = os.getcwd() -test_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "test_apps")) +cwd = Path.cwd() +test_path = (Path(__file__) / ".." / "test_apps").resolve() @pytest.fixture @@ -152,29 +153,25 @@ def test_find_best_app(test_apps): ( ("test", cwd, "test"), ("test.py", cwd, "test"), - ("a/test", os.path.join(cwd, "a"), "test"), + ("a/test", cwd / "a", "test"), ("test/__init__.py", cwd, "test"), ("test/__init__", cwd, "test"), # nested package ( - os.path.join(test_path, "cliapp", "inner1", "__init__"), + test_path / "cliapp" / "inner1" / "__init__", test_path, "cliapp.inner1", ), ( - os.path.join(test_path, "cliapp", "inner1", "inner2"), + test_path / "cliapp" / "inner1" / "inner2", test_path, "cliapp.inner1.inner2", ), # dotted name ("test.a.b", cwd, "test.a.b"), - (os.path.join(test_path, "cliapp.app"), test_path, "cliapp.app"), + (test_path / "cliapp.app", test_path, "cliapp.app"), # not a Python file, will be caught during import - ( - os.path.join(test_path, "cliapp", "message.txt"), - test_path, - "cliapp.message.txt", - ), + (test_path / "cliapp" / "message.txt", test_path, "cliapp.message.txt"), ), ) def test_prepare_import(request, value, path, result): @@ -193,7 +190,7 @@ def test_prepare_import(request, value, path, result): request.addfinalizer(reset_path) assert prepare_import(value) == result - assert sys.path[0] == path + assert sys.path[0] == str(path) @pytest.mark.parametrize( @@ -278,9 +275,8 @@ def test_scriptinfo(test_apps, monkeypatch): assert obj.load_app() is app # import app with module's absolute path - cli_app_path = os.path.abspath( - os.path.join(os.path.dirname(__file__), "test_apps", "cliapp", "app.py") - ) + cli_app_path = str(test_path / "cliapp" / "app.py") + obj = ScriptInfo(app_import_path=cli_app_path) app = obj.load_app() assert app.name == "testapp" @@ -302,19 +298,13 @@ def test_scriptinfo(test_apps, monkeypatch): pytest.raises(NoAppException, obj.load_app) # import app from wsgi.py in current directory - monkeypatch.chdir( - os.path.abspath( - os.path.join(os.path.dirname(__file__), "test_apps", "helloworld") - ) - ) + monkeypatch.chdir(test_path / "helloworld") obj = ScriptInfo() app = obj.load_app() assert app.name == "hello" # import app from app.py in current directory - monkeypatch.chdir( - os.path.abspath(os.path.join(os.path.dirname(__file__), "test_apps", "cliapp")) - ) + monkeypatch.chdir(test_path / "cliapp") obj = ScriptInfo() app = obj.load_app() assert app.name == "testapp" @@ -513,7 +503,7 @@ def test_load_dotenv(monkeypatch): monkeypatch.setenv("EGGS", "3") monkeypatch.chdir(test_path) assert load_dotenv() - assert os.getcwd() == test_path + assert Path.cwd() == test_path # .flaskenv doesn't overwrite .env assert os.environ["FOO"] == "env" # set only in .flaskenv @@ -533,9 +523,8 @@ def test_dotenv_path(monkeypatch): for item in ("FOO", "BAR", "EGGS"): monkeypatch._setitem.append((os.environ, item, notset)) - cwd = os.getcwd() - load_dotenv(os.path.join(test_path, ".flaskenv")) - assert os.getcwd() == cwd + load_dotenv(test_path / ".flaskenv") + assert Path.cwd() == cwd assert "FOO" in os.environ From afc907fd0d4a4e96398829d75ded9711a3046070 Mon Sep 17 00:00:00 2001 From: David Lord Date: Mon, 17 May 2021 16:03:12 -0700 Subject: [PATCH 4/7] use _typeshed.wsgi instead of wsgiref.types --- src/flask/typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flask/typing.py b/src/flask/typing.py index 9a664e41..5f27308c 100644 --- a/src/flask/typing.py +++ b/src/flask/typing.py @@ -2,8 +2,8 @@ import typing as t if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication # noqa: F401 from werkzeug.datastructures import Headers # noqa: F401 - from wsgiref.types import WSGIApplication # noqa: F401 from .wrappers import Response # noqa: F401 # The possible types that are directly convertible or are a Response object. From 10425fb9b13d977128f18c1051fb93edc9aee2de Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 20 May 2021 12:35:43 -0700 Subject: [PATCH 5/7] re-add deprecated Config.from_json method --- CHANGES.rst | 2 ++ src/flask/config.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index fa24b104..0b5a939d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -23,6 +23,8 @@ Unreleased - Roll back 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` Version 2.0.0 diff --git a/src/flask/config.py b/src/flask/config.py index 86f21dc8..c79a558e 100644 --- a/src/flask/config.py +++ b/src/flask/config.py @@ -202,6 +202,31 @@ class Config(dict): return self.from_mapping(obj) + def from_json(self, filename: str, silent: bool = False) -> bool: + """Update the values in the config from a JSON file. The loaded + data is passed to the :meth:`from_mapping` method. + + :param filename: The path to the JSON file. This can be an + absolute path or relative to the config root path. + :param silent: Ignore the file if it doesn't exist. + + .. deprecated:: 2.0.0 + Will be removed in Flask 2.1. Use :meth:`from_file` instead. + This was removed early in 2.0.0, was added back in 2.0.1. + + .. versionadded:: 0.11 + """ + import warnings + from . import json + + warnings.warn( + "'from_json' is deprecated and will be removed in Flask" + " 2.1. Use 'from_file(path, json.load)' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self.from_file(filename, json.load, silent=silent) + def from_mapping( self, mapping: t.Optional[t.Mapping[str, t.Any]] = None, **kwargs: t.Any ) -> bool: From cfda27089932a102953da73fdab17cf9814334e4 Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 20 May 2021 21:03:02 -0700 Subject: [PATCH 6/7] update pallets-sphinx-themes --- docs/conf.py | 6 +++--- requirements/dev.txt | 2 +- requirements/docs.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index bcea8858..ae2922d7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,10 +49,10 @@ html_context = { ] } html_sidebars = { - "index": ["project.html", "localtoc.html", "searchbox.html"], - "**": ["localtoc.html", "relations.html", "searchbox.html"], + "index": ["project.html", "localtoc.html", "searchbox.html", "ethicalads.html"], + "**": ["localtoc.html", "relations.html", "searchbox.html", "ethicalads.html"], } -singlehtml_sidebars = {"index": ["project.html", "localtoc.html"]} +singlehtml_sidebars = {"index": ["project.html", "localtoc.html", "ethicalads.html"]} html_static_path = ["_static"] html_favicon = "_static/flask-icon.png" html_logo = "_static/flask-icon.png" diff --git a/requirements/dev.txt b/requirements/dev.txt index 4a2acbb7..232601f0 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -60,7 +60,7 @@ packaging==20.9 # pytest # sphinx # tox -pallets-sphinx-themes==2.0.0 +pallets-sphinx-themes==2.0.1 # via -r requirements/docs.in pep517==0.10.0 # via pip-tools diff --git a/requirements/docs.txt b/requirements/docs.txt index e99d842e..daf4530b 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -28,7 +28,7 @@ packaging==20.9 # via # pallets-sphinx-themes # sphinx -pallets-sphinx-themes==2.0.0 +pallets-sphinx-themes==2.0.1 # via -r requirements/docs.in pygments==2.9.0 # via From 9889ca8bcabbb1b1290ca4403b0242e01bae4c47 Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 20 May 2021 21:03:33 -0700 Subject: [PATCH 7/7] update pallets and sphinx requirements --- requirements/dev.txt | 10 +++++----- requirements/docs.in | 2 +- requirements/docs.txt | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 232601f0..1b6998cf 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -18,11 +18,11 @@ blinker==1.4 # via -r requirements/tests.in certifi==2020.12.5 # via requests -cfgv==3.2.0 +cfgv==3.3.0 # via pre-commit chardet==4.0.0 # via requests -click==8.0.0 +click==8.0.1 # via pip-tools distlib==0.3.1 # via virtualenv @@ -44,9 +44,9 @@ imagesize==1.2.0 # via sphinx iniconfig==1.1.1 # via pytest -jinja2==3.0.0 +jinja2==3.0.1 # via sphinx -markupsafe==2.0.0 +markupsafe==2.0.1 # via jinja2 mypy-extensions==0.4.3 # via mypy @@ -102,7 +102,7 @@ sphinx-issues==1.2.0 # via -r requirements/docs.in sphinx-tabs==3.0.0 # via -r requirements/docs.in -git+https://github.com/sphinx-doc/sphinx.git@96dbe5e3 +sphinx==4.0.2 # via # -r requirements/docs.in # pallets-sphinx-themes diff --git a/requirements/docs.in b/requirements/docs.in index d3519043..3ee050af 100644 --- a/requirements/docs.in +++ b/requirements/docs.in @@ -1,5 +1,5 @@ Pallets-Sphinx-Themes -git+https://github.com/sphinx-doc/sphinx.git@96dbe5e3 # https://github.com/sphinx-doc/sphinx/issues/921 +Sphinx sphinx-issues sphinxcontrib-log-cabinet sphinx-tabs diff --git a/requirements/docs.txt b/requirements/docs.txt index daf4530b..245f04b6 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -20,9 +20,9 @@ idna==2.10 # via requests imagesize==1.2.0 # via sphinx -jinja2==3.0.0 +jinja2==3.0.1 # via sphinx -markupsafe==2.0.0 +markupsafe==2.0.1 # via jinja2 packaging==20.9 # via @@ -46,7 +46,7 @@ sphinx-issues==1.2.0 # via -r requirements/docs.in sphinx-tabs==3.0.0 # via -r requirements/docs.in -git+https://github.com/sphinx-doc/sphinx.git@96dbe5e3 +sphinx==4.0.2 # via # -r requirements/docs.in # pallets-sphinx-themes