From bda1306749c62ef4f11cfe567ed7d56c8ad94240 Mon Sep 17 00:00:00 2001
From: Michael Merickel <github@m.merickel.org>
Date: Mon, 15 Oct 2018 16:56:42 +0200
Subject: [PATCH] Merge pull request #3388 from mmerickel/black

---
 src/pyramid/httpexceptions.py |  336 +++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 248 insertions(+), 88 deletions(-)

diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py
index bef8420..959a45f 100644
--- a/src/pyramid/httpexceptions.py
+++ b/src/pyramid/httpexceptions.py
@@ -137,15 +137,11 @@
 from webob import html_escape as _html_escape
 from webob.acceptparse import create_accept_header
 
-from pyramid.compat import (
-    class_types,
-    text_type,
-    binary_type,
-    text_,
-    )
+from pyramid.compat import class_types, text_type, binary_type, text_
 
 from pyramid.interfaces import IExceptionResponse
 from pyramid.response import Response
+
 
 def _no_escape(value):
     if value is None:
@@ -159,10 +155,10 @@
             value = text_type(value)
     return value
 
+
 @implementer(IExceptionResponse)
 class HTTPException(Response, Exception):
-
-    ## You should set in subclasses:
+    # You should set in subclasses:
     # code = 200
     # title = 'OK'
     # explanation = 'why this happens'
@@ -190,23 +186,29 @@
     #   implies that this class' ``exception`` property always returns
     #   ``self`` (it exists only for bw compat at this point).
     #
-    # - documentation improvements (Pyramid-specific docstrings where necessary)
+    # - documentation improvements (Pyramid-specific docstrings where
+    #   necessary)
     #
     code = 520
     title = 'Unknown Error'
     explanation = ''
-    body_template_obj = Template('''\
+    body_template_obj = Template(
+        '''\
 ${explanation}${br}${br}
 ${detail}
 ${html_comment}
-''')
+'''
+    )
 
-    plain_template_obj = Template('''\
+    plain_template_obj = Template(
+        '''\
 ${status}
 
-${body}''')
+${body}'''
+    )
 
-    html_template_obj = Template('''\
+    html_template_obj = Template(
+        '''\
 <html>
  <head>
   <title>${status}</title>
@@ -215,13 +217,21 @@
   <h1>${status}</h1>
   ${body}
  </body>
-</html>''')
+</html>'''
+    )
 
-    ## Set this to True for responses that should have no request body
+    # Set this to True for responses that should have no request body
     empty_body = False
 
-    def __init__(self, detail=None, headers=None, comment=None,
-                 body_template=None, json_formatter=None, **kw):
+    def __init__(
+        self,
+        detail=None,
+        headers=None,
+        comment=None,
+        body_template=None,
+        json_formatter=None,
+        **kw
+    ):
         status = '%s %s' % (self.code, self.title)
         Response.__init__(self, status=status, **kw)
         Exception.__init__(self, detail)
@@ -243,9 +253,7 @@
         return str(self.detail) if self.detail else self.explanation
 
     def _json_formatter(self, status, body, title, environ):
-        return {'message': body,
-                'code': status,
-                'title': self.title}
+        return {'message': body, 'code': status, 'title': self.title}
 
     def prepare(self, environ):
         if not self.has_body and not self.empty_body:
@@ -255,7 +263,9 @@
             accept = create_accept_header(accept_value)
             # Attempt to match text/html or application/json, if those don't
             # match, we will fall through to defaulting to text/plain
-            acceptable = accept.acceptable_offers(['text/html', 'application/json'])
+            acceptable = accept.acceptable_offers(
+                ['text/html', 'application/json']
+            )
             acceptable = [offer[0] for offer in acceptable] + ['text/plain']
             match = acceptable[0]
 
@@ -281,8 +291,10 @@
                     def substitute(self, status, body):
                         jsonbody = self.excobj._json_formatter(
                             status=status,
-                            body=body, title=self.excobj.title,
-                            environ=environ)
+                            body=body,
+                            title=self.excobj.title,
+                            environ=environ,
+                        )
                         return json.dumps(jsonbody)
 
                 page_template = JsonPageTemplate(self)
@@ -299,7 +311,7 @@
                 'detail': escape(self.detail or ''),
                 'comment': escape(comment),
                 'html_comment': html_comment,
-                }
+            }
             body_tmpl = self.body_template_obj
             if HTTPException.body_template_obj is not body_tmpl:
                 # Custom template; add headers to args
@@ -324,7 +336,7 @@
         # bw compat only
         return self
 
-    exception = wsgi_response # bw compat only
+    exception = wsgi_response  # bw compat only
 
     def __call__(self, environ, start_response):
         # differences from webob.exc.WSGIHTTPException
@@ -337,7 +349,9 @@
         self.prepare(environ)
         return Response.__call__(self, environ, start_response)
 
-WSGIHTTPException = HTTPException # b/c post 1.5
+
+WSGIHTTPException = HTTPException  # b/c post 1.5
+
 
 class HTTPError(HTTPException):
     """
@@ -346,6 +360,7 @@
     This is an exception which indicates that an error has occurred,
     and that any work in progress should not be committed.
     """
+
 
 class HTTPRedirection(HTTPException):
     """
@@ -357,15 +372,18 @@
     condition.
     """
 
+
 class HTTPSuccessful(HTTPException):
     """
     Base class for exceptions with status codes in the 200s (successful
     responses)
     """
 
+
 ############################################################
-## 2xx success
+# 2xx success
 ############################################################
+
 
 class HTTPOk(HTTPSuccessful):
     """
@@ -375,8 +393,10 @@
 
     code: 200, title: OK
     """
+
     code = 200
     title = 'OK'
+
 
 class HTTPCreated(HTTPSuccessful):
     """
@@ -387,8 +407,10 @@
 
     code: 201, title: Created
     """
+
     code = 201
     title = 'Created'
+
 
 class HTTPAccepted(HTTPSuccessful):
     """
@@ -399,9 +421,11 @@
 
     code: 202, title: Accepted
     """
+
     code = 202
     title = 'Accepted'
     explanation = 'The request is accepted for processing.'
+
 
 class HTTPNonAuthoritativeInformation(HTTPSuccessful):
     """
@@ -413,8 +437,10 @@
 
     code: 203, title: Non-Authoritative Information
     """
+
     code = 203
     title = 'Non-Authoritative Information'
+
 
 class HTTPNoContent(HTTPSuccessful):
     """
@@ -426,9 +452,11 @@
 
     code: 204, title: No Content
     """
+
     code = 204
     title = 'No Content'
     empty_body = True
+
 
 class HTTPResetContent(HTTPSuccessful):
     """
@@ -440,9 +468,11 @@
 
     code: 205, title: Reset Content
     """
+
     code = 205
     title = 'Reset Content'
     empty_body = True
+
 
 class HTTPPartialContent(HTTPSuccessful):
     """
@@ -453,14 +483,17 @@
 
     code: 206, title: Partial Content
     """
+
     code = 206
     title = 'Partial Content'
 
-## FIXME: add 207 Multi-Status (but it's complicated)
+
+# FIXME: add 207 Multi-Status (but it's complicated)
 
 ############################################################
-## 3xx redirection
+# 3xx redirection
 ############################################################
+
 
 class _HTTPMove(HTTPRedirection):
     """
@@ -472,6 +505,7 @@
 
     You must provide a ``location`` keyword argument.
     """
+
     # differences from webob.exc._HTTPMove:
     #
     # - ${location} isn't wrapped in an <a> tag in body
@@ -486,18 +520,33 @@
     # - ``add_slash`` argument is no longer accepted:  code that passes
     #   add_slash argument to the constructor will receive an exception.
     explanation = 'The resource has been moved to'
-    body_template_obj = Template('''\
+    body_template_obj = Template(
+        '''\
 ${explanation} ${location}; you should be redirected automatically.
 ${detail}
-${html_comment}''')
+${html_comment}'''
+    )
 
-    def __init__(self, location='', detail=None, headers=None, comment=None,
-                 body_template=None, **kw):
+    def __init__(
+        self,
+        location='',
+        detail=None,
+        headers=None,
+        comment=None,
+        body_template=None,
+        **kw
+    ):
         if location is None:
             raise ValueError("HTTP redirects need a location to redirect to.")
         super(_HTTPMove, self).__init__(
-            detail=detail, headers=headers, comment=comment,
-            body_template=body_template, location=location, **kw)
+            detail=detail,
+            headers=headers,
+            comment=comment,
+            body_template=body_template,
+            location=location,
+            **kw
+        )
+
 
 class HTTPMultipleChoices(_HTTPMove):
     """
@@ -511,8 +560,10 @@
 
     code: 300, title: Multiple Choices
     """
+
     code = 300
     title = 'Multiple Choices'
+
 
 class HTTPMovedPermanently(_HTTPMove):
     """
@@ -524,8 +575,10 @@
 
     code: 301, title: Moved Permanently
     """
+
     code = 301
     title = 'Moved Permanently'
+
 
 class HTTPFound(_HTTPMove):
     """
@@ -536,9 +589,11 @@
 
     code: 302, title: Found
     """
+
     code = 302
     title = 'Found'
     explanation = 'The resource was found at'
+
 
 # This one is safe after a POST (the redirected location will be
 # retrieved with GET):
@@ -552,8 +607,10 @@
 
     code: 303, title: See Other
     """
+
     code = 303
     title = 'See Other'
+
 
 class HTTPNotModified(HTTPRedirection):
     """
@@ -565,10 +622,12 @@
 
     code: 304, title: Not Modified
     """
+
     # FIXME: this should include a date or etag header
     code = 304
     title = 'Not Modified'
     empty_body = True
+
 
 class HTTPUseProxy(_HTTPMove):
     """
@@ -579,11 +638,12 @@
 
     code: 305, title: Use Proxy
     """
+
     # Not a move, but looks a little like one
     code = 305
     title = 'Use Proxy'
-    explanation = (
-        'The resource must be accessed through a proxy located at')
+    explanation = 'The resource must be accessed through a proxy located at'
+
 
 class HTTPTemporaryRedirect(_HTTPMove):
     """
@@ -594,8 +654,10 @@
 
     code: 307, title: Temporary Redirect
     """
+
     code = 307
     title = 'Temporary Redirect'
+
 
 class HTTPPermanentRedirect(_HTTPMove):
     """
@@ -607,12 +669,15 @@
 
     code: 308, title: Permanent Redirect
     """
+
     code = 308
     title = 'Permanent Redirect'
 
+
 ############################################################
-## 4xx client error
+# 4xx client error
 ############################################################
+
 
 class HTTPClientError(HTTPError):
     """
@@ -623,8 +688,10 @@
     a bug.  A server-side traceback is not warranted.  Unless specialized,
     this is a '400 Bad Request'
     """
+
     code = 400
     title = 'Bad Request'
+
 
 class HTTPBadRequest(HTTPClientError):
     """
@@ -635,8 +702,12 @@
 
     code: 400, title: Bad Request
     """
-    explanation = ('The server could not comply with the request since '
-                   'it is either malformed or otherwise incorrect.')
+
+    explanation = (
+        'The server could not comply with the request since '
+        'it is either malformed or otherwise incorrect.'
+    )
+
 
 class HTTPUnauthorized(HTTPClientError):
     """
@@ -646,13 +717,16 @@
 
     code: 401, title: Unauthorized
     """
+
     code = 401
     title = 'Unauthorized'
     explanation = (
         'This server could not verify that you are authorized to '
         'access the document you requested.  Either you supplied the '
         'wrong credentials (e.g., bad password), or your browser '
-        'does not understand how to supply the credentials required.')
+        'does not understand how to supply the credentials required.'
+    )
+
 
 class HTTPPaymentRequired(HTTPClientError):
     """
@@ -660,9 +734,11 @@
 
     code: 402, title: Payment Required
     """
+
     code = 402
     title = 'Payment Required'
-    explanation = ('Access was denied for financial reasons.')
+    explanation = 'Access was denied for financial reasons.'
+
 
 class HTTPForbidden(HTTPClientError):
     """
@@ -693,6 +769,7 @@
     exception as necessary to provide extended information in an error
     report shown to a user.
     """
+
     # differences from webob.exc.HTTPForbidden:
     #
     # - accepts a ``result`` keyword argument
@@ -705,13 +782,27 @@
     #
     code = 403
     title = 'Forbidden'
-    explanation = ('Access was denied to this resource.')
-    def __init__(self, detail=None, headers=None, comment=None,
-                 body_template=None, result=None, **kw):
-        HTTPClientError.__init__(self, detail=detail, headers=headers,
-                                 comment=comment, body_template=body_template,
-                                 **kw)
+    explanation = 'Access was denied to this resource.'
+
+    def __init__(
+        self,
+        detail=None,
+        headers=None,
+        comment=None,
+        body_template=None,
+        result=None,
+        **kw
+    ):
+        HTTPClientError.__init__(
+            self,
+            detail=detail,
+            headers=headers,
+            comment=comment,
+            body_template=body_template,
+            **kw
+        )
         self.result = result
+
 
 class HTTPNotFound(HTTPClientError):
     """
@@ -732,9 +823,11 @@
     string will be available as the ``message`` attribute of this exception,
     for availability to the :term:`Not Found View`.
     """
+
     code = 404
     title = 'Not Found'
-    explanation = ('The resource could not be found.')
+    explanation = 'The resource could not be found.'
+
 
 class HTTPMethodNotAllowed(HTTPClientError):
     """
@@ -745,14 +838,18 @@
 
     code: 405, title: Method Not Allowed
     """
+
     # differences from webob.exc.HTTPMethodNotAllowed:
     #
     # - body_template_obj uses ${br} instead of <br />
     code = 405
     title = 'Method Not Allowed'
-    body_template_obj = Template('''\
+    body_template_obj = Template(
+        '''\
 The method ${REQUEST_METHOD} is not allowed for this resource. ${br}${br}
-${detail}''')
+${detail}'''
+    )
+
 
 class HTTPNotAcceptable(HTTPClientError):
     """
@@ -765,11 +862,13 @@
 
     code: 406, title: Not Acceptable
     """
+
     # differences from webob.exc.HTTPNotAcceptable:
     #
     # - "template" attribute left off (useless, bug in webob?)
     code = 406
     title = 'Not Acceptable'
+
 
 class HTTPProxyAuthenticationRequired(HTTPClientError):
     """
@@ -780,9 +879,11 @@
 
     code: 407, title: Proxy Authentication Required
     """
+
     code = 407
     title = 'Proxy Authentication Required'
-    explanation = ('Authentication with a local proxy is needed.')
+    explanation = 'Authentication with a local proxy is needed.'
+
 
 class HTTPRequestTimeout(HTTPClientError):
     """
@@ -793,10 +894,14 @@
 
     code: 408, title: Request Timeout
     """
+
     code = 408
     title = 'Request Timeout'
-    explanation = ('The server has waited too long for the request to '
-                   'be sent by the client.')
+    explanation = (
+        'The server has waited too long for the request to '
+        'be sent by the client.'
+    )
+
 
 class HTTPConflict(HTTPClientError):
     """
@@ -807,10 +912,13 @@
 
     code: 409, title: Conflict
     """
+
     code = 409
     title = 'Conflict'
-    explanation = ('There was a conflict when trying to complete '
-                   'your request.')
+    explanation = (
+        'There was a conflict when trying to complete ' 'your request.'
+    )
+
 
 class HTTPGone(HTTPClientError):
     """
@@ -821,10 +929,14 @@
 
     code: 410, title: Gone
     """
+
     code = 410
     title = 'Gone'
-    explanation = ('This resource is no longer available.  No forwarding '
-                   'address is given.')
+    explanation = (
+        'This resource is no longer available.  No forwarding '
+        'address is given.'
+    )
+
 
 class HTTPLengthRequired(HTTPClientError):
     """
@@ -835,9 +947,11 @@
 
     code: 411, title: Length Required
     """
+
     code = 411
     title = 'Length Required'
-    explanation = ('Content-Length header required.')
+    explanation = 'Content-Length header required.'
+
 
 class HTTPPreconditionFailed(HTTPClientError):
     """
@@ -849,9 +963,11 @@
 
     code: 412, title: Precondition Failed
     """
+
     code = 412
     title = 'Precondition Failed'
-    explanation = ('Request precondition failed.')
+    explanation = 'Request precondition failed.'
+
 
 class HTTPRequestEntityTooLarge(HTTPClientError):
     """
@@ -863,9 +979,11 @@
 
     code: 413, title: Request Entity Too Large
     """
+
     code = 413
     title = 'Request Entity Too Large'
-    explanation = ('The body of your request was too large for this server.')
+    explanation = 'The body of your request was too large for this server.'
+
 
 class HTTPRequestURITooLong(HTTPClientError):
     """
@@ -877,9 +995,11 @@
 
     code: 414, title: Request-URI Too Long
     """
+
     code = 414
     title = 'Request-URI Too Long'
-    explanation = ('The request URI was too long for this server.')
+    explanation = 'The request URI was too long for this server.'
+
 
 class HTTPUnsupportedMediaType(HTTPClientError):
     """
@@ -891,11 +1011,13 @@
 
     code: 415, title: Unsupported Media Type
     """
+
     # differences from webob.exc.HTTPUnsupportedMediaType:
     #
     # - "template_obj" attribute left off (useless, bug in webob?)
     code = 415
     title = 'Unsupported Media Type'
+
 
 class HTTPRequestRangeNotSatisfiable(HTTPClientError):
     """
@@ -909,9 +1031,11 @@
 
     code: 416, title: Request Range Not Satisfiable
     """
+
     code = 416
     title = 'Request Range Not Satisfiable'
-    explanation = ('The Range requested is not available.')
+    explanation = 'The Range requested is not available.'
+
 
 class HTTPExpectationFailed(HTTPClientError):
     """
@@ -922,9 +1046,11 @@
 
     code: 417, title: Expectation Failed
     """
+
     code = 417
     title = 'Expectation Failed'
-    explanation = ('Expectation failed.')
+    explanation = 'Expectation failed.'
+
 
 class HTTPUnprocessableEntity(HTTPClientError):
     """
@@ -940,10 +1066,12 @@
 
     code: 422, title: Unprocessable Entity
     """
-    ## Note: from WebDAV
+
+    # Note: from WebDAV
     code = 422
     title = 'Unprocessable Entity'
     explanation = 'Unable to process the contained instructions'
+
 
 class HTTPLocked(HTTPClientError):
     """
@@ -953,10 +1081,12 @@
 
     code: 423, title: Locked
     """
-    ## Note: from WebDAV
+
+    # Note: from WebDAV
     code = 423
     title = 'Locked'
-    explanation = ('The resource is locked')
+    explanation = 'The resource is locked'
+
 
 class HTTPFailedDependency(HTTPClientError):
     """
@@ -967,12 +1097,15 @@
 
     code: 424, title: Failed Dependency
     """
-    ## Note: from WebDAV
+
+    # Note: from WebDAV
     code = 424
     title = 'Failed Dependency'
     explanation = (
         'The method could not be performed because the requested '
-        'action dependended on another action and that action failed')
+        'action dependended on another action and that action failed'
+    )
+
 
 class HTTPPreconditionRequired(HTTPClientError):
     """
@@ -991,10 +1124,11 @@
 
     code: 428, title: Precondition Required
     """
+
     code = 428
     title = 'Precondition Required'
-    explanation = (
-        'The origin server requires the request to be conditional.')
+    explanation = 'The origin server requires the request to be conditional.'
+
 
 class HTTPTooManyRequests(HTTPClientError):
     """
@@ -1007,11 +1141,14 @@
 
     code: 429, title: Too Many Requests
     """
+
     code = 429
     title = 'Too Many Requests'
     explanation = (
         'The action could not be performed because there were too '
-        'many requests by the client.')
+        'many requests by the client.'
+    )
+
 
 class HTTPRequestHeaderFieldsTooLarge(HTTPClientError):
     """
@@ -1025,13 +1162,14 @@
 
     code: 431, title: Request Header Fields Too Large
     """
+
     code = 431
     title = 'Request Header Fields Too Large'
-    explanation = (
-        'The requests header fields were too large.')
+    explanation = 'The requests header fields were too large.'
+
 
 ############################################################
-## 5xx Server Error
+# 5xx Server Error
 ############################################################
 #  Response status codes beginning with the digit "5" indicate cases in
 #  which the server is aware that it has erred or is incapable of
@@ -1041,6 +1179,7 @@
 #  agents SHOULD display any included entity to the user. These response
 #  codes are applicable to any request method.
 
+
 class HTTPServerError(HTTPError):
     """
     base class for the 500s, where the server is in-error
@@ -1048,8 +1187,10 @@
     This is an error condition in which the server is presumed to be
     in-error.  Unless specialized, this is a '500 Internal Server Error'.
     """
+
     code = 500
     title = 'Internal Server Error'
+
 
 class HTTPInternalServerError(HTTPServerError):
     """
@@ -1060,9 +1201,12 @@
 
     code: 500, title: Internal Server Error
     """
+
     explanation = (
         'The server has either erred or is incapable of performing '
-        'the requested operation.')
+        'the requested operation.'
+    )
+
 
 class HTTPNotImplemented(HTTPServerError):
     """
@@ -1073,11 +1217,13 @@
 
     code: 501, title: Not Implemented
     """
+
     # differences from webob.exc.HTTPNotAcceptable:
     #
     # - "template" attr left off (useless, bug in webob?)
     code = 501
     title = 'Not Implemented'
+
 
 class HTTPBadGateway(HTTPServerError):
     """
@@ -1089,9 +1235,11 @@
 
     code: 502, title: Bad Gateway
     """
+
     code = 502
     title = 'Bad Gateway'
-    explanation = ('Bad gateway.')
+    explanation = 'Bad gateway.'
+
 
 class HTTPServiceUnavailable(HTTPServerError):
     """
@@ -1102,10 +1250,14 @@
 
     code: 503, title: Service Unavailable
     """
+
     code = 503
     title = 'Service Unavailable'
-    explanation = ('The server is currently unavailable. '
-                   'Please try again at a later time.')
+    explanation = (
+        'The server is currently unavailable. '
+        'Please try again at a later time.'
+    )
+
 
 class HTTPGatewayTimeout(HTTPServerError):
     """
@@ -1118,9 +1270,11 @@
 
     code: 504, title: Gateway Timeout
     """
+
     code = 504
     title = 'Gateway Timeout'
-    explanation = ('The gateway has timed out.')
+    explanation = 'The gateway has timed out.'
+
 
 class HTTPVersionNotSupported(HTTPServerError):
     """
@@ -1132,9 +1286,11 @@
 
     code: 505, title: HTTP Version Not Supported
     """
+
     code = 505
     title = 'HTTP Version Not Supported'
-    explanation = ('The HTTP version is not supported.')
+    explanation = 'The HTTP version is not supported.'
+
 
 class HTTPInsufficientStorage(HTTPServerError):
     """
@@ -1145,9 +1301,11 @@
 
     code: 507, title: Insufficient Storage
     """
+
     code = 507
     title = 'Insufficient Storage'
-    explanation = ('There was not enough space to save the resource')
+    explanation = 'There was not enough space to save the resource'
+
 
 def exception_response(status_code, **kw):
     """Creates an HTTP exception based on a status code. Example::
@@ -1159,22 +1317,24 @@
     exc = status_map[status_code](**kw)
     return exc
 
+
 def default_exceptionresponse_view(context, request):
     if not isinstance(context, Exception):
         # backwards compat for an exception response view registered via
         # config.set_notfound_view or config.set_forbidden_view
         # instead of as a proper exception view
         context = request.exception or context
-    return context # assumed to be an IResponse
+    return context  # assumed to be an IResponse
+
 
 status_map = {}
 code = None
 for name, value in list(globals().items()):
     if (
-            isinstance(value, class_types) and
-            issubclass(value, HTTPException) and
-            value not in {HTTPClientError, HTTPServerError} and
-            not name.startswith('_')
+        isinstance(value, class_types)
+        and issubclass(value, HTTPException)
+        and value not in {HTTPClientError, HTTPServerError}
+        and not name.startswith('_')
     ):
         code = getattr(value, 'code', None)
         if code:

--
Gitblit v1.9.3