Skip to content
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
45 changes: 44 additions & 1 deletion src/superannotate/lib/app/interface/sdk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2903,7 +2903,7 @@ def list_items(
project: Union[NotEmptyStr, int],
folder: Optional[Union[NotEmptyStr, int]] = None,
*,
include: List[Literal["custom_metadata", "category"]] = None,
include: List[Literal["custom_metadata", "categories"]] = None,
**filters,
):
"""
Expand All @@ -2923,6 +2923,7 @@ def list_items(
Possible values are

- "custom_metadata": Includes custom metadata attached to the item.
- "categories": Includes categories attached to the item.
:type include: list of str, optional

:param filters: Specifies filtering criteria (e.g., name, ID, annotation status),
Expand Down Expand Up @@ -2993,6 +2994,40 @@ def list_items(
}
]

Request Example with include categories:
::

client.list_items(
project="My Multimodal",
folder="folder1",
include=["categories"]
)

Response Example:
::

[
{
"id": 48909383,
"name": "scan_123.jpeg",
"path": "Medical Annotations/folder1",
"url": "https://sa-public-files.s3.../scan_123.jpeg",
"annotation_status": "InProgress",
"createdAt": "2022-02-10T14:32:21.000Z",
"updatedAt": "2022-02-15T20:46:44.000Z",
"entropy_value": None,
"assignments": [],
"categories": [
{
"createdAt": "2025-01-29T13:51:39.000Z",
"updatedAt": "2025-01-29T13:51:39.000Z",
"id": 328577,
"name": "my_category",
},
],
}
]

Additional Filter Examples:
::

Expand All @@ -3014,6 +3049,14 @@ def list_items(
if isinstance(project, int)
else self.controller.get_project(project)
)
if (
include
and "categories" in include
and project.type != ProjectType.MULTIMODAL.value
):
raise AppException(
"The 'categories' option in the 'include' field is only supported for Multimodal projects."
)
if folder is None:
folder = self.controller.get_folder(project, "root")
else:
Expand Down
17 changes: 17 additions & 0 deletions src/superannotate/lib/core/entities/items.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional

from lib.core.entities.base import BaseItemEntity
from lib.core.entities.base import TimedBaseModel
from lib.core.enums import ApprovalStatus
from lib.core.enums import ProjectType
from lib.core.pydantic_v1 import Extra
Expand All @@ -16,6 +17,21 @@ class Config:
extra = Extra.ignore


class MultiModalItemCategoryEntity(TimedBaseModel):
id: int = Field(None, alias="category_id")
name: str = Field(None, alias="category_name")

class Config:
extra = Extra.ignore


class MultiModalItemEntity(BaseItemEntity):
categories: Optional[list[MultiModalItemCategoryEntity]]

class Config:
extra = Extra.ignore


class VideoEntity(BaseItemEntity):
approval_status: Optional[ApprovalStatus] = Field(None)

Expand Down Expand Up @@ -51,4 +67,5 @@ class Config:
ProjectType.TILED: ImageEntity,
ProjectType.VIDEO: VideoEntity,
ProjectType.DOCUMENT: DocumentEntity,
ProjectType.MULTIMODAL: MultiModalItemEntity,
}
3 changes: 3 additions & 0 deletions src/superannotate/lib/core/usecases/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from lib.core.entities import ImageEntity
from lib.core.entities import ProjectEntity
from lib.core.entities import VideoEntity
from lib.core.entities.items import MultiModalItemEntity
from lib.core.exceptions import AppException
from lib.core.exceptions import AppValidationException
from lib.core.exceptions import BackendError
Expand Down Expand Up @@ -60,6 +61,8 @@ def serialize_item_entity(
return VideoEntity(**entity.dict(by_alias=True))
elif project.type == constants.ProjectType.DOCUMENT.value:
return DocumentEntity(**entity.dict(by_alias=True))
elif project.type == constants.ProjectType.MULTIMODAL.value:
return MultiModalItemEntity(**entity.dict(by_alias=True))
return entity


Expand Down