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