Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/client.py
# Copyright (C) 2017-2020 The Software Heritage developers | # Copyright (C) 2017-2020 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
"""Module in charge of defining an swh-deposit client | """Module in charge of defining an swh-deposit client | ||||
""" | """ | ||||
import hashlib | import hashlib | ||||
import os | import os | ||||
import requests | import requests | ||||
import xmltodict | import xmltodict | ||||
import logging | import logging | ||||
from abc import ABCMeta, abstractmethod | from abc import ABCMeta, abstractmethod | ||||
from typing import Any, Dict | |||||
from urllib.parse import urljoin | from urllib.parse import urljoin | ||||
from swh.core.config import SWHConfig | from swh.core.config import SWHConfig | ||||
logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
class MaintenanceError(ValueError): | |||||
"""Informational maintenance error exception | |||||
""" | |||||
pass | |||||
def _parse(stream, encoding="utf-8"): | def _parse(stream, encoding="utf-8"): | ||||
"""Given a xml stream, parse the result. | """Given a xml stream, parse the result. | ||||
Args: | Args: | ||||
stream (bytes/text): The stream to parse | stream (bytes/text): The stream to parse | ||||
encoding (str): The encoding to use if to decode the bytes | encoding (str): The encoding to use if to decode the bytes | ||||
stream | stream | ||||
▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | def do_execute(self, method, url, info): | ||||
By default, execute a simple query to url with the http | By default, execute a simple query to url with the http | ||||
method. Override this in daughter class to improve the | method. Override this in daughter class to improve the | ||||
default behavior if needed. | default behavior if needed. | ||||
""" | """ | ||||
return self.do(method, url) | return self.do(method, url) | ||||
def execute(self, *args, **kwargs): | def execute(self, *args, **kwargs) -> Dict[str, Any]: | ||||
"""Main endpoint to prepare and execute the http query to the api. | """Main endpoint to prepare and execute the http query to the api. | ||||
Raises: | |||||
MaintenanceError if some api maintenance is happening. | |||||
Returns: | |||||
Dict of computed api data | |||||
""" | """ | ||||
url = self.compute_url(*args, **kwargs) | url = self.compute_url(*args, **kwargs) | ||||
method = self.compute_method(*args, **kwargs) | method = self.compute_method(*args, **kwargs) | ||||
info = self.compute_information(*args, **kwargs) | info = self.compute_information(*args, **kwargs) | ||||
try: | try: | ||||
r = self.do_execute(method, url, info) | r = self.do_execute(method, url, info) | ||||
except Exception as e: | except Exception as e: | ||||
msg = self.error_msg % (url, e) | msg = self.error_msg % (url, e) | ||||
r = self.empty_result | r = self.empty_result | ||||
r.update( | r.update( | ||||
{"error": msg,} | {"error": msg,} | ||||
) | ) | ||||
return r | return r | ||||
else: | else: | ||||
if r.ok: | if r.ok: | ||||
if int(r.status_code) == 204: # 204 returns no body | if int(r.status_code) == 204: # 204 returns no body | ||||
return {"status": r.status_code} | return {"status": r.status_code} | ||||
else: | else: | ||||
return self.parse_result_ok(r.text) | return self.parse_result_ok(r.text) | ||||
else: | else: | ||||
error = self.parse_result_error(r.text) | error = self.parse_result_error(r.text) | ||||
empty = self.empty_result | empty = self.empty_result | ||||
error.update(empty) | error.update(empty) | ||||
if r.status_code == 503: | |||||
summary = error.get("summary") | |||||
detail = error.get("sword:verboseDescription") | |||||
# Maintenance error | |||||
if summary and detail: | |||||
raise MaintenanceError(f"{summary}: {detail}") | |||||
error.update( | error.update( | ||||
{"status": r.status_code,} | {"status": r.status_code,} | ||||
) | ) | ||||
return error | return error | ||||
class ServiceDocumentDepositClient(BaseDepositClient): | class ServiceDocumentDepositClient(BaseDepositClient): | ||||
"""Service Document information retrieval. | """Service Document information retrieval. | ||||
▲ Show 20 Lines • Show All 325 Lines • Show Last 20 Lines |