Commits

Ben Bangert committed 642cfff

Add option to skip saving session when a framework handled exception occurs.

  • Participants
  • Parent commits 775f006

Comments (0)

Files changed (3)

pylons/configuration.py

         self.set_renderer_globals_factory(globals_factory)
         self.registry.helpers = None
         self.registry.session_options = None
+        self.registry.session_exception = True
         self.set_request_factory(Request)
         return result
     
             module_ref = resolve_dotted(module_ref)
         self.registry.helpers = module_ref
     
-    def add_sessions(self, settings=None, **fallback):
+    def add_sessions(self, settings=None, exception_abort=True, **fallback):
         """Add's session support to the WSGI app
         
-        Provided a settings dict, it will pull out session options
-        that begin with either 'beaker.session.' or 'session.'. A
-        settings dict is optional, and in the event it is not present,
-        the fallback keyword arguments will be used instead.
+        The ``settings`` argument should be a dict, usually the same
+        settings dict that the :class:`Configurator` was instantiated
+        with. Values will be pulled out of the dict that have a key
+        that begin with either 'beaker.session.' or 'session.'. Options
+        from this dict replace any options of the same name from the
+        fallback keyword args.
         
-        If a settings dict is provided, the fallback keyword arguments
-        will be merged such that settings arguments will be used first.
+        The ``exception_abort`` argument determines whether the session
+        will be persisted to the database and a cookie sent to the
+        browser in the event that an exception occurs during the request
+        processing. By default, this is set to ``True`` to prevent the 
+        session from being saved if an exception in the framework
+        occurs. Exceptions raised from view code that are not handled
+        by the framework will always cause the session to be aborted.
+        
+        ``fallback`` keyword arguments should be provided to ensure a
+        working application in the event no INI settings are found
+        since many features in a website will depend on sessions. These
+        options 
         
         """
         session_settings = fallback
                 if key.startswith(prefix):
                     name = key.split(prefix)[1]
                     session_settings[name] = settings[key]
+        self.registry.session_exception = exception_abort
         self.registry.session_options = session_settings
-        
 
     def add_route(self, name, pattern, **kw):
         """ Support the syntax supported by

pylons/controllers/util.py

         set if necessary on the response object.
         
         """
+        attrs = self.__dict__
+        exception_abort = self.registry.session_exception
         sess_opts = self.registry.session_options
         if not sess_opts:
             raise Exception("Can't use the session without configuring sessions")
         session = SessionObject(self.environ)
         def session_callback(request, response):
+            if 'exception' in attrs and exception_abort:
+                return None
             if session.accessed():
                 session.persist()
                 if session.__dict__['_headers']['set_cookie']:

tests/test_units/test_controller.py

         def throw_no_sess():
             req.abort_session()
         self.assertRaises(Exception, throw_no_sess)
+    
+    def test_session_abort_exception(self):
+        from pylons.controllers.util import Response
+        req = self._make_req()
+        assert len(req.response_callbacks) == 0
+        req.session['fred'] = 42
+        req.session.save()
+        assert req.session.accessed() == True
+        assert len(req.response_callbacks) > 0
+        
+        resp = Response()
+        req.exception = True
+        assert req.response_callbacks[0](req, resp) == None
+        assert 'Set-Cookie' not in resp.headers
+        
 
 
 def make_controllers():