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
2 changes: 1 addition & 1 deletion requirements_extra.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Sphinx==6.1.3
Sphinx==6.2.1
Jinja2==3.1.2
tox==4.4.5
sphinx_rtd_theme==1.2.0
Expand Down
5 changes: 1 addition & 4 deletions src/superannotate/lib/app/interface/sdk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,7 @@ def search_annotation_classes(
response = self.controller.annotation_classes.list(condition)
if response.errors:
raise AppException(response.errors)
return [
i.dict(exclude={"attribute_groups": {"__all__": {"is_multiselect"}}})
for i in response.data
]
return response.data

def set_project_status(self, project: NotEmptyStr, status: PROJECT_STATUS):
"""Set project status
Expand Down
2 changes: 0 additions & 2 deletions src/superannotate/lib/core/entities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from lib.core.entities.project import UserEntity
from lib.core.entities.project import WorkflowEntity
from lib.core.entities.project_entities import BaseEntity
from lib.core.entities.project_entities import ImageInfoEntity
from lib.core.entities.project_entities import S3FileEntity

__all__ = [
Expand All @@ -44,7 +43,6 @@
"ConfigEntity",
"WorkflowEntity",
"FolderEntity",
"ImageInfoEntity",
"S3FileEntity",
"AnnotationClassEntity",
"TeamEntity",
Expand Down
7 changes: 3 additions & 4 deletions src/superannotate/lib/core/entities/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Attribute(TimedBaseModel):
name: Optional[StrictStr]

class Config:
extra = Extra.allow
extra = Extra.ignore

def __hash__(self):
return hash(f"{self.id}{self.group_id}{self.name}")
Expand All @@ -73,12 +73,11 @@ class AttributeGroup(TimedBaseModel):
group_type: Optional[GroupTypeEnum]
class_id: Optional[StrictInt]
name: Optional[StrictStr]
is_multiselect: Optional[bool]
attributes: Optional[List[Attribute]]
default_value: Any

class Config:
extra = Extra.allow
extra = Extra.ignore
use_enum_values = True

def __hash__(self):
Expand All @@ -97,7 +96,7 @@ def __hash__(self):
return hash(f"{self.id}{self.type}{self.name}")

class Config:
extra = Extra.allow
extra = Extra.ignore
json_encoders = {
HexColor: lambda v: v.__root__,
BaseTitledEnum: lambda v: v.value,
Expand Down
2 changes: 1 addition & 1 deletion src/superannotate/lib/core/entities/folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FolderEntity(TimedBaseModel):
status: Optional[FolderStatus]
project_id: Optional[int]
team_id: Optional[int]
is_root: Optional[bool] = (False,)
is_root: Optional[bool] = False
folder_users: Optional[List[dict]]
completedCount: Optional[int]

Expand Down
17 changes: 8 additions & 9 deletions src/superannotate/lib/core/entities/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@ def validate(cls, v: datetime):


class TimedBaseModel(BaseModel):
createdAt: Optional[StringDate] = Field(
None, alias="createdAt", description="Date of creation"
)
updatedAt: Optional[StringDate] = Field(
None, alias="updatedAt", description="Update date"
)
createdAt: Optional[StringDate] = None
updatedAt: Optional[StringDate] = None


class AttachmentEntity(BaseModel):
Expand All @@ -59,7 +55,10 @@ class WorkflowEntity(BaseModel):
className: Optional[str]
step: Optional[int]
tool: Optional[int]
attribute: List = (tuple(),)
attribute: List = tuple()

class Config:
extra = Extra.ignore

def __copy__(self):
return WorkflowEntity(step=self.step, tool=self.tool, attribute=self.attribute)
Expand Down Expand Up @@ -91,8 +90,8 @@ class Config:
class ProjectEntity(TimedBaseModel):
id: Optional[int]
team_id: Optional[int]
name: Optional[str]
type: Optional[ProjectType]
name: str
type: ProjectType
description: Optional[str]
instructions_link: Optional[str]
creator_id: Optional[str]
Expand Down
18 changes: 0 additions & 18 deletions src/superannotate/lib/core/entities/project_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,6 @@ def to_dict(self):
raise NotImplementedError


class ImageInfoEntity(BaseEntity):
def __init__(
self,
uuid=None,
width: float = None,
height: float = None,
):
super().__init__(uuid),
self.width = width
self.height = height

def to_dict(self):
return {
"width": self.width,
"height": self.height,
}


class S3FileEntity(BaseEntity):
def __init__(self, uuid, data, metadata: dict = None):
super().__init__(uuid)
Expand Down
6 changes: 5 additions & 1 deletion src/superannotate/lib/core/usecases/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ def __init__(
def execute(self):
response = self._service_provider.annotation_classes.list(self._condition)
if response.ok:
self._response.data = response.data
classes = [
entity.dict(by_alias=True, exclude_unset=True)
for entity in response.data
]
self._response.data = classes
else:
self._response.errors = response.error
return self._response
Expand Down
14 changes: 9 additions & 5 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
DATA_SET_PATH = Path(__file__).parent / "data_set"
sys.path.insert(0, str(LIB_PATH))

__all__ = ["DATA_SET_PATH"]

# from src.superannotate.lib.core import setup_logging
#
# logger = get_default_logger()
# logger.setLevel("DEBUG")
def compare_result(result: dict, expected: dict, ignore_keys: set = None):
for key in result:
if ignore_keys and key in ignore_keys:
continue
assert result[key] == expected[key]
return True


__all__ = ["DATA_SET_PATH", "compare_result"]
2 changes: 1 addition & 1 deletion tests/integration/classes/test_create_annotation_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_multi_select_to_checklist(self):
attribute_groups=[
{
"name": "test",
"is_multiselect": 1,
"group_type": "checklist",
"attributes": [{"name": "Car"}, {"name": "Track"}, {"name": "Bus"}],
}
],
Expand Down
10 changes: 10 additions & 0 deletions tests/integration/folders/test_get_folder_metadata.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from src.superannotate import AppException
from src.superannotate import SAClient
from tests import compare_result
from tests.integration.base import BaseTestCase
from tests.integration.folders import FOLDER_KEYS

Expand All @@ -12,6 +13,12 @@ class TestGetFolderMetadata(BaseTestCase):
PROJECT_TYPE = "Vector"
SPECIAL_CHARS = r"/\:*?“<>|"
TEST_FOLDER_NAME = "folder_"
IGNORE_KEYS = {"id", "team_id", "createdAt", "updatedAt", "project_id"}
EXPECTED_FOLDER_METADATA = {
"folder_users": None,
"name": "folder_",
"status": "NotStarted",
}

def test_get_folder_metadata(self):
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME)
Expand All @@ -20,6 +27,9 @@ def test_get_folder_metadata(self):
)
assert "is_root" not in folder_metadata
self.assertListEqual(list(folder_metadata.keys()), FOLDER_KEYS)
assert compare_result(
folder_metadata, self.EXPECTED_FOLDER_METADATA, self.IGNORE_KEYS
)

# get not exiting folder
with self.assertRaises(AppException) as cm:
Expand Down
22 changes: 18 additions & 4 deletions tests/integration/items/test_get_item_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

from src.superannotate import SAClient
from tests import compare_result
from tests.integration.base import BaseTestCase

sa = SAClient()
Expand All @@ -15,6 +16,20 @@ class TestGetEntityMetadataVector(BaseTestCase):
CSV_PATH = "data_set/attach_urls.csv"
IMAGE_NAME = "example_image_1.jpg"
ATTACHED_IMAGE_NAME = "6022a74d5384c50017c366b3"
IGNORE_KEYS = {"id", "createdAt", "updatedAt"}
EXPECTED_ITEM_METADATA = {
"name": "example_image_1.jpg",
"path": "TestGetEntityMetadataVector",
"url": None,
"annotator_email": None,
"qa_email": None,
"annotation_status": "InProgress",
"entropy_value": None,
"prediction_status": "NotStarted",
"segmentation_status": None,
"approval_status": None,
"is_pinned": False,
}

@property
def folder_path(self):
Expand All @@ -30,10 +45,9 @@ def test_get_item_metadata(self):
)
item_metadata = sa.get_item_metadata(self.PROJECT_NAME, self.IMAGE_NAME)
assert item_metadata["path"] == f"{self.PROJECT_NAME}"
assert item_metadata["prediction_status"] == "NotStarted"
assert item_metadata["segmentation_status"] is None
assert item_metadata["annotation_status"] == "InProgress"
assert item_metadata["approval_status"] is None
assert compare_result(
item_metadata, self.EXPECTED_ITEM_METADATA, self.IGNORE_KEYS
)


class TestGetEntityMetadataPixel(BaseTestCase):
Expand Down
19 changes: 19 additions & 0 deletions tests/integration/projects/test_get_project_metadata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from src.superannotate import SAClient
from tests import compare_result
from tests.integration.base import BaseTestCase

sa = SAClient()
Expand All @@ -8,6 +9,21 @@ class TestGetProjectMetadata(BaseTestCase):
PROJECT_NAME = "TestGetProjectMetadata"
PROJECT_TYPE = "Vector"
PROJECT_DESCRIPTION = "DESCRIPTION"
IGNORE_KEYS = {"id", "creator_id", "team_id", "createdAt", "updatedAt"}
EXPECTED_PROJECT_METADATA = {
"name": "TestGetProjectMetadata",
"type": "Vector",
"description": "DESCRIPTION",
"instructions_link": None,
"entropy_status": 1,
"sharing_status": None,
"status": "NotStarted",
"folder_id": None,
"upload_state": "EXTERNAL",
"users": [],
"completed_items_count": None,
"root_folder_completed_items_count": None,
}

def test_metadata_payload(self):
"""
Expand All @@ -23,3 +39,6 @@ def test_metadata_payload(self):
assert project["item_count"] == 10
projects = sa.search_projects(name=self.PROJECT_NAME, return_metadata=True)
assert "item_count" not in projects[0]
assert compare_result(
projects[0], self.EXPECTED_PROJECT_METADATA, self.IGNORE_KEYS
)