Ticket #7515: clear_and_destroy2.diff

File clear_and_destroy2.diff, 8.4 KB (added by mrts, 7 years ago)

Remove redundant .save()s from tests and update to r8158

  • django/contrib/sessions/middleware.py

     
    1616        try:
    1717            accessed = request.session.accessed
    1818            modified = request.session.modified
     19            destroyed = request.session.destroyed
    1920        except AttributeError:
     21            # request doesn't have 'session' attribute
     22            # FIXME: is it such a good idea to hide this exception?
     23            # if process_request() fails to set request.session we should
     24            # raise here as well instead of silently failing,
     25            # perhaps a SessionNotSetError?
    2026            pass
    2127        else:
    2228            if accessed:
    2329                patch_vary_headers(response, ('Cookie',))
    24             if modified or settings.SESSION_SAVE_EVERY_REQUEST:
     30            if modified or destroyed or settings.SESSION_SAVE_EVERY_REQUEST:
    2531                if request.session.get_expire_at_browser_close():
    2632                    max_age = None
    2733                    expires = None
     
    3036                    expires_time = time.time() + max_age
    3137                    expires = cookie_date(expires_time)
    3238                # Save the session data and refresh the client cookie.
    33                 request.session.save()
     39                needs_saving = modified or settings.SESSION_SAVE_EVERY_REQUEST
     40                if destroyed and not needs_saving:
     41                    # New session not modified after destruction.
     42                    # Note that not saving here results in new key generation
     43                    # in load() on the next request. If this is undesirable,
     44                    # the three-branched needs_saving logic is not required.
     45                    pass
     46                elif destroyed and needs_saving:
     47                    # New session modified after destruction.  We
     48                    # need to guarantee no exception from the persistance
     49                    # layer can block sending the new session cookie to
     50                    # client.
     51                    try:
     52                        request.session.save()
     53                    except:
     54                        pass
     55                else:
     56                    request.session.save()
    3457                response.set_cookie(settings.SESSION_COOKIE_NAME,
    3558                        request.session.session_key, max_age=max_age,
    3659                        expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
  • django/contrib/sessions/tests.py

     
    2222>>> db_session.delete(db_session.session_key)
    2323>>> db_session.exists(db_session.session_key)
    2424False
     25>>> db_session['foo'] = 'bar'
     26>>> db_session.save()
     27>>> db_session.exists(db_session.session_key)
     28True
     29>>> prev_key = db_session.session_key
     30>>> db_session.destroy()
     31>>> db_session.exists(db_session.session_key)
     32False
     33>>> db_session.exists(prev_key)
     34False
     35>>> db_session.session_key == prev_key
     36False
     37>>> len(db_session.session_key)
     3832
     39>>> db_session.modified, db_session.accessed
     40(False, True)
     41>>> db_session['foo'] = 'bar'
     42>>> db_session.modified, db_session.accessed
     43(True, True)
     44>>> db_session.save()
     45>>> db_session.exists(db_session.session_key)
     46True
    2547
    2648>>> file_session = FileSession()
    2749>>> file_session.modified
     
    3961>>> file_session.delete(file_session.session_key)
    4062>>> file_session.exists(file_session.session_key)
    4163False
     64>>> file_session['foo'] = 'bar'
     65>>> file_session.save()
     66>>> file_session.exists(file_session.session_key)
     67True
     68>>> prev_key = file_session.session_key
     69>>> file_session.destroy()
     70>>> file_session.exists(file_session.session_key)
     71False
     72>>> file_session.exists(prev_key)
     73False
     74>>> file_session.session_key == prev_key
     75False
     76>>> len(file_session.session_key)
     7732
     78>>> file_session.modified, file_session.accessed
     79(False, True)
     80>>> file_session['foo'] = 'bar'
     81>>> file_session.modified, file_session.accessed
     82(True, True)
     83>>> file_session.save()
     84>>> file_session.exists(file_session.session_key)
     85True
    4286
    4387# Make sure the file backend checks for a good storage dir
    4488>>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer"
     
    61105>>> cache_session.delete(cache_session.session_key)
    62106>>> cache_session.exists(cache_session.session_key)
    63107False
     108>>> cache_session['foo'] = 'bar'
     109>>> cache_session.save()
     110>>> cache_session.exists(cache_session.session_key)
     111True
     112>>> prev_key = cache_session.session_key
     113>>> cache_session.destroy()
     114>>> cache_session.exists(cache_session.session_key)
     115False
     116>>> cache_session.exists(prev_key)
     117False
     118>>> cache_session.session_key == prev_key
     119False
     120>>> len(cache_session.session_key)
     12132
     122>>> cache_session.modified, cache_session.accessed
     123(False, True)
     124>>> cache_session['foo'] = 'bar'
     125>>> cache_session.modified, cache_session.accessed
     126(True, True)
     127>>> cache_session.save()
     128>>> cache_session.exists(cache_session.session_key)
     129True
    64130
    65131>>> s = SessionBase()
    66132>>> s._session['some key'] = 'exists' # Pre-populate the session with some data
     
    147213>>> list(i)
    148214[('x', 1)]
    149215
    150  
     216# test .clear()
     217>>> s.modified = s.accessed = False
     218>>> s.items()
     219[('x', 1)]
     220>>> s.clear()
     221>>> s.items()
     222[]
     223>>> s.accessed, s.modified
     224(True, True)
    151225
     226
    152227#########################
    153228# Custom session expiry #
    154229#########################
  • django/contrib/sessions/backends/base.py

     
    2525        self._session_key = session_key
    2626        self.accessed = False
    2727        self.modified = False
     28        self.destroyed = False
    2829
    2930    def __contains__(self, key):
    3031        return key in self._session
     
    5354        self.modified = self.modified or key in self._session
    5455        return self._session.pop(key, *args)
    5556
     57    def clear(self):
     58        self._session.clear()
     59        self.modified = True
     60
     61    def destroy(self):
     62        self._session.clear()
     63        try:
     64            # remove old session, may fail
     65            self.delete(self._session_key)
     66        except:
     67            # ignore exceptions to guarantee session key reset
     68            pass
     69        self._session_key = self._get_new_session_key(safe=True)
     70        self.modified = False
     71        self.accessed = True
     72        self.destroyed = True
     73
    5674    def setdefault(self, key, value):
    5775        if key in self._session:
    5876            return self._session[key]
     
    107125    def iteritems(self):
    108126        return self._session.iteritems()
    109127
    110     def _get_new_session_key(self):
     128    def _get_new_session_key(self, safe=False):
    111129        "Returns session key that isn't being used."
    112130        # The random module is seeded when this Apache child is created.
    113131        # Use settings.SECRET_KEY as added salt.
     
    119137        while 1:
    120138            session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
    121139                                  pid, time.time(), settings.SECRET_KEY)).hexdigest()
    122             if not self.exists(session_key):
    123                 break
     140            if safe:
     141                try:
     142                    if not self.exists(session_key):
     143                        break
     144                except:
     145                    # Depends on the assumption that key collisions are rare,
     146                    # see ticket #1180
     147                    pass
     148            else:
     149                if not self.exists(session_key):
     150                    break
    124151        return session_key
    125152
    126153    def _get_session_key(self):
  • docs/sessions.txt

     
    106106
    107107    * ``setdefault()`` (**New in Django development version**)
    108108
     109    * ``clear()`` (**New in Django development version**)
     110
    109111It also has these methods:
    110112
     113    * ``destroy()``
     114
     115      **New in Django development version**
     116
     117      Clears session data, deletes the old session from session storage and
     118      creates a new empty session in exception-safe manner. This is the
     119      recommended, safe way of resetting sessions on e.g. user logout.
     120
    111121    * ``set_test_cookie()``
    112122
    113123      Sets a test cookie to determine whether the user's browser supports
Back to Top