diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index affc4859..db5d8949 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -23,7 +23,6 @@ jobs: - {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} - {name: '3.6', python: '3.6', os: ubuntu-latest, tox: py36} - {name: 'PyPy', python: pypy3, os: ubuntu-latest, tox: pypy3} - - {name: Version Range, python: '3.9', os: ubuntu-latest, tox: 'devel'} - {name: Docs, python: '3.9', os: ubuntu-latest, tox: docs} steps: - uses: actions/checkout@v2 diff --git a/src/flask/testing.py b/src/flask/testing.py index 2da66d79..a316bf42 100644 --- a/src/flask/testing.py +++ b/src/flask/testing.py @@ -1,9 +1,11 @@ from contextlib import contextmanager +from copy import copy import werkzeug.test from click.testing import CliRunner from werkzeug.test import Client from werkzeug.urls import url_parse +from werkzeug.wrappers import BaseRequest from . import _request_ctx_stack from .cli import ScriptInfo @@ -159,39 +161,45 @@ class FlaskClient(Client): headers = resp.get_wsgi_headers(c.request.environ) self.cookie_jar.extract_wsgi(c.request.environ, headers) - def open(self, *args, **kwargs): - as_tuple = kwargs.pop("as_tuple", False) - buffered = kwargs.pop("buffered", False) - follow_redirects = kwargs.pop("follow_redirects", False) + def open( + self, *args, as_tuple=False, buffered=False, follow_redirects=False, **kwargs + ): + # Same logic as super.open, but apply environ_base and preserve_context. + request = None - if ( - not kwargs - and len(args) == 1 - and isinstance(args[0], (werkzeug.test.EnvironBuilder, dict)) - ): - environ = self.environ_base.copy() + def copy_environ(other): + return { + **self.environ_base, + **other, + "flask._preserve_context": self.preserve_context, + } - if isinstance(args[0], werkzeug.test.EnvironBuilder): - environ.update(args[0].get_environ()) - else: - environ.update(args[0]) + if not kwargs and len(args) == 1: + arg = args[0] - environ["flask._preserve_context"] = self.preserve_context - else: - kwargs.setdefault("environ_overrides", {})[ - "flask._preserve_context" - ] = self.preserve_context - kwargs.setdefault("environ_base", self.environ_base) + if isinstance(arg, werkzeug.test.EnvironBuilder): + builder = copy(arg) + builder.environ_base = copy_environ(builder.environ_base or {}) + request = builder.get_request() + elif isinstance(arg, dict): + request = EnvironBuilder.from_environ( + arg, app=self.application, environ_base=copy_environ({}) + ).get_request() + elif isinstance(arg, BaseRequest): + request = copy(arg) + request.environ = copy_environ(request.environ) + + if request is None: + kwargs["environ_base"] = copy_environ(kwargs.get("environ_base", {})) builder = EnvironBuilder(self.application, *args, **kwargs) try: - environ = builder.get_environ() + request = builder.get_request() finally: builder.close() - return Client.open( - self, - environ, + return super().open( + request, as_tuple=as_tuple, buffered=buffered, follow_redirects=follow_redirects, diff --git a/tests/test_json.py b/tests/test_json.py index 73374fd1..d3aba5a9 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -327,9 +327,9 @@ def test_modified_url_encoding(app, client): def index(): return flask.request.args["foo"] - rv = client.get("/?foo=정상처리".encode("euc-kr")) + rv = client.get("/", query_string={"foo": "정상처리"}, charset="euc-kr") assert rv.status_code == 200 - assert rv.data == "정상처리".encode() + assert rv.get_data(as_text=True) == "정상처리" def test_json_key_sorting(app, client): diff --git a/tox.ini b/tox.ini index db58200e..5b4662a3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,6 @@ [tox] envlist = py{39,38,37,36,py3} - py38-devel style docs skip_missing_interpreters = true @@ -10,11 +9,11 @@ skip_missing_interpreters = true deps = -r requirements/tests.txt - devel: https://github.com/pallets/werkzeug/archive/master.tar.gz - devel: https://github.com/pallets/markupsafe/archive/master.tar.gz - devel: https://github.com/pallets/jinja/archive/master.tar.gz - devel: https://github.com/pallets/itsdangerous/archive/master.tar.gz - devel: https://github.com/pallets/click/archive/master.tar.gz + https://github.com/pallets/werkzeug/archive/master.tar.gz + https://github.com/pallets/markupsafe/archive/master.tar.gz + https://github.com/pallets/jinja/archive/master.tar.gz + https://github.com/pallets/itsdangerous/archive/master.tar.gz + https://github.com/pallets/click/archive/master.tar.gz commands = pip install -q -e examples/tutorial[test]