Skip to content

Commit eb33a55

Browse files
authored
Merge pull request #180 from superannotateai/re-design-sdk
Re design sdk
2 parents 2db1cf3 + 0c02124 commit eb33a55

File tree

15 files changed

+3634
-56
lines changed

15 files changed

+3634
-56
lines changed

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
minversion = 3.0
33
log_cli=true
44
python_files = test_*.py
5-
addopts = -n32 --dist=loadscope
5+
;addopts = -n32 --dist=loadscope

src/superannotate/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
from superannotate.lib.app.interface.sdk_interface import create_project
6161
from superannotate.lib.app.interface.sdk_interface import create_project_from_metadata
6262
from superannotate.lib.app.interface.sdk_interface import delete_annotation_class
63+
from superannotate.lib.app.interface.sdk_interface import delete_annotations
6364
from superannotate.lib.app.interface.sdk_interface import (
6465
delete_contributor_to_team_invitation,
6566
)
@@ -235,6 +236,7 @@
235236
"assign_images",
236237
"unassign_images",
237238
"download_image_annotations",
239+
"delete_annotations",
238240
"upload_image_to_project",
239241
"upload_image_annotations",
240242
"upload_images_from_public_urls_to_project",

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

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -608,9 +608,11 @@ def upload_images_from_public_urls_to_project(
608608
raise AppException("Not all image URLs have corresponding names.")
609609

610610
project_name, folder_name = extract_project_folder(project)
611-
existing_images = controller.search_images(
612-
project_name=project_name, folder_path=folder_name
613-
).data
611+
existing_images = controller.get_duplicated_images(
612+
project_name=project_name,
613+
folder_name=folder_name,
614+
images=img_names,
615+
)
614616

615617
image_name_url_map = {}
616618
duplicate_images = []
@@ -1221,6 +1223,9 @@ def assign_folder(project_name: str, folder_name: str, users: List[str]):
12211223
f"Skipping {user} from assignees. {user} is not a verified contributor for the {project_name}"
12221224
)
12231225

1226+
if not verified_users:
1227+
return
1228+
12241229
response = controller.assign_folder(
12251230
project_name=project_name, folder_name=folder_name, users=list(verified_users)
12261231
)
@@ -1498,7 +1503,7 @@ def get_image_annotations(project: Union[str, dict], image_name: str):
14981503
project_name=project_name, folder_name=folder_name, image_name=image_name
14991504
)
15001505
if res.errors:
1501-
raise AppValidationException(res)
1506+
raise AppException(res)
15021507
return res.data
15031508

15041509

@@ -1556,7 +1561,7 @@ def upload_images_from_folder_to_project(
15561561
)
15571562
images_to_upload, _ = use_case.images_to_upload
15581563
if use_case.is_valid():
1559-
with tqdm(total=len(images_to_upload)) as progress_bar:
1564+
with tqdm(total=len(images_to_upload), desc="Uploading images") as progress_bar:
15601565
for _ in use_case.execute():
15611566
progress_bar.update(1)
15621567
return use_case.data
@@ -1721,7 +1726,7 @@ def upload_images_from_s3_bucket_to_project(
17211726
:type image_quality_in_editor: str
17221727
"""
17231728
project_name, folder_name = extract_project_folder(project)
1724-
controller.backend_upload_from_s3(
1729+
response = controller.backend_upload_from_s3(
17251730
project_name=project_name,
17261731
folder_name=folder_name,
17271732
folder_path=folder_path,
@@ -1730,6 +1735,8 @@ def upload_images_from_s3_bucket_to_project(
17301735
bucket_name=bucket_name,
17311736
image_quality=image_quality_in_editor,
17321737
)
1738+
if response.errors:
1739+
raise AppException(response.errors)
17331740

17341741

17351742
@Trackable
@@ -1859,7 +1866,7 @@ def upload_videos_from_folder_to_project(
18591866
)
18601867

18611868
uploaded_images, failed_images = [], []
1862-
for path in tqdm(video_paths):
1869+
for path in tqdm(video_paths, desc="Uploading videos"):
18631870
with tempfile.TemporaryDirectory() as temp_path:
18641871
res = controller.extract_video_frames(
18651872
project_name=project_name,
@@ -1953,7 +1960,9 @@ def upload_video_to_project(
19531960
)
19541961
images_to_upload, _ = use_case.images_to_upload
19551962
if use_case.is_valid():
1956-
with tqdm(total=len(images_to_upload)) as progress_bar:
1963+
with tqdm(
1964+
total=len(images_to_upload), desc="Uploading frames."
1965+
) as progress_bar:
19571966
for _ in use_case.execute():
19581967
progress_bar.update(1)
19591968
return use_case.data[0]
@@ -2488,8 +2497,10 @@ def upload_annotations_from_folder_to_project(
24882497
uploaded_annotations = []
24892498
failed_annotations = []
24902499
missing_annotations = []
2491-
chunk_size = 10
2492-
with tqdm(total=len(annotation_paths)) as progress_bar:
2500+
chunk_size = 50
2501+
with tqdm(
2502+
total=len(annotation_paths), desc="Uploading annotations"
2503+
) as progress_bar:
24932504
for i in range(0, len(annotation_paths), chunk_size):
24942505
response = controller.upload_annotations_from_folder(
24952506
project_name=project_name,
@@ -2549,7 +2560,9 @@ def upload_preannotations_from_folder_to_project(
25492560
failed_annotations = []
25502561
missing_annotations = []
25512562
chunk_size = 10
2552-
with tqdm(total=len(annotation_paths)) as progress_bar:
2563+
with tqdm(
2564+
total=len(annotation_paths), desc="Uploading pre annotations"
2565+
) as progress_bar:
25532566
for i in range(0, len(annotation_paths), chunk_size):
25542567
response = controller.upload_annotations_from_folder(
25552568
project_name=project_name,
@@ -3511,7 +3524,7 @@ def _upload_s3_image(image_path: str):
35113524
executor.submit(upload_method, image_path)
35123525
for image_path in images_to_upload
35133526
]
3514-
with tqdm(total=len(images_to_upload)) as progress_bar:
3527+
with tqdm(total=len(images_to_upload), desc="Uploading images") as progress_bar:
35153528
for future in concurrent.futures.as_completed(results):
35163529
processed_image = future.result()
35173530
if processed_image.uploaded and processed_image.entity:
@@ -3587,3 +3600,24 @@ def aggregate_annotations_as_df(
35873600
verbose,
35883601
folder_names,
35893602
)
3603+
3604+
3605+
@Trackable
3606+
@validate_input
3607+
def delete_annotations(project: str, image_names: List[str] = None):
3608+
"""
3609+
Delete image annotations from a given list of images.
3610+
3611+
:param project: project name or folder path (e.g., "project1/folder1")
3612+
:type project: str
3613+
:param image_names: image names. If None, all image annotations from a given project/folder will be deleted.
3614+
:type image_names: list of strs
3615+
"""
3616+
3617+
project_name, folder_name = extract_project_folder(project)
3618+
3619+
response = controller.delete_annotations(
3620+
project_name=project, folder_name=folder_name, image_names=image_names
3621+
)
3622+
if response.errors:
3623+
raise AppException(response.errors)

src/superannotate/lib/core/serviceproviders.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,17 @@ def run_prediction(
296296
self, team_id: int, project_id: int, ml_model_id: int, image_ids: list
297297
):
298298
raise NotImplementedError
299+
300+
def delete_image_annotations(
301+
self,
302+
team_id: int,
303+
project_id: int,
304+
folder_id: int = None,
305+
image_names: List[str] = None,
306+
) -> int:
307+
raise NotImplementedError
308+
309+
def get_annotations_delete_progress(
310+
self, team_id: int, project_id: int, poll_id: int
311+
):
312+
raise NotImplementedError

0 commit comments

Comments
 (0)