Convert make_test_environ_builder into class (fixes #3207)

This commit is contained in:
Daniel Pope 2019-05-31 15:49:23 +01:00
parent 91e53da054
commit 976dfedaa9
4 changed files with 99 additions and 48 deletions

View file

@ -2359,9 +2359,9 @@ class Flask(_PackageBoundObject):
:param kwargs: other keyword arguments passed to
:class:`~werkzeug.test.EnvironBuilder`.
"""
from flask.testing import make_test_environ_builder
from flask.testing import EnvironBuilder
builder = make_test_environ_builder(self, *args, **kwargs)
builder = EnvironBuilder(self, *args, **kwargs)
try:
return self.request_context(builder.get_environ())

View file

@ -9,8 +9,9 @@
:copyright: © 2010 by the Pallets team.
:license: BSD, see LICENSE for more details.
"""
import warnings
import werkzeug
import werkzeug.test
from contextlib import contextmanager
from click.testing import CliRunner
@ -21,11 +22,9 @@ from flask.json import dumps as json_dumps
from werkzeug.urls import url_parse
def make_test_environ_builder(
app, path="/", base_url=None, subdomain=None, url_scheme=None, *args, **kwargs
):
"""Create a :class:`~werkzeug.test.EnvironBuilder`, taking some
defaults from the application.
class EnvironBuilder(werkzeug.test.EnvironBuilder):
"""An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the
application.
:param app: The Flask application to configure the environment from.
:param path: URL path being requested.
@ -45,41 +44,72 @@ def make_test_environ_builder(
:class:`~werkzeug.test.EnvironBuilder`.
"""
assert not (base_url or subdomain or url_scheme) or (base_url is not None) != bool(
subdomain or url_scheme
), 'Cannot pass "subdomain" or "url_scheme" with "base_url".'
def __init__(
self,
app,
path="/",
base_url=None,
subdomain=None,
url_scheme=None,
*args,
**kwargs
):
assert not (base_url or subdomain or url_scheme) or (
base_url is not None
) != bool(
subdomain or url_scheme
), 'Cannot pass "subdomain" or "url_scheme" with "base_url".'
if base_url is None:
http_host = app.config.get("SERVER_NAME") or "localhost"
app_root = app.config["APPLICATION_ROOT"]
if base_url is None:
http_host = app.config.get("SERVER_NAME") or "localhost"
app_root = app.config["APPLICATION_ROOT"]
if subdomain:
http_host = "{0}.{1}".format(subdomain, http_host)
if subdomain:
http_host = "{0}.{1}".format(subdomain, http_host)
if url_scheme is None:
url_scheme = app.config["PREFERRED_URL_SCHEME"]
if url_scheme is None:
url_scheme = app.config["PREFERRED_URL_SCHEME"]
url = url_parse(path)
base_url = "{scheme}://{netloc}/{path}".format(
scheme=url.scheme or url_scheme,
netloc=url.netloc or http_host,
path=app_root.lstrip("/"),
url = url_parse(path)
base_url = "{scheme}://{netloc}/{path}".format(
scheme=url.scheme or url_scheme,
netloc=url.netloc or http_host,
path=app_root.lstrip("/"),
)
path = url.path
if url.query:
sep = b"?" if isinstance(url.query, bytes) else "?"
path += sep + url.query
if "json" in kwargs:
assert "data" not in kwargs, "Client cannot provide both 'json' and 'data'."
kwargs["data"] = self.json_dumps(kwargs.pop("json"), app=app)
if "content_type" not in kwargs:
kwargs["content_type"] = "application/json"
super(EnvironBuilder, self).__init__(path, base_url, *args, **kwargs)
self.app = app
json_dumps = staticmethod(json_dumps)
def make_test_environ_builder(*args, **kwargs):
"""Create a :class:`flask.testing.EnvironBuilder`.
.. deprecated: 1.1
Will be removed in 1.2. Construct ``flask.testing.EnvironBuilder``
directly instead.
"""
warnings.warn(
DeprecationWarning(
'"make_test_environ_builder()" is deprecated and will be removed '
'in 1.2. Construct "flask.testing.EnvironBuilder" directly '
"instead."
)
path = url.path
if url.query:
sep = b"?" if isinstance(url.query, bytes) else "?"
path += sep + url.query
# TODO use EnvironBuilder.json_dumps once we require Werkzeug 0.15
if "json" in kwargs:
assert "data" not in kwargs, "Client cannot provide both 'json' and 'data'."
kwargs["data"] = json_dumps(kwargs.pop("json"), app=app)
if "content_type" not in kwargs:
kwargs["content_type"] = "application/json"
return EnvironBuilder(path, base_url, *args, **kwargs)
)
return EnvironBuilder(*args, **kwargs)
class FlaskClient(Client):
@ -167,11 +197,11 @@ class FlaskClient(Client):
if (
not kwargs
and len(args) == 1
and isinstance(args[0], (EnvironBuilder, dict))
and isinstance(args[0], (werkzeug.test.EnvironBuilder, dict))
):
environ = self.environ_base.copy()
if isinstance(args[0], EnvironBuilder):
if isinstance(args[0], werkzeug.test.EnvironBuilder):
environ.update(args[0].get_environ())
else:
environ.update(args[0])
@ -182,7 +212,7 @@ class FlaskClient(Client):
"flask._preserve_context"
] = self.preserve_context
kwargs.setdefault("environ_base", self.environ_base)
builder = make_test_environ_builder(self.application, *args, **kwargs)
builder = EnvironBuilder(self.application, *args, **kwargs)
try:
environ = builder.get_environ()

View file

@ -243,9 +243,9 @@ def test_bad_environ_raises_bad_request():
# because werkzeug enforces latin1 on Python 2.
# However it works when actually passed to the server.
from flask.testing import make_test_environ_builder
from flask.testing import EnvironBuilder
builder = make_test_environ_builder(app)
builder = EnvironBuilder(app)
environ = builder.get_environ()
# use a non-printable character in the Host - this is key to this test
@ -267,9 +267,9 @@ def test_environ_for_valid_idna_completes():
# because werkzeug enforces latin1 on Python 2.
# However it works when actually passed to the server.
from flask.testing import make_test_environ_builder
from flask.testing import EnvironBuilder
builder = make_test_environ_builder(app)
builder = EnvironBuilder(app)
environ = builder.get_environ()
# these characters are all IDNA-compatible

View file

@ -18,7 +18,7 @@ from flask import appcontext_popped
from flask._compat import text_type
from flask.cli import ScriptInfo
from flask.json import jsonify
from flask.testing import make_test_environ_builder, FlaskCliRunner
from flask.testing import make_test_environ_builder, FlaskCliRunner, EnvironBuilder
try:
import blinker
@ -88,7 +88,7 @@ def test_client_open_environ(app, client, request):
def index():
return flask.request.remote_addr
builder = make_test_environ_builder(app, path="/index", method="GET")
builder = EnvironBuilder(app, path="/index", method="GET")
request.addfinalizer(builder.close)
rv = client.open(builder)
@ -113,13 +113,34 @@ def test_specify_url_scheme(app, client):
def test_path_is_url(app):
eb = make_test_environ_builder(app, "https://example.com/")
eb = EnvironBuilder(app, "https://example.com/")
assert eb.url_scheme == "https"
assert eb.host == "example.com"
assert eb.script_root == ""
assert eb.path == "/"
def test_make_test_environ_builder(app):
with pytest.deprecated_call():
eb = make_test_environ_builder(app, "https://example.com/")
assert eb.url_scheme == "https"
assert eb.host == "example.com"
assert eb.script_root == ""
assert eb.path == "/"
def test_environbuilder_json_dumps(app):
"""EnvironBuilder.json_dumps() takes settings from the app."""
app.config["JSON_AS_ASCII"] = False
eb = EnvironBuilder(app, json=u"\u20ac")
assert eb.input_stream.read().decode("utf8") == u'"\u20ac"'
def test_environbuilder_json_dumps_static():
"""EnvironBuilder.json_dumps() can be called as a static method."""
assert EnvironBuilder.json_dumps(u"\u20ac") == u'"\\u20ac"'
def test_blueprint_with_subdomain():
app = flask.Flask(__name__, subdomain_matching=True)
app.config["SERVER_NAME"] = "example.com:1234"