# HG changeset patch # User Sylvain Thénault # Date 1389946040 -3600 # Node ID 946aded614f36f08ea151d269eb95e7e90f46549 # Parent 9c13ebd45cb6d7c72008ee70477bf664d2538024 [web error] exception may not have a 'status' attribute, generating an AttributeError that hides the original error. Closes #3381670 diff -r 9c13ebd45cb6 -r 946aded614f3 web/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 diff -r 9c13ebd45cb6 -r 946aded614f3 web/test/unittest_application.py --- 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()