apache-airflow-providers-google 15.1.0rc1__py3-none-any.whl → 19.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. airflow/providers/google/3rd-party-licenses/NOTICE +2 -12
  2. airflow/providers/google/__init__.py +3 -3
  3. airflow/providers/google/ads/hooks/ads.py +39 -6
  4. airflow/providers/google/ads/operators/ads.py +2 -2
  5. airflow/providers/google/ads/transfers/ads_to_gcs.py +2 -2
  6. airflow/providers/google/assets/gcs.py +1 -11
  7. airflow/providers/google/cloud/bundles/__init__.py +16 -0
  8. airflow/providers/google/cloud/bundles/gcs.py +161 -0
  9. airflow/providers/google/cloud/hooks/alloy_db.py +1 -1
  10. airflow/providers/google/cloud/hooks/bigquery.py +176 -293
  11. airflow/providers/google/cloud/hooks/cloud_batch.py +1 -1
  12. airflow/providers/google/cloud/hooks/cloud_build.py +1 -1
  13. airflow/providers/google/cloud/hooks/cloud_composer.py +288 -15
  14. airflow/providers/google/cloud/hooks/cloud_logging.py +109 -0
  15. airflow/providers/google/cloud/hooks/cloud_memorystore.py +1 -1
  16. airflow/providers/google/cloud/hooks/cloud_run.py +18 -10
  17. airflow/providers/google/cloud/hooks/cloud_sql.py +102 -23
  18. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +29 -7
  19. airflow/providers/google/cloud/hooks/compute.py +1 -1
  20. airflow/providers/google/cloud/hooks/compute_ssh.py +6 -2
  21. airflow/providers/google/cloud/hooks/datacatalog.py +10 -1
  22. airflow/providers/google/cloud/hooks/dataflow.py +72 -95
  23. airflow/providers/google/cloud/hooks/dataform.py +1 -1
  24. airflow/providers/google/cloud/hooks/datafusion.py +21 -19
  25. airflow/providers/google/cloud/hooks/dataplex.py +2 -2
  26. airflow/providers/google/cloud/hooks/dataprep.py +1 -1
  27. airflow/providers/google/cloud/hooks/dataproc.py +73 -72
  28. airflow/providers/google/cloud/hooks/dataproc_metastore.py +1 -1
  29. airflow/providers/google/cloud/hooks/dlp.py +1 -1
  30. airflow/providers/google/cloud/hooks/functions.py +1 -1
  31. airflow/providers/google/cloud/hooks/gcs.py +112 -15
  32. airflow/providers/google/cloud/hooks/gdm.py +1 -1
  33. airflow/providers/google/cloud/hooks/gen_ai.py +196 -0
  34. airflow/providers/google/cloud/hooks/kubernetes_engine.py +3 -3
  35. airflow/providers/google/cloud/hooks/looker.py +6 -2
  36. airflow/providers/google/cloud/hooks/managed_kafka.py +1 -1
  37. airflow/providers/google/cloud/hooks/mlengine.py +4 -3
  38. airflow/providers/google/cloud/hooks/pubsub.py +3 -0
  39. airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
  40. airflow/providers/google/cloud/hooks/spanner.py +74 -9
  41. airflow/providers/google/cloud/hooks/stackdriver.py +11 -9
  42. airflow/providers/google/cloud/hooks/tasks.py +1 -1
  43. airflow/providers/google/cloud/hooks/translate.py +2 -2
  44. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +2 -210
  45. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +3 -3
  46. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +28 -2
  47. airflow/providers/google/cloud/hooks/vertex_ai/experiment_service.py +202 -0
  48. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +308 -8
  49. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +79 -75
  50. airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +1 -1
  51. airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +1 -1
  52. airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +1 -1
  53. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +223 -0
  54. airflow/providers/google/cloud/hooks/vision.py +3 -3
  55. airflow/providers/google/cloud/hooks/workflows.py +1 -1
  56. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  57. airflow/providers/google/cloud/links/base.py +77 -13
  58. airflow/providers/google/cloud/links/bigquery.py +0 -47
  59. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  60. airflow/providers/google/cloud/links/bigtable.py +0 -48
  61. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  62. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  63. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  64. airflow/providers/google/cloud/links/{life_sciences.py → cloud_run.py} +5 -27
  65. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  66. airflow/providers/google/cloud/links/cloud_storage_transfer.py +17 -44
  67. airflow/providers/google/cloud/links/cloud_tasks.py +7 -26
  68. airflow/providers/google/cloud/links/compute.py +0 -58
  69. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  70. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  71. airflow/providers/google/cloud/links/dataflow.py +0 -34
  72. airflow/providers/google/cloud/links/dataform.py +0 -64
  73. airflow/providers/google/cloud/links/datafusion.py +1 -96
  74. airflow/providers/google/cloud/links/dataplex.py +0 -154
  75. airflow/providers/google/cloud/links/dataprep.py +0 -24
  76. airflow/providers/google/cloud/links/dataproc.py +11 -95
  77. airflow/providers/google/cloud/links/datastore.py +0 -31
  78. airflow/providers/google/cloud/links/kubernetes_engine.py +9 -60
  79. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  80. airflow/providers/google/cloud/links/mlengine.py +0 -70
  81. airflow/providers/google/cloud/links/pubsub.py +0 -32
  82. airflow/providers/google/cloud/links/spanner.py +0 -33
  83. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  84. airflow/providers/google/cloud/links/translate.py +17 -187
  85. airflow/providers/google/cloud/links/vertex_ai.py +28 -195
  86. airflow/providers/google/cloud/links/workflows.py +0 -52
  87. airflow/providers/google/cloud/log/gcs_task_handler.py +58 -22
  88. airflow/providers/google/cloud/log/stackdriver_task_handler.py +9 -6
  89. airflow/providers/google/cloud/openlineage/CloudStorageTransferJobFacet.json +68 -0
  90. airflow/providers/google/cloud/openlineage/CloudStorageTransferRunFacet.json +60 -0
  91. airflow/providers/google/cloud/openlineage/DataFusionRunFacet.json +32 -0
  92. airflow/providers/google/cloud/openlineage/facets.py +102 -1
  93. airflow/providers/google/cloud/openlineage/mixins.py +10 -8
  94. airflow/providers/google/cloud/openlineage/utils.py +15 -1
  95. airflow/providers/google/cloud/operators/alloy_db.py +71 -56
  96. airflow/providers/google/cloud/operators/bigquery.py +73 -636
  97. airflow/providers/google/cloud/operators/bigquery_dts.py +4 -6
  98. airflow/providers/google/cloud/operators/bigtable.py +37 -8
  99. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  100. airflow/providers/google/cloud/operators/cloud_batch.py +3 -3
  101. airflow/providers/google/cloud/operators/cloud_build.py +76 -33
  102. airflow/providers/google/cloud/operators/cloud_composer.py +129 -41
  103. airflow/providers/google/cloud/operators/cloud_logging_sink.py +341 -0
  104. airflow/providers/google/cloud/operators/cloud_memorystore.py +69 -43
  105. airflow/providers/google/cloud/operators/cloud_run.py +24 -6
  106. airflow/providers/google/cloud/operators/cloud_sql.py +8 -17
  107. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +93 -12
  108. airflow/providers/google/cloud/operators/compute.py +9 -41
  109. airflow/providers/google/cloud/operators/datacatalog.py +157 -21
  110. airflow/providers/google/cloud/operators/dataflow.py +40 -16
  111. airflow/providers/google/cloud/operators/dataform.py +15 -5
  112. airflow/providers/google/cloud/operators/datafusion.py +42 -21
  113. airflow/providers/google/cloud/operators/dataplex.py +194 -110
  114. airflow/providers/google/cloud/operators/dataprep.py +1 -5
  115. airflow/providers/google/cloud/operators/dataproc.py +80 -36
  116. airflow/providers/google/cloud/operators/dataproc_metastore.py +97 -89
  117. airflow/providers/google/cloud/operators/datastore.py +23 -7
  118. airflow/providers/google/cloud/operators/dlp.py +6 -29
  119. airflow/providers/google/cloud/operators/functions.py +17 -8
  120. airflow/providers/google/cloud/operators/gcs.py +12 -9
  121. airflow/providers/google/cloud/operators/gen_ai.py +389 -0
  122. airflow/providers/google/cloud/operators/kubernetes_engine.py +62 -100
  123. airflow/providers/google/cloud/operators/looker.py +2 -2
  124. airflow/providers/google/cloud/operators/managed_kafka.py +108 -53
  125. airflow/providers/google/cloud/operators/natural_language.py +1 -1
  126. airflow/providers/google/cloud/operators/pubsub.py +68 -15
  127. airflow/providers/google/cloud/operators/spanner.py +26 -13
  128. airflow/providers/google/cloud/operators/speech_to_text.py +2 -3
  129. airflow/providers/google/cloud/operators/stackdriver.py +1 -9
  130. airflow/providers/google/cloud/operators/tasks.py +1 -12
  131. airflow/providers/google/cloud/operators/text_to_speech.py +2 -3
  132. airflow/providers/google/cloud/operators/translate.py +41 -17
  133. airflow/providers/google/cloud/operators/translate_speech.py +2 -3
  134. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +39 -19
  135. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +30 -10
  136. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +55 -27
  137. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +70 -8
  138. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +43 -9
  139. airflow/providers/google/cloud/operators/vertex_ai/experiment_service.py +435 -0
  140. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +532 -1
  141. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +135 -115
  142. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +12 -10
  143. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +57 -11
  144. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +31 -8
  145. airflow/providers/google/cloud/operators/vertex_ai/ray.py +393 -0
  146. airflow/providers/google/cloud/operators/video_intelligence.py +1 -1
  147. airflow/providers/google/cloud/operators/vision.py +2 -2
  148. airflow/providers/google/cloud/operators/workflows.py +18 -15
  149. airflow/providers/google/cloud/secrets/secret_manager.py +3 -2
  150. airflow/providers/google/cloud/sensors/bigquery.py +3 -3
  151. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -3
  152. airflow/providers/google/cloud/sensors/bigtable.py +11 -4
  153. airflow/providers/google/cloud/sensors/cloud_composer.py +533 -30
  154. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -3
  155. airflow/providers/google/cloud/sensors/dataflow.py +26 -10
  156. airflow/providers/google/cloud/sensors/dataform.py +2 -3
  157. airflow/providers/google/cloud/sensors/datafusion.py +4 -5
  158. airflow/providers/google/cloud/sensors/dataplex.py +2 -3
  159. airflow/providers/google/cloud/sensors/dataprep.py +2 -2
  160. airflow/providers/google/cloud/sensors/dataproc.py +2 -3
  161. airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -3
  162. airflow/providers/google/cloud/sensors/gcs.py +4 -5
  163. airflow/providers/google/cloud/sensors/looker.py +2 -3
  164. airflow/providers/google/cloud/sensors/pubsub.py +4 -5
  165. airflow/providers/google/cloud/sensors/tasks.py +2 -2
  166. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +2 -3
  167. airflow/providers/google/cloud/sensors/workflows.py +2 -3
  168. airflow/providers/google/cloud/transfers/adls_to_gcs.py +1 -1
  169. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +2 -2
  170. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +4 -3
  171. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +11 -8
  172. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +10 -5
  173. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +7 -3
  174. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +12 -1
  175. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +24 -10
  176. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +104 -5
  177. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  178. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +3 -3
  179. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +4 -4
  180. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +21 -13
  181. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +4 -3
  182. airflow/providers/google/cloud/transfers/gcs_to_local.py +6 -4
  183. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +11 -5
  184. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +6 -2
  185. airflow/providers/google/cloud/transfers/gdrive_to_local.py +2 -2
  186. airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
  187. airflow/providers/google/cloud/transfers/local_to_gcs.py +2 -2
  188. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
  189. airflow/providers/google/cloud/transfers/oracle_to_gcs.py +36 -11
  190. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +42 -9
  191. airflow/providers/google/cloud/transfers/s3_to_gcs.py +13 -7
  192. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +2 -2
  193. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +14 -5
  194. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +3 -3
  195. airflow/providers/google/cloud/transfers/sql_to_gcs.py +10 -10
  196. airflow/providers/google/cloud/triggers/bigquery.py +76 -35
  197. airflow/providers/google/cloud/triggers/cloud_build.py +1 -1
  198. airflow/providers/google/cloud/triggers/cloud_composer.py +303 -47
  199. airflow/providers/google/cloud/triggers/cloud_run.py +3 -3
  200. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +92 -2
  201. airflow/providers/google/cloud/triggers/dataflow.py +122 -0
  202. airflow/providers/google/cloud/triggers/datafusion.py +1 -1
  203. airflow/providers/google/cloud/triggers/dataplex.py +14 -2
  204. airflow/providers/google/cloud/triggers/dataproc.py +123 -53
  205. airflow/providers/google/cloud/triggers/kubernetes_engine.py +47 -28
  206. airflow/providers/google/cloud/triggers/mlengine.py +1 -1
  207. airflow/providers/google/cloud/triggers/pubsub.py +15 -19
  208. airflow/providers/google/cloud/triggers/vertex_ai.py +1 -1
  209. airflow/providers/google/cloud/utils/bigquery_get_data.py +1 -1
  210. airflow/providers/google/cloud/utils/credentials_provider.py +2 -2
  211. airflow/providers/google/cloud/utils/field_sanitizer.py +1 -1
  212. airflow/providers/google/cloud/utils/field_validator.py +2 -3
  213. airflow/providers/google/common/auth_backend/google_openid.py +4 -4
  214. airflow/providers/google/common/deprecated.py +2 -1
  215. airflow/providers/google/common/hooks/base_google.py +27 -9
  216. airflow/providers/google/common/hooks/operation_helpers.py +1 -1
  217. airflow/providers/google/common/links/storage.py +0 -22
  218. airflow/providers/google/common/utils/get_secret.py +31 -0
  219. airflow/providers/google/common/utils/id_token_credentials.py +3 -4
  220. airflow/providers/google/firebase/hooks/firestore.py +1 -1
  221. airflow/providers/google/firebase/operators/firestore.py +3 -3
  222. airflow/providers/google/get_provider_info.py +56 -52
  223. airflow/providers/google/go_module_utils.py +35 -3
  224. airflow/providers/google/leveldb/hooks/leveldb.py +27 -2
  225. airflow/providers/google/leveldb/operators/leveldb.py +2 -2
  226. airflow/providers/google/marketing_platform/hooks/campaign_manager.py +1 -1
  227. airflow/providers/google/marketing_platform/hooks/display_video.py +3 -109
  228. airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -1
  229. airflow/providers/google/marketing_platform/links/analytics_admin.py +5 -14
  230. airflow/providers/google/marketing_platform/operators/analytics_admin.py +2 -3
  231. airflow/providers/google/marketing_platform/operators/campaign_manager.py +6 -6
  232. airflow/providers/google/marketing_platform/operators/display_video.py +28 -489
  233. airflow/providers/google/marketing_platform/operators/search_ads.py +2 -2
  234. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +2 -2
  235. airflow/providers/google/marketing_platform/sensors/display_video.py +3 -64
  236. airflow/providers/google/suite/hooks/calendar.py +2 -2
  237. airflow/providers/google/suite/hooks/sheets.py +16 -2
  238. airflow/providers/google/suite/operators/sheets.py +8 -3
  239. airflow/providers/google/suite/sensors/drive.py +2 -2
  240. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +3 -3
  241. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  242. airflow/providers/google/suite/transfers/local_to_drive.py +3 -3
  243. airflow/providers/google/suite/transfers/sql_to_sheets.py +5 -4
  244. airflow/providers/google/version_compat.py +15 -1
  245. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/METADATA +90 -46
  246. apache_airflow_providers_google-19.3.0.dist-info/RECORD +331 -0
  247. apache_airflow_providers_google-19.3.0.dist-info/licenses/NOTICE +5 -0
  248. airflow/providers/google/cloud/hooks/automl.py +0 -673
  249. airflow/providers/google/cloud/hooks/life_sciences.py +0 -159
  250. airflow/providers/google/cloud/links/automl.py +0 -193
  251. airflow/providers/google/cloud/operators/automl.py +0 -1362
  252. airflow/providers/google/cloud/operators/life_sciences.py +0 -119
  253. airflow/providers/google/cloud/operators/mlengine.py +0 -112
  254. apache_airflow_providers_google-15.1.0rc1.dist-info/RECORD +0 -321
  255. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/WHEEL +0 -0
  256. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.3.0.dist-info}/entry_points.txt +0 -0
  257. {airflow/providers/google → apache_airflow_providers_google-19.3.0.dist-info/licenses}/LICENSE +0 -0
@@ -25,8 +25,9 @@ This module contains Google PubSub operators.
25
25
 
26
26
  from __future__ import annotations
27
27
 
28
- from collections.abc import Sequence
29
- from typing import TYPE_CHECKING, Any, Callable
28
+ from collections.abc import Callable, Sequence
29
+ from functools import cached_property
30
+ from typing import TYPE_CHECKING, Any
30
31
 
31
32
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
32
33
  from google.cloud.pubsub_v1.types import (
@@ -40,7 +41,8 @@ from google.cloud.pubsub_v1.types import (
40
41
  SchemaSettings,
41
42
  )
42
43
 
43
- from airflow.exceptions import AirflowException
44
+ from airflow.configuration import conf
45
+ from airflow.providers.common.compat.sdk import AirflowException
44
46
  from airflow.providers.google.cloud.hooks.pubsub import PubSubHook
45
47
  from airflow.providers.google.cloud.links.pubsub import PubSubSubscriptionLink, PubSubTopicLink
46
48
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
@@ -51,7 +53,8 @@ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
51
53
  if TYPE_CHECKING:
52
54
  from google.api_core.retry import Retry
53
55
 
54
- from airflow.utils.context import Context
56
+ from airflow.providers.common.compat.sdk import Context
57
+ from airflow.providers.openlineage.extractors import OperatorLineage
55
58
 
56
59
 
57
60
  class PubSubCreateTopicOperator(GoogleCloudBaseOperator):
@@ -182,7 +185,6 @@ class PubSubCreateTopicOperator(GoogleCloudBaseOperator):
182
185
  self.log.info("Created topic %s", self.topic)
183
186
  PubSubTopicLink.persist(
184
187
  context=context,
185
- task_instance=self,
186
188
  topic_id=self.topic,
187
189
  project_id=self.project_id or hook.project_id,
188
190
  )
@@ -359,15 +361,18 @@ class PubSubCreateSubscriptionOperator(GoogleCloudBaseOperator):
359
361
  self.timeout = timeout
360
362
  self.metadata = metadata
361
363
  self.impersonation_chain = impersonation_chain
364
+ self._resolved_subscription_name: str | None = None
362
365
 
363
- def execute(self, context: Context) -> str:
364
- hook = PubSubHook(
366
+ @cached_property
367
+ def pubsub_hook(self):
368
+ return PubSubHook(
365
369
  gcp_conn_id=self.gcp_conn_id,
366
370
  impersonation_chain=self.impersonation_chain,
367
371
  )
368
372
 
373
+ def execute(self, context: Context) -> str:
369
374
  self.log.info("Creating subscription for topic %s", self.topic)
370
- result = hook.create_subscription(
375
+ result = self.pubsub_hook.create_subscription(
371
376
  project_id=self.project_id,
372
377
  topic=self.topic,
373
378
  subscription=self.subscription,
@@ -389,14 +394,34 @@ class PubSubCreateSubscriptionOperator(GoogleCloudBaseOperator):
389
394
  )
390
395
 
391
396
  self.log.info("Created subscription for topic %s", self.topic)
397
+
398
+ # Store resolved subscription for Open Lineage
399
+ self._resolved_subscription_name = self.subscription or result
400
+
392
401
  PubSubSubscriptionLink.persist(
393
402
  context=context,
394
- task_instance=self,
395
- subscription_id=self.subscription or result, # result returns subscription name
396
- project_id=self.project_id or hook.project_id,
403
+ subscription_id=self._resolved_subscription_name, # result returns subscription name
404
+ project_id=self.project_id or self.pubsub_hook.project_id,
397
405
  )
398
406
  return result
399
407
 
408
+ def get_openlineage_facets_on_complete(self, _) -> OperatorLineage:
409
+ from airflow.providers.common.compat.openlineage.facet import Dataset
410
+ from airflow.providers.openlineage.extractors import OperatorLineage
411
+
412
+ topic_project_id = self.project_id or self.pubsub_hook.project_id
413
+ subscription_project_id = self.subscription_project_id or topic_project_id
414
+
415
+ return OperatorLineage(
416
+ inputs=[Dataset(namespace="pubsub", name=f"topic:{topic_project_id}:{self.topic}")],
417
+ outputs=[
418
+ Dataset(
419
+ namespace="pubsub",
420
+ name=f"subscription:{subscription_project_id}:{self._resolved_subscription_name}",
421
+ )
422
+ ],
423
+ )
424
+
400
425
 
401
426
  class PubSubDeleteTopicOperator(GoogleCloudBaseOperator):
402
427
  """
@@ -655,6 +680,9 @@ class PubSubPublishMessageOperator(GoogleCloudBaseOperator):
655
680
  ordering_key in PubsubMessage will be delivered to the subscribers in the order
656
681
  in which they are received by the Pub/Sub system. Otherwise, they may be
657
682
  delivered in any order. Default is False.
683
+ :param enable_open_telemetry_tracing: If true, enables OpenTelemetry tracing for
684
+ published messages. This allows distributed tracing of messages as they flow
685
+ through Pub/Sub topics. Default is False.
658
686
  :param impersonation_chain: Optional service account to impersonate using short-term
659
687
  credentials, or chained list of accounts required to get the access_token
660
688
  of the last account in the list, which will be impersonated in the request.
@@ -670,6 +698,7 @@ class PubSubPublishMessageOperator(GoogleCloudBaseOperator):
670
698
  "topic",
671
699
  "messages",
672
700
  "enable_message_ordering",
701
+ "enable_open_telemetry_tracing",
673
702
  "impersonation_chain",
674
703
  )
675
704
  ui_color = "#0273d4"
@@ -682,6 +711,7 @@ class PubSubPublishMessageOperator(GoogleCloudBaseOperator):
682
711
  project_id: str = PROVIDE_PROJECT_ID,
683
712
  gcp_conn_id: str = "google_cloud_default",
684
713
  enable_message_ordering: bool = False,
714
+ enable_open_telemetry_tracing: bool = False,
685
715
  impersonation_chain: str | Sequence[str] | None = None,
686
716
  **kwargs,
687
717
  ) -> None:
@@ -691,19 +721,32 @@ class PubSubPublishMessageOperator(GoogleCloudBaseOperator):
691
721
  self.messages = messages
692
722
  self.gcp_conn_id = gcp_conn_id
693
723
  self.enable_message_ordering = enable_message_ordering
724
+ self.enable_open_telemetry_tracing = enable_open_telemetry_tracing
694
725
  self.impersonation_chain = impersonation_chain
695
726
 
696
- def execute(self, context: Context) -> None:
697
- hook = PubSubHook(
727
+ @cached_property
728
+ def pubsub_hook(self):
729
+ return PubSubHook(
698
730
  gcp_conn_id=self.gcp_conn_id,
699
731
  impersonation_chain=self.impersonation_chain,
700
732
  enable_message_ordering=self.enable_message_ordering,
733
+ enable_open_telemetry_tracing=self.enable_open_telemetry_tracing,
701
734
  )
702
735
 
736
+ def execute(self, context: Context) -> None:
703
737
  self.log.info("Publishing to topic %s", self.topic)
704
- hook.publish(project_id=self.project_id, topic=self.topic, messages=self.messages)
738
+ self.pubsub_hook.publish(project_id=self.project_id, topic=self.topic, messages=self.messages)
705
739
  self.log.info("Published to topic %s", self.topic)
706
740
 
741
+ def get_openlineage_facets_on_complete(self, _) -> OperatorLineage:
742
+ from airflow.providers.common.compat.openlineage.facet import Dataset
743
+ from airflow.providers.openlineage.extractors import OperatorLineage
744
+
745
+ project_id = self.project_id or self.pubsub_hook.project_id
746
+ output_dataset = [Dataset(namespace="pubsub", name=f"topic:{project_id}:{self.topic}")]
747
+
748
+ return OperatorLineage(outputs=output_dataset)
749
+
707
750
 
708
751
  class PubSubPullOperator(GoogleCloudBaseOperator):
709
752
  """
@@ -770,7 +813,7 @@ class PubSubPullOperator(GoogleCloudBaseOperator):
770
813
  messages_callback: Callable[[list[ReceivedMessage], Context], Any] | None = None,
771
814
  gcp_conn_id: str = "google_cloud_default",
772
815
  impersonation_chain: str | Sequence[str] | None = None,
773
- deferrable: bool = False,
816
+ deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
774
817
  poll_interval: int = 300,
775
818
  **kwargs,
776
819
  ) -> None:
@@ -854,3 +897,13 @@ class PubSubPullOperator(GoogleCloudBaseOperator):
854
897
  messages_json = [ReceivedMessage.to_dict(m) for m in pulled_messages]
855
898
 
856
899
  return messages_json
900
+
901
+ def get_openlineage_facets_on_complete(self, _) -> OperatorLineage:
902
+ from airflow.providers.common.compat.openlineage.facet import Dataset
903
+ from airflow.providers.openlineage.extractors import OperatorLineage
904
+
905
+ output_dataset = [
906
+ Dataset(namespace="pubsub", name=f"subscription:{self.project_id}:{self.subscription}")
907
+ ]
908
+
909
+ return OperatorLineage(outputs=output_dataset)
@@ -20,16 +20,18 @@
20
20
  from __future__ import annotations
21
21
 
22
22
  from collections.abc import Sequence
23
+ from functools import cached_property
23
24
  from typing import TYPE_CHECKING
24
25
 
25
- from airflow.exceptions import AirflowException
26
+ from airflow.providers.common.compat.sdk import AirflowException
26
27
  from airflow.providers.google.cloud.hooks.spanner import SpannerHook
27
28
  from airflow.providers.google.cloud.links.spanner import SpannerDatabaseLink, SpannerInstanceLink
28
29
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
29
30
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
30
31
 
31
32
  if TYPE_CHECKING:
32
- from airflow.utils.context import Context
33
+ from airflow.providers.common.compat.sdk import Context
34
+ from airflow.providers.openlineage.extractors import OperatorLineage
33
35
 
34
36
 
35
37
  class SpannerDeployInstanceOperator(GoogleCloudBaseOperator):
@@ -122,7 +124,6 @@ class SpannerDeployInstanceOperator(GoogleCloudBaseOperator):
122
124
  )
123
125
  SpannerInstanceLink.persist(
124
126
  context=context,
125
- task_instance=self,
126
127
  instance_id=self.instance_id,
127
128
  project_id=self.project_id or hook.project_id,
128
129
  )
@@ -255,6 +256,13 @@ class SpannerQueryDatabaseInstanceOperator(GoogleCloudBaseOperator):
255
256
  self.impersonation_chain = impersonation_chain
256
257
  super().__init__(**kwargs)
257
258
 
259
+ @cached_property
260
+ def hook(self) -> SpannerHook:
261
+ return SpannerHook(
262
+ gcp_conn_id=self.gcp_conn_id,
263
+ impersonation_chain=self.impersonation_chain,
264
+ )
265
+
258
266
  def _validate_inputs(self) -> None:
259
267
  if self.project_id == "":
260
268
  raise AirflowException("The required parameter 'project_id' is empty")
@@ -266,10 +274,6 @@ class SpannerQueryDatabaseInstanceOperator(GoogleCloudBaseOperator):
266
274
  raise AirflowException("The required parameter 'query' is empty")
267
275
 
268
276
  def execute(self, context: Context):
269
- hook = SpannerHook(
270
- gcp_conn_id=self.gcp_conn_id,
271
- impersonation_chain=self.impersonation_chain,
272
- )
273
277
  if isinstance(self.query, str):
274
278
  queries = [x.strip() for x in self.query.split(";")]
275
279
  self.sanitize_queries(queries)
@@ -281,8 +285,8 @@ class SpannerQueryDatabaseInstanceOperator(GoogleCloudBaseOperator):
281
285
  self.instance_id,
282
286
  self.database_id,
283
287
  )
284
- self.log.info(queries)
285
- hook.execute_dml(
288
+ self.log.info("Executing queries: %s", queries)
289
+ result_rows_count_per_query = self.hook.execute_dml(
286
290
  project_id=self.project_id,
287
291
  instance_id=self.instance_id,
288
292
  database_id=self.database_id,
@@ -290,11 +294,11 @@ class SpannerQueryDatabaseInstanceOperator(GoogleCloudBaseOperator):
290
294
  )
291
295
  SpannerDatabaseLink.persist(
292
296
  context=context,
293
- task_instance=self,
294
297
  instance_id=self.instance_id,
295
298
  database_id=self.database_id,
296
- project_id=self.project_id or hook.project_id,
299
+ project_id=self.project_id or self.hook.project_id,
297
300
  )
301
+ return result_rows_count_per_query
298
302
 
299
303
  @staticmethod
300
304
  def sanitize_queries(queries: list[str]) -> None:
@@ -306,6 +310,17 @@ class SpannerQueryDatabaseInstanceOperator(GoogleCloudBaseOperator):
306
310
  if queries and queries[-1] == "":
307
311
  queries.pop()
308
312
 
313
+ def get_openlineage_facets_on_complete(self, task_instance) -> OperatorLineage | None:
314
+ """Build a generic OpenLineage facet, aligned with SQL-based operators."""
315
+ from airflow.providers.common.compat.openlineage.utils.sql import get_openlineage_facets_with_sql
316
+
317
+ return get_openlineage_facets_with_sql(
318
+ hook=self.hook,
319
+ sql=self.query,
320
+ conn_id=self.gcp_conn_id,
321
+ database=self.database_id,
322
+ )
323
+
309
324
 
310
325
  class SpannerDeployDatabaseInstanceOperator(GoogleCloudBaseOperator):
311
326
  """
@@ -380,7 +395,6 @@ class SpannerDeployDatabaseInstanceOperator(GoogleCloudBaseOperator):
380
395
  )
381
396
  SpannerDatabaseLink.persist(
382
397
  context=context,
383
- task_instance=self,
384
398
  instance_id=self.instance_id,
385
399
  database_id=self.database_id,
386
400
  project_id=self.project_id or hook.project_id,
@@ -496,7 +510,6 @@ class SpannerUpdateDatabaseInstanceOperator(GoogleCloudBaseOperator):
496
510
  )
497
511
  SpannerDatabaseLink.persist(
498
512
  context=context,
499
- task_instance=self,
500
513
  instance_id=self.instance_id,
501
514
  database_id=self.database_id,
502
515
  project_id=self.project_id or hook.project_id,
@@ -25,7 +25,7 @@ from typing import TYPE_CHECKING
25
25
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
26
26
  from google.protobuf.json_format import MessageToDict
27
27
 
28
- from airflow.exceptions import AirflowException
28
+ from airflow.providers.common.compat.sdk import AirflowException
29
29
  from airflow.providers.google.cloud.hooks.speech_to_text import CloudSpeechToTextHook, RecognitionAudio
30
30
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
31
31
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
@@ -35,7 +35,7 @@ if TYPE_CHECKING:
35
35
  from google.api_core.retry import Retry
36
36
  from google.cloud.speech_v1.types import RecognitionConfig
37
37
 
38
- from airflow.utils.context import Context
38
+ from airflow.providers.common.compat.sdk import Context
39
39
 
40
40
 
41
41
  class CloudSpeechToTextRecognizeSpeechOperator(GoogleCloudBaseOperator):
@@ -117,7 +117,6 @@ class CloudSpeechToTextRecognizeSpeechOperator(GoogleCloudBaseOperator):
117
117
  if self.audio.uri:
118
118
  FileDetailsLink.persist(
119
119
  context=context,
120
- task_instance=self,
121
120
  # Slice from: "gs://{BUCKET_NAME}/{FILE_NAME}" to: "{BUCKET_NAME}/{FILE_NAME}"
122
121
  uri=self.audio.uri[5:],
123
122
  project_id=self.project_id or hook.project_id,
@@ -34,7 +34,7 @@ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
34
34
  if TYPE_CHECKING:
35
35
  from google.api_core.retry import Retry
36
36
 
37
- from airflow.utils.context import Context
37
+ from airflow.providers.common.compat.sdk import Context
38
38
 
39
39
 
40
40
  class StackdriverListAlertPoliciesOperator(GoogleCloudBaseOperator):
@@ -145,7 +145,6 @@ class StackdriverListAlertPoliciesOperator(GoogleCloudBaseOperator):
145
145
  )
146
146
  StackdriverPoliciesLink.persist(
147
147
  context=context,
148
- operator_instance=self,
149
148
  project_id=self.project_id or self.hook.project_id,
150
149
  )
151
150
  return [AlertPolicy.to_dict(policy) for policy in result]
@@ -228,7 +227,6 @@ class StackdriverEnableAlertPoliciesOperator(GoogleCloudBaseOperator):
228
227
  )
229
228
  StackdriverPoliciesLink.persist(
230
229
  context=context,
231
- operator_instance=self,
232
230
  project_id=self.project_id or self.hook.project_id,
233
231
  )
234
232
 
@@ -311,7 +309,6 @@ class StackdriverDisableAlertPoliciesOperator(GoogleCloudBaseOperator):
311
309
  )
312
310
  StackdriverPoliciesLink.persist(
313
311
  context=context,
314
- operator_instance=self,
315
312
  project_id=self.project_id or self.hook.project_id,
316
313
  )
317
314
 
@@ -394,7 +391,6 @@ class StackdriverUpsertAlertOperator(GoogleCloudBaseOperator):
394
391
  )
395
392
  StackdriverPoliciesLink.persist(
396
393
  context=context,
397
- operator_instance=self,
398
394
  project_id=self.project_id or self.hook.project_id,
399
395
  )
400
396
 
@@ -580,7 +576,6 @@ class StackdriverListNotificationChannelsOperator(GoogleCloudBaseOperator):
580
576
  )
581
577
  StackdriverNotificationsLink.persist(
582
578
  context=context,
583
- operator_instance=self,
584
579
  project_id=self.project_id or self.hook.project_id,
585
580
  )
586
581
  return [NotificationChannel.to_dict(channel) for channel in channels]
@@ -666,7 +661,6 @@ class StackdriverEnableNotificationChannelsOperator(GoogleCloudBaseOperator):
666
661
  )
667
662
  StackdriverNotificationsLink.persist(
668
663
  context=context,
669
- operator_instance=self,
670
664
  project_id=self.project_id or self.hook.project_id,
671
665
  )
672
666
 
@@ -751,7 +745,6 @@ class StackdriverDisableNotificationChannelsOperator(GoogleCloudBaseOperator):
751
745
  )
752
746
  StackdriverNotificationsLink.persist(
753
747
  context=context,
754
- operator_instance=self,
755
748
  project_id=self.project_id or self.hook.project_id,
756
749
  )
757
750
 
@@ -838,7 +831,6 @@ class StackdriverUpsertNotificationChannelOperator(GoogleCloudBaseOperator):
838
831
  )
839
832
  StackdriverNotificationsLink.persist(
840
833
  context=context,
841
- operator_instance=self,
842
834
  project_id=self.project_id or self.hook.project_id,
843
835
  )
844
836
 
@@ -35,7 +35,7 @@ if TYPE_CHECKING:
35
35
  from google.api_core.retry import Retry
36
36
  from google.protobuf.field_mask_pb2 import FieldMask
37
37
 
38
- from airflow.utils.context import Context
38
+ from airflow.providers.common.compat.sdk import Context
39
39
 
40
40
 
41
41
  MetaData = Sequence[tuple[str, str]]
@@ -137,7 +137,6 @@ class CloudTasksQueueCreateOperator(GoogleCloudBaseOperator):
137
137
  metadata=self.metadata,
138
138
  )
139
139
  CloudTasksQueueLink.persist(
140
- operator_instance=self,
141
140
  context=context,
142
141
  queue_name=queue.name,
143
142
  )
@@ -236,7 +235,6 @@ class CloudTasksQueueUpdateOperator(GoogleCloudBaseOperator):
236
235
  metadata=self.metadata,
237
236
  )
238
237
  CloudTasksQueueLink.persist(
239
- operator_instance=self,
240
238
  context=context,
241
239
  queue_name=queue.name,
242
240
  )
@@ -319,7 +317,6 @@ class CloudTasksQueueGetOperator(GoogleCloudBaseOperator):
319
317
  metadata=self.metadata,
320
318
  )
321
319
  CloudTasksQueueLink.persist(
322
- operator_instance=self,
323
320
  context=context,
324
321
  queue_name=queue.name,
325
322
  )
@@ -406,7 +403,6 @@ class CloudTasksQueuesListOperator(GoogleCloudBaseOperator):
406
403
  metadata=self.metadata,
407
404
  )
408
405
  CloudTasksLink.persist(
409
- operator_instance=self,
410
406
  context=context,
411
407
  project_id=self.project_id or hook.project_id,
412
408
  )
@@ -564,7 +560,6 @@ class CloudTasksQueuePurgeOperator(GoogleCloudBaseOperator):
564
560
  metadata=self.metadata,
565
561
  )
566
562
  CloudTasksQueueLink.persist(
567
- operator_instance=self,
568
563
  context=context,
569
564
  queue_name=queue.name,
570
565
  )
@@ -647,7 +642,6 @@ class CloudTasksQueuePauseOperator(GoogleCloudBaseOperator):
647
642
  metadata=self.metadata,
648
643
  )
649
644
  CloudTasksQueueLink.persist(
650
- operator_instance=self,
651
645
  context=context,
652
646
  queue_name=queue.name,
653
647
  )
@@ -730,7 +724,6 @@ class CloudTasksQueueResumeOperator(GoogleCloudBaseOperator):
730
724
  metadata=self.metadata,
731
725
  )
732
726
  CloudTasksQueueLink.persist(
733
- operator_instance=self,
734
727
  context=context,
735
728
  queue_name=queue.name,
736
729
  )
@@ -830,7 +823,6 @@ class CloudTasksTaskCreateOperator(GoogleCloudBaseOperator):
830
823
  metadata=self.metadata,
831
824
  )
832
825
  CloudTasksQueueLink.persist(
833
- operator_instance=self,
834
826
  context=context,
835
827
  queue_name=task.name,
836
828
  )
@@ -923,7 +915,6 @@ class CloudTasksTaskGetOperator(GoogleCloudBaseOperator):
923
915
  metadata=self.metadata,
924
916
  )
925
917
  CloudTasksQueueLink.persist(
926
- operator_instance=self,
927
918
  context=context,
928
919
  queue_name=task.name,
929
920
  )
@@ -1016,7 +1007,6 @@ class CloudTasksTasksListOperator(GoogleCloudBaseOperator):
1016
1007
  metadata=self.metadata,
1017
1008
  )
1018
1009
  CloudTasksQueueLink.persist(
1019
- operator_instance=self,
1020
1010
  context=context,
1021
1011
  queue_name=f"projects/{self.project_id or hook.project_id}/"
1022
1012
  f"locations/{self.location}/queues/{self.queue_name}",
@@ -1190,7 +1180,6 @@ class CloudTasksTaskRunOperator(GoogleCloudBaseOperator):
1190
1180
  metadata=self.metadata,
1191
1181
  )
1192
1182
  CloudTasksQueueLink.persist(
1193
- operator_instance=self,
1194
1183
  context=context,
1195
1184
  queue_name=task.name,
1196
1185
  )
@@ -25,7 +25,7 @@ from typing import TYPE_CHECKING
25
25
 
26
26
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
27
27
 
28
- from airflow.exceptions import AirflowException
28
+ from airflow.providers.common.compat.sdk import AirflowException
29
29
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
30
30
  from airflow.providers.google.cloud.hooks.text_to_speech import CloudTextToSpeechHook
31
31
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
@@ -36,7 +36,7 @@ if TYPE_CHECKING:
36
36
  from google.api_core.retry import Retry
37
37
  from google.cloud.texttospeech_v1.types import AudioConfig, SynthesisInput, VoiceSelectionParams
38
38
 
39
- from airflow.utils.context import Context
39
+ from airflow.providers.common.compat.sdk import Context
40
40
 
41
41
 
42
42
  class CloudTextToSpeechSynthesizeOperator(GoogleCloudBaseOperator):
@@ -150,7 +150,6 @@ class CloudTextToSpeechSynthesizeOperator(GoogleCloudBaseOperator):
150
150
  )
151
151
  FileDetailsLink.persist(
152
152
  context=context,
153
- task_instance=self,
154
153
  uri=f"{self.target_bucket_name}/{self.target_filename}",
155
154
  project_id=cloud_storage_hook.project_id,
156
155
  )