@@ -1455,7 +1455,17 @@ def delete_blob(
14551455 timeout = timeout ,
14561456 )
14571457
1458- def delete_blobs (self , blobs , on_error = None , client = None , timeout = _DEFAULT_TIMEOUT ):
1458+ def delete_blobs (
1459+ self ,
1460+ blobs ,
1461+ on_error = None ,
1462+ client = None ,
1463+ timeout = _DEFAULT_TIMEOUT ,
1464+ if_generation_match = None ,
1465+ if_generation_not_match = None ,
1466+ if_metageneration_match = None ,
1467+ if_metageneration_not_match = None ,
1468+ ):
14591469 """Deletes a list of blobs from the current bucket.
14601470
14611471 Uses :meth:`delete_blob` to delete each individual blob.
@@ -1484,15 +1494,74 @@ def delete_blobs(self, blobs, on_error=None, client=None, timeout=_DEFAULT_TIMEO
14841494 Can also be passed as a tuple (connect_timeout, read_timeout).
14851495 See :meth:`requests.Session.request` documentation for details.
14861496
1497+ :type if_generation_match: list of long
1498+ :param if_generation_match: (Optional) Make the operation conditional on whether
1499+ the blob's current generation matches the given value.
1500+ Setting to 0 makes the operation succeed only if there
1501+ are no live versions of the blob. The list must match
1502+ ``blobs`` item-to-item.
1503+
1504+ :type if_generation_not_match: list of long
1505+ :param if_generation_not_match: (Optional) Make the operation conditional on whether
1506+ the blob's current generation does not match the given
1507+ value. If no live blob exists, the precondition fails.
1508+ Setting to 0 makes the operation succeed only if there
1509+ is a live version of the blob. The list must match
1510+ ``blobs`` item-to-item.
1511+
1512+ :type if_metageneration_match: list of long
1513+ :param if_metageneration_match: (Optional) Make the operation conditional on whether the
1514+ blob's current metageneration matches the given value.
1515+ The list must match ``blobs`` item-to-item.
1516+
1517+ :type if_metageneration_not_match: list of long
1518+ :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the
1519+ blob's current metageneration does not match the given value.
1520+ The list must match ``blobs`` item-to-item.
1521+
14871522 :raises: :class:`~google.cloud.exceptions.NotFound` (if
14881523 `on_error` is not passed).
1524+
1525+ Example:
1526+ Delete blobs using generation match preconditions.
1527+
1528+ >>> from google.cloud import storage
1529+
1530+ >>> client = storage.Client()
1531+ >>> bucket = client.bucket("bucket-name")
1532+
1533+ >>> blobs = [bucket.blob("blob-name-1"), bucket.blob("blob-name-2")]
1534+ >>> if_generation_match = [None] * len(blobs)
1535+ >>> if_generation_match[0] = "123" # precondition for "blob-name-1"
1536+
1537+ >>> bucket.delete_blobs(blobs, if_generation_match=if_generation_match)
14891538 """
1539+ _raise_if_len_differs (
1540+ len (blobs ),
1541+ if_generation_match = if_generation_match ,
1542+ if_generation_not_match = if_generation_not_match ,
1543+ if_metageneration_match = if_metageneration_match ,
1544+ if_metageneration_not_match = if_metageneration_not_match ,
1545+ )
1546+ if_generation_match = iter (if_generation_match or [])
1547+ if_generation_not_match = iter (if_generation_not_match or [])
1548+ if_metageneration_match = iter (if_metageneration_match or [])
1549+ if_metageneration_not_match = iter (if_metageneration_not_match or [])
1550+
14901551 for blob in blobs :
14911552 try :
14921553 blob_name = blob
14931554 if not isinstance (blob_name , six .string_types ):
14941555 blob_name = blob .name
1495- self .delete_blob (blob_name , client = client , timeout = timeout )
1556+ self .delete_blob (
1557+ blob_name ,
1558+ client = client ,
1559+ timeout = timeout ,
1560+ if_generation_match = next (if_generation_match , None ),
1561+ if_generation_not_match = next (if_generation_not_match , None ),
1562+ if_metageneration_match = next (if_metageneration_match , None ),
1563+ if_metageneration_not_match = next (if_metageneration_not_match , None ),
1564+ )
14961565 except NotFound :
14971566 if on_error is not None :
14981567 on_error (blob )
@@ -2980,3 +3049,23 @@ def generate_signed_url(
29803049 headers = headers ,
29813050 query_parameters = query_parameters ,
29823051 )
3052+
3053+
3054+ def _raise_if_len_differs (expected_len , ** generation_match_args ):
3055+ """
3056+ Raise an error if any generation match argument
3057+ is set and its len differs from the given value.
3058+
3059+ :type expected_len: int
3060+ :param expected_len: Expected argument length in case it's set.
3061+
3062+ :type generation_match_args: dict
3063+ :param generation_match_args: Lists, which length must be checked.
3064+
3065+ :raises: :exc:`ValueError` if any argument set, but has an unexpected length.
3066+ """
3067+ for name , value in generation_match_args .items ():
3068+ if value is not None and len (value ) != expected_len :
3069+ raise ValueError (
3070+ "'{}' length must be the same as 'blobs' length" .format (name )
3071+ )
0 commit comments