Skip to content

Commit e7a1c50

Browse files
authored
GCSDeleteObjectsOperator empty prefix bug fix (#24353)
1 parent dd35fda commit e7a1c50

File tree

2 files changed

+25
-5
lines changed
  • airflow/providers/google/cloud/operators
  • tests/providers/google/cloud/operators

2 files changed

+25
-5
lines changed

β€Žairflow/providers/google/cloud/operators/gcs.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,11 @@ def __init__(
305305
self.delegate_to = delegate_to
306306
self.impersonation_chain = impersonation_chain
307307

308-
if not objects and not prefix:
309-
raise ValueError("Either object or prefix should be set. Both are None")
308+
if objects is None and prefix is None:
309+
err_message = "(Task {task_id}) Either object or prefix should be set. Both are None.".format(
310+
**kwargs
311+
)
312+
raise ValueError(err_message)
310313

311314
super().__init__(**kwargs)
312315

β€Žtests/providers/google/cloud/operators/test_gcs.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
TEST_PROJECT = "test-project"
3939
DELIMITER = ".csv"
4040
PREFIX = "TEST"
41-
MOCK_FILES = ["TEST1.csv", "TEST2.csv", "TEST3.csv"]
41+
MOCK_FILES = ["TEST1.csv", "TEST2.csv", "TEST3.csv", "OTHERTEST1.csv"]
4242
TEST_OBJECT = "dir1/test-object"
4343
LOCAL_FILE_PATH = "/home/airflow/gcp/test-object"
4444
IMPERSONATION_CHAIN = ["ACCOUNT_1", "ACCOUNT_2", "ACCOUNT_3"]
@@ -108,7 +108,7 @@ def test_object_create_acl(self, mock_hook):
108108
)
109109

110110

111-
class TestGoogleCloudStorageDeleteOperator(unittest.TestCase):
111+
class TestGCSDeleteObjectsOperator(unittest.TestCase):
112112
@mock.patch("airflow.providers.google.cloud.operators.gcs.GCSHook")
113113
def test_delete_objects(self, mock_hook):
114114
operator = GCSDeleteObjectsOperator(task_id=TASK_ID, bucket_name=TEST_BUCKET, objects=MOCK_FILES[0:2])
@@ -125,7 +125,7 @@ def test_delete_objects(self, mock_hook):
125125

126126
@mock.patch("airflow.providers.google.cloud.operators.gcs.GCSHook")
127127
def test_delete_prefix(self, mock_hook):
128-
mock_hook.return_value.list.return_value = MOCK_FILES[1:3]
128+
mock_hook.return_value.list.return_value = MOCK_FILES[1:4]
129129
operator = GCSDeleteObjectsOperator(task_id=TASK_ID, bucket_name=TEST_BUCKET, prefix=PREFIX)
130130

131131
operator.execute(None)
@@ -138,6 +138,23 @@ def test_delete_prefix(self, mock_hook):
138138
any_order=True,
139139
)
140140

141+
@mock.patch("airflow.providers.google.cloud.operators.gcs.GCSHook")
142+
def test_delete_prefix_as_empty_string(self, mock_hook):
143+
mock_hook.return_value.list.return_value = MOCK_FILES[0:4]
144+
operator = GCSDeleteObjectsOperator(task_id=TASK_ID, bucket_name=TEST_BUCKET, prefix="")
145+
146+
operator.execute(None)
147+
mock_hook.return_value.list.assert_called_once_with(bucket_name=TEST_BUCKET, prefix="")
148+
mock_hook.return_value.delete.assert_has_calls(
149+
calls=[
150+
mock.call(bucket_name=TEST_BUCKET, object_name=MOCK_FILES[0]),
151+
mock.call(bucket_name=TEST_BUCKET, object_name=MOCK_FILES[1]),
152+
mock.call(bucket_name=TEST_BUCKET, object_name=MOCK_FILES[2]),
153+
mock.call(bucket_name=TEST_BUCKET, object_name=MOCK_FILES[3]),
154+
],
155+
any_order=True,
156+
)
157+
141158

142159
class TestGoogleCloudStorageListOperator(unittest.TestCase):
143160
@mock.patch("airflow.providers.google.cloud.operators.gcs.GCSHook")

0 commit comments

Comments
 (0)