mirror of https://github.com/pallets/flask.git
Add session to RequestContext.copy()
This commit is contained in:
parent
7e714bd28b
commit
e08bcf9f97
|
@ -9,6 +9,12 @@ Version 1.1
|
||||||
|
|
||||||
Unreleased
|
Unreleased
|
||||||
|
|
||||||
|
- :meth:`flask.RequestContext.copy` includes the current session
|
||||||
|
object in the request context copy. This prevents ``flask.session``
|
||||||
|
pointing to an out-of-date object. (`#2935`)
|
||||||
|
|
||||||
|
.. _#2935: https://github.com/pallets/flask/issues/2935
|
||||||
|
|
||||||
|
|
||||||
Version 1.0.3
|
Version 1.0.3
|
||||||
-------------
|
-------------
|
||||||
|
|
18
flask/ctx.py
18
flask/ctx.py
|
@ -122,7 +122,8 @@ def copy_current_request_context(f):
|
||||||
"""A helper function that decorates a function to retain the current
|
"""A helper function that decorates a function to retain the current
|
||||||
request context. This is useful when working with greenlets. The moment
|
request context. This is useful when working with greenlets. The moment
|
||||||
the function is decorated a copy of the request context is created and
|
the function is decorated a copy of the request context is created and
|
||||||
then pushed when the function is called.
|
then pushed when the function is called. The current session is also
|
||||||
|
included in the copied request context.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
@ -133,8 +134,8 @@ def copy_current_request_context(f):
|
||||||
def index():
|
def index():
|
||||||
@copy_current_request_context
|
@copy_current_request_context
|
||||||
def do_some_work():
|
def do_some_work():
|
||||||
# do some work here, it can access flask.request like you
|
# do some work here, it can access flask.request or
|
||||||
# would otherwise in the view function.
|
# flask.session like you would otherwise in the view function.
|
||||||
...
|
...
|
||||||
gevent.spawn(do_some_work)
|
gevent.spawn(do_some_work)
|
||||||
return 'Regular response'
|
return 'Regular response'
|
||||||
|
@ -276,14 +277,14 @@ class RequestContext(object):
|
||||||
that situation, otherwise your unittests will leak memory.
|
that situation, otherwise your unittests will leak memory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, app, environ, request=None):
|
def __init__(self, app, environ, request=None, session=None):
|
||||||
self.app = app
|
self.app = app
|
||||||
if request is None:
|
if request is None:
|
||||||
request = app.request_class(environ)
|
request = app.request_class(environ)
|
||||||
self.request = request
|
self.request = request
|
||||||
self.url_adapter = app.create_url_adapter(self.request)
|
self.url_adapter = app.create_url_adapter(self.request)
|
||||||
self.flashes = None
|
self.flashes = None
|
||||||
self.session = None
|
self.session = session
|
||||||
|
|
||||||
# Request contexts can be pushed multiple times and interleaved with
|
# Request contexts can be pushed multiple times and interleaved with
|
||||||
# other request contexts. Now only if the last level is popped we
|
# other request contexts. Now only if the last level is popped we
|
||||||
|
@ -321,10 +322,15 @@ class RequestContext(object):
|
||||||
request object is locked.
|
request object is locked.
|
||||||
|
|
||||||
.. versionadded:: 0.10
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
|
.. versionchanged:: 1.1
|
||||||
|
The current session object is used instead of reloading the original
|
||||||
|
data. This prevents `flask.session` pointing to an out-of-date object.
|
||||||
"""
|
"""
|
||||||
return self.__class__(self.app,
|
return self.__class__(self.app,
|
||||||
environ=self.request.environ,
|
environ=self.request.environ,
|
||||||
request=self.request
|
request=self.request,
|
||||||
|
session=self.session
|
||||||
)
|
)
|
||||||
|
|
||||||
def match_request(self):
|
def match_request(self):
|
||||||
|
|
|
@ -156,6 +156,7 @@ class TestGreenletContextCopying(object):
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
|
flask.session['fizz'] = 'buzz'
|
||||||
reqctx = flask._request_ctx_stack.top.copy()
|
reqctx = flask._request_ctx_stack.top.copy()
|
||||||
|
|
||||||
def g():
|
def g():
|
||||||
|
@ -166,6 +167,7 @@ class TestGreenletContextCopying(object):
|
||||||
assert flask.current_app == app
|
assert flask.current_app == app
|
||||||
assert flask.request.path == '/'
|
assert flask.request.path == '/'
|
||||||
assert flask.request.args['foo'] == 'bar'
|
assert flask.request.args['foo'] == 'bar'
|
||||||
|
assert flask.session.get('fizz') == 'buzz'
|
||||||
assert not flask.request
|
assert not flask.request
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
@ -183,6 +185,7 @@ class TestGreenletContextCopying(object):
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
|
flask.session['fizz'] = 'buzz'
|
||||||
reqctx = flask._request_ctx_stack.top.copy()
|
reqctx = flask._request_ctx_stack.top.copy()
|
||||||
|
|
||||||
@flask.copy_current_request_context
|
@flask.copy_current_request_context
|
||||||
|
@ -191,6 +194,7 @@ class TestGreenletContextCopying(object):
|
||||||
assert flask.current_app == app
|
assert flask.current_app == app
|
||||||
assert flask.request.path == '/'
|
assert flask.request.path == '/'
|
||||||
assert flask.request.args['foo'] == 'bar'
|
assert flask.request.args['foo'] == 'bar'
|
||||||
|
assert flask.session.get('fizz') == 'buzz'
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
greenlets.append(greenlet(g))
|
greenlets.append(greenlet(g))
|
||||||
|
|
Loading…
Reference in New Issue