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
@@ -827,9 +828,9 @@ def upload_images_to_project(
827828 :return: uploaded, could-not-upload, existing-images filepaths
828829 :rtype: tuple (3 members) of list of strs
829830 """
830- project , project_folder = get_project_and_folder_metadata (project )
831- project_folder_name = project ["name" ] + (
832- f'/{ project_folder ["name" ]} ' if project_folder else ""
831+ project , folder = get_project_and_folder_metadata (project )
832+ folder_name = project ["name" ] + (
833+ f'/{ folder ["name" ]} ' if folder else ""
833834 )
834835 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
835836 if upload_state == "External" :
@@ -847,7 +848,7 @@ def upload_images_to_project(
847848 project
848849 )
849850 team_id , project_id = project ["team_id" ], project ["id" ]
850- existing_images = search_images ((project , project_folder ))
851+ existing_images = search_images ((project , folder ))
851852 duplicate_images = []
852853 for existing_image in existing_images :
853854 i = - 1
@@ -865,31 +866,31 @@ def upload_images_to_project(
865866 )
866867 len_img_paths = len (img_paths )
867868 logger .info (
868- "Uploading %s images to project %s." , len_img_paths , project_folder_name
869+ "Uploading %s images to project %s." , len_img_paths , folder_name
869870 )
870871 if len_img_paths == 0 :
871872 return ([], [], duplicate_images )
872- params = {'team_id' : team_id }
873+
874+
875+ if folder :
876+ folder_id = folder ["id" ]
877+ else :
878+ folder_id = get_project_root_folder_id (project )
879+
880+ params = {'team_id' : team_id , 'folder_id' : folder_id }
873881 uploaded = [[] for _ in range (_NUM_THREADS )]
874882 tried_upload = [[] for _ in range (_NUM_THREADS )]
875883 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
876884 finish_event = threading .Event ()
877- chunksize = int (math .ceil (len (img_paths ) / _NUM_THREADS ))
878- response = _api .send_request (
879- req_type = 'GET' ,
880- path = f'/project/{ project_id } /sdkImageUploadToken' ,
881- params = params
882- )
883- if not response .ok :
884- raise SABaseException (
885- response .status_code , "Couldn't get upload token " + response .text
886- )
887- if project_folder is not None :
888- project_folder_id = project_folder ["id" ]
889- else :
890- project_folder_id = None
891- res = response .json ()
885+
886+ res = _get_upload_auth_token (params = params ,project_id = project_id )
887+
892888 prefix = res ['filePath' ]
889+ limit = res ['availableImageCount' ]
890+ images_to_upload = img_paths [:limit ]
891+ images_to_skip = img_paths [limit :]
892+ chunksize = int (math .ceil (len (images_to_upload ) / _NUM_THREADS ))
893+
893894 tqdm_thread = threading .Thread (
894895 target = __tqdm_thread_image_upload ,
895896 args = (len_img_paths , tried_upload , finish_event ),
@@ -902,9 +903,9 @@ def upload_images_to_project(
902903 t = threading .Thread (
903904 target = __upload_images_to_aws_thread ,
904905 args = (
905- res , img_paths , project , annotation_status , prefix , thread_id ,
906+ res , images_to_upload , project , annotation_status , prefix , thread_id ,
906907 chunksize , couldnt_upload , uploaded , tried_upload ,
907- image_quality_in_editor , from_s3_bucket , project_folder_id
908+ image_quality_in_editor , from_s3_bucket , folder_id
908909 ),
909910 daemon = True
910911 )
@@ -923,6 +924,7 @@ def upload_images_to_project(
923924 for f in upload_thread :
924925 list_of_uploaded .append (str (f ))
925926
927+ list_of_not_uploaded += images_to_skip
926928 return (list_of_uploaded , list_of_not_uploaded , duplicate_images )
927929
928930
@@ -960,9 +962,9 @@ def attach_image_urls_to_project(
960962 :rtype: tuple
961963 """
962964
963- project , project_folder = get_project_and_folder_metadata (project )
964- project_folder_name = project ["name" ] + (
965- f'/{ project_folder ["name" ]} ' if project_folder else ""
965+ project , folder = get_project_and_folder_metadata (project )
966+ folder_name = project ["name" ] + (
967+ f'/{ folder ["name" ]} ' if folder else ""
966968 )
967969 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
968970 if upload_state == "Basic" :
@@ -978,7 +980,7 @@ def attach_image_urls_to_project(
978980 duplicate_idx_csv = existing_names .duplicated (subset = "name" , keep = "first" )
979981 duplicate_images = existing_names [duplicate_idx_csv ]["name" ].tolist ()
980982 existing_names = existing_names [~ duplicate_idx_csv ]
981- existing_images = search_images ((project , project_folder ))
983+ existing_images = search_images ((project , folder ))
982984 duplicate_idx = []
983985 for ind , _ in image_data [image_data ["name" ].isnull ()].iterrows ():
984986 while True :
@@ -1000,37 +1002,35 @@ def attach_image_urls_to_project(
10001002 )
10011003 image_data = pd .DataFrame (image_data , columns = ["name" , "url" ])
10021004 img_names_urls = image_data .values .tolist ()
1003- len_img_names_urls = len (img_names_urls )
10041005 logger .info (
1005- "Uploading %s images to project %s." , len_img_names_urls ,
1006- project_folder_name
1006+ "Uploading %s images to project %s." , len ( img_names_urls ) ,
1007+ folder_name
10071008 )
1008- if len_img_names_urls == 0 :
1009+ if len ( img_names_urls ) == 0 :
10091010 return ([], [], duplicate_images )
1010- params = {'team_id' : team_id }
1011+
1012+ if folder :
1013+ folder_id = folder ["id" ]
1014+ else :
1015+ folder_id = get_project_root_folder_id (project )
1016+
1017+ params = {'team_id' : team_id , 'folder_id' : folder_id }
10111018 uploaded = [[] for _ in range (_NUM_THREADS )]
10121019 tried_upload = [[] for _ in range (_NUM_THREADS )]
10131020 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
10141021 finish_event = threading .Event ()
1015- chunksize = int (math .ceil (len_img_names_urls / _NUM_THREADS ))
1016- response = _api .send_request (
1017- req_type = 'GET' ,
1018- path = f'/project/{ project_id } /sdkImageUploadToken' ,
1019- params = params
1020- )
1021- if not response .ok :
1022- raise SABaseException (
1023- response .status_code , "Couldn't get upload token " + response .text
1024- )
1025- if project_folder is not None :
1026- project_folder_id = project_folder ["id" ]
1027- else :
1028- project_folder_id = None
1029- res = response .json ()
1022+
1023+ res = _get_upload_auth_token (params = params ,project_id = project_id )
1024+
10301025 prefix = res ['filePath' ]
1026+ limit = res ['availableImageCount' ]
1027+ images_to_upload = img_names_urls [:limit ]
1028+ images_to_skip = img_names_urls [limit :]
1029+ chunksize = int (math .ceil (len (images_to_upload ) / _NUM_THREADS ))
1030+
10311031 tqdm_thread = threading .Thread (
10321032 target = __tqdm_thread_image_upload ,
1033- args = (len_img_names_urls , tried_upload , finish_event ),
1033+ args = (len ( images_to_upload ) , tried_upload , finish_event ),
10341034 daemon = True
10351035 )
10361036 tqdm_thread .start ()
@@ -1039,9 +1039,9 @@ def attach_image_urls_to_project(
10391039 t = threading .Thread (
10401040 target = __attach_image_urls_to_project_thread ,
10411041 args = (
1042- res , img_names_urls , project , annotation_status , prefix ,
1042+ res , images_to_upload , project , annotation_status , prefix ,
10431043 thread_id , chunksize , couldnt_upload , uploaded , tried_upload ,
1044- project_folder_id
1044+ folder_id
10451045 ),
10461046 daemon = True
10471047 )
@@ -1060,6 +1060,7 @@ def attach_image_urls_to_project(
10601060 for f in upload_thread :
10611061 list_of_uploaded .append (str (f ))
10621062
1063+ list_of_not_uploaded += [i [0 ] for i in images_to_skip ]
10631064 return (list_of_uploaded , list_of_not_uploaded , duplicate_images )
10641065
10651066
0 commit comments