3434 fill_class_and_attribute_ids , get_annotation_classes_name_to_id ,
3535 search_annotation_classes
3636)
37- from .images import get_image_metadata , search_images , search_images_all_folders
37+ from .images import get_image_metadata , search_images , search_images_all_folders , get_project_root_folder_id
3838from .project_api import (
3939 get_project_and_folder_metadata , get_project_metadata_bare ,
4040 get_project_metadata_with_users
4141)
4242from .users import get_team_contributor_metadata
43+ from .utils import _get_upload_auth_token
4344
4445logger = logging .getLogger ("superannotate-python-sdk" )
4546
@@ -825,9 +826,9 @@ def upload_images_to_project(
825826 :return: uploaded, could-not-upload, existing-images filepaths
826827 :rtype: tuple (3 members) of list of strs
827828 """
828- project , project_folder = get_project_and_folder_metadata (project )
829- project_folder_name = project ["name" ] + (
830- f'/{ project_folder ["name" ]} ' if project_folder else ""
829+ project , folder = get_project_and_folder_metadata (project )
830+ folder_name = project ["name" ] + (
831+ f'/{ folder ["name" ]} ' if folder else ""
831832 )
832833 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
833834 if upload_state == "External" :
@@ -845,7 +846,7 @@ def upload_images_to_project(
845846 project
846847 )
847848 team_id , project_id = project ["team_id" ], project ["id" ]
848- existing_images = search_images ((project , project_folder ))
849+ existing_images = search_images ((project , folder ))
849850 duplicate_images = []
850851 for existing_image in existing_images :
851852 i = - 1
@@ -863,31 +864,31 @@ def upload_images_to_project(
863864 )
864865 len_img_paths = len (img_paths )
865866 logger .info (
866- "Uploading %s images to project %s." , len_img_paths , project_folder_name
867+ "Uploading %s images to project %s." , len_img_paths , folder_name
867868 )
868869 if len_img_paths == 0 :
869870 return ([], [], duplicate_images )
870- params = {'team_id' : team_id }
871+
872+
873+ if folder :
874+ folder_id = folder ["id" ]
875+ else :
876+ folder_id = get_project_root_folder_id (project )
877+
878+ params = {'team_id' : team_id , 'folder_id' : folder_id }
871879 uploaded = [[] for _ in range (_NUM_THREADS )]
872880 tried_upload = [[] for _ in range (_NUM_THREADS )]
873881 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
874882 finish_event = threading .Event ()
875- chunksize = int (math .ceil (len (img_paths ) / _NUM_THREADS ))
876- response = _api .send_request (
877- req_type = 'GET' ,
878- path = f'/project/{ project_id } /sdkImageUploadToken' ,
879- params = params
880- )
881- if not response .ok :
882- raise SABaseException (
883- response .status_code , "Couldn't get upload token " + response .text
884- )
885- if project_folder is not None :
886- project_folder_id = project_folder ["id" ]
887- else :
888- project_folder_id = None
889- res = response .json ()
883+
884+ res = _get_upload_auth_token (params = params ,project_id = project_id )
885+
890886 prefix = res ['filePath' ]
887+ limit = res ['availableImageCount' ]
888+ images_to_upload = img_paths [:limit ]
889+ images_to_skip = img_paths [limit :]
890+ chunksize = int (math .ceil (len (images_to_upload ) / _NUM_THREADS ))
891+
891892 tqdm_thread = threading .Thread (
892893 target = __tqdm_thread_image_upload ,
893894 args = (len_img_paths , tried_upload , finish_event ),
@@ -900,9 +901,9 @@ def upload_images_to_project(
900901 t = threading .Thread (
901902 target = __upload_images_to_aws_thread ,
902903 args = (
903- res , img_paths , project , annotation_status , prefix , thread_id ,
904+ res , images_to_upload , project , annotation_status , prefix , thread_id ,
904905 chunksize , couldnt_upload , uploaded , tried_upload ,
905- image_quality_in_editor , from_s3_bucket , project_folder_id
906+ image_quality_in_editor , from_s3_bucket , folder_id
906907 ),
907908 daemon = True
908909 )
@@ -921,6 +922,7 @@ def upload_images_to_project(
921922 for f in upload_thread :
922923 list_of_uploaded .append (str (f ))
923924
925+ list_of_not_uploaded += images_to_skip
924926 return (list_of_uploaded , list_of_not_uploaded , duplicate_images )
925927
926928
@@ -958,9 +960,9 @@ def attach_image_urls_to_project(
958960 :rtype: tuple
959961 """
960962
961- project , project_folder = get_project_and_folder_metadata (project )
962- project_folder_name = project ["name" ] + (
963- f'/{ project_folder ["name" ]} ' if project_folder else ""
963+ project , folder = get_project_and_folder_metadata (project )
964+ folder_name = project ["name" ] + (
965+ f'/{ folder ["name" ]} ' if folder else ""
964966 )
965967 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
966968 if upload_state == "Basic" :
@@ -976,7 +978,7 @@ def attach_image_urls_to_project(
976978 duplicate_idx_csv = existing_names .duplicated (subset = "name" , keep = "first" )
977979 duplicate_images = existing_names [duplicate_idx_csv ]["name" ].tolist ()
978980 existing_names = existing_names [~ duplicate_idx_csv ]
979- existing_images = search_images ((project , project_folder ))
981+ existing_images = search_images ((project , folder ))
980982 duplicate_idx = []
981983 for ind , _ in image_data [image_data ["name" ].isnull ()].iterrows ():
982984 while True :
@@ -998,37 +1000,35 @@ def attach_image_urls_to_project(
9981000 )
9991001 image_data = pd .DataFrame (image_data , columns = ["name" , "url" ])
10001002 img_names_urls = image_data .values .tolist ()
1001- len_img_names_urls = len (img_names_urls )
10021003 logger .info (
1003- "Attaching %s images to project %s." , len_img_names_urls ,
1004- project_folder_name
1004+ "Uploading %s images to project %s." , len ( img_names_urls ) ,
1005+ folder_name
10051006 )
1006- if len_img_names_urls == 0 :
1007+ if len ( img_names_urls ) == 0 :
10071008 return ([], [], duplicate_images )
1008- params = {'team_id' : team_id }
1009+
1010+ if folder :
1011+ folder_id = folder ["id" ]
1012+ else :
1013+ folder_id = get_project_root_folder_id (project )
1014+
1015+ params = {'team_id' : team_id , 'folder_id' : folder_id }
10091016 uploaded = [[] for _ in range (_NUM_THREADS )]
10101017 tried_upload = [[] for _ in range (_NUM_THREADS )]
10111018 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
10121019 finish_event = threading .Event ()
1013- chunksize = int (math .ceil (len_img_names_urls / _NUM_THREADS ))
1014- response = _api .send_request (
1015- req_type = 'GET' ,
1016- path = f'/project/{ project_id } /sdkImageUploadToken' ,
1017- params = params
1018- )
1019- if not response .ok :
1020- raise SABaseException (
1021- response .status_code , "Couldn't get upload token " + response .text
1022- )
1023- if project_folder is not None :
1024- project_folder_id = project_folder ["id" ]
1025- else :
1026- project_folder_id = None
1027- res = response .json ()
1020+
1021+ res = _get_upload_auth_token (params = params ,project_id = project_id )
1022+
10281023 prefix = res ['filePath' ]
1024+ limit = res ['availableImageCount' ]
1025+ images_to_upload = img_names_urls [:limit ]
1026+ images_to_skip = img_names_urls [limit :]
1027+ chunksize = int (math .ceil (len (images_to_upload ) / _NUM_THREADS ))
1028+
10291029 tqdm_thread = threading .Thread (
10301030 target = __tqdm_thread_image_upload ,
1031- args = (len_img_names_urls , tried_upload , finish_event ),
1031+ args = (len ( images_to_upload ) , tried_upload , finish_event ),
10321032 daemon = True
10331033 )
10341034 tqdm_thread .start ()
@@ -1037,9 +1037,9 @@ def attach_image_urls_to_project(
10371037 t = threading .Thread (
10381038 target = __attach_image_urls_to_project_thread ,
10391039 args = (
1040- res , img_names_urls , project , annotation_status , prefix ,
1040+ res , images_to_upload , project , annotation_status , prefix ,
10411041 thread_id , chunksize , couldnt_upload , uploaded , tried_upload ,
1042- project_folder_id
1042+ folder_id
10431043 ),
10441044 daemon = True
10451045 )
@@ -1058,6 +1058,7 @@ def attach_image_urls_to_project(
10581058 for f in upload_thread :
10591059 list_of_uploaded .append (str (f ))
10601060
1061+ list_of_not_uploaded += [i [0 ] for i in images_to_skip ]
10611062 return (list_of_uploaded , list_of_not_uploaded , duplicate_images )
10621063
10631064
0 commit comments