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
60 changes: 38 additions & 22 deletions src/superannotate/lib/core/usecases/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -2710,12 +2710,12 @@ def __init__(
self,
annotation_classes: BaseManageableRepository,
annotation_class: AnnotationClassEntity,
project_name: str,
project: ProjectEntity,
):
super().__init__()
self._annotation_classes = annotation_classes
self._annotation_class = annotation_class
self._project_name = project_name
self._project = project

def validate_uniqueness(self):
annotation_classes = self._annotation_classes.get_all(
Expand All @@ -2730,11 +2730,20 @@ def validate_uniqueness(self):
):
raise AppValidationException("Annotation class already exits.")

def validate_project_type(self):
if (
self._project.project_type != ProjectType.VECTOR.value
and self._annotation_class.type == "tag"
):
raise AppException(
f"Predefined tagging functionality is not supported for projects of type {ProjectType.get_name(self._project.project_type)}."
)

def execute(self):
if self.is_valid():
logger.info(
"Creating annotation class in project %s with name %s",
self._project_name,
self._project.name,
self._annotation_class.name,
)
created = self._annotation_classes.insert(entity=self._annotation_class)
Expand Down Expand Up @@ -2840,27 +2849,34 @@ def validate_annotation_classes(self):
if "attribute_groups" not in self._annotation_classes:
raise AppValidationException("Field attribute_groups is required.")

def validate_project_type(self):
if self._project.project_type != ProjectType.VECTOR.value and "tag" in [
i.type for i in self._annotation_classes
]:
raise AppException(
f"Predefined tagging functionality is not supported for projects of type {ProjectType.get_name(self._project.project_type)}."
)

def execute(self):
existing_annotation_classes = self._annotation_classes_repo.get_all()
existing_classes_name = [i.name for i in existing_annotation_classes]
unique_annotation_classes = []
for annotation_class in self._annotation_classes:
if annotation_class.name in existing_classes_name:
logger.warning(
"Annotation class %s already in project. Skipping.",
annotation_class.name,
if self.is_valid():
existing_annotation_classes = self._annotation_classes_repo.get_all()
existing_classes_name = [i.name for i in existing_annotation_classes]
unique_annotation_classes = []
for annotation_class in self._annotation_classes:
if annotation_class.name in existing_classes_name:
logger.warning(
"Annotation class %s already in project. Skipping.",
annotation_class.name,
)
continue
else:
unique_annotation_classes.append(annotation_class)
created = []
for i in range(len(unique_annotation_classes) - self.CHUNK_SIZE, 0, self.CHUNK_SIZE):
created += self._annotation_classes_repo.bulk_insert(
entities=unique_annotation_classes[i : i + self.CHUNK_SIZE], # noqa: E203
)
continue
else:
unique_annotation_classes.append(annotation_class)

created = []

for i in range(len(unique_annotation_classes) - self.CHUNK_SIZE, 0, self.CHUNK_SIZE):
created += self._annotation_classes_repo.bulk_insert(
entities=unique_annotation_classes[i : i + self.CHUNK_SIZE], # noqa: E203
)
self._response.data = created
self._response.data = created
return self._response


Expand Down
2 changes: 1 addition & 1 deletion src/superannotate/lib/infrastructure/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ def create_annotation_class(
use_case = usecases.CreateAnnotationClassUseCase(
annotation_classes=annotation_classes,
annotation_class=annotation_class,
project_name=project_name,
project=project,
)
use_case.execute()
return use_case.execute()
Expand Down
63 changes: 63 additions & 0 deletions tests/integration/classes/test_create_annotation_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,66 @@ def test_create_annotation_class(self):
sa.create_annotation_class(self.PROJECT_NAME, "test_add", "#FF0000", type="tag")
classes = sa.search_annotation_classes(self.PROJECT_NAME)
self.assertEqual(classes[0]["type"], "tag")


class TestCreateAnnotationClassNonVectorWithError(BaseTestCase):
PROJECT_NAME = "test_create_annotation_class"
PROJECT_TYPE = "Video"
PROJECT_DESCRIPTION = "Example Project test pixel basic images"

def test_create_annotation_class(self):
msg = ""
try:
sa.create_annotation_class(self.PROJECT_NAME, "test_add", "#FF0000", type="tag")
except Exception as e:
msg = str(e)
self.assertEqual(msg, "Predefined tagging functionality is not supported for projects of type Video.")


class TestCreateAnnotationClassesNonVectorWithError(BaseTestCase):
PROJECT_NAME = "test_create_annotation_class"
PROJECT_TYPE = "Video"
PROJECT_DESCRIPTION = "Example Project test pixel basic images"

def test_create_annotation_class(self):
with tempfile.TemporaryDirectory() as tmpdir_name:
temp_path = f"{tmpdir_name}/new_classes.json"
with open(temp_path,
"w") as new_classes:
new_classes.write(
'''
[
{
"id":56820,
"project_id":7617,
"name":"Personal vehicle",
"color":"#547497",
"count":18,
"createdAt":"2020-09-29T10:39:39.000Z",
"updatedAt":"2020-09-29T10:48:18.000Z",
"type": "tag",
"attribute_groups":[
{
"id":21448,
"class_id":56820,
"name":"Large",
"is_multiselect":0,
"createdAt":"2020-09-29T10:39:39.000Z",
"updatedAt":"2020-09-29T10:39:39.000Z",
"attributes":[]
}
]
}
]

'''
)
msg = ""
try:
sa.create_annotation_classes_from_classes_json(
self.PROJECT_NAME, temp_path
)
except Exception as e:
msg = str(e)
self.assertEqual(msg, "Predefined tagging functionality is not supported for projects of type Video.")