[web error] exception may not have a 'status' attribute, generating an AttributeError that hides the original error. Closes #3381670 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 17 Jan 2014 09:07:20 +0100
branchstable
changeset 9428 946aded614f3
parent 9427 9c13ebd45cb6
child 9429 aed6ef251135
[web error] exception may not have a 'status' attribute, generating an AttributeError that hides the original error. Closes #3381670
web/application.py
web/test/unittest_application.py
--- a/web/application.py	Fri Jan 17 09:06:40 2014 +0100
+++ b/web/application.py	Fri Jan 17 09:07:20 2014 +0100
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -39,7 +39,7 @@
 from cubicweb.web import LOGGER, component
 from cubicweb.web import (
     StatusResponse, DirectResponse, Redirect, NotFound, LogOut,
-    RemoteCallFailed, InvalidSession, RequestError)
+    RemoteCallFailed, InvalidSession, RequestError, PublishException)
 
 from cubicweb.web.request import CubicWebRequestBase
 
@@ -567,7 +567,7 @@
             content = self.vreg['views'].main_template(req, template, view=errview)
         except Exception:
             content = self.vreg['views'].main_template(req, 'error-template')
-        if getattr(ex, 'status', None) is not None:
+        if isinstance(ex, PublishException) and ex.status is not None:
             req.status_out = ex.status
         return content
 
@@ -580,11 +580,11 @@
 
     def ajax_error_handler(self, req, ex):
         req.set_header('content-type', 'application/json')
-        status = ex.status
-        if status is None:
-            status = httplib.INTERNAL_SERVER_ERROR
+        status = httplib.INTERNAL_SERVER_ERROR
+        if isinstance(ex, PublishException) and ex.status is not None:
+            status = ex.status
+        req.status_out = status
         json_dumper = getattr(ex, 'dumps', lambda : unicode(ex))
-        req.status_out = status
         return json_dumper()
 
     # special case handling
--- a/web/test/unittest_application.py	Fri Jan 17 09:06:40 2014 +0100
+++ b/web/test/unittest_application.py	Fri Jan 17 09:07:20 2014 +0100
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -19,13 +19,15 @@
 
 import base64, Cookie
 import sys
+import httplib
 from urllib import unquote
 
 from logilab.common.testlib import TestCase, unittest_main
 from logilab.common.decorators import clear_cache, classproperty
 
 from cubicweb import AuthenticationError, Unauthorized
-from cubicweb.devtools.testlib import CubicWebTC
+from cubicweb import view
+from cubicweb.devtools.testlib import CubicWebTC, real_error_handling
 from cubicweb.devtools.fake import FakeRequest
 from cubicweb.web import LogOut, Redirect, INTERNAL_FIELD_VALUE
 from cubicweb.web.views.basecontrollers import ViewController
@@ -264,6 +266,18 @@
                           {'login-subject': u'the value "admin" is already used, use another one'})
         self.assertEqual(forminfo['values'], req.form)
 
+    def test_ajax_view_raise_arbitrary_error(self):
+        class ErrorAjaxView(view.View):
+            __regid__ = 'test.ajax.error'
+            def call(self):
+                raise Exception('whatever')
+        with self.temporary_appobjects(ErrorAjaxView):
+            with real_error_handling(self.app) as app:
+                req = self.request(vid='test.ajax.error')
+                req.ajax_request = True
+                page = app.handle_request(req, '')
+        self.assertEqual(httplib.INTERNAL_SERVER_ERROR,
+                         req.status_out)
 
     def _test_cleaned(self, kwargs, injected, cleaned):
         req = self.request(**kwargs)
@@ -433,5 +447,6 @@
         req.form['rql'] = 'rql:Any OV1, X WHERE X custom_workflow OV1?'
         self.app_handle_request(req)
 
+
 if __name__ == '__main__':
     unittest_main()