Changeset 1947
- Timestamp:
- 04/26/08 17:19:05
- Files:
-
- branches/800-error-handlers/cherrypy/_cperror.py (modified) (4 diffs)
- branches/800-error-handlers/cherrypy/_cprequest.py (modified) (5 diffs)
- branches/800-error-handlers/cherrypy/test/test_core.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/800-error-handlers/cherrypy/_cperror.py
r1941 r1947 3 3 from cgi import escape as _escape 4 4 from sys import exc_info as _exc_info 5 from traceback import format_exception as _format_exception 5 6 from urlparse import urljoin as _urljoin 6 7 from cherrypy.lib import http as _http … … 288 289 if kwargs.get('version') is None: 289 290 kwargs['version'] = cherrypy.__version__ 291 290 292 for k, v in kwargs.iteritems(): 291 293 if v is None: … … 294 296 kwargs[k] = _escape(kwargs[k]) 295 297 296 template = _HTTPErrorTemplate 297 298 # Replace the default template with a custom one? 299 error_page_file = cherrypy.request.error_page.get(code, '') 300 if error_page_file: 298 # Use a custom template or callable for the error page? 299 pages = cherrypy.request.error_page 300 error_page = pages.get(code) or pages.get('default') 301 if error_page: 301 302 try: 302 template = file(error_page_file, 'rb').read() 303 if callable(error_page): 304 return error_page(**kwargs) 305 else: 306 return file(error_page, 'rb').read() % kwargs 303 307 except: 308 e = _format_exception(*_exc_info())[-1] 304 309 m = kwargs['message'] 305 310 if m: 306 311 m += "<br />" 307 m += ("In addition, the custom error page " 308 "failed:\n<br />%s" % (_exc_info()[1])) 312 m += "In addition, the custom error page failed:\n<br />%s" % e 309 313 kwargs['message'] = m 310 314 311 return template % kwargs315 return _HTTPErrorTemplate % kwargs 312 316 313 317 … … 378 382 [body]) 379 383 384 branches/800-error-handlers/cherrypy/_cprequest.py
r1941 r1947 146 146 def error_page_namespace(k, v): 147 147 """Attach error pages declared in config.""" 148 cherrypy.request.error_page[int(k)] = v 148 if k != 'default': 149 k = int(k) 150 cherrypy.request.error_page[k] = v 149 151 150 152 … … 394 396 error_page__doc = """ 395 397 A dict of {error code: response filename or callable} pairs. 396 The named response files should be Python string-formatting templates, 397 and can expect by default to receive format values with the mapping 398 keys 'status', 'message', 'traceback', and 'version'. The set of 399 format mappings can be extended by overriding HTTPError.set_response. 400 401 If a callable is provided, it will be called with the HTTPError 402 instance as the only argument. The callable is expected to set 403 response.status, .headers and .body appropriately. 404 405 If no entry is given for an error code, the HTTPError's set_response 406 method will handle the error (by setting .status, .headers, and .body). 398 399 The error code must be an int representing a given HTTP error code, 400 or the string 'default', which will be used if no matching entry 401 is found for a given numeric code. 402 403 If a filename is provided, the file should contain a Python string- 404 formatting template, and can expect by default to receive format 405 values with the mapping keys %(status)s, %(message)s, %(traceback)s, 406 and %(version)s. The set of format mappings can be extended by 407 overriding HTTPError.set_response. 408 409 If a callable is provided, it will be called by default with keyword 410 arguments 'status', 'message', 'traceback', and 'version', as for a 411 string-formatting template. The callable must return a string which 412 will be set to response.body. It may also override headers or perform 413 any other processing. 414 415 If no entry is given for an error code, and no 'default' entry exists, 416 a default template will be used. 407 417 """ 408 418 … … 600 610 cherrypy.response.finalize() 601 611 except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 602 ep = self.error_page.get(inst.status, '') 603 if ep and callable(ep): 604 ep(inst) 605 else: 606 inst.set_response() 612 inst.set_response() 607 613 self.stage = 'before_finalize (HTTPError)' 608 614 self.hooks.run('before_finalize') … … 736 742 cherrypy.response.finalize() 737 743 except cherrypy.HTTPRedirect, inst: 738 ep = self.error_page.get(inst.status, '') 739 if ep and callable(ep): 740 ep(inst) 741 else: 742 inst.set_response() 744 inst.set_response() 743 745 cherrypy.response.finalize() 744 746 … … 900 902 901 903 904 branches/800-error-handlers/cherrypy/test/test_core.py
r1941 r1947 242 242 243 243 244 def page401(e): 245 cherrypy.response.status = e.status 246 cherrypy._cperror.clean_headers(e.status) 247 cherrypy.response.body = "Well, I'm very sorry but you haven't paid!" 244 def callable_error_page(status, **kwargs): 245 return "Error %s - Well, I'm very sorry but you haven't paid!" % status 248 246 249 247 … … 256 254 raise cherrypy.HTTPError(int(err), "No, <b>really</b>, not found!") 257 255 custom._cp_config = {'error_page.404': os.path.join(localDir, "static/index.html"), 258 'error_page.401': page401,256 'error_page.401': callable_error_page, 259 257 } 258 259 def custom_default(self): 260 return 1 + 'a' # raise an unexpected error 261 custom_default._cp_config = {'error_page.default': callable_error_page} 260 262 261 263 def noexist(self): … … 729 731 ignore.pop() 730 732 731 # Test custom error page .733 # Test custom error page for a specific error. 732 734 self.getPage("/error/custom") 733 735 self.assertStatus(404) 734 736 self.assertBody("Hello, world\r\n" + (" " * 499)) 735 737 736 # Test custom error page .738 # Test custom error page for a specific error. 737 739 self.getPage("/error/custom?err=401") 738 740 self.assertStatus(401) 739 self.assertBody("Well, I'm very sorry but you haven't paid!") 741 self.assertBody("Error 401 Unauthorized - Well, I'm very sorry but you haven't paid!") 742 743 # Test default custom error page. 744 self.getPage("/error/custom_default") 745 self.assertStatus(500) 746 self.assertBody("Error 500 Internal Server Error - Well, I'm very sorry but you haven't paid!".ljust(513)) 740 747 741 748 # Test error in custom error page (ticket #305). … … 745 752 msg = ("No, <b>really</b>, not found!<br />" 746 753 "In addition, the custom error page failed:\n<br />" 747 " [Errno 2] No such file or directory: 'nonexistent.html'")754 "IOError: [Errno 2] No such file or directory: 'nonexistent.html'") 748 755 self.assertInBody(msg) 749 756

