Skip to content

Commit

Permalink
fix jsonData passed to false kwarg
Browse files Browse the repository at this point in the history
  • Loading branch information
JR-1991 committed Jul 19, 2024
1 parent 3b6fe06 commit d2c890b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
42 changes: 38 additions & 4 deletions pyDataverse/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,28 @@ def post_request(self, url, data=None, auth=False, params=None, files=None):
if self.api_token:
params["key"] = self.api_token


if isinstance(data, str):
data = json.loads(data)

# Decide whether to use 'data' or 'json' args
request_params = self._check_json_data_form(data)

if self.client is None:
return self._sync_request(
method=httpx.post,
url=url,
json=data,
params=params,
files=files,
**request_params
)
else:
return self._async_request(
method=self.client.post,
url=url,
json=data,
params=params,
files=files,
**request_params,
)

def put_request(self, url, data=None, auth=False, params=None):
Expand Down Expand Up @@ -216,19 +220,22 @@ def put_request(self, url, data=None, auth=False, params=None):
if isinstance(data, str):
data = json.loads(data)

# Decide whether to use 'data' or 'json' args
request_params = self._check_json_data_form(data)

if self.client is None:
return self._sync_request(
method=httpx.put,
url=url,
json=data,
params=params,
**request_params,
)
else:
return self._async_request(
method=self.client.put,
url=url,
json=data,
params=params,
**request_params,
)

def delete_request(self, url, auth=False, params=None):
Expand Down Expand Up @@ -268,6 +275,33 @@ def delete_request(self, url, auth=False, params=None):
params=params,
)

@staticmethod
def _check_json_data_form(data: Optional[Dict]):
"""This method checks and distributes given payload to match Dataverse expectations.
In the case of the form-data keyed by "jsonData", Dataverse expects
the payload as a string in a form of a dictionary. This is not possible
using HTTPXs json parameter, so we need to handle this case separately.
"""

if not data:
return {}
elif not isinstance(data, dict):
raise ValueError("Data must be a dictionary.")
elif "jsonData" not in data:
return {"json": data}

assert list(data.keys()) == ["jsonData"], (
"jsonData must be the only key in the dictionary."
)

# Content of JSON data should ideally be a string
content = data["jsonData"]
if not isinstance(content, str):
data["jsonData"] = json.dumps(content)

return {"data": data}

def _sync_request(
self,
method,
Expand Down
33 changes: 33 additions & 0 deletions tests/api/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def test_file_replacement(self):
"description": "My description.",
"categories": ["Data"],
"forceReplace": False,
"directoryLabel": "some/other",
}

response = api.replace_datafile(
Expand All @@ -152,12 +153,17 @@ def test_file_replacement(self):

# Assert
replaced_id = self._get_file_id(BASE_URL, API_TOKEN, pid)
file_metadata = self._get_file_metadata(BASE_URL, API_TOKEN, replaced_id)
data_file = file_metadata["dataFile"]
replaced_content = self._fetch_datafile_content(
BASE_URL,
API_TOKEN,
replaced_id,
)

assert data_file["description"] == "My description.", "Description does not match."
assert data_file["categories"] == ["Data"], "Categories do not match."
assert file_metadata["directoryLabel"] == "some/other", "Directory label does not match."
assert response.status_code == 200, "File replacement failed."
assert (
replaced_content == mutated
Expand Down Expand Up @@ -246,3 +252,30 @@ def _fetch_datafile_content(
response.raise_for_status()

return response.content.decode("utf-8")


@staticmethod
def _get_file_metadata(
BASE_URL: str,
API_TOKEN: str,
id: str,
):
"""
Retrieves the metadata for a file in Dataverse.
Args:
BASE_URL (str): The base URL of the Dataverse instance.
API_TOKEN (str): The API token for authentication.
id (str): The ID of the file.
Returns:
dict: The metadata for the file.
"""
response = httpx.get(
url=f"{BASE_URL}/api/files/{id}",
headers={"X-Dataverse-key": API_TOKEN},
)

response.raise_for_status()

return response.json()["data"]

0 comments on commit d2c890b

Please sign in to comment.