diff --git a/darwin/future/core/client.py b/darwin/future/core/client.py index f2c7e9874..b80b81031 100644 --- a/darwin/future/core/client.py +++ b/darwin/future/core/client.py @@ -10,7 +10,12 @@ from requests.adapters import HTTPAdapter, Retry from darwin.future.core.types.common import JSONType, QueryString -from darwin.future.exceptions import NotFound, Unauthorized, UnprocessibleEntity +from darwin.future.exceptions import ( + BadRequest, + NotFound, + Unauthorized, + UnprocessibleEntity, +) class TeamsConfig(BaseModel): @@ -235,6 +240,8 @@ def raise_for_darwin_exception(response: requests.Response) -> None: """ if response.status_code == 200: return + if response.status_code == 400: + raise BadRequest(response) if response.status_code == 401: raise Unauthorized(response) if response.status_code == 404: diff --git a/darwin/future/core/items/move_items_to_folder.py b/darwin/future/core/items/move_items_to_folder.py new file mode 100644 index 000000000..1643b21c1 --- /dev/null +++ b/darwin/future/core/items/move_items_to_folder.py @@ -0,0 +1,48 @@ +from typing import Dict, List +from uuid import UUID + +from darwin.future.core.client import ClientCore +from darwin.future.core.types.common import JSONType +from darwin.future.data_objects.typing import UnknownType + + +def move_list_of_items_to_folder( + api_client: ClientCore, + team_slug: str, + dataset_id: int, + item_ids: List[UUID], + path: str, + filters: Dict[str, UnknownType] = {}, +) -> JSONType: + """ + Move specified items to a folder + + Parameters + ---------- + client: Client + The client to use for the request + team_slug: str + The slug of the team containing the items + dataset_id: int + The ID of the dataset containing the items + item_ids: List[UUID] + The IDs of the items to be moved + path: str + The path to the folder to move the items to + filters: Dict[str, UnknownType] + Dataset filter parameters + + Returns + ------- + JSONType + """ + payload = { + "filters": { + "dataset_ids": [dataset_id], + "item_ids": [str(item_id) for item_id in item_ids], + **filters, + }, + "path": path, + } + + return api_client.post(f"/v2/teams/{team_slug}/items/path", data=payload) diff --git a/darwin/future/exceptions.py b/darwin/future/exceptions.py index 0a77bada2..39da4b186 100644 --- a/darwin/future/exceptions.py +++ b/darwin/future/exceptions.py @@ -2,6 +2,7 @@ from typing import Optional, Sequence + from darwin.future.data_objects.typing import KeyValuePairDict, UnknownType @@ -107,6 +108,10 @@ class UnrecognizableFileEncoding(DarwinException): pass +class BadRequest(DarwinException): + pass + + class MissingSlug(DarwinException): pass diff --git a/darwin/future/tests/core/datasets/test_create_dataset.py b/darwin/future/tests/core/datasets/test_create_dataset.py index 26630ac44..af9268665 100644 --- a/darwin/future/tests/core/datasets/test_create_dataset.py +++ b/darwin/future/tests/core/datasets/test_create_dataset.py @@ -1,10 +1,10 @@ import responses from pytest import raises -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.datasets import create_dataset from darwin.future.data_objects.dataset import DatasetCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * # noqa: F401, F403 from .fixtures import * # noqa: F401, F403 @@ -29,7 +29,7 @@ def test_it_creates_a_dataset( def test_it_raises_an_error_on_http_error( basic_dataset: DatasetCore, base_client: ClientCore ) -> None: - with raises(HTTPError): + with raises(BadRequest): with responses.RequestsMock() as rsps: rsps.add( rsps.POST, diff --git a/darwin/future/tests/core/datasets/test_delete_dataset.py b/darwin/future/tests/core/datasets/test_delete_dataset.py index f93eeeb01..4008b0fe8 100644 --- a/darwin/future/tests/core/datasets/test_delete_dataset.py +++ b/darwin/future/tests/core/datasets/test_delete_dataset.py @@ -1,9 +1,9 @@ import responses from pytest import raises -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.datasets import remove_dataset +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * from .fixtures import * @@ -26,7 +26,7 @@ def test_it_deletes_a_dataset(base_client: ClientCore) -> None: def test_it_throws_http_errors_returned_by_the_client(base_client: ClientCore) -> None: - with raises(HTTPError): + with raises(BadRequest): with responses.RequestsMock() as rsps: rsps.add( rsps.PUT, diff --git a/darwin/future/tests/core/datasets/test_get_dataset.py b/darwin/future/tests/core/datasets/test_get_dataset.py index 7fbe51d73..926df7123 100644 --- a/darwin/future/tests/core/datasets/test_get_dataset.py +++ b/darwin/future/tests/core/datasets/test_get_dataset.py @@ -1,11 +1,11 @@ import responses from pydantic import ValidationError from pytest import raises -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.datasets import get_dataset from darwin.future.data_objects.dataset import DatasetCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * from .fixtures import * @@ -34,7 +34,7 @@ def test_it_raises_an_error_on_http_error(base_client: ClientCore) -> None: json={}, status=400, ) - with raises(HTTPError): + with raises(BadRequest): get_dataset(base_client, "test-dataset") get_dataset(base_client, "test-dataset") diff --git a/darwin/future/tests/core/datasets/test_list_datasets.py b/darwin/future/tests/core/datasets/test_list_datasets.py index dcc84530a..4de7fa065 100644 --- a/darwin/future/tests/core/datasets/test_list_datasets.py +++ b/darwin/future/tests/core/datasets/test_list_datasets.py @@ -2,11 +2,11 @@ import pytest import responses -from requests.exceptions import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.datasets import list_datasets from darwin.future.data_objects.dataset import DatasetCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * from .fixtures import * @@ -42,7 +42,7 @@ def test_it_returns_an_error_if_the_client_returns_an_http_error( json={}, status=400, ) - with pytest.raises(HTTPError) as execinfo: + with pytest.raises(BadRequest) as execinfo: list_datasets(base_client) - assert execinfo.value.response.status_code == 400 # type: ignore + assert execinfo.value.args[0].status_code == 400 # type: ignore diff --git a/darwin/future/tests/core/items/test_move_items_to_folder.py b/darwin/future/tests/core/items/test_move_items_to_folder.py new file mode 100644 index 000000000..66a11e728 --- /dev/null +++ b/darwin/future/tests/core/items/test_move_items_to_folder.py @@ -0,0 +1,63 @@ +from uuid import UUID + +import responses +from pytest import raises + +from darwin.future.core.client import ClientCore +from darwin.future.core.items.move_items_to_folder import move_list_of_items_to_folder +from darwin.future.exceptions import BadRequest +from darwin.future.tests.core.fixtures import * + + +@responses.activate +def test_move_list_of_items_to_folder_including_filters( + base_client: ClientCore, +) -> None: + # Define the expected response + responses.add( + responses.POST, + base_client.config.api_endpoint + "v2/teams/test-team/items/path", + json={"affected_item_count": 2}, + ) + + # Call the function + response = move_list_of_items_to_folder( + api_client=base_client, + team_slug="test-team", + dataset_id=000000, + item_ids=[ + UUID("00000000-0000-0000-0000-000000000000"), + UUID("00000000-0000-0000-0000-000000000000"), + ], + filters={ + "not_statuses": ["uploading", "annotate"], + "not_assignees": [123, 456, 789], + }, + path="/test/path", + ) + + # Check that the response mathces what we expect + assert response == {"affected_item_count": 2} + + +def test_move_list_of_items_to_folder_with_error_response( + base_client: ClientCore, +) -> None: + with raises(BadRequest): + with responses.RequestsMock() as rsps: + rsps.add( + responses.POST, + base_client.config.api_endpoint + "v2/teams/test-team/items/path", + status=400, + ) + + move_list_of_items_to_folder( + api_client=base_client, + team_slug="test-team", + dataset_id=000000, + item_ids=[ + UUID("00000000-0000-0000-0000-000000000000"), + UUID("00000000-0000-0000-0000-000000000000"), + ], + path="/test/path", + ) diff --git a/darwin/future/tests/core/workflows/test_get_workflow.py b/darwin/future/tests/core/workflows/test_get_workflow.py index b073c0002..36d6923a1 100644 --- a/darwin/future/tests/core/workflows/test_get_workflow.py +++ b/darwin/future/tests/core/workflows/test_get_workflow.py @@ -1,12 +1,12 @@ import responses from pydantic import ValidationError from pytest import raises -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.types.common import JSONType from darwin.future.core.workflows import get_workflow from darwin.future.data_objects.workflow import WorkflowCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * @@ -84,5 +84,5 @@ def test_get_workflows_with_error(base_client: ClientCore) -> None: status=400 ) # fmt: on - with raises(HTTPError): + with raises(BadRequest): get_workflow(base_client, NON_EXISTENT_ID) diff --git a/darwin/future/tests/core/workflows/test_get_workflows.py b/darwin/future/tests/core/workflows/test_get_workflows.py index 9400c3658..aef85afea 100644 --- a/darwin/future/tests/core/workflows/test_get_workflows.py +++ b/darwin/future/tests/core/workflows/test_get_workflows.py @@ -3,12 +3,12 @@ import pytest import responses from pydantic import ValidationError -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.types.common import JSONType from darwin.future.core.workflows import get_workflows from darwin.future.data_objects.workflow import WorkflowCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * @@ -81,5 +81,5 @@ def test_get_workflows_with_error(base_client: ClientCore) -> None: ) # Call the function being tested - with pytest.raises(HTTPError): + with pytest.raises(BadRequest): get_workflows(base_client) diff --git a/darwin/future/tests/core/workflows/test_list_workflows.py b/darwin/future/tests/core/workflows/test_list_workflows.py index 23daf0ace..167c0799c 100644 --- a/darwin/future/tests/core/workflows/test_list_workflows.py +++ b/darwin/future/tests/core/workflows/test_list_workflows.py @@ -2,12 +2,12 @@ import responses from pydantic import ValidationError -from requests import HTTPError from darwin.future.core.client import ClientCore from darwin.future.core.types.common import JSONType from darwin.future.core.workflows import list_workflows from darwin.future.data_objects.workflow import WorkflowCore +from darwin.future.exceptions import BadRequest from darwin.future.tests.core.fixtures import * @@ -93,6 +93,6 @@ def test_list_workflows_with_error(base_client: ClientCore) -> None: assert isinstance(exceptions, List) assert len(exceptions) == 1 - assert isinstance(exceptions[0], HTTPError) + assert isinstance(exceptions[0], BadRequest) assert not workflows