Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding archive and delete endpoints #59

Merged
merged 3 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc_template/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Configuration file for the Sphinx documentation builder."""

#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
Expand Down
1 change: 1 addition & 0 deletions src/aind_codeocean_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
"""Python wrapper of CodeOcean's REST API"""

__version__ = "0.4.1"
50 changes: 50 additions & 0 deletions src/aind_codeocean_api/codeocean.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Module to interface with Code Ocean's backend.
"""

import json
import logging
from enum import Enum
Expand All @@ -23,6 +24,7 @@ class CodeOceanClient:
class _URLStrings(Enum):
"""Enum class for CodeOcean's url strings"""

ARCHIVE = "archive"
CAPSULES = "capsules"
COMPUTATIONS = "computations"
DATA_ASSETS = "data_assets"
Expand Down Expand Up @@ -553,3 +555,51 @@ def update_permissions(
)
response = requests.post(url, json=permissions, auth=(self.token, ""))
return response

def archive_data_asset(
self, data_asset_id: str, archive: bool = True
) -> requests.models.Response:
"""
This will archive or unarchive a data asset using a PATCH request to
the Code Ocean API.

Parameters
---------------
data_asset_id : string
ID of the data asset

Returns
---------------
requests.models.Response
"""

url = (
f"{self.asset_url}/{data_asset_id}/"
f"{self._URLStrings.ARCHIVE.value}"
)
response = requests.patch(
url, params={"archive": archive}, auth=(self.token, "")
)
return response

def delete_data_asset(
self, data_asset_id: str
) -> requests.models.Response:
"""
This will delete a data asset using a DELETE request to the Code Ocean
API.

Parameters
---------------
data_asset_id : string
ID of the data asset

Returns
---------------
requests.models.Response
"""

url = f"{self.asset_url}/{data_asset_id}"

response = requests.delete(url, auth=(self.token, ""))
return response
1 change: 1 addition & 0 deletions src/aind_codeocean_api/credentials.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Basic CodeOcean Credentials Handling."""

import functools
import json
import os
Expand Down
74 changes: 74 additions & 0 deletions tests/test_codeocean_requests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tests CodeOcean API python interface"""

import json
import unittest
from typing import Any, Callable, List
Expand Down Expand Up @@ -85,11 +86,29 @@ def request_put_response(url: str, json: dict) -> MockResponse:
status_code=200, content=success_message, url=url
)

def request_patch_response(url: str) -> MockResponse:
"""Mock a patch response"""
success_message = map_input_to_success_message(url)
return MockResponse(
status_code=202, content=success_message, url=url
)

def request_delete_response(url: str) -> MockResponse:
"""Mock a delete response"""
success_message = map_input_to_success_message(url)
return MockResponse(
status_code=204, content=success_message, url=url
)

# TODO: Change these to enums
if req_type == "post":
return request_post_response
elif req_type == "get":
return request_get_response
elif req_type == "patch":
return request_patch_response
elif req_type == "delete":
return request_delete_response
else:
return request_put_response

Expand Down Expand Up @@ -990,6 +1009,61 @@ def request_post_response(json: dict) -> MockResponse:
)
self.assertEqual(response.status_code, 204)

@mock.patch("requests.patch")
def test_archive_data_asset(
self, mock_api_patch: unittest.mock.MagicMock
) -> None:
"""Tests the response of archiving a data asset"""

def map_to_success_message(_) -> dict:
"""Map to a success message"""
return ""

mocked_success_patch = self.mock_success_response(
map_to_success_message, req_type="patch"
)

example_data_asset_id = "da8dd108-2a10-471d-82b9-1e671b107bf8"
expected_url = (
f"{self.co_client.asset_url}/"
"{example_data_asset_id}/archive?archive=True"
)

mock_api_patch.return_value = mocked_success_patch(url=expected_url)

response = self.co_client.archive_data_asset(
data_asset_id=example_data_asset_id, archive=True
)

self.assertEqual(response.url, expected_url)
self.assertEqual(response.status_code, 202)

@mock.patch("requests.delete")
def test_delete_data_asset(
self, mock_api_delete: unittest.mock.MagicMock
) -> None:
"""Tests the response of deleting a data asset"""

def map_to_success_message(_) -> dict:
"""Map to a success message"""
return ""

mocked_success_delete = self.mock_success_response(
map_to_success_message, req_type="delete"
)

example_data_asset_id = "da8dd108-2a10-471d-82b9-1e671b107bf8"
expected_url = f"{self.co_client.asset_url}/{example_data_asset_id}"

mock_api_delete.return_value = mocked_success_delete(url=expected_url)

response = self.co_client.delete_data_asset(
data_asset_id=example_data_asset_id
)

self.assertEqual(response.url, expected_url)
self.assertEqual(response.status_code, 204)


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions tests/test_credentials.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tests credentials loader."""

import json
import os
import unittest
Expand Down
Loading