Skip to content

Commit ed1af5d

Browse files
Vaghinak BasentsyanVaghinak Basentsyan
authored andcommitted
Tests moved to annotations folder
1 parent e8510ae commit ed1af5d

18 files changed

+181
-588
lines changed

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,9 +2387,6 @@ def upload_annotations_from_folder_to_project(
23872387
)
23882388
logger.info("The JSON files should follow a specific naming convention, matching file names already present "
23892389
"on the platform. Existing annotations will be overwritten")
2390-
logger.info(
2391-
"Uploading all annotations from %s to project %s.", folder_path, project_name
2392-
)
23932390

23942391
annotation_paths = get_annotation_paths(
23952392
folder_path, from_s3_bucket, recursive_subfolders

src/superannotate/lib/core/helpers.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ def fill_annotation_ids(
6060
annotation_class_name = annotation["className"]
6161
if annotation_class_name not in annotation_classes_name_maps.keys():
6262
if annotation_class_name not in unknown_classes:
63-
reporter.store_message("Couldn't find classes ", annotation_class_name)
63+
reporter.log_warning(f"Couldn't find class {annotation_class_name}")
64+
reporter.store_message("missing_classes", annotation_class_name)
6465
unknown_classes[annotation_class_name] = {
6566
"id": -(len(unknown_classes) + 1),
6667
"attribute_groups": {},
@@ -94,9 +95,7 @@ def fill_annotation_ids(
9495
reporter.log_warning(
9596
f"Couldn't find annotation group {attribute['groupName']}."
9697
)
97-
reporter.store_message(
98-
"Couldn't find annotation groups", attribute["groupName"]
99-
)
98+
reporter.store_message("missing_attribute_groups", f"{annotation['className']}.{attribute['groupName']}")
10099
continue
101100
attribute["groupId"] = annotation_classes_name_maps[annotation_class_name][
102101
"attribute_groups"
@@ -112,7 +111,7 @@ def fill_annotation_ids(
112111
f"Couldn't find annotation name {attribute['name']} in"
113112
f" annotation group {attribute['groupName']}",
114113
)
115-
reporter.store_message("Couldn't find attributes", attribute["name"])
114+
reporter.store_message("missing_attributes", attribute["name"])
116115
continue
117116
attribute["id"] = annotation_classes_name_maps[annotation_class_name][
118117
"attribute_groups"

src/superannotate/lib/core/types.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
from typing import Dict
12
from typing import List
23
from typing import Optional
34
from typing import Union
4-
from typing import Dict
55

66
from pydantic import BaseModel
77
from pydantic import constr
@@ -48,15 +48,15 @@ class Metadata(BaseModel):
4848

4949

5050
class PointLabels(BaseModel):
51-
__root__: Dict[constr(regex=r"^[0-9]*$"), str]
51+
__root__: Dict[constr(regex=r'^[0-9]*$'), str]
5252

5353

5454
class BaseInstance(BaseModel):
5555
type: AnnotationType
56-
classId: int
56+
classId: Optional[int]
5757
groupId: Optional[int]
5858
attributes: List[Attribute]
59-
point_labels: Optional[PointLabels]
59+
# point_labels: Optional[PointLabels]
6060

6161
class Config:
6262
error_msg_templates = {
@@ -96,20 +96,20 @@ class Ellipse(BaseInstance):
9696

9797

9898
class TemplatePoint(BaseModel):
99-
id: int
99+
id: Optional[int]
100100
x: float
101101
y: float
102102

103103

104104
class TemplateConnection(BaseModel):
105-
id: int
105+
id: Optional[int]
106106
to: int
107107

108108

109109
class Template(BaseInstance):
110110
points: List[TemplatePoint]
111111
connections: List[Optional[TemplateConnection]]
112-
templateId: int
112+
templateId: Optional[int]
113113

114114

115115
class EmptyPoint(BaseModel):
@@ -133,7 +133,7 @@ class PixelAnnotationPart(BaseModel):
133133

134134

135135
class PixelAnnotationInstance(BaseModel):
136-
classId: int
136+
classId: Optional[int]
137137
groupId: Optional[int]
138138
parts: List[PixelAnnotationPart]
139139
attributes: List[Attribute]
@@ -189,7 +189,7 @@ class Config:
189189

190190
class MLModel(BaseModel):
191191
name: NotEmptyStr
192-
id: int
192+
id: Optional[int]
193193
path: NotEmptyStr
194194
config_path: NotEmptyStr
195195
team_id: Optional[int]
@@ -206,7 +206,7 @@ class VideoMetaData(BaseModel):
206206

207207
class VideoInstanceMeta(BaseModel):
208208
type: NotEmptyStr
209-
classId: int
209+
classId: Optional[int]
210210

211211

212212
class VideoTimeStamp(BaseModel):

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

Lines changed: 72 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from lib.core.entities import ImageEntity
1414
from lib.core.entities import ProjectEntity
1515
from lib.core.exceptions import AppException
16-
from lib.core.exceptions import AppValidationException
1716
from lib.core.helpers import convert_to_video_editor_json
1817
from lib.core.helpers import fill_annotation_ids
1918
from lib.core.helpers import map_annotation_classes_name
@@ -177,64 +176,84 @@ def _upload_annotation(
177176
# raise e
178177
return path, False
179178

179+
def get_bucket_to_upload(self, ids: List[int]):
180+
upload_data = self.get_annotation_upload_data(ids)
181+
if upload_data:
182+
session = boto3.Session(
183+
aws_access_key_id=upload_data.access_key,
184+
aws_secret_access_key=upload_data.secret_key,
185+
aws_session_token=upload_data.session_token,
186+
region_name=upload_data.region,
187+
)
188+
resource = session.resource("s3")
189+
return resource.Bucket(upload_data.bucket)
190+
191+
def _log_report(self):
192+
for key, values in self.reporter.custom_messages.items():
193+
template = key + ": {}"
194+
if key == "missing_classes":
195+
template = "Could not find annotation classes matching existing classes on the platform: [{}]"
196+
elif key == "missing_attribute_groups":
197+
template = "Could not find attribute groups matching existing attribute groups on the platform: [{}]"
198+
elif key == "missing_attributes":
199+
template = "Could not find attributes matching existing attributes on the platform: [{}]"
200+
logger.warning(
201+
template.format(", ".join(values))
202+
)
203+
180204
def execute(self):
181205
uploaded_annotations = []
182206
failed_annotations = []
183-
iterations_range = range(
184-
0, len(self.annotations_to_upload), self.AUTH_DATA_CHUNK_SIZE
185-
)
186-
self.reporter.start_progress(iterations_range,description="Uploading Annotations")
187-
for _ in iterations_range:
188-
annotations_to_upload = self.annotations_to_upload[
189-
_ : _ + self.AUTH_DATA_CHUNK_SIZE # noqa: E203
190-
]
191-
upload_data = self.get_annotation_upload_data(
192-
[int(image.id) for image in annotations_to_upload]
207+
if self.annotations_to_upload:
208+
iterations_range = range(
209+
0, len(self.annotations_to_upload), self.AUTH_DATA_CHUNK_SIZE
193210
)
194-
if upload_data:
195-
session = boto3.Session(
196-
aws_access_key_id=upload_data.access_key,
197-
aws_secret_access_key=upload_data.secret_key,
198-
aws_session_token=upload_data.session_token,
199-
region_name=upload_data.region,
211+
self.reporter.start_progress(iterations_range, description="Uploading Annotations")
212+
for _ in iterations_range:
213+
annotations_to_upload = self.annotations_to_upload[
214+
_ : _ + self.AUTH_DATA_CHUNK_SIZE # noqa: E203
215+
]
216+
upload_data = self.get_annotation_upload_data(
217+
[int(image.id) for image in annotations_to_upload]
200218
)
201-
resource = session.resource("s3")
202-
bucket = resource.Bucket(upload_data.bucket)
203-
image_id_name_map = {
204-
image.id: image for image in self.annotations_to_upload
205-
}
206-
# dummy progress
207-
for _ in range(len(annotations_to_upload) - len(upload_data.images)):
208-
self.reporter.update_progress()
209-
with concurrent.futures.ThreadPoolExecutor(
210-
max_workers=self.MAX_WORKERS
211-
) as executor:
212-
results = [
213-
executor.submit(
214-
self._upload_annotation,
215-
image_id,
216-
image_id_name_map[image_id].name,
217-
upload_data,
218-
image_id_name_map[image_id].path,
219-
bucket,
220-
)
221-
for image_id, image_data in upload_data.images.items()
222-
]
223-
for future in concurrent.futures.as_completed(results):
224-
annotation, uploaded = future.result()
225-
if uploaded:
226-
uploaded_annotations.append(annotation)
227-
else:
228-
failed_annotations.append(annotation)
219+
bucket = self.get_bucket_to_upload([int(image.id) for image in annotations_to_upload])
220+
if bucket:
221+
image_id_name_map = {
222+
image.id: image for image in self.annotations_to_upload
223+
}
224+
# dummy progress
225+
for _ in range(len(annotations_to_upload) - len(upload_data.images)):
229226
self.reporter.update_progress()
227+
with concurrent.futures.ThreadPoolExecutor(
228+
max_workers=self.MAX_WORKERS
229+
) as executor:
230+
results = [
231+
executor.submit(
232+
self._upload_annotation,
233+
image_id,
234+
image_id_name_map[image_id].name,
235+
upload_data,
236+
image_id_name_map[image_id].path,
237+
bucket,
238+
)
239+
for image_id, image_data in upload_data.images.items()
240+
]
241+
for future in concurrent.futures.as_completed(results):
242+
annotation, uploaded = future.result()
243+
if uploaded:
244+
uploaded_annotations.append(annotation)
245+
else:
246+
failed_annotations.append(annotation)
247+
self.reporter.update_progress()
230248

231-
self._response.data = (
232-
uploaded_annotations,
233-
failed_annotations,
234-
[annotation.path for annotation in self._missing_annotations],
235-
)
236-
for message in self.reporter.messages:
237-
logger.warning(message)
249+
self._response.data = (
250+
uploaded_annotations,
251+
failed_annotations,
252+
[annotation.path for annotation in self._missing_annotations],
253+
)
254+
self._log_report()
255+
else:
256+
self._response.errors = "Could not find annotations matching existing items on the platform."
238257
return self._response
239258

240259

@@ -401,5 +420,5 @@ def execute(self):
401420
self._project.name,
402421
)
403422
else:
404-
self._response.errors = f"Invalid json"
423+
self._response.errors = "Invalid json"
405424
return self._response

0 commit comments

Comments
 (0)