Skip to content

Commit

Permalink
Merge pull request #2041 from pallets/client-close-input
Browse files Browse the repository at this point in the history
test client response.close() closes input stream
  • Loading branch information
davidism committed Feb 11, 2021
2 parents 575d8c6 + df14dd9 commit 40dc95b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ Unreleased
add an ``Authorization`` header. It can be an ``Authorization``
object or a ``(username, password)`` tuple for ``Basic`` auth.
:pr:`1809`
- Calling ``response.close()`` on a response from the test ``Client``
will close the request input stream. This matches file behavior
and can prevent a ``ResourceWarning`` in some cases. :issue:`1785`
- ``EnvironBuilder.from_environ`` decodes values encoded for WSGI, to
avoid double encoding the new values. :pr:`1959`
- The default stat reloader will watch Python files under
Expand Down
28 changes: 24 additions & 4 deletions src/werkzeug/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,11 @@ def resolve_redirect(
builder.method = "GET"

# Clear the body and the headers that describe it.
builder.input_stream = None

if builder.input_stream is not None:
builder.input_stream.close()
builder.input_stream = None

builder.content_type = None
builder.content_length = None
builder.headers.pop("Transfer-Encoding", None)
Expand Down Expand Up @@ -1028,6 +1032,11 @@ def open(
2.1. Use :attr:`TestResponse.request` and
``request.environ`` instead.
.. versionchanged:: 2.0.0
The request input stream is closed when calling
``response.close()``. Input streams for redirects are
automatically closed.
.. versionchanged:: 0.5
If a dict is provided as file in the dict for the ``data``
parameter the content type has to be called ``content_type``
Expand Down Expand Up @@ -1089,14 +1098,21 @@ def open(
response.history = tuple(history)
history.append(response)
response = self.resolve_redirect(response, buffered=buffered)

response.history = tuple(history)
else:
# This is the final request after redirects, or not
# following redirects.
response.history = tuple(history)
# Close the input stream when closing the response, in case
# the input is an open temporary file.
response.call_on_close(request.input_stream.close)

if as_tuple:
warnings.warn(
"'as_tuple' is deprecated and will be removed in"
" version 2.1. Access 'response.request.environ'"
" instead."
" instead.",
DeprecationWarning,
stacklevel=2,
)
return request.environ, response # type: ignore

Expand Down Expand Up @@ -1248,6 +1264,10 @@ class TestResponse(Response):
Test client requests will always return an instance of this class.
If a custom response class is passed to the client, it is
subclassed along with this to support test information.
If the test request included large files, or if the application is
serving a file, call :meth:`close` to close any open files and
prevent Python showing a ``ResourceWarning``.
"""

request: Request
Expand Down
4 changes: 2 additions & 2 deletions src/werkzeug/wrappers/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,9 @@ def stream(self) -> t.BinaryIO:
_assert_not_shallow(self)
return get_input_stream(self.environ)

input_stream = environ_property(
input_stream = environ_property[t.BinaryIO](
"wsgi.input",
"""The WSGI input stream.
doc="""The WSGI input stream.
In general it's a bad idea to use this one because you can
easily read past the boundary. Use the :attr:`stream`
Expand Down

0 comments on commit 40dc95b

Please sign in to comment.