in src/wagtail_localize_smartling/api/client.py [0:0]
def download_translations(self, *, job: "Job") -> Generator[ZipFile, None, None]:
# This is an unusual case where a successful response is a ZIP file,
# rather than JSON. JSON responses will be returned for errors.
url = urljoin(
self._base_url,
f"/files-api/v2/projects/{quote(job.project.project_id)}/locales/all/file/zip",
)
with requests.get(
url,
headers=self._headers,
params={
"fileUri": job.file_uri,
"retrievalType": "published",
"includeOriginalStrings": False,
},
stream=True,
timeout=smartling_settings.API_TIMEOUT_SECONDS,
) as response:
# Log consistently with other requests. Don't log the method and URL
# until we've initiated the request so it doesn't get interleaved
# with any auth requests triggered by generating the headers
logger.info("Smartling API request: GET %s", url)
logger.info(
"Smartling API response: %s %s",
response.status_code,
f"{response.elapsed.total_seconds()}s",
)
# Only 200 responses contain a ZIP file, everything else is an error
if response.status_code != 200:
try:
response_json = response.json()
except requests.exceptions.JSONDecodeError as e:
raise InvalidResponse(
f"Response was not valid JSON: {response.text}"
) from e
serializer = ResponseSerializer(data=response_json)
try:
serializer.is_valid(raise_exception=True)
except rest_framework.serializers.ValidationError as e:
raise InvalidResponse(
f"Response did not match expected format: {serializer.initial_data}" # noqa: E501
) from e
try:
response.raise_for_status()
except HTTPError as e:
code, errors = serializer.response_errors
raise FailedResponse(code=code, errors=errors) from e
# Ok, cool, the response body is a ZIP file
# TODO buffer to a temporary file instead of a BytesIO for large files
buffer = BytesIO()
for chunk in response.iter_content(chunk_size=8192):
buffer.write(chunk)
buffer.seek(0)
with ZipFile(buffer) as zf:
yield zf