Added optional kwargs to get_expiry_age/date.
This change allows for cleaner tests: we can test the exact output. Refs #18194: this change makes it possible to compute session expiry dates at times other than when the session is saved. Fixed #18458: the existence of the `modification` kwarg implies that you must pass it to get_expiry_age/date if you call these functions outside of a short request - response cycle (the intended use case).
This commit is contained in:
parent
fc2681b22b
commit
cd17a24083
|
@ -170,28 +170,52 @@ class SessionBase(object):
|
||||||
|
|
||||||
_session = property(_get_session)
|
_session = property(_get_session)
|
||||||
|
|
||||||
def get_expiry_age(self, expiry=None):
|
def get_expiry_age(self, **kwargs):
|
||||||
"""Get the number of seconds until the session expires.
|
"""Get the number of seconds until the session expires.
|
||||||
|
|
||||||
expiry is an optional parameter specifying the datetime of expiry.
|
Optionally, this function accepts `modification` and `expiry` keyword
|
||||||
|
arguments specifying the modification and expiry of the session.
|
||||||
"""
|
"""
|
||||||
if expiry is None:
|
try:
|
||||||
|
modification = kwargs['modification']
|
||||||
|
except KeyError:
|
||||||
|
modification = timezone.now()
|
||||||
|
# Make the difference between "expiry=None passed in kwargs" and
|
||||||
|
# "expiry not passed in kwargs", in order to guarantee not to trigger
|
||||||
|
# self.load() when expiry is provided.
|
||||||
|
try:
|
||||||
|
expiry = kwargs['expiry']
|
||||||
|
except KeyError:
|
||||||
expiry = self.get('_session_expiry')
|
expiry = self.get('_session_expiry')
|
||||||
|
|
||||||
if not expiry: # Checks both None and 0 cases
|
if not expiry: # Checks both None and 0 cases
|
||||||
return settings.SESSION_COOKIE_AGE
|
return settings.SESSION_COOKIE_AGE
|
||||||
if not isinstance(expiry, datetime):
|
if not isinstance(expiry, datetime):
|
||||||
return expiry
|
return expiry
|
||||||
delta = expiry - timezone.now()
|
delta = expiry - modification
|
||||||
return delta.days * 86400 + delta.seconds
|
return delta.days * 86400 + delta.seconds
|
||||||
|
|
||||||
def get_expiry_date(self):
|
def get_expiry_date(self, **kwargs):
|
||||||
"""Get session the expiry date (as a datetime object)."""
|
"""Get session the expiry date (as a datetime object).
|
||||||
|
|
||||||
|
Optionally, this function accepts `modification` and `expiry` keyword
|
||||||
|
arguments specifying the modification and expiry of the session.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
modification = kwargs['modification']
|
||||||
|
except KeyError:
|
||||||
|
modification = timezone.now()
|
||||||
|
# Same comment as in get_expiry_age
|
||||||
|
try:
|
||||||
|
expiry = kwargs['expiry']
|
||||||
|
except KeyError:
|
||||||
expiry = self.get('_session_expiry')
|
expiry = self.get('_session_expiry')
|
||||||
|
|
||||||
if isinstance(expiry, datetime):
|
if isinstance(expiry, datetime):
|
||||||
return expiry
|
return expiry
|
||||||
if not expiry: # Checks both None and 0 cases
|
if not expiry: # Checks both None and 0 cases
|
||||||
expiry = settings.SESSION_COOKIE_AGE
|
expiry = settings.SESSION_COOKIE_AGE
|
||||||
return timezone.now() + timedelta(seconds=expiry)
|
return modification + timedelta(seconds=expiry)
|
||||||
|
|
||||||
def set_expiry(self, value):
|
def set_expiry(self, value):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -40,7 +40,7 @@ class SessionStore(DBStore):
|
||||||
)
|
)
|
||||||
data = self.decode(s.session_data)
|
data = self.decode(s.session_data)
|
||||||
cache.set(self.cache_key, data,
|
cache.set(self.cache_key, data,
|
||||||
self.get_expiry_age(s.expire_date))
|
self.get_expiry_age(expiry=s.expire_date))
|
||||||
except (Session.DoesNotExist, SuspiciousOperation):
|
except (Session.DoesNotExist, SuspiciousOperation):
|
||||||
self.create()
|
self.create()
|
||||||
data = {}
|
data = {}
|
||||||
|
|
|
@ -197,31 +197,43 @@ class SessionTestsMixin(object):
|
||||||
self.assertEqual(self.session.get_expiry_age(), settings.SESSION_COOKIE_AGE)
|
self.assertEqual(self.session.get_expiry_age(), settings.SESSION_COOKIE_AGE)
|
||||||
|
|
||||||
def test_custom_expiry_seconds(self):
|
def test_custom_expiry_seconds(self):
|
||||||
# Using seconds
|
modification = timezone.now()
|
||||||
self.session.set_expiry(10)
|
|
||||||
delta = self.session.get_expiry_date() - timezone.now()
|
|
||||||
self.assertIn(delta.seconds, (9, 10))
|
|
||||||
|
|
||||||
age = self.session.get_expiry_age()
|
self.session.set_expiry(10)
|
||||||
self.assertIn(age, (9, 10))
|
|
||||||
|
date = self.session.get_expiry_date(modification=modification)
|
||||||
|
self.assertEqual(date, modification + timedelta(seconds=10))
|
||||||
|
|
||||||
|
age = self.session.get_expiry_age(modification=modification)
|
||||||
|
self.assertEqual(age, 10)
|
||||||
|
|
||||||
def test_custom_expiry_timedelta(self):
|
def test_custom_expiry_timedelta(self):
|
||||||
# Using timedelta
|
modification = timezone.now()
|
||||||
self.session.set_expiry(timedelta(seconds=10))
|
|
||||||
delta = self.session.get_expiry_date() - timezone.now()
|
|
||||||
self.assertIn(delta.seconds, (9, 10))
|
|
||||||
|
|
||||||
age = self.session.get_expiry_age()
|
# Mock timezone.now, because set_expiry calls it on this code path.
|
||||||
self.assertIn(age, (9, 10))
|
original_now = timezone.now
|
||||||
|
try:
|
||||||
|
timezone.now = lambda: modification
|
||||||
|
self.session.set_expiry(timedelta(seconds=10))
|
||||||
|
finally:
|
||||||
|
timezone.now = original_now
|
||||||
|
|
||||||
|
date = self.session.get_expiry_date(modification=modification)
|
||||||
|
self.assertEqual(date, modification + timedelta(seconds=10))
|
||||||
|
|
||||||
|
age = self.session.get_expiry_age(modification=modification)
|
||||||
|
self.assertEqual(age, 10)
|
||||||
|
|
||||||
def test_custom_expiry_datetime(self):
|
def test_custom_expiry_datetime(self):
|
||||||
# Using fixed datetime
|
modification = timezone.now()
|
||||||
self.session.set_expiry(timezone.now() + timedelta(seconds=10))
|
|
||||||
delta = self.session.get_expiry_date() - timezone.now()
|
|
||||||
self.assertIn(delta.seconds, (9, 10))
|
|
||||||
|
|
||||||
age = self.session.get_expiry_age()
|
self.session.set_expiry(modification + timedelta(seconds=10))
|
||||||
self.assertIn(age, (9, 10))
|
|
||||||
|
date = self.session.get_expiry_date(modification=modification)
|
||||||
|
self.assertEqual(date, modification + timedelta(seconds=10))
|
||||||
|
|
||||||
|
age = self.session.get_expiry_age(modification=modification)
|
||||||
|
self.assertEqual(age, 10)
|
||||||
|
|
||||||
def test_custom_expiry_reset(self):
|
def test_custom_expiry_reset(self):
|
||||||
self.session.set_expiry(None)
|
self.session.set_expiry(None)
|
||||||
|
|
|
@ -250,12 +250,23 @@ You can edit it multiple times.
|
||||||
with no custom expiration (or those set to expire at browser close), this
|
with no custom expiration (or those set to expire at browser close), this
|
||||||
will equal :setting:`SESSION_COOKIE_AGE`.
|
will equal :setting:`SESSION_COOKIE_AGE`.
|
||||||
|
|
||||||
|
This function accepts two optional keyword arguments:
|
||||||
|
|
||||||
|
- ``modification``: last modification of the session, as a
|
||||||
|
:class:`~datetime.datetime` object. Defaults to the current time.
|
||||||
|
- ``expiry``: expiry information for the session, as a
|
||||||
|
:class:`~datetime.datetime` object, an :class:`int` (in seconds), or
|
||||||
|
``None``. Defaults to the value stored in the session by
|
||||||
|
:meth:`set_expiry`, if there is one, or ``None``.
|
||||||
|
|
||||||
.. method:: get_expiry_date
|
.. method:: get_expiry_date
|
||||||
|
|
||||||
Returns the date this session will expire. For sessions with no custom
|
Returns the date this session will expire. For sessions with no custom
|
||||||
expiration (or those set to expire at browser close), this will equal the
|
expiration (or those set to expire at browser close), this will equal the
|
||||||
date :setting:`SESSION_COOKIE_AGE` seconds from now.
|
date :setting:`SESSION_COOKIE_AGE` seconds from now.
|
||||||
|
|
||||||
|
This function accepts the same keyword argumets as :meth:`get_expiry_age`.
|
||||||
|
|
||||||
.. method:: get_expire_at_browser_close
|
.. method:: get_expire_at_browser_close
|
||||||
|
|
||||||
Returns either ``True`` or ``False``, depending on whether the user's
|
Returns either ``True`` or ``False``, depending on whether the user's
|
||||||
|
|
Loading…
Reference in New Issue