@@ -986,6 +986,21 @@ def list_objects(self, bucket: str) -> List[str]:
986986 objs .append (obj ["Key" ])
987987 return objs
988988
989+ def list_object_versions (self , bucket : str ) -> Dict [str , List [str ]]:
990+ """
991+ List version identifiers of stored resource objects
992+ :param bucket: Bucket name
993+ :return: Dictionary of object version identifiers {key: [version_ids, ...]}
994+ """
995+ objs = defaultdict (list )
996+ paginator = self .s3 .get_paginator ("list_object_versions" )
997+ for page in paginator .paginate (Bucket = bucket ):
998+ for obj in page .get ("Versions" , list ()):
999+ objs [obj ["Key" ]].append (obj ["VersionId" ])
1000+ for obj in page .get ("DeleteMarkers" , list ()):
1001+ objs [obj ["Key" ]].append (obj ["VersionId" ])
1002+ return dict (objs )
1003+
9891004 def remove_object (self , bucket : str , object_uid : str ) -> None :
9901005 """
9911006 Remove resource object from object storage
@@ -1002,7 +1017,28 @@ def remove_objects(self, bucket: str, object_uids: Iterable[str]) -> None:
10021017 :param bucket: Bucket name
10031018 :param object_uids: Object identifiers
10041019 """
1005- for delete_objects in chunks ([{"Key" : uid } for uid in object_uids ], 1000 ):
1020+ for delete_objects in chunks ([{"Key" : uid } for uid in object_uids ], 100 ):
1021+ self .s3 .delete_objects (Bucket = bucket , Delete = {"Objects" : delete_objects })
1022+
1023+ def remove_object_versions (
1024+ self , bucket : str , object_versions : Dict [str , List [str ]]
1025+ ) -> None :
1026+ """
1027+ Bulk remove resource object versions from object storage
1028+
1029+ :param bucket: Bucket name
1030+ :param object_versions: Object version identifiers
1031+ """
1032+ versions = iter (
1033+ (uid , version_id )
1034+ for uid , versions in object_versions .items ()
1035+ for version_id in versions
1036+ )
1037+ deletion_chunks = chunks (
1038+ [{"Key" : uid , "VersionId" : version_id } for uid , version_id in versions ],
1039+ 100 ,
1040+ )
1041+ for delete_objects in deletion_chunks :
10061042 self .s3 .delete_objects (Bucket = bucket , Delete = {"Objects" : delete_objects })
10071043
10081044 def check_bucket_exists (self , bucket : str , create : bool = False ) -> bool :
0 commit comments