mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	[1.5.x] 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).
Backport of cd17a24 from master.
			
			
This commit is contained in:
		| @@ -170,28 +170,52 @@ class SessionBase(object): | ||||
|  | ||||
|     _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. | ||||
|  | ||||
|         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') | ||||
|  | ||||
|         if not expiry:   # Checks both None and 0 cases | ||||
|             return settings.SESSION_COOKIE_AGE | ||||
|         if not isinstance(expiry, datetime): | ||||
|             return expiry | ||||
|         delta = expiry - timezone.now() | ||||
|         delta = expiry - modification | ||||
|         return delta.days * 86400 + delta.seconds | ||||
|  | ||||
|     def get_expiry_date(self): | ||||
|         """Get session the expiry date (as a datetime object).""" | ||||
|         expiry = self.get('_session_expiry') | ||||
|     def get_expiry_date(self, **kwargs): | ||||
|         """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') | ||||
|  | ||||
|         if isinstance(expiry, datetime): | ||||
|             return expiry | ||||
|         if not expiry:   # Checks both None and 0 cases | ||||
|             expiry = settings.SESSION_COOKIE_AGE | ||||
|         return timezone.now() + timedelta(seconds=expiry) | ||||
|         return modification + timedelta(seconds=expiry) | ||||
|  | ||||
|     def set_expiry(self, value): | ||||
|         """ | ||||
|   | ||||
| @@ -40,7 +40,7 @@ class SessionStore(DBStore): | ||||
|                 ) | ||||
|                 data = self.decode(s.session_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): | ||||
|                 self.create() | ||||
|                 data = {} | ||||
|   | ||||
| @@ -197,31 +197,43 @@ class SessionTestsMixin(object): | ||||
|         self.assertEqual(self.session.get_expiry_age(), settings.SESSION_COOKIE_AGE) | ||||
|  | ||||
|     def test_custom_expiry_seconds(self): | ||||
|         # Using seconds | ||||
|         self.session.set_expiry(10) | ||||
|         delta = self.session.get_expiry_date() - timezone.now() | ||||
|         self.assertIn(delta.seconds, (9, 10)) | ||||
|         modification = timezone.now() | ||||
|  | ||||
|         age = self.session.get_expiry_age() | ||||
|         self.assertIn(age, (9, 10)) | ||||
|         self.session.set_expiry(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): | ||||
|         # Using timedelta | ||||
|         self.session.set_expiry(timedelta(seconds=10)) | ||||
|         delta = self.session.get_expiry_date() - timezone.now() | ||||
|         self.assertIn(delta.seconds, (9, 10)) | ||||
|         modification = timezone.now() | ||||
|  | ||||
|         age = self.session.get_expiry_age() | ||||
|         self.assertIn(age, (9, 10)) | ||||
|         # Mock timezone.now, because set_expiry calls it on this code path. | ||||
|         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): | ||||
|         # Using fixed datetime | ||||
|         self.session.set_expiry(timezone.now() + timedelta(seconds=10)) | ||||
|         delta = self.session.get_expiry_date() - timezone.now() | ||||
|         self.assertIn(delta.seconds, (9, 10)) | ||||
|         modification = timezone.now() | ||||
|  | ||||
|         age = self.session.get_expiry_age() | ||||
|         self.assertIn(age, (9, 10)) | ||||
|         self.session.set_expiry(modification + timedelta(seconds=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): | ||||
|         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 | ||||
|       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 | ||||
|  | ||||
|       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 | ||||
|       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 | ||||
|  | ||||
|       Returns either ``True`` or ``False``, depending on whether the user's | ||||
|   | ||||
		Reference in New Issue
	
	Block a user