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

tag, untag an Item / ItemQuery object #733

Merged
merged 9 commits into from
Nov 30, 2023
41 changes: 41 additions & 0 deletions darwin/future/core/items/tag_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

from darwin.future.core.client import ClientCore
from darwin.future.core.types.common import JSONType
from darwin.future.data_objects.typing import UnknownType


def tag_items(
client: ClientCore,
team_slug: str,
dataset_ids: int | list[int],
tag_id: int,
filters: dict[str, UnknownType],
) -> JSONType:
"""
Adds tag annotation to all items slots matched by filters.

Args:
client (ClientCore): The Darwin Core client.
team_slug (str): The team slug.
dataset_ids (int | list[int]): The dataset ids.
saurbhc marked this conversation as resolved.
Show resolved Hide resolved
tag_id (int): The tag id.
filters Dict[str, UnknownType]: The parameters of the filter.

Returns:
JSONType: The response data.
"""
assert (
filters
), "No parameters provided, please provide at least one non-dataset id filter"
payload = {
"filters": {
"dataset_ids": dataset_ids
if isinstance(dataset_ids, list)
else [dataset_ids],
**filters,
},
"annotation_class_id": tag_id,
}

return client.post(f"/v2/teams/{team_slug}/items/slots/tags", data=payload)
42 changes: 42 additions & 0 deletions darwin/future/core/items/untag_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

from darwin.future.core.client import ClientCore
from darwin.future.core.types.common import JSONType
from darwin.future.data_objects.typing import UnknownType


def untag_items(
client: ClientCore,
team_slug: str,
dataset_ids: int | list[int],
tag_id: int,
filters: dict[str, UnknownType],
) -> JSONType:
"""
Untags items slots matched by filters.

Args:
client (ClientCore): The Darwin Core client.
team_slug (str): The team slug.
dataset_ids (int | list[int]): The dataset ids.
saurbhc marked this conversation as resolved.
Show resolved Hide resolved
tag_id (int): The tag id.

filters Dict[str, UnknownType]: The parameters of the filter.

Returns:
JSONType: The response data.
"""
assert (
filters
), "No parameters provided, please provide at least one non-dataset id filter"
payload = {
"filters": {
"dataset_ids": dataset_ids
if isinstance(dataset_ids, list)
else [dataset_ids],
**filters,
},
"annotation_class_id": tag_id,
}

return client.delete(f"/v2/teams/{team_slug}/items/slots/tags", data=payload)
31 changes: 31 additions & 0 deletions darwin/future/meta/objects/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from darwin.future.core.items.move_items_to_folder import move_list_of_items_to_folder
from darwin.future.core.items.restore_items import restore_list_of_items
from darwin.future.core.items.set_item_priority import set_item_priority
from darwin.future.core.items.tag_items import tag_items
from darwin.future.core.items.untag_items import untag_items
from darwin.future.data_objects.item import ItemCore, ItemLayout, ItemSlot
from darwin.future.exceptions import BadRequest
from darwin.future.meta.objects.base import MetaBase


Expand Down Expand Up @@ -105,6 +108,34 @@ def archive(self) -> None:
filters = {"item_ids": [str(self.id)]}
archive_list_of_items(self.client, team_slug, dataset_id, filters)

def tag(self, tag_id: int) -> None:
team_slug, dataset_id = (
self.meta_params["team_slug"],
self.meta_params["dataset_id"]
if "dataset_id" in self.meta_params
else self.meta_params["dataset_ids"],
)
assert isinstance(team_slug, str)
if not isinstance(tag_id, int):
raise BadRequest(f"tag_id must be an integer, got {type(tag_id)}")
dataset_id = cast(Union[int, List[int]], dataset_id)
filters = {"item_ids": [str(self.id)]}
tag_items(self.client, team_slug, dataset_id, tag_id, filters)

def untag(self, tag_id: int) -> None:
team_slug, dataset_id = (
self.meta_params["team_slug"],
self.meta_params["dataset_id"]
if "dataset_id" in self.meta_params
else self.meta_params["dataset_ids"],
)
assert isinstance(team_slug, str)
if not isinstance(tag_id, int):
raise BadRequest(f"tag_id must be an integer, got {type(tag_id)}")
dataset_id = cast(Union[int, List[int]], dataset_id)
filters = {"item_ids": [str(self.id)]}
untag_items(self.client, team_slug, dataset_id, tag_id, filters)

@property
def name(self) -> str:
return self._element.name
Expand Down
51 changes: 50 additions & 1 deletion darwin/future/meta/queries/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
from darwin.future.core.items.delete_items import delete_list_of_items
from darwin.future.core.items.get import list_items
from darwin.future.core.items.move_items_to_folder import move_list_of_items_to_folder
from darwin.future.core.items.set_item_priority import set_item_priority
from darwin.future.core.items.restore_items import restore_list_of_items
from darwin.future.core.items.set_item_priority import set_item_priority
from darwin.future.core.items.tag_items import tag_items
from darwin.future.core.items.untag_items import untag_items
from darwin.future.core.types.common import QueryString
from darwin.future.core.types.query import PaginatedQuery
from darwin.future.exceptions import BadRequest
from darwin.future.meta.objects.item import Item


Expand Down Expand Up @@ -143,3 +146,49 @@ def archive(self) -> None:
ids = [item.id for item in self]
filters = {"item_ids": [str(item) for item in ids]}
archive_list_of_items(self.client, team_slug, dataset_ids, filters)

def tag(self, tag_id: int) -> None:
if "team_slug" not in self.meta_params:
raise ValueError("Must specify team_slug to query items")
if (
"dataset_ids" not in self.meta_params
and "dataset_id" not in self.meta_params
):
raise ValueError("Must specify dataset_ids to query items")
saurbhc marked this conversation as resolved.
Show resolved Hide resolved
if not tag_id:
raise ValueError("Must specify tag_id to tag items with")
if not isinstance(tag_id, int):
raise BadRequest(f"tag_id must be an integer, got {type(tag_id)}")
dataset_ids = (
self.meta_params["dataset_ids"]
if "dataset_ids" in self.meta_params
else self.meta_params["dataset_id"]
)
team_slug = self.meta_params["team_slug"]
self.collect_all()
ids = [item.id for item in self]
filters = {"item_ids": [str(item) for item in ids]}
tag_items(self.client, team_slug, dataset_ids, tag_id, filters)

def untag(self, tag_id: int) -> None:
if "team_slug" not in self.meta_params:
raise ValueError("Must specify team_slug to query items")
if (
"dataset_ids" not in self.meta_params
and "dataset_id" not in self.meta_params
):
raise ValueError("Must specify dataset_ids to query items")
saurbhc marked this conversation as resolved.
Show resolved Hide resolved
if not tag_id:
raise ValueError("Must specify tag_id to untag items with")
if not isinstance(tag_id, int):
raise BadRequest(f"tag_id must be an integer, got {type(tag_id)}")
dataset_ids = (
self.meta_params["dataset_ids"]
if "dataset_ids" in self.meta_params
else self.meta_params["dataset_id"]
)
team_slug = self.meta_params["team_slug"]
self.collect_all()
ids = [item.id for item in self]
filters = {"item_ids": [str(item) for item in ids]}
untag_items(self.client, team_slug, dataset_ids, tag_id, filters)
94 changes: 94 additions & 0 deletions darwin/future/tests/core/items/test_tag_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pytest
import responses

from darwin.future.core.client import ClientCore
from darwin.future.core.items.tag_items import tag_items
from darwin.future.exceptions import BadRequest
from darwin.future.tests.core.fixtures import *


@responses.activate
def test_tag_items(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = 123456
item_ids = [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002",
]
filters = {"item_ids": item_ids}

responses.add(
responses.POST,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"created_commands": 2},
status=200,
)

response = tag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)

assert response == {"created_commands": 2}
saurbhc marked this conversation as resolved.
Show resolved Hide resolved


@responses.activate
def test_tag_items_empty_filters_error(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = 123456
# this should raise an error as no filters are provided
filters = {}

responses.add(
responses.POST,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"created_commands": 2},
status=200,
)

with pytest.raises(AssertionError) as excinfo:
tag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)
(msg,) = excinfo.value.args
assert (
msg
== "No parameters provided, please provide at least one non-dataset id filter"
)


@responses.activate
def test_tag_items_bad_request_error(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = "123456"
item_ids = [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002",
]
filters = {"item_ids": item_ids}

responses.add(
responses.POST,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"error": "Bad Request"},
status=400,
)

with pytest.raises(BadRequest):
tag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)
94 changes: 94 additions & 0 deletions darwin/future/tests/core/items/test_untag_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pytest
import responses

from darwin.future.core.client import ClientCore
from darwin.future.core.items.untag_items import untag_items
from darwin.future.exceptions import BadRequest
from darwin.future.tests.core.fixtures import *


@responses.activate
def test_untag_items(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = 123456
item_ids = [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002",
]
filters = {"item_ids": item_ids}

responses.add(
responses.DELETE,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"created_commands": 2},
status=200,
)

response = untag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)

assert response == {"created_commands": 2}
saurbhc marked this conversation as resolved.
Show resolved Hide resolved


@responses.activate
def test_untag_items_empty_filters_error(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = 123456
# this should raise an error as no filters are provided
filters = {}

responses.add(
responses.DELETE,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"created_commands": 2},
status=200,
)

with pytest.raises(AssertionError) as excinfo:
untag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)
(msg,) = excinfo.value.args
assert (
msg
== "No parameters provided, please provide at least one non-dataset id filter"
)


@responses.activate
def test_untag_items_bad_request_error(base_client: ClientCore) -> None:
team_slug = "test-team"
dataset_ids = [1, 2, 3]
tag_id = "123456"
item_ids = [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002",
]
filters = {"item_ids": item_ids}

responses.add(
responses.DELETE,
base_client.config.api_endpoint + "v2/teams/test-team/items/slots/tags",
json={"error": "Bad Request"},
status=400,
)

with pytest.raises(BadRequest):
untag_items(
client=base_client,
team_slug=team_slug,
dataset_ids=dataset_ids,
tag_id=tag_id,
filters=filters,
)
Loading
Loading