Mercurial > piecrust2
comparison piecrust/serving/server.py @ 517:c7e8b4a5afe3
serve: Improve error reporting when pages are not found.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 27 Jul 2015 00:48:19 -0700 |
parents | 16e705c58cae |
children | bab91fcef741 |
comparison
equal
deleted
inserted
replaced
516:73bd408caebc | 517:c7e8b4a5afe3 |
---|---|
51 | 51 |
52 def __call__(self, environ, start_response): | 52 def __call__(self, environ, start_response): |
53 return self.server._run_request(environ, start_response) | 53 return self.server._run_request(environ, start_response) |
54 | 54 |
55 | 55 |
56 class MultipleNotFound(HTTPException): | |
57 code = 404 | |
58 | |
59 def __init__(self, description, nfes): | |
60 super(MultipleNotFound, self).__init__(description) | |
61 self._nfes = nfes | |
62 | |
63 def get_description(self, environ=None): | |
64 from werkzeug.utils import escape | |
65 desc = '<p>' + self.description + '</p>' | |
66 desc += '<p>' | |
67 for nfe in self._nfes: | |
68 desc += '<li>' + escape(nfe.description) + '</li>' | |
69 desc += '</p>' | |
70 return desc | |
71 | |
72 | |
56 class Server(object): | 73 class Server(object): |
57 def __init__(self, root_dir, | 74 def __init__(self, root_dir, |
58 debug=False, sub_cache_dir=None, enable_debug_info=True, | 75 debug=False, sub_cache_dir=None, enable_debug_info=True, |
59 static_preview=True, run_sse_check=None): | 76 static_preview=True, run_sse_check=None): |
60 self.root_dir = root_dir | 77 self.root_dir = root_dir |
94 def _run_request(self, environ, start_response): | 111 def _run_request(self, environ, start_response): |
95 try: | 112 try: |
96 return self._try_run_request(environ, start_response) | 113 return self._try_run_request(environ, start_response) |
97 except Exception as ex: | 114 except Exception as ex: |
98 if self.debug: | 115 if self.debug: |
99 if isinstance(ex, HTTPException): | |
100 return ex | |
101 raise | 116 raise |
102 return self._handle_error(ex, environ, start_response) | 117 return self._handle_error(ex, environ, start_response) |
103 | 118 |
104 def _try_run_request(self, environ, start_response): | 119 def _try_run_request(self, environ, start_response): |
105 request = Request(environ) | 120 request = Request(environ) |
143 # Nope. Let's see if it's an actual page. | 158 # Nope. Let's see if it's an actual page. |
144 try: | 159 try: |
145 response = self._try_serve_page(app, environ, request) | 160 response = self._try_serve_page(app, environ, request) |
146 return response(environ, start_response) | 161 return response(environ, start_response) |
147 except (RouteNotFoundError, SourceNotFoundError) as ex: | 162 except (RouteNotFoundError, SourceNotFoundError) as ex: |
148 raise NotFound(str(ex)) from ex | 163 raise NotFound() from ex |
149 except HTTPException: | 164 except HTTPException: |
150 raise | 165 raise |
151 except Exception as ex: | 166 except Exception as ex: |
152 if app.debug: | 167 if app.debug: |
153 logger.exception(ex) | 168 logger.exception(ex) |
222 routes = find_routes(app.routes, req_path) | 237 routes = find_routes(app.routes, req_path) |
223 if len(routes) == 0: | 238 if len(routes) == 0: |
224 raise RouteNotFoundError("Can't find route for: %s" % req_path) | 239 raise RouteNotFoundError("Can't find route for: %s" % req_path) |
225 | 240 |
226 rendered_page = None | 241 rendered_page = None |
227 first_not_found = None | 242 not_found_errors = [] |
228 for route, route_metadata in routes: | 243 for route, route_metadata in routes: |
229 try: | 244 try: |
230 logger.debug("Trying to render match from source '%s'." % | 245 logger.debug("Trying to render match from source '%s'." % |
231 route.source_name) | 246 route.source_name) |
232 rendered_page = self._try_render_page( | 247 rendered_page = self._try_render_page( |
233 app, route, route_metadata, page_num, req_path) | 248 app, route, route_metadata, page_num, req_path) |
234 if rendered_page is not None: | 249 if rendered_page is not None: |
235 break | 250 break |
236 except NotFound as nfe: | 251 except NotFound as nfe: |
237 if first_not_found is None: | 252 not_found_errors.append(nfe) |
238 first_not_found = nfe | |
239 else: | |
240 raise SourceNotFoundError( | |
241 "Can't find path for: %s (looked in: %s)" % | |
242 (req_path, [r.source_name for r, _ in routes])) | |
243 | 253 |
244 # If we haven't found any good match, raise whatever exception we | 254 # If we haven't found any good match, raise whatever exception we |
245 # first got. Otherwise, raise a generic exception. | 255 # first got. Otherwise, raise a generic exception. |
246 if rendered_page is None: | 256 if rendered_page is None: |
247 first_not_found = first_not_found or NotFound( | 257 msg = ("Can't find path for '%s', looked in sources: %s" % |
248 "This page couldn't be found.") | 258 (req_path, |
249 raise first_not_found | 259 ', '.join([r.source_name for r, _ in routes]))) |
260 raise MultipleNotFound(msg, not_found_errors) | |
250 | 261 |
251 # Start doing stuff. | 262 # Start doing stuff. |
252 page = rendered_page.page | 263 page = rendered_page.page |
253 rp_content = rendered_page.content | 264 rp_content = rendered_page.content |
254 | 265 |
312 taxonomy_info = None | 323 taxonomy_info = None |
313 source = app.getSource(route.source_name) | 324 source = app.getSource(route.source_name) |
314 if route.taxonomy_name is None: | 325 if route.taxonomy_name is None: |
315 factory = source.findPageFactory(route_metadata, MODE_PARSING) | 326 factory = source.findPageFactory(route_metadata, MODE_PARSING) |
316 if factory is None: | 327 if factory is None: |
317 return None | 328 raise NotFound("No path found for '%s' in source '%s'." % |
329 (req_path, source.name)) | |
318 else: | 330 else: |
319 taxonomy = app.getTaxonomy(route.taxonomy_name) | 331 taxonomy = app.getTaxonomy(route.taxonomy_name) |
320 route_terms = route_metadata.get(taxonomy.term_name) | |
321 if route_terms is None: | |
322 return None | |
323 | |
324 tax_terms = route.getTaxonomyTerms(route_metadata) | 332 tax_terms = route.getTaxonomyTerms(route_metadata) |
325 taxonomy_info = (taxonomy, tax_terms) | 333 taxonomy_info = (taxonomy, tax_terms) |
326 | 334 |
327 tax_page_ref = taxonomy.getPageRef(source) | 335 tax_page_ref = taxonomy.getPageRef(source) |
328 factory = tax_page_ref.getFactory() | 336 factory = tax_page_ref.getFactory() |
399 code = 500 | 407 code = 500 |
400 if isinstance(exception, HTTPException): | 408 if isinstance(exception, HTTPException): |
401 code = exception.code | 409 code = exception.code |
402 | 410 |
403 path = 'error' | 411 path = 'error' |
404 if isinstance(exception, NotFound): | 412 if isinstance(exception, (NotFound, MultipleNotFound)): |
405 path += '404' | 413 path += '404' |
406 | 414 |
407 descriptions = self._get_exception_descriptions(exception) | 415 descriptions = self._get_exception_descriptions(exception) |
408 | 416 |
409 env = Environment(loader=ErrorMessageLoader()) | 417 env = Environment(loader=ErrorMessageLoader()) |
414 return response(environ, start_response) | 422 return response(environ, start_response) |
415 | 423 |
416 def _get_exception_descriptions(self, exception): | 424 def _get_exception_descriptions(self, exception): |
417 desc = [] | 425 desc = [] |
418 while exception is not None: | 426 while exception is not None: |
419 if isinstance(exception, HTTPException): | 427 if isinstance(exception, MultipleNotFound): |
428 desc += [e.description for e in exception._nfes] | |
429 elif isinstance(exception, HTTPException): | |
420 desc.append(exception.description) | 430 desc.append(exception.description) |
421 else: | 431 else: |
422 desc.append(str(exception)) | 432 desc.append(str(exception)) |
423 | 433 |
424 inner_ex = exception.__cause__ | 434 inner_ex = exception.__cause__ |