Coverage for datacite/datacite.py: 100%
37 statements
« prev ^ index » next coverage.py v7.10.1, created at 2025-07-29 15:38 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2025-07-29 15:38 +0000
1import logging
2from typing import Any
4import humps
5import requests
6from django.conf import settings
7from requests.auth import HTTPBasicAuth
9# Specific User-Agent is asked by Datacite for contacting the client in case
10# of abuse: https://support.datacite.org/docs/api#api-versions
11DATACITE_USER_AGENT = f"Dalima ({settings.DC_URL}; mailto:{settings.DC_MAIL})"
13logger = logging.getLogger(__name__)
16class DataciteRESTClient:
17 """
18 REST client for the Datacite API.
19 """
21 headers = {"User-Agent": DATACITE_USER_AGENT}
22 authentication = HTTPBasicAuth(settings.DATACITE_USER, settings.DATACITE_PASSWORD)
23 base_url = settings.DATACITE_BASE_URL
25 def __init__(
26 self,
27 base_url: str | None = None,
28 user: str | None = None,
29 password: str | None = None,
30 ) -> None:
31 if user and password:
32 self.authentication = HTTPBasicAuth(user, password)
33 if base_url:
34 self.base_url = base_url
36 def get_doi_metadata(self, doi: str = "", params: dict | None = None) -> Any:
37 """
38 Get the metadata associated to the given DOI from Datacite database
39 :param doi: DOI to query
40 :param params: parameters to the query
41 :return: metadata of the given DOI or None if it could not be fetched
42 """
43 resp = requests.get(
44 url=self.base_url + "dois/" + doi,
45 params=params,
46 headers=self.headers,
47 timeout=settings.DATACITE_TIMEOUT,
48 auth=self.authentication,
49 )
50 if resp.status_code == requests.codes.ok:
51 logger.info(
52 "Fetched metadata for %s from Datacite.", doi if doi else "__all__"
53 )
54 return humps.decamelize(resp.json()["data"])
55 logger.warning(
56 "Failed to fetched metadata for %s from Datacite.",
57 doi if doi else "__all__",
58 )
59 return None
61 def get_metadata_of_doi_list(
62 self, doi_list: list, params: dict | None = None
63 ) -> list:
64 """
65 Get the metadata the DOIs of the given list from Datacite database
66 :param doi_list: list of DOI to query
67 :param params: parameters to the query
68 :return: the list of metadata of the given DOI list.
69 If none was fetched, it is not included
70 """
71 metadata_list: list = []
72 for doi in doi_list:
73 if not doi:
74 continue
75 doi_metadata = self.get_doi_metadata(doi, params)
76 if doi_metadata is not None:
77 metadata_list.append(doi_metadata)
78 return metadata_list
80 def upsert_doi(
81 self,
82 doi: str,
83 doi_metadata: dict,
84 params: dict | None = None,
85 ) -> Any:
86 """
87 Creates or updates a DOI in the Datacite database with the given metadata
88 and parameters
89 :param doi: doi to modify. If None, it will create one.
90 :param doi_metadata: doi metadata to insert into the Datacite database
91 :param params: parameters for the requests
92 :return: the dictionary of the response or none if status code != 200 or 201.
93 """
94 resp = requests.put(
95 url=self.base_url + "dois/" + doi,
96 json={
97 "data": {
98 "type": "dois",
99 "attributes": humps.camelize(doi_metadata),
100 }
101 },
102 params=params,
103 headers=self.headers,
104 timeout=settings.DATACITE_TIMEOUT,
105 auth=self.authentication,
106 )
107 resp.raise_for_status()
109 return humps.decamelize(resp.json()["data"])