Skip to content

Commit a8a9b01

Browse files
author
Konstantinos Bairaktaris
committed
Refactor transifex.api's exceptions for down/uploads
Previously, for uploads and downloads we could get a "successful" response that includes an error report for a download or upload. This means that as far as {json:api} semantics go, no error has happened. However, we intercepted this response and raised it as if it was a {json:api} exception. This raising was buggy because it didn't use the `JsonApiException.new` invocation (and thus can't be captured with `JsonApiException.get`) and also it didn't have the third required argument which was the response. Instead of fixing the aforementioned bugs however, we decided to implement new exception classes in `transifex.api` (which is the SDK itself, as opposed to `transifex.api.jsonapi` which is the "SDK library"). This makes it clearer to the user that as far as the {json:api} semantics are concerned, no error has occured. The problem is that the download or upload "job"'s status (which was successfully retrieved) is reporting an error. The new exception classes give priority to their first argument which is the 'detail' field of the first error included in the response. The rest of the errors, if any, will be accessible from the exception's second argument. Keep in mind that at the time of writing, Transifex APIv3 will only include one error in the case of an unsuccessful upload or download.
1 parent 5fd1f97 commit a8a9b01

2 files changed

Lines changed: 46 additions & 21 deletions

File tree

transifex/api/__init__.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import transifex
44

5+
from .exceptions import DownloadException, UploadException
56
from .jsonapi import JsonApi
67
from .jsonapi import Resource as JsonApiResource
7-
from .jsonapi.exceptions import JsonApiException
88

99

1010
class DownloadMixin(object):
@@ -19,16 +19,11 @@ def download(cls, interval=5, *args, **kwargs):
1919
download = cls.create(*args, **kwargs)
2020
while True:
2121
if hasattr(download, "errors") and len(download.errors) > 0:
22-
errors = [
23-
{
24-
"code": e["code"],
25-
"detail": e["detail"],
26-
"title": e["detail"],
27-
"status": "409",
28-
}
29-
for e in download.errors
30-
]
31-
raise JsonApiException(409, errors)
22+
# The way Transifex APIv3 works right now, only one error will be
23+
# returned, so we give priority to the first error's 'detail' field. If
24+
# more errors are included in the future, the user can inspect the
25+
# exception's second argument
26+
raise DownloadException(download.error[0]["detail"], download.errors)
3227
if download.redirect:
3328
return download.redirect
3429
time.sleep(interval)
@@ -54,16 +49,11 @@ def upload(cls, content, interval=5, **data):
5449

5550
while True:
5651
if hasattr(upload, "errors") and len(upload.errors) > 0:
57-
errors = [
58-
{
59-
"code": e["code"],
60-
"detail": e["detail"],
61-
"title": e["detail"],
62-
"status": "409",
63-
}
64-
for e in upload.errors
65-
]
66-
raise JsonApiException(409, errors)
52+
# The way Transifex APIv3 works right now, only one error will be
53+
# returned, so we give priority to the first error's 'detail' field. If
54+
# more errors are included in the future, the user can inspect the
55+
# exception's second argument
56+
raise UploadException(upload.errors[0]["detail"], upload.errors)
6757

6858
if upload.redirect:
6959
return upload.follow()

transifex/api/exceptions.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class FileExchangeException(Exception):
2+
def __init__(self, message, errors):
3+
super().__init__(message, errors)
4+
5+
@property
6+
def message(self):
7+
return self.args[0]
8+
9+
@property
10+
def errors(self):
11+
return self.args[1]
12+
13+
def __str__(self):
14+
"""We expect Transifex APIv3 to only return one error during a file exchange.
15+
Even though for future compatibility we include the full list of errors in the
16+
exception objects, we override 'str' so that if someone does:
17+
18+
>>> try:
19+
... transifex_api.ResourceStringsAsyncUpload(...)
20+
... except UploadException as e:
21+
... print(f"Upload error: {e}")
22+
23+
We want the first error's 'detail' field to appear. The full error list
24+
can still be accessed via the second argument.
25+
"""
26+
27+
return self.message
28+
29+
30+
class DownloadException(FileExchangeException):
31+
pass
32+
33+
34+
class UploadException(FileExchangeException):
35+
pass

0 commit comments

Comments
 (0)