Various error improvements
This commit is contained in:
@@ -26,7 +26,7 @@ class HTTPError(FacebookError):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
if not self.status_code:
|
if not self.status_code:
|
||||||
return self.message
|
return self.message
|
||||||
return "#{}: {}".format(self.status_code, self.message)
|
return "Got {} response: {}".format(self.status_code, self.message)
|
||||||
|
|
||||||
|
|
||||||
@attrs_exception
|
@attrs_exception
|
||||||
@@ -43,7 +43,7 @@ class ParseError(FacebookError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = "{}. Please report this, and the associated data: {}"
|
msg = "{}. Please report this, along with the data below!\n{}"
|
||||||
return msg.format(self.message, self.data)
|
return msg.format(self.message, self.data)
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ class ExternalError(FacebookError):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.code:
|
if self.code:
|
||||||
return "{}: #{}, {}".format(self.message, self.code, self.description)
|
return "#{} {}: {}".format(self.code, self.message, self.description)
|
||||||
return "{}: {}".format(self.message, self.description)
|
return "{}: {}".format(self.message, self.description)
|
||||||
|
|
||||||
|
|
||||||
@@ -116,8 +116,7 @@ def handle_payload_error(j):
|
|||||||
error_cls = InvalidParameters
|
error_cls = InvalidParameters
|
||||||
else:
|
else:
|
||||||
error_cls = ExternalError
|
error_cls = ExternalError
|
||||||
# TODO: Use j["errorSummary"]
|
raise error_cls(j["errorSummary"], description=j["errorDescription"], code=code)
|
||||||
raise error_cls("Error sending request", j["errorDescription"], code=code)
|
|
||||||
|
|
||||||
|
|
||||||
def handle_graphql_errors(j):
|
def handle_graphql_errors(j):
|
||||||
@@ -131,23 +130,27 @@ def handle_graphql_errors(j):
|
|||||||
# TODO: Use `severity` and `description`
|
# TODO: Use `severity` and `description`
|
||||||
raise GraphQLError(
|
raise GraphQLError(
|
||||||
# TODO: What data is always available?
|
# TODO: What data is always available?
|
||||||
error.get("summary", "Unknown error"),
|
message=error.get("summary", "Unknown error"),
|
||||||
error.get("message", ""),
|
description=error.get("message", ""),
|
||||||
code=error.get("code"),
|
code=error.get("code"),
|
||||||
debug_info=error.get("debug_info"),
|
debug_info=error.get("debug_info"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def handle_http_error(code):
|
def handle_http_error(code):
|
||||||
msg = "Error sending request: Got {} response.".format(code)
|
|
||||||
if code == 404:
|
if code == 404:
|
||||||
raise HTTPError(
|
raise HTTPError(
|
||||||
msg + " This is either because you specified an invalid URL, or because"
|
"This might be because you provided an invalid id"
|
||||||
" you provided an invalid id (Facebook usually require integer ids)",
|
+ " (Facebook usually require integer ids)",
|
||||||
|
status_code=code,
|
||||||
|
)
|
||||||
|
if code == 500:
|
||||||
|
raise HTTPError(
|
||||||
|
"There is probably an error on the endpoint, or it might be rate limited",
|
||||||
status_code=code,
|
status_code=code,
|
||||||
)
|
)
|
||||||
if 400 <= code < 600:
|
if 400 <= code < 600:
|
||||||
raise HTTPError(msg, status_code=code)
|
raise HTTPError("Failed sending request", status_code=code)
|
||||||
|
|
||||||
|
|
||||||
def handle_requests_error(e):
|
def handle_requests_error(e):
|
||||||
|
@@ -202,7 +202,7 @@ class Session:
|
|||||||
else:
|
else:
|
||||||
code, msg = get_error_data(r.text, r.url)
|
code, msg = get_error_data(r.text, r.url)
|
||||||
raise _exception.ExternalError(
|
raise _exception.ExternalError(
|
||||||
"Login failed at url {}".format(r.url), msg, code=code
|
"Login failed at url {!r}".format(r.url), msg, code=code
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_logged_in(self):
|
def is_logged_in(self):
|
||||||
@@ -238,7 +238,7 @@ class Session:
|
|||||||
r = self._session.get(url, params={"ref": "mb", "h": logout_h})
|
r = self._session.get(url, params={"ref": "mb", "h": logout_h})
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
_exception.handle_requests_error(e)
|
_exception.handle_requests_error(e)
|
||||||
handle_http_error(r.status_code)
|
_exception.handle_http_error(r.status_code)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_session(cls, session):
|
def _from_session(cls, session):
|
||||||
@@ -367,6 +367,8 @@ class Session:
|
|||||||
data["ephemeral_ttl_mode:"] = "0"
|
data["ephemeral_ttl_mode:"] = "0"
|
||||||
j = self._post("/messaging/send/", data)
|
j = self._post("/messaging/send/", data)
|
||||||
|
|
||||||
|
_exception.handle_payload_error(j)
|
||||||
|
|
||||||
# update JS token if received in response
|
# update JS token if received in response
|
||||||
fb_dtsg = _util.get_jsmods_require(j, 2)
|
fb_dtsg = _util.get_jsmods_require(j, 2)
|
||||||
if fb_dtsg is not None:
|
if fb_dtsg is not None:
|
||||||
|
@@ -359,6 +359,9 @@ class ThreadABC(metaclass=abc.ABCMeta):
|
|||||||
_graphql.from_query_id("515216185516880", data)
|
_graphql.from_query_id("515216185516880", data)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not j[self.id]:
|
||||||
|
raise _exception.ParseError("Could not find images", data=j)
|
||||||
|
|
||||||
result = j[self.id]["message_shared_media"]
|
result = j[self.id]["message_shared_media"]
|
||||||
|
|
||||||
print(len(result["edges"]))
|
print(len(result["edges"]))
|
||||||
|
@@ -64,10 +64,10 @@ ERROR_DATA = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("exception,code,description,summary", ERROR_DATA)
|
@pytest.mark.parametrize("exception,code,summary,description", ERROR_DATA)
|
||||||
def test_handle_payload_error(exception, code, summary, description):
|
def test_handle_payload_error(exception, code, summary, description):
|
||||||
data = {"error": code, "errorSummary": summary, "errorDescription": description}
|
data = {"error": code, "errorSummary": summary, "errorDescription": description}
|
||||||
with pytest.raises(exception, match=r"Error sending request: #\d+"):
|
with pytest.raises(exception, match=r"#\d+ .+:"):
|
||||||
handle_payload_error(data)
|
handle_payload_error(data)
|
||||||
|
|
||||||
|
|
||||||
@@ -76,14 +76,14 @@ def test_handle_payload_error_no_error():
|
|||||||
assert handle_payload_error({"payload": {"abc": ["Something", "else"]}}) is None
|
assert handle_payload_error({"payload": {"abc": ["Something", "else"]}}) is None
|
||||||
|
|
||||||
|
|
||||||
def test_handle_graphql_errors():
|
def test_handle_graphql_crash():
|
||||||
error = {
|
error = {
|
||||||
"allow_user_retry": False,
|
"allow_user_retry": False,
|
||||||
"api_error_code": -1,
|
"api_error_code": -1,
|
||||||
"code": 1675030,
|
"code": 1675030,
|
||||||
"debug_info": None,
|
"debug_info": None,
|
||||||
"description": "Error performing query.",
|
"description": "Error performing query.",
|
||||||
"fbtrace_id": "CLkuLR752sB",
|
"fbtrace_id": "ABCDEFG",
|
||||||
"is_silent": False,
|
"is_silent": False,
|
||||||
"is_transient": False,
|
"is_transient": False,
|
||||||
"message": (
|
"message": (
|
||||||
@@ -98,11 +98,103 @@ def test_handle_graphql_errors():
|
|||||||
"summary": "Query error",
|
"summary": "Query error",
|
||||||
}
|
}
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
GraphQLError, match="Query error: #1675030, Errors while executing"
|
GraphQLError, match="#1675030 Query error: Errors while executing"
|
||||||
):
|
):
|
||||||
handle_graphql_errors({"data": {"message_thread": None}, "errors": [error]})
|
handle_graphql_errors({"data": {"message_thread": None}, "errors": [error]})
|
||||||
|
|
||||||
|
|
||||||
|
def test_handle_graphql_invalid_values():
|
||||||
|
error = {
|
||||||
|
"message": (
|
||||||
|
'Invalid values provided for variables of operation "MessengerThreadlist":'
|
||||||
|
' Value ""as"" cannot be used for variable "$limit": Expected an integer'
|
||||||
|
' value, got "as".'
|
||||||
|
),
|
||||||
|
"severity": "CRITICAL",
|
||||||
|
"code": 1675012,
|
||||||
|
"api_error_code": None,
|
||||||
|
"summary": "Your request couldn't be processed",
|
||||||
|
"description": (
|
||||||
|
"There was a problem with this request."
|
||||||
|
" We're working on getting it fixed as soon as we can."
|
||||||
|
),
|
||||||
|
"is_silent": False,
|
||||||
|
"is_transient": False,
|
||||||
|
"requires_reauth": False,
|
||||||
|
"allow_user_retry": False,
|
||||||
|
"debug_info": None,
|
||||||
|
"query_path": None,
|
||||||
|
"fbtrace_id": "ABCDEFG",
|
||||||
|
"www_request_id": "AABBCCDDEEFFGG",
|
||||||
|
}
|
||||||
|
msg = "#1675012 Your request couldn't be processed: Invalid values"
|
||||||
|
with pytest.raises(GraphQLError, match=msg):
|
||||||
|
handle_graphql_errors({"errors": [error]})
|
||||||
|
|
||||||
|
|
||||||
|
def test_handle_graphql_no_message():
|
||||||
|
error = {
|
||||||
|
"code": 1675012,
|
||||||
|
"api_error_code": None,
|
||||||
|
"summary": "Your request couldn't be processed",
|
||||||
|
"description": (
|
||||||
|
"There was a problem with this request."
|
||||||
|
" We're working on getting it fixed as soon as we can."
|
||||||
|
),
|
||||||
|
"is_silent": False,
|
||||||
|
"is_transient": False,
|
||||||
|
"requires_reauth": False,
|
||||||
|
"allow_user_retry": False,
|
||||||
|
"debug_info": None,
|
||||||
|
"query_path": None,
|
||||||
|
"fbtrace_id": "ABCDEFG",
|
||||||
|
"www_request_id": "AABBCCDDEEFFGG",
|
||||||
|
"sentry_block_user_info": None,
|
||||||
|
"help_center_id": None,
|
||||||
|
}
|
||||||
|
msg = "#1675012 Your request couldn't be processed: "
|
||||||
|
with pytest.raises(GraphQLError, match=msg):
|
||||||
|
handle_graphql_errors({"errors": [error]})
|
||||||
|
|
||||||
|
|
||||||
|
def test_handle_graphql_no_summary():
|
||||||
|
error = {
|
||||||
|
"message": (
|
||||||
|
'Errors while executing operation "MessengerViewerContactMethods":'
|
||||||
|
" At Query.viewer:Viewer.all_emails: Field implementation threw an"
|
||||||
|
" exception. Check your server logs for more information."
|
||||||
|
),
|
||||||
|
"severity": "ERROR",
|
||||||
|
"path": ["viewer", "all_emails"],
|
||||||
|
}
|
||||||
|
with pytest.raises(GraphQLError, match="Unknown error: Errors while executing"):
|
||||||
|
handle_graphql_errors(
|
||||||
|
{"data": {"viewer": {"user": None, "all_emails": []}}, "errors": [error]}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_handle_graphql_syntax_error():
|
||||||
|
error = {
|
||||||
|
"code": 1675001,
|
||||||
|
"api_error_code": None,
|
||||||
|
"summary": "Query Syntax Error",
|
||||||
|
"description": "Syntax error.",
|
||||||
|
"is_silent": True,
|
||||||
|
"is_transient": False,
|
||||||
|
"requires_reauth": False,
|
||||||
|
"allow_user_retry": False,
|
||||||
|
"debug_info": 'Unexpected ">" at character 328: Expected ")".',
|
||||||
|
"query_path": None,
|
||||||
|
"fbtrace_id": "ABCDEFG",
|
||||||
|
"www_request_id": "AABBCCDDEEFFGG",
|
||||||
|
"sentry_block_user_info": None,
|
||||||
|
"help_center_id": None,
|
||||||
|
}
|
||||||
|
msg = "#1675001 Query Syntax Error: "
|
||||||
|
with pytest.raises(GraphQLError, match=msg):
|
||||||
|
handle_graphql_errors({"response": None, "error": error})
|
||||||
|
|
||||||
|
|
||||||
def test_handle_graphql_errors_singular_error_key():
|
def test_handle_graphql_errors_singular_error_key():
|
||||||
with pytest.raises(GraphQLError, match="#123"):
|
with pytest.raises(GraphQLError, match="#123"):
|
||||||
handle_graphql_errors({"error": {"code": 123}})
|
handle_graphql_errors({"error": {"code": 123}})
|
||||||
|
Reference in New Issue
Block a user