From 773e2b9f99f78778ca4239a750d5f4213e128490 Mon Sep 17 00:00:00 2001 From: kgriffs Date: Mon, 7 Apr 2014 17:54:55 -0500 Subject: [PATCH] doc(errors): Clean up docstrings Several of the HTTPError subclasses had incorrect or malformed docstrings; these were fixed and type annotations were added in support of sphinx. --- doc/api/errors.rst | 2 - doc/api/request_and_response.rst | 12 +- doc/index.rst | 4 +- falcon/exceptions.py | 316 +++++++++++++------------------ falcon/http_error.py | 63 +++--- 5 files changed, 169 insertions(+), 228 deletions(-) diff --git a/doc/api/errors.rst b/doc/api/errors.rst index 96380b5..dc9f67f 100644 --- a/doc/api/errors.rst +++ b/doc/api/errors.rst @@ -20,11 +20,9 @@ Base Class .. autoclass:: falcon.HTTPError :members: - :undoc-members: Predefined Errors ----------------- .. automodule:: falcon.exceptions :members: - :undoc-members: diff --git a/doc/api/request_and_response.rst b/doc/api/request_and_response.rst index 860d1f7..e36a4d83 100644 --- a/doc/api/request_and_response.rst +++ b/doc/api/request_and_response.rst @@ -1,7 +1,7 @@ .. _request: -Req & Resp -========== +Objects +======= Instances of the Request and Response classes are passed into responders as the second and third arguments, respectively. @@ -17,14 +17,14 @@ and third arguments, respectively. resp.body = '{"message": "Hello world!"}' resp.status = falcon.HTTP_200 -Request Class -------------- +Request +------- .. autoclass:: falcon.Request :members: -Response Class --------------- +Response +-------- .. autoclass:: falcon.Response :members: diff --git a/doc/index.rst b/doc/index.rst index 7e3c4e3..1ed65d5 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -92,8 +92,8 @@ User Guide .. *Coming soon* -API Documentation ------------------ +Classes and Functions +--------------------- .. toctree:: :maxdepth: 2 diff --git a/falcon/exceptions.py b/falcon/exceptions.py index 0f001fc..ce55290 100644 --- a/falcon/exceptions.py +++ b/falcon/exceptions.py @@ -17,48 +17,41 @@ import falcon.status_codes as status class HTTPBadRequest(HTTPError): - """400 Bad Request + """400 Bad Request. - From RFC 2616: - - "The request could not be understood by the server due to malformed + The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without - modifications." + modifications. (RFC 2616) + + Args: + title (str): Error title, for example: 'TTL Out of Range'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ HTTPError.__init__(self, status.HTTP_400, title, description, **kwargs) class HTTPUnauthorized(HTTPError): - """401 Unauthorized + """401 Unauthorized. Use when authentication is required, and the provided credentials are not valid, or no credentials were provided in the first place. + Args: + title (str): Error title, for example: 'Authentication Required'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + scheme (str): Authentication scheme to use as the value of the + WWW-Authenticate header in the response (default None). + kwargs (optional): Same as for ``HTTPError``. + """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - title: Human-friendly error title - description: Human-friendly description of the error, along with a - helpful suggestion or two. - scheme: Authentication scheme to use as the value of the - WWW-Authenticate header in the response (default None). - - The remaining (optional) args are the same as for HTTPError. - - - """ headers = kwargs.setdefault('headers', {}) scheme = kwargs.pop('scheme', None) @@ -69,66 +62,55 @@ class HTTPUnauthorized(HTTPError): class HTTPForbidden(HTTPError): - """403 Forbidden + """403 Forbidden. Use when the client's credentials are good, but they do not have permission to access the requested resource. - Note from RFC 2616: - - "If the request method was not HEAD and the server wishes to make + If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 - (Not Found) can be used instead." + (Not Found) can be used instead. (RFC 2616) + + Args: + title (str): Error title, for example: 'Permission Denied'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_403, title, description, **kwargs) class HTTPNotFound(HTTPError): - """404 Not Found + """404 Not Found. Use this when the URL path does not map to an existing resource, or you do not wish to disclose exactly why a request was refused. """ def __init__(self): - """Initialize""" - HTTPError.__init__(self, status.HTTP_404, None, None) class HTTPMethodNotAllowed(HTTPError): - """405 Method Not Allowed + """405 Method Not Allowed. - From RFC 2616: - - "The method specified in the Request-Line is not allowed for the + The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested - resource." + resource. (RFC 2616) + + Args: + allowed_methods (list of str): Allowed HTTP methods for this + resource, for example: ['GET', 'POST', 'HEAD']. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, allowed_methods, **kwargs): - """Initilize with allowed methods - - Args: - allowed_methods: A list of allowed HTTP methods for this resource, - such as ['GET', 'POST', 'HEAD']. - - The remaining (optional) args are the same as for HTTPError. - - """ headers = kwargs.setdefault('headers', {}) headers['Allow'] = ', '.join(allowed_methods) @@ -136,140 +118,125 @@ class HTTPMethodNotAllowed(HTTPError): class HTTPNotAcceptable(HTTPError): - """406 Not Acceptable + """406 Not Acceptable. - Use this to reject the clients without a specific media type - support in their Accept headers. + The client requested a resource in a representation that is not + supported by the server. The client must indicate a supported + media type in the Accept header. - From RFC 2616: - - "The resource identified by the request is only capable of generating + The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable - according to the accept headers sent in the request." + according to the accept headers sent in the request. (RFC 2616) + + Args: + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, description, **kwargs): - """Initialize - - Args: - description: Human-friendly description of the error, along with a - helpful suggestion or two. - - The remaining (optional) args are the same as for HTTPError. - - """ - HTTPError.__init__(self, status.HTTP_406, 'Media type not acceptable', description, **kwargs) class HTTPConflict(HTTPError): - """409 Conflict + """409 Conflict. - From RFC 2616: - - "The request could not be completed due to a conflict with the current + The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be - possible and is not required." + possible and is not required. - "Conflicts are most likely to occur in response to a PUT request. For + Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response - Content-Type." + Content-Type. + + (RFC 2616) + + Args: + title (str): Error title, for example: 'Editing Conflict'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_409, title, description, **kwargs) class HTTPLengthRequired(HTTPError): - """411 Length Required + """411 Length Required. - From RFC 2616: + The server refuses to accept the request without a defined + Content-Length. The client MAY repeat the request if it adds a + valid Content-Length header field containing the length of the + message-body in the request message. (RFC 2616) - "The server refuses to accept the request without a defined - Content- Length. The client MAY repeat the request if it adds a - valid Content-Length header field containing the length of the - message-body in the request message." + Args: + title (str): Error title, for example: 'Missing Content-Length'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ HTTPError.__init__(self, status.HTTP_411, title, description, **kwargs) class HTTPPreconditionFailed(HTTPError): - """412 Precondition Failed + """412 Precondition Failed. - From RFC 2616: - - "The precondition given in one or more of the request-header fields + The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server. This response code allows the client to place preconditions on the current resource metainformation (header field data) and thus prevent the requested - method from being applied to a resource other than the one intended." + method from being applied to a resource other than the one intended. + (RFC 2616) + + Args: + title (str): Error title, for example: 'Image Not Modified'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_412, title, description, **kwargs) class HTTPUnsupportedMediaType(HTTPError): - """415 Unsupported Media Type + """415 Unsupported Media Type. - Sets title to "Unsupported media type". + The client is trying to submit a resource encoded as an Internet media + type that the server does not support. + + Args: + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. """ def __init__(self, description, **kwargs): - """Initialize - - Args: - description: Human-friendly description of the error, along with a - helpful suggestion or two. - - The remaining (optional) args are the same as for HTTPError. - - """ - HTTPError.__init__(self, status.HTTP_415, 'Unsupported media type', description, **kwargs) class HTTPRangeNotSatisfiable(HTTPError): - """416 Range Not Satisfiable + """416 Range Not Satisfiable. - See also: http://goo.gl/yvh9H + The requested range is not valid. See also: http://goo.gl/Qsa4EF Args: resource_length: The maximum value for the last-byte-pos of a range @@ -280,17 +247,6 @@ class HTTPRangeNotSatisfiable(HTTPError): """ def __init__(self, resource_length, media_type=None): - """Initialize - - Args: - resource_length: The maximum value for the last-byte-pos of a - range request. Used to set the Content-Range header. - media_type: Media type to use as the value of the Content-Type - header, or None to use the default passed to the API - initializer. - - """ - headers = {'Content-Range': 'bytes */' + str(resource_length)} if media_type is not None: headers['Content-Type'] = media_type @@ -299,77 +255,71 @@ class HTTPRangeNotSatisfiable(HTTPError): class HTTPUpgradeRequired(HTTPError): - """426 Upgrade Required""" + """426 Upgrade Required. + + The protocol used by the client is not supported. It must retry the + request using the protocol identified in the Upgrade header. + + Args: + title (str): Error title. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. + + """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_426, title, description, **kwargs) class HTTPInternalServerError(HTTPError): - """500 Internal Server Error""" + """500 Internal Server Error. + + Args: + title (str): Error title, for example: 'This Should Never Happen'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. + + """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_500, title, description, **kwargs) class HTTPBadGateway(HTTPError): - """502 Bad Gateway""" + """502 Bad Gateway + + Args: + title (str): Error title, for example: 'Upstream Server is Unavailable'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + kwargs (optional): Same as for ``HTTPError``. + + """ def __init__(self, title, description, **kwargs): - """Initialize - - Args: - Same as for HTTPError, except status is set for you. - - """ - HTTPError.__init__(self, status.HTTP_502, title, description, **kwargs) class HTTPServiceUnavailable(HTTPError): - """503 Service Unavailable""" + """503 Service Unavailable. + + Args: + title (str): Error title, for example: 'Temporarily Unavailable'. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two. + retry_after (date or int): Value for the Retry-After header. If a date + object, will serialize as an HTTP date. Otherwise, a non-negative + int is expected, representing the number of seconds to wait. See + also: http://goo.gl/DIrWr . + kwargs (optional): Same as for ``HTTPError``. + + """ def __init__(self, title, description, retry_after, **kwargs): """Initialize - Args: - title: Human-friendly error title. Set to None if you wish Falcon - to return an empty response body (all remaining args will - be ignored except for headers.) Do this only when you don't - wish to disclose sensitive information about why a request was - refused, or if the status and headers are self-descriptive. - description: Human-friendly description of the error, along with a - helpful suggestion or two (default None). - retry_after: Value for the Retry-After header. If a date object, - will serialize as an HTTP date. Otherwise, a non-negative int - is expected, representing the number of seconds to wait. See - also: http://goo.gl/DIrWr - headers: A dictionary of extra headers to return in the - response to the client (default None). - href: A URL someone can visit to find out more information - (default None). - href_rel: If href is given, use this value for the rel - attribute (default 'doc'). - href_text: If href is given, use this as the friendly - title/description for the link (defaults to "API documentation - for this error"). - code: An internal code that customers can reference in their - support request or to help them when searching for knowledge - base articles related to this error. """ headers = kwargs.setdefault('headers', {}) diff --git a/falcon/http_error.py b/falcon/http_error.py index c83183a..7311b9a 100644 --- a/falcon/http_error.py +++ b/falcon/http_error.py @@ -33,14 +33,33 @@ class HTTPError(Exception): when something goes wrong. Attributes: - status: HTTP status line, such as "748 Confounded by Ponies". - title: Error title to send to the client. - description: Description of the error to send to the client. - headers: A dictionary of extra headers to add to the response. - link: An href that the client can provide to the user for getting help. - code: An internal application code that a user can reference when + status (str): HTTP status line, such as "748 Confounded by Ponies". + title (str): Error title to send to the client. + description (str): Description of the error to send to the client. + headers (dict): Extra headers to add to the response. + link (str): An href that the client can provide to the user for getting help. + code (int): An internal application code that a user can reference when requesting support for the error. + Args: + status (str): HTTP status code and text, such as "400 Bad Request" + title (str): Human-friendly error title. Set to None if you wish Falcon + to return an empty response body (all remaining args will + be ignored except for headers.) Do this only when you don't + wish to disclose sensitive information about why a request was + refused, or if the status and headers are self-descriptive. + description (str): Human-friendly description of the error, along with + a helpful suggestion or two (default None). + headers (dict): Extra headers to return in the + response to the client (default None). + href (str): A URL someone can visit to find out more information + (default None). Unicode characters are percent-encoded. + href_text (str): If href is given, use this as the friendly + title/description for the link (defaults to "API documentation + for this error"). + code (int): An internal code that customers can reference in their + support request or to help them when searching for knowledge + base articles related to this error. """ __slots__ = ( @@ -54,33 +73,6 @@ class HTTPError(Exception): def __init__(self, status, title, description=None, headers=None, href=None, href_text=None, code=None): - """Initialize with information that can be reported to the client - - Falcon will catch instances of HTTPError (and subclasses), then use - the associated information to generate a nice response for the client. - - Args: - status: HTTP status code and text, such as "400 Bad Request" - title: Human-friendly error title. Set to None if you wish Falcon - to return an empty response body (all remaining args will - be ignored except for headers.) Do this only when you don't - wish to disclose sensitive information about why a request was - refused, or if the status and headers are self-descriptive. - description: Human-friendly description of the error, along with a - helpful suggestion or two (default None). - headers: A dictionary of extra headers to return in the - response to the client (default None). - href: A URL someone can visit to find out more information - (default None). Unicode characters are percent-encoded. - href_text: If href is given, use this as the friendly - title/description for the link (defaults to "API documentation - for this error"). - code: An internal code that customers can reference in their - support request or to help them when searching for knowledge - base articles related to this error. - - """ - self.status = status self.title = title self.description = description @@ -98,8 +90,9 @@ class HTTPError(Exception): def json(self): """Returns a pretty JSON-encoded version of the exception - Note: Excludes the HTTP status line, since the results of this call - are meant to be returned in the body of an HTTP response. + Note: + Excludes the HTTP status line, since the results of this call + are meant to be returned in the body of an HTTP response. Returns: A JSON representation of the exception except the status line, or