Add ExternalError.description and GraphQLError.debug_info

This commit is contained in:
Mads Marquart
2020-01-15 14:03:35 +01:00
parent e25f53d9a9
commit 28791b2118
6 changed files with 36 additions and 26 deletions

View File

@@ -12,6 +12,7 @@ class FacebookError(Exception):
All exceptions in the module inherit this.
"""
#: A message describing the error
message = attr.ib(type=str)
@@ -19,8 +20,14 @@ class FacebookError(Exception):
class HTTPError(FacebookError):
"""Base class for errors with the HTTP(s) connection to Facebook."""
#: The returned HTTP status code, if relevant
status_code = attr.ib(None, type=int)
def __str__(self):
if not self.status_code:
return self.message
return "#{}: {}".format(self.status_code, self.message)
@attrs_exception
class ParseError(FacebookError):
@@ -44,24 +51,31 @@ class ParseError(FacebookError):
class ExternalError(FacebookError):
"""Base class for errors that Facebook return."""
#: The error message that Facebook returned (In the user's own language)
message = attr.ib(type=str)
#: The error message that Facebook returned (Possibly in the user's own language)
description = attr.ib(type=str)
#: The error code that Facebook returned
code = attr.ib(None, type=int)
def __str__(self):
if self.code:
return "#{}: {}".format(self.code, self.message)
return self.message
return "{}: #{}, {}".format(self.message, self.code, self.description)
return "{}: {}".format(self.message, self.description)
@attrs_exception
class GraphQLError(ExternalError):
"""Raised by Facebook if there was an error in the GraphQL query."""
# TODO: Add `summary`, `severity` and `description`
# TODO: Handle multiple errors
#: Query debug information
debug_info = attr.ib(None, type=str)
def __str__(self):
if self.debug_info:
return "{}, {}".format(super().__str__(), self.debug_info)
return super().__str__()
@attrs_exception
class InvalidParameters(ExternalError):
@@ -103,10 +117,7 @@ def handle_payload_error(j):
else:
error_cls = ExternalError
# TODO: Use j["errorSummary"]
# "errorDescription" is in the users own language!
raise error_cls(
"Error sending request: {}".format(j["errorDescription"]), code=code
)
raise error_cls("Error sending request", j["errorDescription"], code=code)
def handle_graphql_errors(j):
@@ -117,10 +128,13 @@ def handle_graphql_errors(j):
errors = j["errors"]
if errors:
error = errors[0] # TODO: Handle multiple errors
# TODO: Use `summary`, `severity` and `description`
# TODO: Use `severity` and `description`
raise GraphQLError(
"{} / {!r}".format(error.get("message"), error.get("debug_info")),
# TODO: What data is always available?
error.get("summary", "Unknown error"),
error.get("message", ""),
code=error.get("code"),
debug_info=error.get("debug_info"),
)

View File

@@ -53,9 +53,7 @@ class Plan:
}
j = thread.session._payload_post("/ajax/eventreminder/create", data)
if "error" in j:
raise _exception.ExternalError(
"Failed creating plan: {}".format(j["error"])
)
raise _exception.ExternalError("Failed creating plan", j["error"])
def edit(
self,

View File

@@ -102,7 +102,6 @@ class Poll:
)
if j.get("status") != "success":
raise _exception.ExternalError(
"Failed updating poll vote: {}: {}".format(
j.get("errorTitle"), j.get("errorMessage")
)
"Failed updating poll vote: {}".format(j.get("errorTitle")),
j.get("errorMessage"),
)

View File

@@ -202,7 +202,7 @@ class Session:
else:
code, msg = get_error_data(r.text, r.url)
raise _exception.ExternalError(
"Login failed. {}, url: {}".format(msg, r.url), code=code
"Login failed at url {}".format(r.url), msg, code=code
)
def is_logged_in(self):

View File

@@ -479,9 +479,7 @@ class ThreadABC(metaclass=abc.ABCMeta):
}
j = self.session._payload_post("/mercury/attachments/forward/", data)
if not j.get("success"):
raise _exception.ExternalError(
"Failed forwarding attachment: {}".format(j["error"])
)
raise _exception.ExternalError("Failed forwarding attachment", j["error"])
def _set_typing(self, typing):
data = {
@@ -545,9 +543,8 @@ class ThreadABC(metaclass=abc.ABCMeta):
)
if j.get("status") != "success":
raise _exception.ExternalError(
"Failed creating poll: {}, {}".format(
j.get("errorTitle"), j.get("errorMessage")
)
"Failed creating poll: {}".format(j.get("errorTitle")),
j.get("errorMessage"),
)
def mute(self, duration: datetime.timedelta = None):

View File

@@ -67,7 +67,7 @@ ERROR_DATA = [
@pytest.mark.parametrize("exception,code,description,summary", ERROR_DATA)
def test_handle_payload_error(exception, code, summary, description):
data = {"error": code, "errorSummary": summary, "errorDescription": description}
with pytest.raises(exception, match=r"#\d+: Error sending request"):
with pytest.raises(exception, match=r"Error sending request: #\d+"):
handle_payload_error(data)
@@ -97,7 +97,9 @@ def test_handle_graphql_errors():
"severity": "CRITICAL",
"summary": "Query error",
}
with pytest.raises(GraphQLError, match="#1675030: Errors while executing"):
with pytest.raises(
GraphQLError, match="Query error: #1675030, Errors while executing"
):
handle_graphql_errors({"data": {"message_thread": None}, "errors": [error]})