1 # -*- test-case-name: twisted.web.test.test_error -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
6 Exception definitions for L{twisted.web}.
9 import operator, warnings
11 from twisted.web import http
14 class Error(Exception):
19 @ivar status: Refers to an HTTP status code, for example L{http.NOT_FOUND}.
22 @param message: A short error message, for example "NOT FOUND".
24 @type response: C{str}
25 @ivar response: A complete HTML document for an error page.
27 def __init__(self, code, message=None, response=None):
29 Initializes a basic exception.
32 @param code: Refers to an HTTP status code, for example
33 L{http.NOT_FOUND}. If no C{message} is given, C{code} is mapped to a
34 descriptive string that is used instead.
37 @param message: A short error message, for example "NOT FOUND".
39 @type response: C{str}
40 @param response: A complete HTML document for an error page.
44 message = http.responses.get(int(code))
46 # If code wasn't a stringified int, can't map the
47 # status code to a descriptive string so keep message
51 Exception.__init__(self, code, message, response)
53 self.message = message
54 self.response = response
58 return '%s %s' % (self[0], self[1])
62 class PageRedirect(Error):
64 A request resulted in an HTTP redirect.
66 @type location: C{str}
67 @ivar location: The location of the redirect which was not followed.
69 def __init__(self, code, message=None, response=None, location=None):
71 Initializes a page redirect exception.
74 @param code: Refers to an HTTP status code, for example
75 L{http.NOT_FOUND}. If no C{message} is given, C{code} is mapped to a
76 descriptive string that is used instead.
79 @param message: A short error message, for example "NOT FOUND".
81 @type response: C{str}
82 @param response: A complete HTML document for an error page.
84 @type location: C{str}
85 @param location: The location response-header field value. It is an
86 absolute URI used to redirect the receiver to a location other than
87 the Request-URI so the request can be completed.
91 message = http.responses.get(int(code))
93 # If code wasn't a stringified int, can't map the
94 # status code to a descriptive string so keep message
98 if location and message:
99 message = "%s to %s" % (message, location)
101 Error.__init__(self, code, message, response)
102 self.location = location
106 class InfiniteRedirection(Error):
108 HTTP redirection is occurring endlessly.
110 @type location: C{str}
111 @ivar location: The first URL in the series of redirections which was
114 def __init__(self, code, message=None, response=None, location=None):
116 Initializes an infinite redirection exception.
119 @param code: Refers to an HTTP status code, for example
120 L{http.NOT_FOUND}. If no C{message} is given, C{code} is mapped to a
121 descriptive string that is used instead.
123 @type message: C{str}
124 @param message: A short error message, for example "NOT FOUND".
126 @type response: C{str}
127 @param response: A complete HTML document for an error page.
129 @type location: C{str}
130 @param location: The location response-header field value. It is an
131 absolute URI used to redirect the receiver to a location other than
132 the Request-URI so the request can be completed.
136 message = http.responses.get(int(code))
138 # If code wasn't a stringified int, can't map the
139 # status code to a descriptive string so keep message
143 if location and message:
144 message = "%s to %s" % (message, location)
146 Error.__init__(self, code, message, response)
147 self.location = location
151 class RedirectWithNoLocation(Error):
153 Exception passed to L{ResponseFailed} if we got a redirect without a
154 C{Location} header field.
159 def __init__(self, code, message, uri):
161 Initializes a page redirect exception when no location is given.
164 @param code: Refers to an HTTP status code, for example
165 L{http.NOT_FOUND}. If no C{message} is given, C{code} is mapped to
166 a descriptive string that is used instead.
168 @type message: C{str}
169 @param message: A short error message.
172 @param uri: The URI which failed to give a proper location header
175 message = "%s to %s" % (message, uri)
177 Error.__init__(self, code, message)
182 class UnsupportedMethod(Exception):
184 Raised by a resource when faced with a strange request method.
186 RFC 2616 (HTTP 1.1) gives us two choices when faced with this situtation:
187 If the type of request is known to us, but not allowed for the requested
188 resource, respond with NOT_ALLOWED. Otherwise, if the request is something
189 we don't know how to deal with in any case, respond with NOT_IMPLEMENTED.
191 When this exception is raised by a Resource's render method, the server
192 will make the appropriate response.
194 This exception's first argument MUST be a sequence of the methods the
195 resource *does* support.
200 def __init__(self, allowedMethods, *args):
201 Exception.__init__(self, allowedMethods, *args)
202 self.allowedMethods = allowedMethods
204 if not operator.isSequenceType(allowedMethods):
205 why = "but my first argument is not a sequence."
206 s = ("First argument must be a sequence of"
207 " supported methods, %s" % (why,))
212 class SchemeNotSupported(Exception):
214 The scheme of a URI was not one of the supported values.
219 from twisted.web import resource as _resource
221 class ErrorPage(_resource.ErrorPage):
223 Deprecated alias for L{twisted.web.resource.ErrorPage}.
225 def __init__(self, *args, **kwargs):
227 "twisted.web.error.ErrorPage is deprecated since Twisted 9.0. "
228 "See twisted.web.resource.ErrorPage.", DeprecationWarning,
230 _resource.ErrorPage.__init__(self, *args, **kwargs)
234 class NoResource(_resource.NoResource):
236 Deprecated alias for L{twisted.web.resource.NoResource}.
238 def __init__(self, *args, **kwargs):
240 "twisted.web.error.NoResource is deprecated since Twisted 9.0. "
241 "See twisted.web.resource.NoResource.", DeprecationWarning,
243 _resource.NoResource.__init__(self, *args, **kwargs)
247 class ForbiddenResource(_resource.ForbiddenResource):
249 Deprecated alias for L{twisted.web.resource.ForbiddenResource}.
251 def __init__(self, *args, **kwargs):
253 "twisted.web.error.ForbiddenResource is deprecated since Twisted "
254 "9.0. See twisted.web.resource.ForbiddenResource.",
255 DeprecationWarning, stacklevel=2)
256 _resource.ForbiddenResource.__init__(self, *args, **kwargs)
260 class RenderError(Exception):
262 Base exception class for all errors which can occur during template
268 class MissingRenderMethod(RenderError):
270 Tried to use a render method which does not exist.
272 @ivar element: The element which did not have the render method.
273 @ivar renderName: The name of the renderer which could not be found.
275 def __init__(self, element, renderName):
276 RenderError.__init__(self, element, renderName)
277 self.element = element
278 self.renderName = renderName
282 return '%r: %r had no render method named %r' % (
283 self.__class__.__name__, self.element, self.renderName)
287 class MissingTemplateLoader(RenderError):
289 L{MissingTemplateLoader} is raised when trying to render an Element without
290 a template loader, i.e. a C{loader} attribute.
292 @ivar element: The Element which did not have a document factory.
294 def __init__(self, element):
295 RenderError.__init__(self, element)
296 self.element = element
300 return '%r: %r had no loader' % (self.__class__.__name__,
305 class UnexposedMethodError(Exception):
307 Raised on any attempt to get a method which has not been exposed.
312 class UnfilledSlot(Exception):
314 During flattening, a slot with no associated data was encountered.
319 class UnsupportedType(Exception):
321 During flattening, an object of a type which cannot be flattened was
327 class FlattenerError(Exception):
329 An error occurred while flattening an object.
331 @ivar _roots: A list of the objects on the flattener's stack at the time
332 the unflattenable object was encountered. The first element is least
333 deeply nested object and the last element is the most deeply nested.
335 def __init__(self, exception, roots, traceback):
336 self._exception = exception
338 self._traceback = traceback
339 Exception.__init__(self, exception, roots, traceback)
342 def _formatRoot(self, obj):
344 Convert an object from C{self._roots} to a string suitable for
345 inclusion in a render-traceback (like a normal Python traceback, but
346 can include "frame" source locations which are not in Python source
349 @param obj: Any object which can be a render step I{root}.
350 Typically, L{Tag}s, strings, and other simple Python types.
352 @return: A string representation of C{obj}.
355 # There's a circular dependency between this class and 'Tag', although
356 # only for an isinstance() check.
357 from twisted.web.template import Tag
358 if isinstance(obj, (str, unicode)):
359 # It's somewhat unlikely that there will ever be a str in the roots
360 # list. However, something like a MemoryError during a str.replace
361 # call (eg, replacing " with ") could possibly cause this.
362 # Likewise, UTF-8 encoding a unicode string to a byte string might
365 if isinstance(obj, str):
369 return repr(obj[:20])[:-1] + '<...>' + repr(obj[-20:])[prefix:]
372 elif isinstance(obj, Tag):
373 if obj.filename is None:
374 return 'Tag <' + obj.tagName + '>'
376 return "File \"%s\", line %d, column %d, in \"%s\"" % (
377 obj.filename, obj.lineNumber,
378 obj.columnNumber, obj.tagName)
385 Present a string representation which includes a template traceback, so
386 we can tell where this error occurred in the template, as well as in
389 # Avoid importing things unnecessarily until we actually need them;
390 # since this is an 'error' module we should be extra paranoid about
392 from traceback import format_list
394 roots = ' ' + '\n '.join([
395 self._formatRoot(r) for r in self._roots]) + '\n'
399 traceback = '\n'.join([
401 for entry in format_list(self._traceback)
402 for line in entry.splitlines()]) + '\n'
406 'Exception while flattening:\n' +
408 self._exception.__class__.__name__ + ': ' +
409 str(self._exception) + '\n')
418 'Error', 'PageRedirect', 'InfiniteRedirection', 'ErrorPage', 'NoResource',
419 'ForbiddenResource', 'RenderError', 'MissingRenderMethod',
420 'MissingTemplateLoader', 'UnexposedMethodError', 'UnfilledSlot',
421 'UnsupportedType', 'FlattenerError', 'RedirectWithNoLocation'