1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
from typing import Dict, Optional, Union, cast
import stripe # noqa
from stripe._error_object import ErrorObject
class StripeError(Exception):
_message: Optional[str]
http_body: Optional[str]
http_status: Optional[int]
json_body: Optional[object]
headers: Optional[Dict[str, str]]
code: Optional[str]
request_id: Optional[str]
error: Optional["ErrorObject"]
def __init__(
self,
message: Optional[str] = None,
http_body: Optional[Union[bytes, str]] = None,
http_status: Optional[int] = None,
json_body: Optional[object] = None,
headers: Optional[Dict[str, str]] = None,
code: Optional[str] = None,
):
super(StripeError, self).__init__(message)
body: Optional[str] = None
if http_body:
# http_body can sometimes be a memoryview which must be cast
# to a "bytes" before calling decode, so we check for the
# decode attribute and then cast
if hasattr(http_body, "decode"):
try:
body = cast(bytes, http_body).decode("utf-8")
except BaseException:
body = (
"<Could not decode body as utf-8. "
"Please report to support@stripe.com>"
)
elif isinstance(http_body, str):
body = http_body
self._message = message
self.http_body = body
self.http_status = http_status
self.json_body = json_body
self.headers = headers or {}
self.code = code
self.request_id = self.headers.get("request-id", None)
self.error = self._construct_error_object()
def __str__(self):
msg = self._message or "<empty message>"
if self.request_id is not None:
return "Request {0}: {1}".format(self.request_id, msg)
else:
return msg
# Returns the underlying `Exception` (base class) message, which is usually
# the raw message returned by Stripe's API. This was previously available
# in python2 via `error.message`. Unlike `str(error)`, it omits "Request
# req_..." from the beginning of the string.
@property
def user_message(self):
return self._message
def __repr__(self):
return "%s(message=%r, http_status=%r, request_id=%r)" % (
self.__class__.__name__,
self._message,
self.http_status,
self.request_id,
)
def _construct_error_object(self) -> Optional[ErrorObject]:
if (
self.json_body is None
or not isinstance(self.json_body, dict)
or "error" not in self.json_body
or not isinstance(self.json_body["error"], dict)
):
return None
from stripe._error_object import ErrorObject
return ErrorObject._construct_from(
values=self.json_body["error"],
requestor=stripe._APIRequestor._global_instance(),
# We pass in API mode as "V1" here because it's required,
# but ErrorObject is reused for both V1 and V2 errors.
api_mode="V1",
)
class APIError(StripeError):
pass
class APIConnectionError(StripeError):
should_retry: bool
def __init__(
self,
message,
http_body=None,
http_status=None,
json_body=None,
headers=None,
code=None,
should_retry=False,
):
super(APIConnectionError, self).__init__(
message, http_body, http_status, json_body, headers, code
)
self.should_retry = should_retry
class StripeErrorWithParamCode(StripeError):
def __repr__(self):
return (
"%s(message=%r, param=%r, code=%r, http_status=%r, "
"request_id=%r)"
% (
self.__class__.__name__,
self._message,
self.param, # pyright: ignore
self.code,
self.http_status,
self.request_id,
)
)
class CardError(StripeErrorWithParamCode):
def __init__(
self,
message,
param,
code,
http_body=None,
http_status=None,
json_body=None,
headers=None,
):
super(CardError, self).__init__(
message, http_body, http_status, json_body, headers, code
)
self.param = param
class IdempotencyError(StripeError):
pass
class InvalidRequestError(StripeErrorWithParamCode):
def __init__(
self,
message,
param,
code=None,
http_body=None,
http_status=None,
json_body=None,
headers=None,
):
super(InvalidRequestError, self).__init__(
message, http_body, http_status, json_body, headers, code
)
self.param = param
class AuthenticationError(StripeError):
pass
class PermissionError(StripeError):
pass
class RateLimitError(StripeError):
pass
class SignatureVerificationError(StripeError):
def __init__(self, message, sig_header, http_body=None):
super(SignatureVerificationError, self).__init__(message, http_body)
self.sig_header = sig_header
# classDefinitions: The beginning of the section generated from our OpenAPI spec
class TemporarySessionExpiredError(StripeError):
pass
# classDefinitions: The end of the section generated from our OpenAPI spec
|