This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 7b79b81a1e2 Keep Campaign Manager delete report provision check in 
__init__ (#70530)
7b79b81a1e2 is described below

commit 7b79b81a1e295a17b5e6d71a307ea275bae7e179
Author: Dr Alex Mitre <[email protected]>
AuthorDate: Sat Aug 29 12:02:35 2026 -0700

    Keep Campaign Manager delete report provision check in __init__ (#70530)
    
    The check only asks which of report_name / report_id was supplied, never
    what the values are, so it belongs in the constructor: a static authoring
    mistake should surface once at Dag parse time rather than on every task
    instance and retry on a worker. Moving it to execute() would also misreport
    a supplied argument as missing under render_template_as_native_obj=True,
    where a provided field can render to None.
    
    See https://github.com/apache/airflow/issues/70296 for the rule this 
follows.
---
 generated/known_airflow_exceptions.txt             |  1 -
 .../operators/campaign_manager.py                  |  9 +++------
 .../operators/test_campaign_manager.py             | 22 +++++++++++++++++++++-
 .../ci/prek/validate_operators_init_exemptions.txt |  1 -
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/generated/known_airflow_exceptions.txt 
b/generated/known_airflow_exceptions.txt
index acfd9ae3eb8..97aab5bce79 100644
--- a/generated/known_airflow_exceptions.txt
+++ b/generated/known_airflow_exceptions.txt
@@ -319,7 +319,6 @@ 
providers/google/src/airflow/providers/google/leveldb/hooks/leveldb.py::4
 
providers/google/src/airflow/providers/google/marketing_platform/hooks/campaign_manager.py::2
 
providers/google/src/airflow/providers/google/marketing_platform/hooks/search_ads.py::1
 
providers/google/src/airflow/providers/google/marketing_platform/operators/bid_manager.py::3
-providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py::2
 
providers/google/src/airflow/providers/google/marketing_platform/sensors/display_video.py::1
 providers/google/src/airflow/providers/google/suite/hooks/calendar.py::1
 providers/google/src/airflow/providers/google/suite/hooks/sheets.py::1
diff --git 
a/providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py
 
b/providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py
index 4634d58b26b..49107025f65 100644
--- 
a/providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py
+++ 
b/providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py
@@ -27,10 +27,10 @@ from typing import TYPE_CHECKING, Any
 
 from googleapiclient import http
 
-from airflow.providers.common.compat.sdk import AirflowException
 from airflow.providers.google.cloud.hooks.gcs import GCSHook
 from airflow.providers.google.marketing_platform.hooks.campaign_manager import 
GoogleCampaignManagerHook
 from airflow.providers.google.version_compat import BaseOperator
+from airflow.utils.helpers import exactly_one
 
 if TYPE_CHECKING:
     from airflow.providers.common.compat.sdk import Context
@@ -84,11 +84,8 @@ class 
GoogleCampaignManagerDeleteReportOperator(BaseOperator):
         **kwargs,
     ) -> None:
         super().__init__(**kwargs)
-        if not (report_name or report_id):
-            raise AirflowException("Please provide `report_name` or 
`report_id`.")
-        if report_name and report_id:
-            raise AirflowException("Please provide only one parameter 
`report_name` or `report_id`.")
-
+        if not exactly_one(report_name is not None, report_id is not None):
+            raise ValueError("Please provide exactly one of `report_name` or 
`report_id`.")
         self.profile_id = profile_id
         self.report_name = report_name
         self.report_id = report_id
diff --git 
a/providers/google/tests/unit/google/marketing_platform/operators/test_campaign_manager.py
 
b/providers/google/tests/unit/google/marketing_platform/operators/test_campaign_manager.py
index dca13918d01..4c91fface0c 100644
--- 
a/providers/google/tests/unit/google/marketing_platform/operators/test_campaign_manager.py
+++ 
b/providers/google/tests/unit/google/marketing_platform/operators/test_campaign_manager.py
@@ -77,7 +77,7 @@ class TestGoogleCampaignManagerDeleteReportOperator:
             api_version=API_VERSION,
             task_id="test_task",
         )
-        op.execute(context=None)
+        op.execute(context={})
         hook_mock.assert_called_once_with(
             gcp_conn_id=GCP_CONN_ID,
             api_version=API_VERSION,
@@ -87,6 +87,26 @@ class TestGoogleCampaignManagerDeleteReportOperator:
             profile_id=PROFILE_ID, report_id=REPORT_ID
         )
 
+    @pytest.mark.parametrize(
+        ("report_name", "report_id"),
+        [
+            pytest.param(None, None, id="both-missing"),
+            pytest.param(REPORT_NAME, REPORT_ID, id="both-provided"),
+        ],
+    )
+    def test_missing_or_conflicting_report_params_fail_at_construction(self, 
report_name, report_id):
+        # Provision checks on templated fields stay in `__init__` (rewritten 
with
+        # `is not None` polarity) so static authoring mistakes surface at Dag 
parse
+        # time — see https://github.com/apache/airflow/issues/70296.
+        with pytest.raises(ValueError, match="Please provide exactly one of 
`report_name` or `report_id`"):
+            GoogleCampaignManagerDeleteReportOperator(
+                profile_id=PROFILE_ID,
+                report_name=report_name,
+                report_id=report_id,
+                api_version=API_VERSION,
+                task_id="test_task",
+            )
+
 
 @pytest.mark.db_test
 class TestGoogleCampaignManagerDownloadReportOperator:
diff --git a/scripts/ci/prek/validate_operators_init_exemptions.txt 
b/scripts/ci/prek/validate_operators_init_exemptions.txt
index 73dd45c9731..af75c526a1d 100644
--- a/scripts/ci/prek/validate_operators_init_exemptions.txt
+++ b/scripts/ci/prek/validate_operators_init_exemptions.txt
@@ -19,5 +19,4 @@ 
providers/google/src/airflow/providers/google/cloud/sensors/bigquery_dts.py::Big
 
providers/google/src/airflow/providers/google/cloud/sensors/cloud_composer.py::CloudComposerExternalTaskSensor
 
providers/google/src/airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py::AzureFileShareToGCSOperator
 
providers/google/src/airflow/providers/google/cloud/transfers/gcs_to_bigquery.py::GCSToBigQueryOperator
-providers/google/src/airflow/providers/google/marketing_platform/operators/campaign_manager.py::GoogleCampaignManagerDeleteReportOperator
 
providers/microsoft/psrp/src/airflow/providers/microsoft/psrp/operators/psrp.py::PsrpOperator

Reply via email to