Repository: googleapis/google-cloud-python

Issue:
Storage: sourceGeneration in copy_blob
Hi,
I need that the copy_blob function of Bucket object in Cloud Storage library manage the "sourceGeneration" parameter to copy the archived version of an object.

Thanks


Discussion:

Resolving patch:
diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py
--- a/storage/google/cloud/storage/bucket.py
+++ b/storage/google/cloud/storage/bucket.py
@@ -654,7 +654,7 @@ def delete_blobs(self, blobs, on_error=None, client=None):
                     raise
 
     def copy_blob(self, blob, destination_bucket, new_name=None,
-                  client=None, preserve_acl=True):
+                  client=None, preserve_acl=True, source_generation=None):
         """Copy the given blob to the given bucket, optionally with a new name.
 
         If :attr:`user_project` is set, bills the API request to that project.
@@ -678,6 +678,10 @@ def copy_blob(self, blob, destination_bucket, new_name=None,
         :param preserve_acl: Optional. Copies ACL from old blob to new blob.
                              Default: True.
 
+        :type source_generation: long
+        :param source_generation: Optional. The generation of the blob to be
+                                  copied.
+
         :rtype: :class:`google.cloud.storage.blob.Blob`
         :returns: The new Blob.
         """
@@ -687,6 +691,9 @@ def copy_blob(self, blob, destination_bucket, new_name=None,
         if self.user_project is not None:
             query_params['userProject'] = self.user_project
 
+        if source_generation is not None:
+            query_params['sourceGeneration'] = source_generation
+
         if new_name is None:
             new_name = blob.name
 


Test patch:
diff --git a/storage/tests/unit/test_bucket.py b/storage/tests/unit/test_bucket.py
--- a/storage/tests/unit/test_bucket.py
+++ b/storage/tests/unit/test_bucket.py
@@ -728,6 +728,31 @@ class _Blob(object):
         self.assertEqual(kw['path'], COPY_PATH)
         self.assertEqual(kw['query_params'], {})
 
+    def test_copy_blobs_source_generation(self):
+        SOURCE = 'source'
+        DEST = 'dest'
+        BLOB_NAME = 'blob-name'
+        GENERATION = 1512565576797178
+
+        class _Blob(object):
+            name = BLOB_NAME
+            path = '/b/%s/o/%s' % (SOURCE, BLOB_NAME)
+
+        connection = _Connection({})
+        client = _Client(connection)
+        source = self._make_one(client=client, name=SOURCE)
+        dest = self._make_one(client=client, name=DEST)
+        blob = _Blob()
+        new_blob = source.copy_blob(blob, dest, source_generation=GENERATION)
+        self.assertIs(new_blob.bucket, dest)
+        self.assertEqual(new_blob.name, BLOB_NAME)
+        kw, = connection._requested
+        COPY_PATH = '/b/%s/o/%s/copyTo/b/%s/o/%s' % (SOURCE, BLOB_NAME,
+                                                     DEST, BLOB_NAME)
+        self.assertEqual(kw['method'], 'POST')
+        self.assertEqual(kw['path'], COPY_PATH)
+        self.assertEqual(kw['query_params'], {'sourceGeneration' : GENERATION})
+
     def test_copy_blobs_preserve_acl(self):
         from google.cloud.storage.acl import ObjectACL