Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding black and applying results #583

Open
wants to merge 1 commit into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,867 changes: 972 additions & 895 deletions recurly/__init__.py

Large diffs are not rendered by default.

82 changes: 52 additions & 30 deletions recurly/errors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from defusedxml import ElementTree
import six


class ResponseError(Exception):

"""An error received from the Recurly API in response to an HTTP
Expand All @@ -13,39 +14,37 @@ def __init__(self, response_xml):
def response_doc(self):
"""The XML document received from the service."""
try:
return self.__dict__['response_doc']
return self.__dict__["response_doc"]
except KeyError:
self.__dict__['response_doc'] = ElementTree.fromstring(
self.response_xml
)
return self.__dict__['response_doc']
self.__dict__["response_doc"] = ElementTree.fromstring(self.response_xml)
return self.__dict__["response_doc"]

@property
def symbol(self):
"""The machine-readable identifier for the error."""
el = self.response_doc.find('symbol')
el = self.response_doc.find("symbol")
if el is not None:
return el.text

@property
def message(self):
"""The human-readable description of the error."""
el = self.response_doc.find('description')
el = self.response_doc.find("description")
if el is not None:
return el.text

@property
def details(self):
"""A further human-readable elaboration on the error."""
el = self.response_doc.find('details')
el = self.response_doc.find("details")
if el is not None:
return el.text

@property
def error(self):
"""A fall-back error message in the event no more specific
error is given."""
el = self.response_doc.find('error')
el = self.response_doc.find("error")
if el is not None:
return el.text

Expand All @@ -58,13 +57,14 @@ def __unicode__(self):
return self.error
details = self.details
if details is not None:
return six.u('%s: %s %s') % (symbol, self.message, details)
return six.u('%s: %s') % (symbol, self.message)
return six.u("%s: %s %s") % (symbol, self.message, details)
return six.u("%s: %s") % (symbol, self.message)


class ClientError(ResponseError):
"""An error resulting from a problem in the client's request (that
is, an error with an HTTP ``4xx`` status code)."""

pass


Expand All @@ -76,11 +76,13 @@ class BadRequestError(ClientError):
Resubmitting the request will likely result in the same error.

"""

pass


class ConfigurationError(Exception):
"""An error related to a bad configuration"""

pass


Expand All @@ -99,6 +101,7 @@ def __unicode__(self):
class PaymentRequiredError(ClientError):
"""An error indicating your Recurly account is in production mode
but is not in good standing (HTTP ``402 Payment Required``)."""

pass


Expand All @@ -110,18 +113,21 @@ class ForbiddenError(ClientError):
your login credentials are for the appropriate account.

"""

pass


class NotFoundError(ClientError):
"""An error for when the resource was not found with the given
identifier (HTTP ``404 Not Found``)."""

pass


class NotAcceptableError(ClientError):
"""An error for when the client's request could not be accepted by
the remote service (HTTP ``406 Not Acceptable``)."""

pass


Expand All @@ -134,12 +140,14 @@ class PreconditionFailedError(ClientError):
corresponds to the HTTP ``412 Precondition Failed`` status code.

"""

pass


class UnsupportedMediaTypeError(ClientError):
"""An error resulting from the submission as an unsupported media
type (HTTP ``415 Unsupported Media Type``)."""

pass


Expand All @@ -153,42 +161,42 @@ def __init__(self, response_doc):
@property
def error_code(self):
"""The machine-readable identifier for the error."""
el = self.response_doc.find('error_code')
el = self.response_doc.find("error_code")
if el is not None:
return el.text

@property
def error_category(self):
"""The machine-readable identifier for the error category."""
el = self.response_doc.find('error_category')
el = self.response_doc.find("error_category")
if el is not None:
return el.text

@property
def customer_message(self):
"""Recommended message for the customer"""
el = self.response_doc.find('customer_message')
el = self.response_doc.find("customer_message")
if el is not None:
return el.text

@property
def merchant_message(self):
"""Recommended message for the merchant"""
el = self.response_doc.find('merchant_message')
el = self.response_doc.find("merchant_message")
if el is not None:
return el.text

@property
def gateway_error_code(self):
"""Error code from the gateway"""
el = self.response_doc.find('gateway_error_code')
el = self.response_doc.find("gateway_error_code")
if el is not None:
return el.text

@property
def three_d_secure_action_token_id(self):
"""3DS Action Token ID for further authentication"""
el = self.response_doc.find('three_d_secure_action_token_id')
el = self.response_doc.find("three_d_secure_action_token_id")
if el is not None:
return el.text

Expand All @@ -201,16 +209,16 @@ class ValidationError(ClientError):
@property
def transaction_error(self):
"""The transaction error object."""
error = self.response_doc.find('transaction_error')
error = self.response_doc.find("transaction_error")
if error is not None:
return TransactionError(error)

@property
def transaction_error_code(self):
"""The machine-readable error code for a transaction error."""
error = self.response_doc.find('transaction_error')
error = self.response_doc.find("transaction_error")
if error is not None:
code = error.find('error_code')
code = error.find("error_code")
if code is not None:
return code.text

Expand All @@ -228,7 +236,7 @@ def __str__(self):
return self.__unicode__()

def __unicode__(self):
return six.u('%s: %s %s') % (self.symbol, self.field, self.message)
return six.u("%s: %s %s") % (self.symbol, self.field, self.message)

@property
def errors(self):
Expand All @@ -240,14 +248,14 @@ def errors(self):

"""
try:
return self.__dict__['errors']
return self.__dict__["errors"]
except KeyError:
pass

suberrors = dict()
for err in self.response_doc.findall('error'):
field = err.attrib['field']
symbol = err.attrib['symbol']
for err in self.response_doc.findall("error"):
field = err.attrib["field"]
symbol = err.attrib["symbol"]
message = err.text
sub_err = self.Suberror(field, symbol, message)

Expand All @@ -260,28 +268,33 @@ def errors(self):
else:
suberrors[field] = sub_err

self.__dict__['errors'] = suberrors
self.__dict__["errors"] = suberrors
return suberrors

def __unicode__(self):
all_error_strings = []
for error_key in sorted(self.errors.keys()):
error = self.errors[error_key]
if isinstance(error, (tuple, list)):
all_error_strings += [six.text_type(e) for e in error] # multiple errors on field
all_error_strings += [
six.text_type(e) for e in error
] # multiple errors on field
else:
all_error_strings.append(six.text_type(error))
return six.u('; ').join(all_error_strings)
return six.u("; ").join(all_error_strings)


class ServerError(ResponseError):
"""An error resulting from a problem creating the server's response
to the request (that is, an error with an HTTP ``5xx`` status code)."""

pass


class InternalServerError(ServerError):
"""An unexpected general server error (HTTP ``500 Internal Server
Error``)."""

pass


Expand All @@ -293,6 +306,7 @@ class BadGatewayError(ServerError):
Try the request again.

"""

pass


Expand All @@ -303,6 +317,7 @@ class ServiceUnavailableError(ServerError):
response. Try the request again.

"""

pass


Expand All @@ -313,6 +328,7 @@ class GatewayTimeoutError(ServerError):
response. Try the request again.

"""

pass


Expand All @@ -335,14 +351,17 @@ class UnexpectedClientError(UnexpectedStatusError):
not be used for classes mapped in the `error_classes` dict.

"""

pass


class UnexpectedServerError(UnexpectedStatusError):
"""An error resulting from an unexpected status code in
the range 500-599 of HTTP status codes. This class should
not be used for classes mapped in the `error_classes` dict.

"""

pass


Expand All @@ -369,13 +388,16 @@ def error_class_for_http_status(status):
try:
return error_classes[status]
except KeyError:

def new_status_error(xml_response):
if (status > 400 and status < 500):
if status > 400 and status < 500:
return UnexpectedClientError(status, xml_response)
if (status > 500 and status < 600):
if status > 500 and status < 600:
return UnexpectedServerError(status, xml_response)
return UnexpectedStatusError(status, xml_response)

return new_status_error


other_errors = [ConfigurationError]
__all__ = [x.__name__ for x in list(error_classes.values()) + other_errors]
34 changes: 18 additions & 16 deletions recurly/link_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,44 @@

TOKEN = r'(?:[^\(\)<>@,;:\\"/\[\]\?={} \t]+?)'
QUOTED_STRING = r'(?:"(?:\\"|[^"])*")'
PARAMETER = r'(?:%(TOKEN)s(?:=(?:%(TOKEN)s|%(QUOTED_STRING)s))?)' % locals()
LINK = r'<[^>]*>\s*(?:;\s*%(PARAMETER)s?\s*)*' % locals()
COMMA = r'(?:\s*(?:,\s*)+)'
LINK_SPLIT = r'%s(?=%s|\s*$)' % (LINK, COMMA)
PARAMETER = r"(?:%(TOKEN)s(?:=(?:%(TOKEN)s|%(QUOTED_STRING)s))?)" % locals()
LINK = r"<[^>]*>\s*(?:;\s*%(PARAMETER)s?\s*)*" % locals()
COMMA = r"(?:\s*(?:,\s*)+)"
LINK_SPLIT = r"%s(?=%s|\s*$)" % (LINK, COMMA)


def _unquotestring(instr):
if instr[0] == instr[-1] == '"':
instr = instr[1:-1]
instr = re.sub(r'\\(.)', r'\1', instr)
instr = re.sub(r"\\(.)", r"\1", instr)
return instr


def _splitstring(instr, item, split):
if not instr:
return []
return [h.strip() for h in re.findall(r'%s(?=%s|\s*$)' % (item, split), instr)]
return [h.strip() for h in re.findall(r"%s(?=%s|\s*$)" % (item, split), instr)]


link_splitter = re.compile(LINK_SPLIT)


def parse_link_value(instr):
"""
Given a link-value (i.e., after separating the header-value on commas),
Given a link-value (i.e., after separating the header-value on commas),
return a dictionary whose keys are link URLs and values are dictionaries
of the parameters for their associated links.
Note that internationalised parameters (e.g., title*) are

Note that internationalised parameters (e.g., title*) are
NOT percent-decoded.

Also, only the last instance of a given parameter will be included.
For example,

For example,

>>> parse_link_value('</foo>; rel="self"; title*=utf-8\'de\'letztes%20Kapitel')
{'/foo': {'title*': "utf-8'de'letztes%20Kapitel", 'rel': 'self'}}

"""
out = {}
if not instr:
Expand All @@ -89,7 +90,8 @@ def parse_link_value(instr):
return out


if __name__ == '__main__':
if __name__ == "__main__":
import sys

if len(sys.argv) > 1:
print(parse_link_value(sys.argv[1]))
print(parse_link_value(sys.argv[1]))
Loading