From 5e83d9d69612bd35dc2bd2e2796aec5f55c304d2 Mon Sep 17 00:00:00 2001 From: Pulkit Aggarwal Date: Thu, 10 Jul 2025 14:39:05 +0000 Subject: [PATCH 1/5] docs: add samples for move api to rename an object --- samples/snippets/snippets_test.py | 18 +++++++ .../snippets/storage_move_file_atomically.py | 52 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 samples/snippets/storage_move_file_atomically.py diff --git a/samples/snippets/snippets_test.py b/samples/snippets/snippets_test.py index 3fe377b6b..fc83eab85 100644 --- a/samples/snippets/snippets_test.py +++ b/samples/snippets/snippets_test.py @@ -73,6 +73,7 @@ import storage_list_soft_deleted_objects import storage_make_public import storage_move_file +import storage_move_file_atomically import storage_object_get_kms_key import storage_remove_bucket_label import storage_remove_cors_configuration @@ -1037,3 +1038,20 @@ def test_storage_restore_soft_deleted_object(test_soft_delete_enabled_bucket, ca # Verify the restoration blob = test_soft_delete_enabled_bucket.get_blob(blob_name) assert blob is not None + +def test_move_object(test_blob): + bucket = test_blob.bucket + try: + test_bucket_create.delete_blob("test_move_blob_atomic") + except google.cloud.exceptions.NotFound: + print(f"test_move_blob_atomic not found in bucket {bucket.name}") + + storage_move_file_atomically.move_object( + bucket.name, + test_blob.name, + "test_move_blob_atomic", + ) + + assert bucket.get_blob("test_move_blob_atomic") is not None + assert bucket.get_blob(test_blob.name) is None + diff --git a/samples/snippets/storage_move_file_atomically.py b/samples/snippets/storage_move_file_atomically.py new file mode 100644 index 000000000..48e9150d5 --- /dev/null +++ b/samples/snippets/storage_move_file_atomically.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +# [START storage_move_object] +from google.cloud import storage + +def move_object(bucket_name, blob_name, new_blob_name): + """Moves a blob to a new name within the same bucket using the move API.""" + # The ID of your GCS bucket + # bucket_name = "your-bucket-name" + + # The ID of your GCS object to move + # blob_name = "your-file-name" + + # The new ID of the GCS object + # new_blob_name = "new-file-name" + + storage_client = storage.Client() + + bucket = storage_client.bucket(bucket_name) + blob_to_move = bucket.blob(blob_name) + + # Use move_blob to perform an efficient, server-side move. + moved_blob = bucket.move_blob( + blob=blob_to_move, new_name=new_blob_name + ) + + print(f"Blob {blob_to_move.name} has been moved to {moved_blob.name}.") + +# [END storage_move_object] + +if __name__ == "__main__": + move_object( + bucket_name=sys.argv[1], + blob_name=sys.argv[2], + new_blob_name=sys.argv[3], + ) From 3f1e5b155dc2d1e6d96d38c83e17b4830d348165 Mon Sep 17 00:00:00 2001 From: Pulkit Aggarwal Date: Thu, 10 Jul 2025 14:39:34 +0000 Subject: [PATCH 2/5] minor change --- samples/snippets/snippets_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/snippets_test.py b/samples/snippets/snippets_test.py index fc83eab85..2908afd66 100644 --- a/samples/snippets/snippets_test.py +++ b/samples/snippets/snippets_test.py @@ -1042,7 +1042,7 @@ def test_storage_restore_soft_deleted_object(test_soft_delete_enabled_bucket, ca def test_move_object(test_blob): bucket = test_blob.bucket try: - test_bucket_create.delete_blob("test_move_blob_atomic") + bucket.delete_blob("test_move_blob_atomic") except google.cloud.exceptions.NotFound: print(f"test_move_blob_atomic not found in bucket {bucket.name}") From 9ae8030c5fcdafc61deb3411943c479c26ac2cda Mon Sep 17 00:00:00 2001 From: Pulkit Aggarwal Date: Thu, 10 Jul 2025 14:48:26 +0000 Subject: [PATCH 3/5] fix lint errors --- samples/snippets/storage_move_file_atomically.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/snippets/storage_move_file_atomically.py b/samples/snippets/storage_move_file_atomically.py index 48e9150d5..ec6b9ce80 100644 --- a/samples/snippets/storage_move_file_atomically.py +++ b/samples/snippets/storage_move_file_atomically.py @@ -19,6 +19,7 @@ # [START storage_move_object] from google.cloud import storage + def move_object(bucket_name, blob_name, new_blob_name): """Moves a blob to a new name within the same bucket using the move API.""" # The ID of your GCS bucket @@ -42,6 +43,7 @@ def move_object(bucket_name, blob_name, new_blob_name): print(f"Blob {blob_to_move.name} has been moved to {moved_blob.name}.") + # [END storage_move_object] if __name__ == "__main__": From df1c492db583817de7bff1c16d8c3354b5244f13 Mon Sep 17 00:00:00 2001 From: Pulkit Aggarwal Date: Thu, 10 Jul 2025 15:07:31 +0000 Subject: [PATCH 4/5] minor fix --- samples/snippets/snippets_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/snippets_test.py b/samples/snippets/snippets_test.py index 2908afd66..91018f3dd 100644 --- a/samples/snippets/snippets_test.py +++ b/samples/snippets/snippets_test.py @@ -1039,6 +1039,7 @@ def test_storage_restore_soft_deleted_object(test_soft_delete_enabled_bucket, ca blob = test_soft_delete_enabled_bucket.get_blob(blob_name) assert blob is not None + def test_move_object(test_blob): bucket = test_blob.bucket try: @@ -1054,4 +1055,3 @@ def test_move_object(test_blob): assert bucket.get_blob("test_move_blob_atomic") is not None assert bucket.get_blob(test_blob.name) is None - From e0c516efc5f08dc609c5265aa586426199d1dba0 Mon Sep 17 00:00:00 2001 From: Pulkit Aggarwal Date: Thu, 17 Jul 2025 05:40:07 +0000 Subject: [PATCH 5/5] resolving comments --- samples/snippets/storage_move_file_atomically.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/snippets/storage_move_file_atomically.py b/samples/snippets/storage_move_file_atomically.py index ec6b9ce80..d659cf366 100644 --- a/samples/snippets/storage_move_file_atomically.py +++ b/samples/snippets/storage_move_file_atomically.py @@ -20,15 +20,15 @@ from google.cloud import storage -def move_object(bucket_name, blob_name, new_blob_name): +def move_object(bucket_name: str, blob_name: str, new_blob_name: str) -> None: """Moves a blob to a new name within the same bucket using the move API.""" - # The ID of your GCS bucket + # The name of your GCS bucket # bucket_name = "your-bucket-name" - # The ID of your GCS object to move + # The name of your GCS object to move # blob_name = "your-file-name" - # The new ID of the GCS object + # The new name of the GCS object # new_blob_name = "new-file-name" storage_client = storage.Client()