mirror of https://github.com/pallets/flask.git
				
				
				
			Merge pull request #3157 from fantix/fix-test-client-teardown
Fix teardown bug in FlaskClient
This commit is contained in:
		
						commit
						2c68f86336
					
				| 
						 | 
				
			
			@ -61,6 +61,9 @@ Unreleased
 | 
			
		|||
-   Blueprints have a ``cli`` Click group like ``app.cli``. CLI commands
 | 
			
		||||
    registered with a blueprint will be available as a group under the
 | 
			
		||||
    ``flask`` command. :issue:`1357`.
 | 
			
		||||
-   When using the test client as a context manager (``with client:``),
 | 
			
		||||
    all preserved request contexts are popped when the block exits,
 | 
			
		||||
    ensuring nested contexts are cleaned up correctly. :pr:`3157`
 | 
			
		||||
 | 
			
		||||
.. _#2935: https://github.com/pallets/flask/issues/2935
 | 
			
		||||
.. _#2957: https://github.com/pallets/flask/issues/2957
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -206,12 +206,17 @@ class FlaskClient(Client):
 | 
			
		|||
    def __exit__(self, exc_type, exc_value, tb):
 | 
			
		||||
        self.preserve_context = False
 | 
			
		||||
 | 
			
		||||
        # on exit we want to clean up earlier.  Normally the request context
 | 
			
		||||
        # stays preserved until the next request in the same thread comes
 | 
			
		||||
        # in.  See RequestGlobals.push() for the general behavior.
 | 
			
		||||
        top = _request_ctx_stack.top
 | 
			
		||||
        if top is not None and top.preserved:
 | 
			
		||||
            top.pop()
 | 
			
		||||
        # Normally the request context is preserved until the next
 | 
			
		||||
        # request in the same thread comes. When the client exits we
 | 
			
		||||
        # want to clean up earlier. Pop request contexts until the stack
 | 
			
		||||
        # is empty or a non-preserved one is found.
 | 
			
		||||
        while True:
 | 
			
		||||
            top = _request_ctx_stack.top
 | 
			
		||||
 | 
			
		||||
            if top is not None and top.preserved:
 | 
			
		||||
                top.pop()
 | 
			
		||||
            else:
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FlaskCliRunner(CliRunner):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -411,3 +411,18 @@ def test_cli_custom_obj(app):
 | 
			
		|||
    runner = app.test_cli_runner()
 | 
			
		||||
    runner.invoke(hello_command, obj=script_info)
 | 
			
		||||
    assert NS.called
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_client_pop_all_preserved(app, req_ctx, client):
 | 
			
		||||
    @app.route("/")
 | 
			
		||||
    def index():
 | 
			
		||||
        # stream_with_context pushes a third context, preserved by client
 | 
			
		||||
        return flask.Response(flask.stream_with_context("hello"))
 | 
			
		||||
 | 
			
		||||
    # req_ctx fixture pushed an initial context, not marked preserved
 | 
			
		||||
    with client:
 | 
			
		||||
        # request pushes a second request context, preserved by client
 | 
			
		||||
        client.get("/")
 | 
			
		||||
 | 
			
		||||
    # only req_ctx fixture should still be pushed
 | 
			
		||||
    assert flask._request_ctx_stack.top is req_ctx
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue