@@ -1415,118 +1415,26 @@ def upload_images_from_folder_to_project(
14151415 :return: uploaded, could-not-upload, existing-images filepaths
14161416 :rtype: tuple (3 members) of list of strs
14171417 """
1418- uploaded_image_entities = []
1419- failed_images = []
1420- project_name , folder_name = extract_project_folder (project )
1421- ProcessedImage = namedtuple ("ProcessedImage" , ["uploaded" , "path" , "entity" ])
1422-
1423- def _upload_local_image (image_path : str ):
1424- with open (image_path , "rb" ) as image :
1425- image_bytes = BytesIO (image .read ())
1426- upload_response = controller .upload_image_to_s3 (
1427- project_name = project_name ,
1428- image_path = image_path ,
1429- image_bytes = image_bytes ,
1430- folder_name = folder_name ,
1431- image_quality_in_editor = image_quality_in_editor ,
1432- )
1433-
1434- if not upload_response .errors and upload_response .data :
1435- entity = upload_response .data
1436- return ProcessedImage (uploaded = True , path = entity .path , entity = entity )
1437- else :
1438- return ProcessedImage (uploaded = False , path = image_path , entity = None )
1439-
1440- def _upload_s3_image (image_path : str ):
1441- try :
1442- image_bytes = controller .get_image_from_s3 (
1443- s3_bucket = from_s3_bucket , image_path = image_path
1444- ).data
1445- except AppValidationException as e :
1446- logger .warning (e )
1447- return image_path
1448- upload_response = controller .upload_image_to_s3 (
1449- project_name = project_name ,
1450- image_path = image_path ,
1451- image_bytes = image_bytes ,
1452- folder_name = folder_name ,
1453- image_quality_in_editor = image_quality_in_editor ,
1454- )
1455- if not upload_response .errors and upload_response .data :
1456- entity = upload_response .data
1457- return ProcessedImage (uploaded = True , path = entity .path , entity = entity )
1458- else :
1459- return ProcessedImage (uploaded = False , path = image_path , entity = None )
1460-
1461- paths = []
1462- if from_s3_bucket is None :
1463- for extension in extensions :
1464- if recursive_subfolders :
1465- paths += list (Path (folder_path ).rglob (f"*.{ extension .lower ()} " ))
1466- if os .name != "nt" :
1467- paths += list (Path (folder_path ).rglob (f"*.{ extension .upper ()} " ))
1468- else :
1469- paths += list (Path (folder_path ).glob (f"*.{ extension .lower ()} " ))
1470- if os .name != "nt" :
1471- paths += list (Path (folder_path ).glob (f"*.{ extension .upper ()} " ))
1472-
1473- else :
1474- s3_client = boto3 .client ("s3" )
1475- paginator = s3_client .get_paginator ("list_objects_v2" )
1476- response_iterator = paginator .paginate (
1477- Bucket = from_s3_bucket , Prefix = folder_path
1478- )
1479- for response in response_iterator :
1480- for object_data in response ["Contents" ]:
1481- key = object_data ["Key" ]
1482- if not recursive_subfolders and "/" in key [len (folder_path ) + 1 :]:
1483- continue
1484- for extension in extensions :
1485- if key .endswith (f".{ extension .lower ()} " ) or key .endswith (
1486- f".{ extension .upper ()} "
1487- ):
1488- paths .append (key )
1489- break
1490-
1491- filtered_paths = []
1492- for path in paths :
1493- not_in_exclude_list = [x not in Path (path ).name for x in exclude_file_patterns ]
1494- if all (not_in_exclude_list ):
1495- filtered_paths .append (path )
14961418
1497- duplication_counter = Counter (filtered_paths )
1498- images_to_upload , duplicated_images = (
1499- set (filtered_paths ),
1500- [item for item in duplication_counter if duplication_counter [item ] > 1 ],
1419+ project_name , folder_name = extract_project_folder (project )
1420+ use_case = controller .upload_images_from_folder_to_project (
1421+ project_name = project_name ,
1422+ folder_name = folder_name ,
1423+ folder_path = folder_path ,
1424+ extensions = extensions ,
1425+ annotation_status = annotation_status ,
1426+ from_s3_bucket = from_s3_bucket ,
1427+ exclude_file_patterns = exclude_file_patterns ,
1428+ recursive_sub_folders = recursive_subfolders ,
1429+ image_quality_in_editor = image_quality_in_editor ,
15011430 )
1502- upload_method = _upload_s3_image if from_s3_bucket else _upload_local_image
1503- with concurrent .futures .ThreadPoolExecutor (max_workers = 10 ) as executor :
1504- results = [
1505- executor .submit (upload_method , image_path )
1506- for image_path in images_to_upload
1507- ]
1431+ images_to_upload , _ = use_case .images_to_upload
1432+ if use_case .is_valid ():
15081433 with tqdm (total = len (images_to_upload )) as progress_bar :
1509- for future in concurrent .futures .as_completed (results ):
1510- processed_image = future .result ()
1511- if processed_image .uploaded and processed_image .entity :
1512- uploaded_image_entities .append (processed_image .entity )
1513- else :
1514- failed_images .append (processed_image .path )
1434+ for _ in use_case .execute ():
15151435 progress_bar .update (1 )
1516- uploaded = []
1517- duplicates = []
1518- for i in range (0 , len (uploaded_image_entities ), 500 ):
1519- response = controller .upload_images (
1520- project_name = project_name ,
1521- folder_name = folder_name ,
1522- images = uploaded_image_entities [i : i + 500 ], # noqa: E203
1523- annotation_status = annotation_status ,
1524- )
1525- attachments , duplications = response .data
1526- uploaded .extend (attachments )
1527- duplicates .extend (duplications )
1528-
1529- return uploaded , failed_images , duplicates
1436+ return use_case .data
1437+ raise AppValidationException (use_case .response .errors )
15301438
15311439
15321440@Trackable
@@ -1782,28 +1690,6 @@ def upload_videos_from_folder_to_project(
17821690 """
17831691
17841692 project_name , folder_name = extract_project_folder (project )
1785- project = controller .get_project_metadata (project_name ).data
1786- if project ["project" ].project_type == constances .ProjectType .VIDEO .value :
1787- raise AppValidationException (
1788- "The function does not support projects containing videos attached with URLs"
1789- )
1790- uploaded_image_entities = []
1791- failed_images = []
1792-
1793- def _upload_image (image_path : str ) -> str :
1794- with open (image_path , "rb" ) as image :
1795- image_bytes = BytesIO (image .read ())
1796- upload_response = controller .upload_image_to_s3 (
1797- project_name = project_name ,
1798- image_path = image_path ,
1799- image_bytes = image_bytes ,
1800- folder_name = folder_name ,
1801- image_quality_in_editor = image_quality_in_editor ,
1802- )
1803- if not upload_response .errors :
1804- uploaded_image_entities .append (upload_response .data )
1805- else :
1806- return image_path
18071693
18081694 video_paths = []
18091695 for extension in extensions :
@@ -1821,7 +1707,9 @@ def _upload_image(image_path: str) -> str:
18211707 not_in_exclude_list = [x not in Path (path ).name for x in exclude_file_patterns ]
18221708 if all (not_in_exclude_list ):
18231709 filtered_paths .append (path )
1824- for path in video_paths :
1710+
1711+ uploaded_images , failed_images = [], []
1712+ for path in tqdm (video_paths ):
18251713 with tempfile .TemporaryDirectory () as temp_path :
18261714 res = controller .extract_video_frames (
18271715 project_name = project_name ,
@@ -1834,25 +1722,25 @@ def _upload_image(image_path: str) -> str:
18341722 annotation_status = annotation_status ,
18351723 image_quality_in_editor = image_quality_in_editor ,
18361724 )
1837- if not res .errors :
1838- extracted_frame_paths = res .data
1839- # with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
1840- # for image_path in extracted_frame_paths:
1841- # failed_images.append(executor.submit(_upload_image, image_path))
1842- for image_path in extracted_frame_paths :
1843- failed_images . append ( _upload_image ( image_path ))
1844- for i in range ( 0 , len ( uploaded_image_entities ), 500 ):
1845- controller . upload_images (
1846- project_name = project_name ,
1847- folder_name = folder_name ,
1848- images = uploaded_image_entities [ i : i + 500 ], # noqa: E203
1849- annotation_status = annotation_status ,
1850- )
1851- uploaded_images = [
1852- image . path
1853- for image in uploaded_image_entities
1854- if image . name not in failed_images
1855- ]
1725+ if res .errors :
1726+ raise AppException ( res .errors )
1727+ use_case = controller . upload_images_from_folder_to_project (
1728+ project_name = project_name ,
1729+ folder_name = folder_name ,
1730+ folder_path = temp_path ,
1731+ annotation_status = annotation_status ,
1732+ image_quality_in_editor = image_quality_in_editor ,
1733+ )
1734+ images_to_upload , _ = use_case . images_to_upload
1735+ if use_case . is_valid ():
1736+ for _ in use_case . execute ():
1737+ pass
1738+ uploaded , failed_images , _ = use_case . data
1739+ uploaded_images . append ( uploaded )
1740+ failed_images . append ( failed_images )
1741+ else :
1742+ raise AppValidationException ( use_case . response . errors )
1743+
18561744 return uploaded_images , failed_images
18571745
18581746
@@ -1892,28 +1780,6 @@ def upload_video_to_project(
18921780 """
18931781
18941782 project_name , folder_name = extract_project_folder (project )
1895- project = controller .get_project_metadata (project_name ).data
1896- if project ["project" ].project_type == constances .ProjectType .VIDEO .value :
1897- raise AppValidationException (
1898- "The function does not support projects containing videos attached with URLs"
1899- )
1900- uploaded_image_entities = []
1901- failed_images = []
1902-
1903- def _upload_image (image_path : str ) -> str :
1904- with open (image_path , "rb" ) as image :
1905- image_bytes = BytesIO (image .read ())
1906- upload_response = controller .upload_image_to_s3 (
1907- project_name = project_name ,
1908- image_path = image_path ,
1909- image_bytes = image_bytes ,
1910- folder_name = folder_name ,
1911- )
1912- if not upload_response .errors :
1913- uploaded_image_entities .append (upload_response .data )
1914- else :
1915- return image_path
1916-
19171783 with tempfile .TemporaryDirectory () as temp_path :
19181784 res = controller .extract_video_frames (
19191785 project_name = project_name ,
@@ -1926,25 +1792,22 @@ def _upload_image(image_path: str) -> str:
19261792 annotation_status = annotation_status ,
19271793 image_quality_in_editor = image_quality_in_editor ,
19281794 )
1929- if not res .errors :
1930- extracted_frame_paths = res .data
1931- with concurrent .futures .ThreadPoolExecutor (max_workers = 10 ) as executor :
1932- for image_path in extracted_frame_paths :
1933- failed_images .append (executor .submit (_upload_image , image_path ))
1934-
1935- for i in range (0 , len (uploaded_image_entities ), 500 ):
1936- controller .upload_images (
1795+ if res .errors :
1796+ raise AppException (res .errors )
1797+ use_case = controller .upload_images_from_folder_to_project (
19371798 project_name = project_name ,
19381799 folder_name = folder_name ,
1939- images = uploaded_image_entities [ i : i + 500 ], # noqa: E203
1800+ folder_path = temp_path ,
19401801 annotation_status = annotation_status ,
1802+ image_quality_in_editor = image_quality_in_editor ,
19411803 )
1942- uploaded_images = [
1943- image .name
1944- for image in uploaded_image_entities
1945- if image .name not in failed_images
1946- ]
1947- return uploaded_images
1804+ images_to_upload , _ = use_case .images_to_upload
1805+ if use_case .is_valid ():
1806+ with tqdm (total = len (images_to_upload )) as progress_bar :
1807+ for _ in use_case .execute ():
1808+ progress_bar .update (1 )
1809+ return use_case .data [0 ]
1810+ raise AppValidationException (use_case .response .errors )
19481811
19491812
19501813@Trackable
0 commit comments