Skip to content

Commit ef9a182

Browse files
authored
Merge pull request #338 from superannotateai/friday
Friday
2 parents d3db484 + 54c02d8 commit ef9a182

File tree

9 files changed

+113
-34
lines changed

9 files changed

+113
-34
lines changed

src/superannotate/lib/app/interface/sdk_interface.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ def search_images(
281281
"""
282282

283283
project_name, folder_name = extract_project_folder(project)
284+
project = controller._get_project(project_name)
284285

285286
response = controller.search_images(
286287
project_name=project_name,
@@ -292,7 +293,7 @@ def search_images(
292293
raise AppException(response.errors)
293294

294295
if return_metadata:
295-
return [ImageSerializer(image).serialize() for image in response.data]
296+
return [ImageSerializer(image).serialize_by_project(project) for image in response.data]
296297
return [image.name for image in response.data]
297298

298299

@@ -889,21 +890,12 @@ def get_image_metadata(
889890
:rtype: dict
890891
"""
891892
project_name, folder_name = extract_project_folder(project)
893+
project = controller._get_project(project_name)
892894
response = controller.get_image_metadata(project_name, folder_name, image_name)
895+
893896
if response.errors:
894897
raise AppException(response.errors)
895-
896-
res_data = response.data
897-
res_data["annotation_status"] = constances.AnnotationStatus.get_name(
898-
res_data["annotation_status"]
899-
)
900-
res_data["prediction_status"] = constances.SegmentationStatus.get_name(
901-
res_data["prediction_status"]
902-
)
903-
res_data["segmentation_status"] = constances.SegmentationStatus.get_name(
904-
res_data["segmentation_status"]
905-
)
906-
return res_data
898+
return ImageSerializer(response.data).serialize_by_project(project)
907899

908900

909901
@Trackable
@@ -1849,13 +1841,14 @@ def set_image_annotation_status(
18491841
:rtype: dict
18501842
"""
18511843
project_name, folder_name = extract_project_folder(project)
1844+
project_entity = controller._get_project(project_name)
18521845
response = controller.set_images_annotation_statuses(
18531846
project_name, folder_name, [image_name], annotation_status
18541847
)
18551848
if response.errors:
18561849
raise AppException(response.errors)
18571850
image = controller.get_image_metadata(project_name, folder_name, image_name).data
1858-
return ImageSerializer(image).serialize()
1851+
return ImageSerializer(image).serialize_by_project(project=project_entity)
18591852

18601853

18611854
@Trackable
@@ -2581,14 +2574,17 @@ def search_images_all_folders(
25812574
:rtype: list of dicts or strs
25822575
"""
25832576

2577+
project_entity = controller._get_project(project)
25842578
res = controller.list_images(
25852579
project_name=project,
25862580
name_prefix=image_name_prefix,
25872581
annotation_status=annotation_status,
25882582
)
25892583
if return_metadata:
2590-
return res.data
2591-
return [image["name"] for image in res.data]
2584+
return [
2585+
ImageSerializer(image).serialize_by_project(project=project_entity) for image in res.data
2586+
]
2587+
return [image.name for image in res.data]
25922588

25932589

25942590
@Trackable

src/superannotate/lib/app/mixp/decorators.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
controller = Controller.get_instance()
1212

13+
# TODO:
1314
try:
1415
if "api.annotate.online" in controller._backend_client.api_url:
1516
TOKEN = "ca95ed96f80e8ec3be791e2d3097cf51"

src/superannotate/lib/app/serializers.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import superannotate.lib.core as constance
44
from superannotate.lib.core.entities import BaseEntity
55
from superannotate.lib.core.entities import ImageEntity
6+
from superannotate.lib.core.entities import ProjectEntity
67

78

89
class BaseSerializers(ABC):
@@ -57,6 +58,47 @@ def serialize(self):
5758
)
5859
return data
5960

61+
62+
def serialize_by_project(self, project: ProjectEntity):
63+
data = super().serialize()
64+
data = {
65+
"name": data.get("name"),
66+
"path": data.get("path"),
67+
"annotation_status": data.get("annotation_status"),
68+
"prediction_status": data.get("prediction_status"),
69+
"segmentation_status": data.get("segmentation_status"),
70+
"approval_status": data.get("approval_status"),
71+
"is_pinned": data.get("is_pinned"),
72+
"annotator_name": data.get("annotator_name"),
73+
"qa_name": data.get("qa_name"),
74+
"entropy_value": data.get("entropy_value"),
75+
"createdAt": data.get("createdAt"),
76+
"updatedAt": data.get("updatedAt"),
77+
}
78+
79+
data["annotation_status"] = constance.AnnotationStatus.get_name(
80+
data["annotation_status"]
81+
)
82+
83+
if project.upload_state == constance.UploadState.EXTERNAL.value:
84+
data["prediction_status"] = None
85+
data["segmentation_status"] = None
86+
else:
87+
if project.project_type == constance.ProjectType.VECTOR.value:
88+
data["prediction_status"] = constance.SegmentationStatus.get_name(
89+
data["prediction_status"]
90+
)
91+
data["segmentation_status"] = None
92+
if project.project_type == constance.ProjectType.PIXEL.value:
93+
data["prediction_status"] = constance.SegmentationStatus.get_name(
94+
data["prediction_status"]
95+
)
96+
data["segmentation_status"] = constance.SegmentationStatus.get_name(
97+
data["segmentation_status"]
98+
)
99+
data["path"] = None
100+
return data
101+
60102
@staticmethod
61103
def deserialize(data):
62104
if isinstance(data, list):

src/superannotate/lib/core/entities/project_entities.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Iterable
55
from typing import List
66

7+
import lib.core as constances
78
from lib.core.enums import SegmentationStatus
89

910

@@ -261,6 +262,8 @@ def __init__(
261262
segmentation_status: int = SegmentationStatus.NOT_STARTED.value,
262263
prediction_status: int = SegmentationStatus.NOT_STARTED.value,
263264
meta: ImageInfoEntity = ImageInfoEntity(),
265+
created_at: str = None,
266+
updated_at: str = None,
264267
**_
265268
):
266269
super().__init__(uuid)
@@ -281,6 +284,8 @@ def __init__(
281284
self.segmentation_status = segmentation_status
282285
self.prediction_status = prediction_status
283286
self.meta = meta
287+
self.created_at = created_at
288+
self.updated_at = updated_at
284289

285290
@staticmethod
286291
def from_dict(**kwargs):
@@ -290,26 +295,35 @@ def from_dict(**kwargs):
290295
if "annotation_status" in kwargs:
291296
kwargs["annotation_status_code"] = kwargs["annotation_status"]
292297
del kwargs["annotation_status"]
298+
if "createdAt" in kwargs:
299+
kwargs["created_at"] = kwargs["createdAt"]
300+
del kwargs["createdAt"]
301+
if "updatedAt" in kwargs:
302+
kwargs["updated_at"] = kwargs["updatedAt"]
303+
del kwargs["updatedAt"]
293304
return ImageEntity(**kwargs)
294305

306+
295307
def to_dict(self):
296308
data = {
297309
"id": self.uuid,
298310
"team_id": self.team_id,
311+
"project_id": self.project_id,
312+
"folder_id": self.folder_id,
299313
"name": self.name,
300314
"path": self.path,
301-
"project_id": self.project_id,
302315
"annotation_status": self.annotation_status_code,
303-
"folder_id": self.folder_id,
304-
"qa_id": self.qa_id,
305-
"qa_name": self.qa_name,
306-
"entropy_value": self.entropy_value,
316+
"prediction_status": self.prediction_status,
317+
"segmentation_status": self.segmentation_status,
307318
"approval_status": self.approval_status,
319+
"is_pinned": self.is_pinned,
308320
"annotator_id": self.annotator_id,
309321
"annotator_name": self.annotator_name,
310-
"is_pinned": self.is_pinned,
311-
"segmentation_status": self.segmentation_status,
312-
"prediction_status": self.prediction_status,
322+
"qa_id": self.qa_id,
323+
"qa_name": self.qa_name,
324+
"entropy_value": self.entropy_value,
325+
"createdAt": self.created_at,
326+
"updatedAt": self.updated_at,
313327
"meta": self.meta.to_dict(),
314328
}
315329
return {k: v for k, v in data.items() if v is not None}

src/superannotate/lib/core/usecases/images.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ def execute(self):
9393
constances.AnnotationStatus.get_value(self._annotation_status),
9494
EQ,
9595
)
96-
9796
self._response.data = self._images.get_all(condition)
9897
return self._response
9998

@@ -161,9 +160,10 @@ def execute(self):
161160
condition &= Condition("annotation_status", self.annotation_status, EQ)
162161
if self._name_prefix:
163162
condition &= Condition("name", self._name_prefix, EQ)
164-
self._response.data = self._service_provider.list_images(
163+
images_list = self._service_provider.list_images(
165164
query_string=condition.build_query()
166165
)
166+
self._response.data = [ImageEntity.from_dict(**image) for image in images_list]
167167
return self._response
168168

169169

@@ -676,7 +676,8 @@ def execute(self):
676676
folder_id=self._folder.uuid,
677677
)
678678
if data:
679-
self._response.data = data[0]
679+
image_entity = ImageEntity.from_dict(**data[0])
680+
self._response.data = image_entity
680681
else:
681682
self._response.errors = AppException("Image not found.")
682683
return self._response

src/superannotate/lib/infrastructure/repositories.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ def dict2entity(data: dict):
396396
annotator_id=data["annotator_id"],
397397
annotator_name=data["annotator_name"],
398398
is_pinned=data.get("is_pinned"),
399+
created_at=data["createdAt"],
400+
updated_at=data["updatedAt"],
399401
)
400402

401403

tests/integration/test_assign_images.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_assign_images(self):
3232
image_metadata = sa.get_image_metadata(
3333
self._project["name"], self.EXAMPLE_IMAGE_1
3434
)
35-
self.assertEqual(image_metadata["qa_id"], email)
35+
self.assertIsNotNone(image_metadata["qa_name"])
3636

3737
def test_assign_images_folder(self):
3838

@@ -52,8 +52,8 @@ def test_assign_images_folder(self):
5252
im1_metadata = sa.get_image_metadata(project_folder, self.EXAMPLE_IMAGE_1)
5353
im2_metadata = sa.get_image_metadata(project_folder, self.EXAMPLE_IMAGE_2)
5454

55-
self.assertEqual(im1_metadata["qa_id"], email)
56-
self.assertEqual(im2_metadata["qa_id"], email)
55+
self.assertIsNotNone(im1_metadata["qa_name"])
56+
self.assertIsNotNone(im2_metadata["qa_name"])
5757

5858
def test_un_assign_images(self):
5959

@@ -70,8 +70,8 @@ def test_un_assign_images(self):
7070
im1_metadata = sa.get_image_metadata(self.PROJECT_NAME, self.EXAMPLE_IMAGE_1)
7171
im2_metadata = sa.get_image_metadata(self.PROJECT_NAME, self.EXAMPLE_IMAGE_2)
7272

73-
self.assertIsNone(im1_metadata["qa_id"])
74-
self.assertIsNone(im2_metadata["qa_id"])
73+
self.assertIsNone(im1_metadata["qa_name"])
74+
self.assertIsNone(im2_metadata["qa_name"])
7575

7676
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME)
7777
project = self.PROJECT_NAME + "/" + self.TEST_FOLDER_NAME
@@ -89,8 +89,8 @@ def test_un_assign_images(self):
8989

9090
im2_metadata = sa.get_image_metadata(project, self.EXAMPLE_IMAGE_2)
9191

92-
self.assertIsNone(im1_metadata["qa_id"])
93-
self.assertIsNone(im2_metadata["qa_id"])
92+
self.assertIsNone(im1_metadata["qa_name"])
93+
self.assertIsNone(im2_metadata["qa_name"])
9494

9595
def test_assign_folder(self):
9696
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME)

tests/integration/test_attach_image_urls.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ def test_attach_image_urls(self):
2828
self.assertEqual(len(existing_images), 1)
2929
images = sa.search_images(project=self.PROJECT_NAME, return_metadata=True)
3030
self.assertTrue(all([image["name"] for image in images]))
31+
truth = {'name': '',
32+
'path': 'https://drive.google.com/uc?export=download&id=1geS2YtQiTYuiduEirKVYxBujHJaIWA3V',
33+
'annotation_status': 'NotStarted', 'prediction_status': None, 'segmentation_status': None,
34+
'approval_status': None, 'is_pinned': 0, 'annotator_name': None, 'qa_name': None, 'entropy_value': None,
35+
'createdAt': '', 'updatedAt': ''}
36+
image = images[0]
37+
image['createdAt'] = ''
38+
image['updatedAt'] = ''
39+
image['name'] = ''
40+
self.assertEqual(image, truth)
3141

3242
def test_double_attach_image_urls(self):
3343
uploaded, could_not_upload, existing_images = sa.attach_image_urls_to_project(

tests/integration/test_basic_images.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ def test_basic_images(self):
3131
sa.create_annotation_classes_from_classes_json(
3232
self.PROJECT_NAME, self.classes_json_path
3333
)
34+
image = sa.get_image_metadata(self.PROJECT_NAME,image_name="example_image_1.jpg" )
35+
image['createdAt'] = ''
36+
image['updatedAt'] = ''
37+
truth ={'name': 'example_image_1.jpg', 'path': None, 'annotation_status': 'InProgress', 'prediction_status':'NotStarted', 'segmentation_status': 'NotStarted', 'approval_status': None, 'is_pinned': 0, 'annotator_name': None, 'qa_name': None, 'entropy_value': None, 'createdAt': '', 'updatedAt': ''}
38+
39+
self.assertEqual(image,truth)
3440

3541
sa.upload_image_annotations(
3642
project=self.PROJECT_NAME,
@@ -82,6 +88,13 @@ def test_basic_images(self):
8288
self.assertEqual(len(images), 1)
8389

8490
image_name = images[0]
91+
92+
image = sa.get_image_metadata(self.PROJECT_NAME,image_name="example_image_1.jpg" )
93+
image['createdAt'] = ''
94+
image['updatedAt'] = ''
95+
truth = {'name': 'example_image_1.jpg', 'path': None, 'annotation_status': 'InProgress', 'prediction_status':'NotStarted', 'segmentation_status': None, 'approval_status': None, 'is_pinned': 0, 'annotator_name': None, 'qa_name': None, 'entropy_value': None, 'createdAt': '', 'updatedAt': ''}
96+
self.assertEqual(image, truth)
97+
8598
sa.download_image(self.PROJECT_NAME, image_name, temp_dir, True)
8699
self.assertEqual(
87100
sa.get_image_annotations(self.PROJECT_NAME, image_name)[

0 commit comments

Comments
 (0)