apache-airflow-providers-google 10.16.0rc1__py3-none-any.whl → 10.17.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 (196) hide show
  1. airflow/providers/google/__init__.py +1 -1
  2. airflow/providers/google/ads/hooks/ads.py +5 -4
  3. airflow/providers/google/ads/operators/ads.py +1 -0
  4. airflow/providers/google/cloud/example_dags/example_cloud_sql_query.py +1 -0
  5. airflow/providers/google/cloud/example_dags/example_cloud_task.py +1 -0
  6. airflow/providers/google/cloud/example_dags/example_facebook_ads_to_gcs.py +1 -0
  7. airflow/providers/google/cloud/example_dags/example_looker.py +1 -0
  8. airflow/providers/google/cloud/example_dags/example_presto_to_gcs.py +1 -0
  9. airflow/providers/google/cloud/example_dags/example_salesforce_to_gcs.py +1 -0
  10. airflow/providers/google/cloud/fs/gcs.py +1 -2
  11. airflow/providers/google/cloud/hooks/automl.py +1 -0
  12. airflow/providers/google/cloud/hooks/bigquery.py +87 -24
  13. airflow/providers/google/cloud/hooks/bigquery_dts.py +1 -0
  14. airflow/providers/google/cloud/hooks/bigtable.py +1 -0
  15. airflow/providers/google/cloud/hooks/cloud_build.py +1 -0
  16. airflow/providers/google/cloud/hooks/cloud_memorystore.py +1 -0
  17. airflow/providers/google/cloud/hooks/cloud_sql.py +1 -0
  18. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +9 -4
  19. airflow/providers/google/cloud/hooks/compute.py +1 -0
  20. airflow/providers/google/cloud/hooks/compute_ssh.py +2 -2
  21. airflow/providers/google/cloud/hooks/dataflow.py +6 -5
  22. airflow/providers/google/cloud/hooks/datafusion.py +1 -0
  23. airflow/providers/google/cloud/hooks/datapipeline.py +1 -0
  24. airflow/providers/google/cloud/hooks/dataplex.py +1 -0
  25. airflow/providers/google/cloud/hooks/dataprep.py +1 -0
  26. airflow/providers/google/cloud/hooks/dataproc.py +3 -2
  27. airflow/providers/google/cloud/hooks/dataproc_metastore.py +1 -0
  28. airflow/providers/google/cloud/hooks/datastore.py +1 -0
  29. airflow/providers/google/cloud/hooks/dlp.py +1 -0
  30. airflow/providers/google/cloud/hooks/functions.py +1 -0
  31. airflow/providers/google/cloud/hooks/gcs.py +12 -5
  32. airflow/providers/google/cloud/hooks/kms.py +1 -0
  33. airflow/providers/google/cloud/hooks/kubernetes_engine.py +178 -300
  34. airflow/providers/google/cloud/hooks/life_sciences.py +1 -0
  35. airflow/providers/google/cloud/hooks/looker.py +1 -0
  36. airflow/providers/google/cloud/hooks/mlengine.py +1 -0
  37. airflow/providers/google/cloud/hooks/natural_language.py +1 -0
  38. airflow/providers/google/cloud/hooks/os_login.py +1 -0
  39. airflow/providers/google/cloud/hooks/pubsub.py +1 -0
  40. airflow/providers/google/cloud/hooks/secret_manager.py +1 -0
  41. airflow/providers/google/cloud/hooks/spanner.py +1 -0
  42. airflow/providers/google/cloud/hooks/speech_to_text.py +1 -0
  43. airflow/providers/google/cloud/hooks/stackdriver.py +1 -0
  44. airflow/providers/google/cloud/hooks/text_to_speech.py +1 -0
  45. airflow/providers/google/cloud/hooks/translate.py +1 -0
  46. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +1 -0
  47. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +255 -3
  48. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +1 -0
  49. airflow/providers/google/cloud/hooks/vertex_ai/dataset.py +1 -0
  50. airflow/providers/google/cloud/hooks/vertex_ai/endpoint_service.py +1 -0
  51. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +197 -0
  52. airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +9 -9
  53. airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +231 -12
  54. airflow/providers/google/cloud/hooks/video_intelligence.py +1 -0
  55. airflow/providers/google/cloud/hooks/vision.py +1 -0
  56. airflow/providers/google/cloud/links/automl.py +1 -0
  57. airflow/providers/google/cloud/links/bigquery.py +1 -0
  58. airflow/providers/google/cloud/links/bigquery_dts.py +1 -0
  59. airflow/providers/google/cloud/links/cloud_memorystore.py +1 -0
  60. airflow/providers/google/cloud/links/cloud_sql.py +1 -0
  61. airflow/providers/google/cloud/links/cloud_tasks.py +1 -0
  62. airflow/providers/google/cloud/links/compute.py +1 -0
  63. airflow/providers/google/cloud/links/datacatalog.py +1 -0
  64. airflow/providers/google/cloud/links/dataflow.py +1 -0
  65. airflow/providers/google/cloud/links/dataform.py +1 -0
  66. airflow/providers/google/cloud/links/datafusion.py +1 -0
  67. airflow/providers/google/cloud/links/dataplex.py +1 -0
  68. airflow/providers/google/cloud/links/dataproc.py +1 -0
  69. airflow/providers/google/cloud/links/kubernetes_engine.py +28 -0
  70. airflow/providers/google/cloud/links/mlengine.py +1 -0
  71. airflow/providers/google/cloud/links/pubsub.py +1 -0
  72. airflow/providers/google/cloud/links/spanner.py +1 -0
  73. airflow/providers/google/cloud/links/stackdriver.py +1 -0
  74. airflow/providers/google/cloud/links/workflows.py +1 -0
  75. airflow/providers/google/cloud/log/stackdriver_task_handler.py +18 -4
  76. airflow/providers/google/cloud/operators/automl.py +1 -0
  77. airflow/providers/google/cloud/operators/bigquery.py +21 -0
  78. airflow/providers/google/cloud/operators/bigquery_dts.py +1 -0
  79. airflow/providers/google/cloud/operators/bigtable.py +1 -0
  80. airflow/providers/google/cloud/operators/cloud_base.py +1 -0
  81. airflow/providers/google/cloud/operators/cloud_build.py +1 -0
  82. airflow/providers/google/cloud/operators/cloud_memorystore.py +1 -0
  83. airflow/providers/google/cloud/operators/cloud_sql.py +1 -0
  84. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +11 -5
  85. airflow/providers/google/cloud/operators/compute.py +1 -0
  86. airflow/providers/google/cloud/operators/dataflow.py +1 -0
  87. airflow/providers/google/cloud/operators/datafusion.py +1 -0
  88. airflow/providers/google/cloud/operators/datapipeline.py +1 -0
  89. airflow/providers/google/cloud/operators/dataprep.py +1 -0
  90. airflow/providers/google/cloud/operators/dataproc.py +3 -2
  91. airflow/providers/google/cloud/operators/dataproc_metastore.py +1 -0
  92. airflow/providers/google/cloud/operators/datastore.py +1 -0
  93. airflow/providers/google/cloud/operators/functions.py +1 -0
  94. airflow/providers/google/cloud/operators/gcs.py +1 -0
  95. airflow/providers/google/cloud/operators/kubernetes_engine.py +600 -4
  96. airflow/providers/google/cloud/operators/life_sciences.py +1 -0
  97. airflow/providers/google/cloud/operators/looker.py +1 -0
  98. airflow/providers/google/cloud/operators/mlengine.py +283 -259
  99. airflow/providers/google/cloud/operators/natural_language.py +1 -0
  100. airflow/providers/google/cloud/operators/pubsub.py +1 -0
  101. airflow/providers/google/cloud/operators/spanner.py +1 -0
  102. airflow/providers/google/cloud/operators/speech_to_text.py +1 -0
  103. airflow/providers/google/cloud/operators/text_to_speech.py +1 -0
  104. airflow/providers/google/cloud/operators/translate.py +1 -0
  105. airflow/providers/google/cloud/operators/translate_speech.py +1 -0
  106. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +14 -7
  107. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +67 -13
  108. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +26 -8
  109. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +1 -0
  110. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +306 -0
  111. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +29 -48
  112. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +52 -17
  113. airflow/providers/google/cloud/operators/video_intelligence.py +1 -0
  114. airflow/providers/google/cloud/operators/vision.py +1 -0
  115. airflow/providers/google/cloud/secrets/secret_manager.py +1 -0
  116. airflow/providers/google/cloud/sensors/bigquery.py +1 -0
  117. airflow/providers/google/cloud/sensors/bigquery_dts.py +1 -0
  118. airflow/providers/google/cloud/sensors/bigtable.py +1 -0
  119. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +1 -0
  120. airflow/providers/google/cloud/sensors/dataflow.py +1 -0
  121. airflow/providers/google/cloud/sensors/dataform.py +1 -0
  122. airflow/providers/google/cloud/sensors/datafusion.py +1 -0
  123. airflow/providers/google/cloud/sensors/dataplex.py +1 -0
  124. airflow/providers/google/cloud/sensors/dataprep.py +1 -0
  125. airflow/providers/google/cloud/sensors/dataproc.py +1 -0
  126. airflow/providers/google/cloud/sensors/gcs.py +1 -0
  127. airflow/providers/google/cloud/sensors/looker.py +1 -0
  128. airflow/providers/google/cloud/sensors/pubsub.py +1 -0
  129. airflow/providers/google/cloud/sensors/tasks.py +1 -0
  130. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +1 -0
  131. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -0
  132. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +1 -0
  133. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +1 -0
  134. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +1 -0
  135. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -0
  136. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +1 -0
  137. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +3 -2
  138. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -0
  139. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -0
  140. airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -0
  141. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -0
  142. airflow/providers/google/cloud/transfers/mysql_to_gcs.py +1 -0
  143. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +19 -1
  144. airflow/providers/google/cloud/transfers/s3_to_gcs.py +3 -5
  145. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -0
  146. airflow/providers/google/cloud/transfers/sql_to_gcs.py +4 -2
  147. airflow/providers/google/cloud/triggers/bigquery.py +4 -3
  148. airflow/providers/google/cloud/triggers/cloud_batch.py +1 -1
  149. airflow/providers/google/cloud/triggers/cloud_run.py +1 -0
  150. airflow/providers/google/cloud/triggers/cloud_sql.py +2 -0
  151. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +14 -2
  152. airflow/providers/google/cloud/triggers/dataplex.py +1 -0
  153. airflow/providers/google/cloud/triggers/dataproc.py +1 -0
  154. airflow/providers/google/cloud/triggers/kubernetes_engine.py +72 -2
  155. airflow/providers/google/cloud/triggers/mlengine.py +2 -0
  156. airflow/providers/google/cloud/triggers/pubsub.py +3 -3
  157. airflow/providers/google/cloud/triggers/vertex_ai.py +107 -15
  158. airflow/providers/google/cloud/utils/field_sanitizer.py +2 -1
  159. airflow/providers/google/cloud/utils/field_validator.py +1 -0
  160. airflow/providers/google/cloud/utils/helpers.py +1 -0
  161. airflow/providers/google/cloud/utils/mlengine_operator_utils.py +1 -0
  162. airflow/providers/google/cloud/utils/mlengine_prediction_summary.py +1 -0
  163. airflow/providers/google/cloud/utils/openlineage.py +1 -0
  164. airflow/providers/google/common/auth_backend/google_openid.py +1 -0
  165. airflow/providers/google/common/hooks/base_google.py +2 -1
  166. airflow/providers/google/common/hooks/discovery_api.py +1 -0
  167. airflow/providers/google/common/links/storage.py +1 -0
  168. airflow/providers/google/common/utils/id_token_credentials.py +1 -0
  169. airflow/providers/google/firebase/hooks/firestore.py +1 -0
  170. airflow/providers/google/get_provider_info.py +9 -3
  171. airflow/providers/google/go_module_utils.py +1 -0
  172. airflow/providers/google/leveldb/hooks/leveldb.py +8 -7
  173. airflow/providers/google/marketing_platform/example_dags/example_display_video.py +1 -0
  174. airflow/providers/google/marketing_platform/hooks/analytics_admin.py +1 -0
  175. airflow/providers/google/marketing_platform/hooks/campaign_manager.py +1 -0
  176. airflow/providers/google/marketing_platform/hooks/display_video.py +1 -0
  177. airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -0
  178. airflow/providers/google/marketing_platform/operators/analytics.py +1 -0
  179. airflow/providers/google/marketing_platform/operators/analytics_admin.py +4 -2
  180. airflow/providers/google/marketing_platform/operators/campaign_manager.py +1 -0
  181. airflow/providers/google/marketing_platform/operators/display_video.py +1 -0
  182. airflow/providers/google/marketing_platform/operators/search_ads.py +1 -0
  183. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +1 -0
  184. airflow/providers/google/marketing_platform/sensors/display_video.py +2 -1
  185. airflow/providers/google/marketing_platform/sensors/search_ads.py +1 -0
  186. airflow/providers/google/suite/hooks/calendar.py +1 -0
  187. airflow/providers/google/suite/hooks/drive.py +1 -0
  188. airflow/providers/google/suite/hooks/sheets.py +1 -0
  189. airflow/providers/google/suite/sensors/drive.py +1 -0
  190. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +7 -0
  191. airflow/providers/google/suite/transfers/gcs_to_sheets.py +4 -1
  192. airflow/providers/google/suite/transfers/local_to_drive.py +1 -0
  193. {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/METADATA +18 -13
  194. {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/RECORD +196 -194
  195. {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/WHEEL +0 -0
  196. {apache_airflow_providers_google-10.16.0rc1.dist-info → apache_airflow_providers_google-10.17.0.dist-info}/entry_points.txt +0 -0
@@ -16,19 +16,44 @@
16
16
  # under the License.
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Any, AsyncIterator, Sequence
19
+ from functools import cached_property
20
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Sequence
20
21
 
21
- from google.cloud.aiplatform_v1 import HyperparameterTuningJob, JobState
22
+ from google.cloud.aiplatform_v1 import (
23
+ BatchPredictionJob,
24
+ HyperparameterTuningJob,
25
+ JobState,
26
+ PipelineState,
27
+ types,
28
+ )
22
29
 
23
30
  from airflow.exceptions import AirflowException
31
+ from airflow.providers.google.cloud.hooks.vertex_ai.batch_prediction_job import BatchPredictionJobAsyncHook
24
32
  from airflow.providers.google.cloud.hooks.vertex_ai.hyperparameter_tuning_job import (
25
33
  HyperparameterTuningJobAsyncHook,
26
34
  )
35
+ from airflow.providers.google.cloud.hooks.vertex_ai.pipeline_job import PipelineJobAsyncHook
27
36
  from airflow.triggers.base import BaseTrigger, TriggerEvent
28
37
 
38
+ if TYPE_CHECKING:
39
+ from proto import Message
29
40
 
30
- class CreateHyperparameterTuningJobTrigger(BaseTrigger):
31
- """CreateHyperparameterTuningJobTrigger run on the trigger worker to perform create operation."""
41
+
42
+ class BaseVertexAIJobTrigger(BaseTrigger):
43
+ """Base class for Vertex AI job triggers.
44
+
45
+ This trigger polls the Vertex AI job and checks its status.
46
+
47
+ In order to use it properly, you must:
48
+ - implement the following methods `_wait_job()`.
49
+ - override required `job_type_verbose_name` attribute to provide meaningful message describing your
50
+ job type.
51
+ - override required `job_serializer_class` attribute to provide proto.Message class that will be used
52
+ to serialize your job with `to_dict()` class method.
53
+ """
54
+
55
+ job_type_verbose_name: str = "Vertex AI Job"
56
+ job_serializer_class: Message = None
32
57
 
33
58
  statuses_success = {
34
59
  JobState.JOB_STATE_PAUSED,
@@ -51,10 +76,13 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
51
76
  self.job_id = job_id
52
77
  self.poll_interval = poll_interval
53
78
  self.impersonation_chain = impersonation_chain
79
+ self.trigger_class_path = (
80
+ f"airflow.providers.google.cloud.triggers.vertex_ai.{self.__class__.__name__}"
81
+ )
54
82
 
55
83
  def serialize(self) -> tuple[str, dict[str, Any]]:
56
84
  return (
57
- "airflow.providers.google.cloud.triggers.vertex_ai.CreateHyperparameterTuningJobTrigger",
85
+ self.trigger_class_path,
58
86
  {
59
87
  "conn_id": self.conn_id,
60
88
  "project_id": self.project_id,
@@ -66,14 +94,8 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
66
94
  )
67
95
 
68
96
  async def run(self) -> AsyncIterator[TriggerEvent]:
69
- hook = self._get_async_hook()
70
97
  try:
71
- job = await hook.wait_hyperparameter_tuning_job(
72
- project_id=self.project_id,
73
- location=self.location,
74
- job_id=self.job_id,
75
- poll_interval=self.poll_interval,
76
- )
98
+ job = await self._wait_job()
77
99
  except AirflowException as ex:
78
100
  yield TriggerEvent(
79
101
  {
@@ -84,16 +106,86 @@ class CreateHyperparameterTuningJobTrigger(BaseTrigger):
84
106
  return
85
107
 
86
108
  status = "success" if job.state in self.statuses_success else "error"
87
- message = f"Hyperparameter tuning job {job.name} completed with status {job.state.name}"
109
+ message = f"{self.job_type_verbose_name} {job.name} completed with status {job.state.name}"
88
110
  yield TriggerEvent(
89
111
  {
90
112
  "status": status,
91
113
  "message": message,
92
- "job": HyperparameterTuningJob.to_dict(job),
114
+ "job": self._serialize_job(job),
93
115
  }
94
116
  )
95
117
 
96
- def _get_async_hook(self) -> HyperparameterTuningJobAsyncHook:
118
+ async def _wait_job(self) -> Any:
119
+ """Awaits a Vertex AI job instance for a status examination."""
120
+ raise NotImplementedError
121
+
122
+ def _serialize_job(self, job: Any) -> Any:
123
+ return self.job_serializer_class.to_dict(job)
124
+
125
+
126
+ class CreateHyperparameterTuningJobTrigger(BaseVertexAIJobTrigger):
127
+ """CreateHyperparameterTuningJobTrigger run on the trigger worker to perform create operation."""
128
+
129
+ job_type_verbose_name = "Hyperparameter Tuning Job"
130
+ job_serializer_class = HyperparameterTuningJob
131
+
132
+ @cached_property
133
+ def async_hook(self) -> HyperparameterTuningJobAsyncHook:
97
134
  return HyperparameterTuningJobAsyncHook(
98
135
  gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain
99
136
  )
137
+
138
+ async def _wait_job(self) -> types.HyperparameterTuningJob:
139
+ job: types.HyperparameterTuningJob = await self.async_hook.wait_hyperparameter_tuning_job(
140
+ project_id=self.project_id,
141
+ location=self.location,
142
+ job_id=self.job_id,
143
+ poll_interval=self.poll_interval,
144
+ )
145
+ return job
146
+
147
+
148
+ class CreateBatchPredictionJobTrigger(BaseVertexAIJobTrigger):
149
+ """CreateBatchPredictionJobTrigger run on the trigger worker to perform create operation."""
150
+
151
+ job_type_verbose_name = "Batch Prediction Job"
152
+ job_serializer_class = BatchPredictionJob
153
+
154
+ @cached_property
155
+ def async_hook(self) -> BatchPredictionJobAsyncHook:
156
+ return BatchPredictionJobAsyncHook(
157
+ gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain
158
+ )
159
+
160
+ async def _wait_job(self) -> types.BatchPredictionJob:
161
+ job: types.BatchPredictionJob = await self.async_hook.wait_batch_prediction_job(
162
+ project_id=self.project_id,
163
+ location=self.location,
164
+ job_id=self.job_id,
165
+ poll_interval=self.poll_interval,
166
+ )
167
+ return job
168
+
169
+
170
+ class RunPipelineJobTrigger(BaseVertexAIJobTrigger):
171
+ """Make async calls to Vertex AI to check the state of a Pipeline Job."""
172
+
173
+ job_type_verbose_name = "Pipeline Job"
174
+ job_serializer_class = types.PipelineJob
175
+ statuses_success = {
176
+ PipelineState.PIPELINE_STATE_PAUSED,
177
+ PipelineState.PIPELINE_STATE_SUCCEEDED,
178
+ }
179
+
180
+ @cached_property
181
+ def async_hook(self) -> PipelineJobAsyncHook:
182
+ return PipelineJobAsyncHook(gcp_conn_id=self.conn_id, impersonation_chain=self.impersonation_chain)
183
+
184
+ async def _wait_job(self) -> types.PipelineJob:
185
+ job: types.PipelineJob = await self.async_hook.wait_for_pipeline_job(
186
+ project_id=self.project_id,
187
+ location=self.location,
188
+ job_id=self.job_id,
189
+ poll_interval=self.poll_interval,
190
+ )
191
+ return job
@@ -67,7 +67,7 @@ specification of the path you should delete - separated with '.'
67
67
  >>> },
68
68
  >>> }
69
69
  >>> }
70
- >>> sanitizer=GcpBodyFieldSanitizer(FIELDS_TO_SANITIZE)
70
+ >>> sanitizer = GcpBodyFieldSanitizer(FIELDS_TO_SANITIZE)
71
71
  >>> sanitizer.sanitize(body)
72
72
  >>> json.dumps(body, indent=2)
73
73
  {
@@ -96,6 +96,7 @@ In case they are dictionaries, subsequent component names key of the field, in
96
96
  arrays - the sanitizer iterates through all dictionaries in the array and searches
97
97
  components in all elements of the array.
98
98
  """
99
+
99
100
  from __future__ import annotations
100
101
 
101
102
  from airflow.exceptions import AirflowException
@@ -129,6 +129,7 @@ Here are the guidelines that you should follow to make validation forward-compat
129
129
  backwards-incompatible changes that might sometimes occur in the APIs.
130
130
 
131
131
  """
132
+
132
133
  from __future__ import annotations
133
134
 
134
135
  import re
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """This module contains helper functions for Google Cloud operators."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
 
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """This module contains helper functions for MLEngine operators."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  import base64
@@ -106,6 +106,7 @@ To test outside of the dag:
106
106
 
107
107
  pcoll
108
108
  """
109
+
109
110
  from __future__ import annotations
110
111
 
111
112
  import argparse
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains code related to OpenLineage and lineage extraction."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Any
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """Authentication backend that use Google credentials for authorization."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import logging
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains a Google Cloud API base hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import datetime
@@ -316,7 +317,7 @@ class GoogleBaseHook(BaseHook):
316
317
  credentials.refresh(auth_req)
317
318
  return credentials.token
318
319
 
319
- @functools.lru_cache(maxsize=None)
320
+ @functools.cached_property
320
321
  def _get_credentials_email(self) -> str:
321
322
  """
322
323
  Return the email address associated with the currently logged in account.
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module allows you to connect to the Google Discovery API Service and query it."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import Sequence
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """This module contains a link for GCS Storage assets."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  from typing import TYPE_CHECKING
@@ -28,6 +28,7 @@ To obtain info about this token, run the following commands:
28
28
 
29
29
  RefreshError
30
30
  """
31
+
31
32
  from __future__ import annotations
32
33
 
33
34
  import json
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """Hook for Google Cloud Firestore service."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import time
@@ -28,8 +28,9 @@ def get_provider_info():
28
28
  "name": "Google",
29
29
  "description": "Google services including:\n\n - `Google Ads <https://ads.google.com/>`__\n - `Google Cloud (GCP) <https://cloud.google.com/>`__\n - `Google Firebase <https://firebase.google.com/>`__\n - `Google LevelDB <https://github.com/google/leveldb/>`__\n - `Google Marketing Platform <https://marketingplatform.google.com/>`__\n - `Google Workspace <https://workspace.google.com/>`__ (formerly Google Suite)\n",
30
30
  "state": "ready",
31
- "source-date-epoch": 1709555588,
31
+ "source-date-epoch": 1712665855,
32
32
  "versions": [
33
+ "10.17.0",
33
34
  "10.16.0",
34
35
  "10.15.0",
35
36
  "10.14.0",
@@ -92,14 +93,15 @@ def get_provider_info():
92
93
  "gcloud-aio-bigquery>=6.1.2",
93
94
  "gcloud-aio-storage>=9.0.0",
94
95
  "gcsfs>=2023.10.0",
95
- "google-ads>=22.1.0",
96
+ "google-ads>=23.1.0",
96
97
  "google-analytics-admin",
97
98
  "google-api-core>=2.11.0,!=2.16.0",
98
99
  "google-api-python-client>=1.6.0",
99
100
  "google-auth>=1.0.0",
100
101
  "google-auth-httplib2>=0.0.1",
101
- "google-cloud-aiplatform>=1.22.1",
102
+ "google-cloud-aiplatform>=1.42.1",
102
103
  "google-cloud-automl>=2.12.0",
104
+ "google-cloud-bigquery>=3.0.1",
103
105
  "google-cloud-bigquery-datatransfer>=3.13.0",
104
106
  "google-cloud-bigtable>=2.17.0",
105
107
  "google-cloud-build>=3.22.0",
@@ -144,6 +146,7 @@ def get_provider_info():
144
146
  "PyOpenSSL",
145
147
  "sqlalchemy-bigquery>=1.2.1",
146
148
  "sqlalchemy-spanner>=1.6.2",
149
+ "python-slugify>=5.0",
147
150
  ],
148
151
  "additional-extras": [
149
152
  {"name": "apache.beam", "dependencies": ["apache-beam[gcp]"]},
@@ -807,6 +810,7 @@ def get_provider_info():
807
810
  "airflow.providers.google.cloud.operators.vertex_ai.hyperparameter_tuning_job",
808
811
  "airflow.providers.google.cloud.operators.vertex_ai.model_service",
809
812
  "airflow.providers.google.cloud.operators.vertex_ai.pipeline_job",
813
+ "airflow.providers.google.cloud.operators.vertex_ai.generative_model",
810
814
  ],
811
815
  },
812
816
  {
@@ -1141,6 +1145,7 @@ def get_provider_info():
1141
1145
  "airflow.providers.google.cloud.hooks.vertex_ai.hyperparameter_tuning_job",
1142
1146
  "airflow.providers.google.cloud.hooks.vertex_ai.model_service",
1143
1147
  "airflow.providers.google.cloud.hooks.vertex_ai.pipeline_job",
1148
+ "airflow.providers.google.cloud.hooks.vertex_ai.generative_model",
1144
1149
  ],
1145
1150
  },
1146
1151
  {
@@ -1532,6 +1537,7 @@ def get_provider_info():
1532
1537
  "airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineClusterLink",
1533
1538
  "airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEnginePodLink",
1534
1539
  "airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineJobLink",
1540
+ "airflow.providers.google.cloud.links.kubernetes_engine.KubernetesEngineWorkloadsLink",
1535
1541
  "airflow.providers.google.cloud.links.pubsub.PubSubSubscriptionLink",
1536
1542
  "airflow.providers.google.cloud.links.pubsub.PubSubTopicLink",
1537
1543
  "airflow.providers.google.cloud.links.cloud_memorystore.MemcachedInstanceDetailsLink",
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """Utilities initializing and managing Go modules."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import os
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Hook for Level DB."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  from airflow.exceptions import AirflowException, AirflowOptionalProviderFeatureException
@@ -93,7 +94,7 @@ class LevelDBHook(BaseHook):
93
94
  """
94
95
  if command == "put":
95
96
  if not value:
96
- raise Exception("Please provide `value`!")
97
+ raise ValueError("Please provide `value`!")
97
98
  return self.put(key, value)
98
99
  elif command == "get":
99
100
  return self.get(key)
@@ -101,9 +102,9 @@ class LevelDBHook(BaseHook):
101
102
  return self.delete(key)
102
103
  elif command == "write_batch":
103
104
  if not keys:
104
- raise Exception("Please provide `keys`!")
105
+ raise ValueError("Please provide `keys`!")
105
106
  if not values:
106
- raise Exception("Please provide `values`!")
107
+ raise ValueError("Please provide `values`!")
107
108
  return self.write_batch(keys, values)
108
109
  else:
109
110
  raise LevelDBHookException("Unknown command for LevelDB hook")
@@ -116,7 +117,7 @@ class LevelDBHook(BaseHook):
116
117
  :param value: value for put execution e.g. ``b'value'``, ``b'another-value'``
117
118
  """
118
119
  if not self.db:
119
- raise Exception(DB_NOT_INITIALIZED_BEFORE)
120
+ raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
120
121
  self.db.put(key, value)
121
122
 
122
123
  def get(self, key: bytes) -> bytes:
@@ -127,7 +128,7 @@ class LevelDBHook(BaseHook):
127
128
  :returns: value of key from db.get
128
129
  """
129
130
  if not self.db:
130
- raise Exception(DB_NOT_INITIALIZED_BEFORE)
131
+ raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
131
132
  return self.db.get(key)
132
133
 
133
134
  def delete(self, key: bytes):
@@ -137,7 +138,7 @@ class LevelDBHook(BaseHook):
137
138
  :param key: key for delete execution, e.g. ``b'key'``, ``b'another-key'``
138
139
  """
139
140
  if not self.db:
140
- raise Exception(DB_NOT_INITIALIZED_BEFORE)
141
+ raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
141
142
  self.db.delete(key)
142
143
 
143
144
  def write_batch(self, keys: list[bytes], values: list[bytes]):
@@ -148,7 +149,7 @@ class LevelDBHook(BaseHook):
148
149
  :param values: values for write_batch execution e.g. ``[b'value', b'another-value']``
149
150
  """
150
151
  if not self.db:
151
- raise Exception(DB_NOT_INITIALIZED_BEFORE)
152
+ raise AirflowException(DB_NOT_INITIALIZED_BEFORE)
152
153
  with self.db.write_batch() as batch:
153
154
  for i, key in enumerate(keys):
154
155
  batch.put(key, values[i])
@@ -18,6 +18,7 @@
18
18
  """
19
19
  Example Airflow DAG that shows how to use DisplayVideo.
20
20
  """
21
+
21
22
  from __future__ import annotations
22
23
 
23
24
  import os
@@ -24,6 +24,7 @@ Hooks for Google Analytics (GA4) Admin service.
24
24
  ListAccountsPager
25
25
  ListGoogleAdsLinksPager
26
26
  """
27
+
27
28
  from __future__ import annotations
28
29
 
29
30
  from typing import TYPE_CHECKING, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Campaign Manager hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google DisplayVideo hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Search Ads 360 hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Analytics 360 operators."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import csv
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Analytics 4 (GA4) operators."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Any, Sequence
@@ -105,8 +106,9 @@ class GoogleAnalyticsAdminListAccountsOperator(GoogleCloudBaseOperator):
105
106
  impersonation_chain=self.impersonation_chain,
106
107
  )
107
108
  self.log.info(
108
- "Requesting list of Google Analytics accounts. "
109
- f"Page size: {self.page_size}, page token: {self.page_token}"
109
+ "Requesting list of Google Analytics accounts. Page size: %s, page token: %s",
110
+ self.page_size,
111
+ self.page_token,
110
112
  )
111
113
  accounts = hook.list_accounts(
112
114
  page_size=self.page_size,
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google CampaignManager operators."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import json
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google DisplayVideo operators."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import csv
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Search Ads operators."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import json
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Campaign Manager sensor."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Sequence
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Sensor for detecting the completion of DV360 reports."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  from typing import TYPE_CHECKING, Sequence
@@ -157,7 +158,7 @@ class GoogleDisplayVideo360RunQuerySensor(BaseSensorOperator):
157
158
 
158
159
  response = hook.get_report(query_id=self.query_id, report_id=self.report_id)
159
160
  status = response.get("metadata", {}).get("status", {}).get("state")
160
- self.log.info(f"STATUS OF THE REPORT {self.report_id} FOR QUERY {self.query_id}: {status}")
161
+ self.log.info("STATUS OF THE REPORT %s FOR QUERY %s: %s", self.report_id, self.query_id, status)
161
162
  if response and status in ["DONE", "FAILED"]:
162
163
  return True
163
164
  return False
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Search Ads sensor."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains a Google Calendar API hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """Hook for Google Drive service."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import IO, Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains a Google Sheets API hook."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import Any, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains Google Drive sensors."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  from typing import TYPE_CHECKING, Sequence
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  """This module contains a Google Cloud Storage to Google Drive transfer operator."""
19
+
19
20
  from __future__ import annotations
20
21
 
21
22
  import tempfile
@@ -79,6 +80,9 @@ class GCSToGoogleDriveOperator(BaseOperator):
79
80
  If set as a sequence, the identities from the list must grant
80
81
  Service Account Token Creator IAM role to the directly preceding identity, with first
81
82
  account from the list granting this role to the originating account (templated).
83
+ :param delegate_to: (Optional) The account to impersonate using domain-wide delegation
84
+ of authority, if any. For this to work, the service account making the
85
+ request must have domain-wide delegation enabled. This only applies to the Google Drive connection.
82
86
  """
83
87
 
84
88
  template_fields: Sequence[str] = (
@@ -99,6 +103,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
99
103
  move_object: bool = False,
100
104
  gcp_conn_id: str = "google_cloud_default",
101
105
  impersonation_chain: str | Sequence[str] | None = None,
106
+ delegate_to: str | None = None,
102
107
  **kwargs,
103
108
  ) -> None:
104
109
  super().__init__(**kwargs)
@@ -110,6 +115,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
110
115
  self.move_object = move_object
111
116
  self.gcp_conn_id = gcp_conn_id
112
117
  self.impersonation_chain = impersonation_chain
118
+ self.delegate_to = delegate_to
113
119
  self.gcs_hook: GCSHook | None = None
114
120
  self.gdrive_hook: GoogleDriveHook | None = None
115
121
 
@@ -121,6 +127,7 @@ class GCSToGoogleDriveOperator(BaseOperator):
121
127
  self.gdrive_hook = GoogleDriveHook(
122
128
  gcp_conn_id=self.gcp_conn_id,
123
129
  impersonation_chain=self.impersonation_chain,
130
+ delegate_to=self.delegate_to,
124
131
  )
125
132
 
126
133
  if WILDCARD in self.source_object: