Skip to content

Commit 2eda4c8

Browse files
committed
Add folder assign test
1 parent f6b1e00 commit 2eda4c8

File tree

4 files changed

+109
-38
lines changed

4 files changed

+109
-38
lines changed

superannotate/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def consensus(*args, **kwargs):
3333
filter_annotation_instances, filter_images_by_comments,
3434
filter_images_by_tags
3535
)
36+
from .db.utils import _search_folders
3637
from .db.annotation_classes import (
3738
create_annotation_class, create_annotation_classes_from_classes_json,
3839
delete_annotation_class, download_annotation_classes_json,

superannotate/db/project_images.py

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
get_project_default_image_quality_in_editor, _get_available_image_counts,
2020
get_project_metadata
2121
)
22+
from .teams import get_team_metadata
2223
from ..mixp.decorators import Trackable
2324
from .utils import _get_upload_auth_token, _get_boto_session_by_credentials, upload_image_array_to_s3, get_image_array_to_upload, __create_image, __copy_images, __move_images, get_project_folder_string
2425

@@ -564,15 +565,14 @@ def assign_images(project, image_names, user):
564565
:param user: user email
565566
:type user: str
566567
"""
567-
568-
# TODO:
569-
# logger.info("Assign %s images to user %s", len(image_names), user)
570-
# if len(image_names) == 0:
571-
# return
568+
logger.info("Assign %s images to user %s", len(image_names), user)
569+
if len(image_names) == 0:
570+
return
572571

573572
project, folder = get_project_and_folder_metadata(project)
574-
if not folder:
575-
folder = 'root'
573+
folder_name = 'root'
574+
if folder:
575+
folder_name = folder['name']
576576

577577
project_meta = get_project_metadata(project)
578578
params = {
@@ -582,7 +582,7 @@ def assign_images(project, image_names, user):
582582
json_req = {
583583
"image_names": image_names,
584584
"assign_user_id": user,
585-
"folder_name": folder,
585+
"folder_name": folder_name,
586586
}
587587
response = _api.send_request(
588588
req_type='PUT',
@@ -596,30 +596,6 @@ def assign_images(project, image_names, user):
596596
response.status_code, "Couldn't assign images " + response.text
597597
)
598598

599-
# images = search_images((project, project_folder), return_metadata=True)
600-
# image_dict = {}
601-
# for image in images:
602-
# image_dict[image["name"]] = image["id"]
603-
604-
# image_ids = []
605-
# for image_name in image_names:
606-
# image_ids.append(image_dict[image_name])
607-
# team_id, project_id = project["team_id"], project["id"]
608-
# params = {"team_id": team_id, "project_id": project_id}
609-
# if project_folder is not None:
610-
# params['folder_id'] = project_folder['id']
611-
# json_req = {"user_id": user, "image_ids": image_ids}
612-
# response = _api.send_request(
613-
# req_type='POST',
614-
# path='/images/assign',
615-
# params=params,
616-
# json_req=json_req
617-
# )
618-
# if not response.ok:
619-
# raise SABaseException(
620-
# response.status_code, "Couldn't assign images " + response.text
621-
# )
622-
623599

624600
def assign_folder(project, folder_name, users):
625601
"""Assigns folder to users. With SDK, the user can be
@@ -634,9 +610,9 @@ def assign_folder(project, folder_name, users):
634610
"""
635611

636612
project_meta = get_project_metadata(project, include_contributors=True)
637-
project_users = project_meta["contributors"]
613+
project_users = get_team_metadata()["users"]
638614
project_name = project_meta['name']
639-
project_users = [i['user_id'] for i in project_users]
615+
project_users = [i['id'] for i in project_users]
640616
verified_contributor = []
641617

642618
for user in users:
@@ -711,11 +687,20 @@ def unassign_images(project, image_names):
711687
:type image_names: list of str
712688
"""
713689
project_meta = get_project_metadata(project)
690+
project, folder = get_project_and_folder_metadata(project)
691+
folder_name = 'root'
692+
if folder:
693+
folder_name = folder['name']
714694
params = {
715695
"project_id": project_meta['id'],
716696
"team_id": project_meta["team_id"]
717697
}
718-
json_req = {"image_names": image_names, "remove_user_ids": ["all"]}
698+
json_req = {
699+
"image_names": image_names,
700+
"remove_user_ids": ["all"],
701+
"folder_name": folder_name
702+
}
703+
719704
response = _api.send_request(
720705
req_type='PUT',
721706
path='/images/editAssignment',

superannotate/db/utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from ..exceptions import SABaseException, SAImageSizeTooLarge, SANonExistingProjectNameException
1414
import datetime
1515
import boto3
16+
from .project_api import get_project_metadata_bare
1617

1718
_api = API.get_instance()
1819
logger = logging.getLogger("superannotate-python-sdk")
@@ -731,3 +732,25 @@ def __attach_image_urls_to_project_thread(
731732
logger.warning(e)
732733
else:
733734
uploaded[thread_id] += uploaded_imgs
735+
736+
737+
def _search_folders(project, folder_name=None, includeUsers=False):
738+
if not isinstance(project, dict):
739+
project = get_project_metadata_bare(project)
740+
team_id, project_id = project["team_id"], project["id"]
741+
params = {
742+
'team_id': team_id,
743+
'project_id': project_id,
744+
'offset': 0,
745+
'name': folder_name,
746+
'is_root': 0,
747+
'includeUsers': includeUsers
748+
}
749+
750+
response = _api.send_request(req_type='GET', path='/folders', params=params)
751+
if not response.ok:
752+
raise SABaseException(
753+
response.status_code, "Couldn't search folders " + response.text
754+
)
755+
response = response.json()
756+
return response

tests/test_assign_images.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_assign_images(tmpdir):
1616
projects = sa.search_projects(PROJECT_NAME_VECTOR1, return_metadata=True)
1717
for project in projects:
1818
sa.delete_project(project)
19-
19+
time.sleep(1)
2020
project = sa.create_project(PROJECT_NAME_VECTOR1, "test", "Vector")
2121
email = sa.get_team_metadata()["users"][0]["email"]
2222
sa.share_project(project, email, "QA")
@@ -70,7 +70,7 @@ def test_assign_images_folder(tmpdir):
7070
projects = sa.search_projects(PROJECT_NAME_VECTOR2, return_metadata=True)
7171
for project in projects:
7272
sa.delete_project(project)
73-
73+
time.sleep(1)
7474
project = sa.create_project(PROJECT_NAME_VECTOR2, "test", "Vector")
7575
email = sa.get_team_metadata()["users"][0]["email"]
7676
sa.share_project(project, email, "QA")
@@ -118,4 +118,66 @@ def test_assign_images_folder(tmpdir):
118118
assert im1_metadata["annotator_id"] == email
119119
assert im2_metadata["annotator_id"] == email
120120
assert im1_metadata["qa_id"] is None
121-
assert im2_metadata["qa_id"] is None
121+
assert im2_metadata["qa_id"] is None
122+
123+
124+
def test_unassign_images(tmpdir):
125+
tmpdir = Path(tmpdir)
126+
projects = sa.search_projects(PROJECT_NAME_VECTOR1, return_metadata=True)
127+
for project in projects:
128+
sa.delete_project(project)
129+
time.sleep(1)
130+
project = sa.create_project(PROJECT_NAME_VECTOR1, "test", "Vector")
131+
email = sa.get_team_metadata()["users"][0]["email"]
132+
sa.share_project(project, email, "QA")
133+
sa.upload_images_from_folder_to_project(
134+
project, "./tests/sample_project_vector"
135+
)
136+
sa.assign_images(
137+
project, ["example_image_1.jpg", "example_image_2.jpg"], email
138+
)
139+
sa.unassign_images(
140+
project,
141+
["example_image_1.jpg", "example_image_2.jpg"],
142+
)
143+
144+
im1_metadata = sa.get_image_metadata(project, "example_image_1.jpg")
145+
im2_metadata = sa.get_image_metadata(project, "example_image_2.jpg")
146+
147+
assert im1_metadata["qa_id"] == None
148+
assert im2_metadata["qa_id"] == None
149+
150+
151+
def test_assign_folder(tmpdir):
152+
tmpdir = Path(tmpdir)
153+
projects = sa.search_projects(PROJECT_NAME_VECTOR1, return_metadata=True)
154+
for project in projects:
155+
sa.delete_project(project)
156+
time.sleep(1)
157+
project = sa.create_project(PROJECT_NAME_VECTOR1, "test", "Vector")
158+
folder_name = "assign_folder"
159+
sa.create_folder(project, folder_name)
160+
email = sa.get_team_metadata()["users"][1]["email"]
161+
sa.share_project(project, email, "QA")
162+
sa.assign_folder(project, folder_name, [email])
163+
folders = sa._search_folders(PROJECT_NAME_VECTOR1, includeUsers=True)
164+
assert len(folders["data"][0]['folder_users']) > 0
165+
166+
167+
def test_unassign_folder(tmpdir):
168+
tmpdir = Path(tmpdir)
169+
projects = sa.search_projects(PROJECT_NAME_VECTOR1, return_metadata=True)
170+
for project in projects:
171+
sa.delete_project(project)
172+
time.sleep(1)
173+
project = sa.create_project(PROJECT_NAME_VECTOR1, "test", "Vector")
174+
folder_name = "assign_folder"
175+
sa.create_folder(project, folder_name)
176+
email = sa.get_team_metadata()["users"][1]["email"]
177+
sa.share_project(project, email, "QA")
178+
sa.assign_folder(project, folder_name, [email])
179+
folders = sa._search_folders(PROJECT_NAME_VECTOR1, includeUsers=True)
180+
assert len(folders["data"][0]['folder_users']) > 0
181+
sa.unassign_folder(project, folder_name)
182+
folders = sa._search_folders(PROJECT_NAME_VECTOR1, includeUsers=True)
183+
assert len(folders["data"][0]['folder_users']) == 0

0 commit comments

Comments
 (0)