apache-airflow-providers-google 15.1.0rc1__py3-none-any.whl → 19.1.0rc1__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 (234) 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 -5
  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/bigquery.py +166 -281
  10. airflow/providers/google/cloud/hooks/cloud_composer.py +287 -14
  11. airflow/providers/google/cloud/hooks/cloud_logging.py +109 -0
  12. airflow/providers/google/cloud/hooks/cloud_run.py +17 -9
  13. airflow/providers/google/cloud/hooks/cloud_sql.py +101 -22
  14. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +27 -6
  15. airflow/providers/google/cloud/hooks/compute_ssh.py +5 -1
  16. airflow/providers/google/cloud/hooks/datacatalog.py +9 -1
  17. airflow/providers/google/cloud/hooks/dataflow.py +71 -94
  18. airflow/providers/google/cloud/hooks/datafusion.py +1 -1
  19. airflow/providers/google/cloud/hooks/dataplex.py +1 -1
  20. airflow/providers/google/cloud/hooks/dataprep.py +1 -1
  21. airflow/providers/google/cloud/hooks/dataproc.py +72 -71
  22. airflow/providers/google/cloud/hooks/gcs.py +111 -14
  23. airflow/providers/google/cloud/hooks/gen_ai.py +196 -0
  24. airflow/providers/google/cloud/hooks/kubernetes_engine.py +2 -2
  25. airflow/providers/google/cloud/hooks/looker.py +6 -1
  26. airflow/providers/google/cloud/hooks/mlengine.py +3 -2
  27. airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
  28. airflow/providers/google/cloud/hooks/spanner.py +73 -8
  29. airflow/providers/google/cloud/hooks/stackdriver.py +10 -8
  30. airflow/providers/google/cloud/hooks/translate.py +1 -1
  31. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +0 -209
  32. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +2 -2
  33. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +27 -1
  34. airflow/providers/google/cloud/hooks/vertex_ai/experiment_service.py +202 -0
  35. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +307 -7
  36. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +79 -75
  37. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +223 -0
  38. airflow/providers/google/cloud/hooks/vision.py +2 -2
  39. airflow/providers/google/cloud/hooks/workflows.py +1 -1
  40. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  41. airflow/providers/google/cloud/links/base.py +77 -13
  42. airflow/providers/google/cloud/links/bigquery.py +0 -47
  43. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  44. airflow/providers/google/cloud/links/bigtable.py +0 -48
  45. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  46. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  47. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  48. airflow/providers/google/cloud/links/{life_sciences.py → cloud_run.py} +5 -27
  49. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  50. airflow/providers/google/cloud/links/cloud_storage_transfer.py +17 -44
  51. airflow/providers/google/cloud/links/cloud_tasks.py +7 -26
  52. airflow/providers/google/cloud/links/compute.py +0 -58
  53. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  54. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  55. airflow/providers/google/cloud/links/dataflow.py +0 -34
  56. airflow/providers/google/cloud/links/dataform.py +0 -64
  57. airflow/providers/google/cloud/links/datafusion.py +1 -96
  58. airflow/providers/google/cloud/links/dataplex.py +0 -154
  59. airflow/providers/google/cloud/links/dataprep.py +0 -24
  60. airflow/providers/google/cloud/links/dataproc.py +11 -95
  61. airflow/providers/google/cloud/links/datastore.py +0 -31
  62. airflow/providers/google/cloud/links/kubernetes_engine.py +9 -60
  63. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  64. airflow/providers/google/cloud/links/mlengine.py +0 -70
  65. airflow/providers/google/cloud/links/pubsub.py +0 -32
  66. airflow/providers/google/cloud/links/spanner.py +0 -33
  67. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  68. airflow/providers/google/cloud/links/translate.py +17 -187
  69. airflow/providers/google/cloud/links/vertex_ai.py +28 -195
  70. airflow/providers/google/cloud/links/workflows.py +0 -52
  71. airflow/providers/google/cloud/log/gcs_task_handler.py +17 -9
  72. airflow/providers/google/cloud/log/stackdriver_task_handler.py +9 -6
  73. airflow/providers/google/cloud/openlineage/CloudStorageTransferJobFacet.json +68 -0
  74. airflow/providers/google/cloud/openlineage/CloudStorageTransferRunFacet.json +60 -0
  75. airflow/providers/google/cloud/openlineage/DataFusionRunFacet.json +32 -0
  76. airflow/providers/google/cloud/openlineage/facets.py +102 -1
  77. airflow/providers/google/cloud/openlineage/mixins.py +10 -8
  78. airflow/providers/google/cloud/openlineage/utils.py +15 -1
  79. airflow/providers/google/cloud/operators/alloy_db.py +70 -55
  80. airflow/providers/google/cloud/operators/bigquery.py +73 -636
  81. airflow/providers/google/cloud/operators/bigquery_dts.py +3 -5
  82. airflow/providers/google/cloud/operators/bigtable.py +36 -7
  83. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  84. airflow/providers/google/cloud/operators/cloud_batch.py +2 -2
  85. airflow/providers/google/cloud/operators/cloud_build.py +75 -32
  86. airflow/providers/google/cloud/operators/cloud_composer.py +128 -40
  87. airflow/providers/google/cloud/operators/cloud_logging_sink.py +341 -0
  88. airflow/providers/google/cloud/operators/cloud_memorystore.py +69 -43
  89. airflow/providers/google/cloud/operators/cloud_run.py +23 -5
  90. airflow/providers/google/cloud/operators/cloud_sql.py +8 -16
  91. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +92 -11
  92. airflow/providers/google/cloud/operators/compute.py +8 -40
  93. airflow/providers/google/cloud/operators/datacatalog.py +157 -21
  94. airflow/providers/google/cloud/operators/dataflow.py +38 -15
  95. airflow/providers/google/cloud/operators/dataform.py +15 -5
  96. airflow/providers/google/cloud/operators/datafusion.py +41 -20
  97. airflow/providers/google/cloud/operators/dataplex.py +193 -109
  98. airflow/providers/google/cloud/operators/dataprep.py +1 -5
  99. airflow/providers/google/cloud/operators/dataproc.py +78 -35
  100. airflow/providers/google/cloud/operators/dataproc_metastore.py +96 -88
  101. airflow/providers/google/cloud/operators/datastore.py +22 -6
  102. airflow/providers/google/cloud/operators/dlp.py +6 -29
  103. airflow/providers/google/cloud/operators/functions.py +16 -7
  104. airflow/providers/google/cloud/operators/gcs.py +10 -8
  105. airflow/providers/google/cloud/operators/gen_ai.py +389 -0
  106. airflow/providers/google/cloud/operators/kubernetes_engine.py +60 -99
  107. airflow/providers/google/cloud/operators/looker.py +1 -1
  108. airflow/providers/google/cloud/operators/managed_kafka.py +107 -52
  109. airflow/providers/google/cloud/operators/natural_language.py +1 -1
  110. airflow/providers/google/cloud/operators/pubsub.py +60 -14
  111. airflow/providers/google/cloud/operators/spanner.py +25 -12
  112. airflow/providers/google/cloud/operators/speech_to_text.py +1 -2
  113. airflow/providers/google/cloud/operators/stackdriver.py +1 -9
  114. airflow/providers/google/cloud/operators/tasks.py +1 -12
  115. airflow/providers/google/cloud/operators/text_to_speech.py +1 -2
  116. airflow/providers/google/cloud/operators/translate.py +40 -16
  117. airflow/providers/google/cloud/operators/translate_speech.py +1 -2
  118. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +39 -19
  119. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +29 -9
  120. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +54 -26
  121. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +70 -8
  122. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +43 -9
  123. airflow/providers/google/cloud/operators/vertex_ai/experiment_service.py +435 -0
  124. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +532 -1
  125. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +135 -116
  126. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +11 -9
  127. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +57 -11
  128. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +30 -7
  129. airflow/providers/google/cloud/operators/vertex_ai/ray.py +393 -0
  130. airflow/providers/google/cloud/operators/video_intelligence.py +1 -1
  131. airflow/providers/google/cloud/operators/vision.py +2 -2
  132. airflow/providers/google/cloud/operators/workflows.py +18 -15
  133. airflow/providers/google/cloud/sensors/bigquery.py +2 -2
  134. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -2
  135. airflow/providers/google/cloud/sensors/bigtable.py +11 -4
  136. airflow/providers/google/cloud/sensors/cloud_composer.py +533 -29
  137. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -2
  138. airflow/providers/google/cloud/sensors/dataflow.py +26 -9
  139. airflow/providers/google/cloud/sensors/dataform.py +2 -2
  140. airflow/providers/google/cloud/sensors/datafusion.py +4 -4
  141. airflow/providers/google/cloud/sensors/dataplex.py +2 -2
  142. airflow/providers/google/cloud/sensors/dataprep.py +2 -2
  143. airflow/providers/google/cloud/sensors/dataproc.py +2 -2
  144. airflow/providers/google/cloud/sensors/dataproc_metastore.py +2 -2
  145. airflow/providers/google/cloud/sensors/gcs.py +4 -4
  146. airflow/providers/google/cloud/sensors/looker.py +2 -2
  147. airflow/providers/google/cloud/sensors/pubsub.py +4 -4
  148. airflow/providers/google/cloud/sensors/tasks.py +2 -2
  149. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +2 -2
  150. airflow/providers/google/cloud/sensors/workflows.py +2 -2
  151. airflow/providers/google/cloud/transfers/adls_to_gcs.py +1 -1
  152. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +2 -2
  153. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +2 -2
  154. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +11 -8
  155. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +4 -4
  156. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +7 -3
  157. airflow/providers/google/cloud/transfers/bigquery_to_mysql.py +12 -1
  158. airflow/providers/google/cloud/transfers/bigquery_to_postgres.py +24 -10
  159. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +104 -5
  160. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  161. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +2 -2
  162. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +3 -3
  163. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +20 -12
  164. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +2 -2
  165. airflow/providers/google/cloud/transfers/gcs_to_local.py +5 -3
  166. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +10 -4
  167. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +6 -2
  168. airflow/providers/google/cloud/transfers/gdrive_to_local.py +2 -2
  169. airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
  170. airflow/providers/google/cloud/transfers/local_to_gcs.py +2 -2
  171. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +1 -1
  172. airflow/providers/google/cloud/transfers/oracle_to_gcs.py +36 -11
  173. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +42 -9
  174. airflow/providers/google/cloud/transfers/s3_to_gcs.py +12 -6
  175. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +2 -2
  176. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +13 -4
  177. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +3 -3
  178. airflow/providers/google/cloud/transfers/sql_to_gcs.py +10 -10
  179. airflow/providers/google/cloud/triggers/bigquery.py +75 -34
  180. airflow/providers/google/cloud/triggers/cloud_build.py +1 -1
  181. airflow/providers/google/cloud/triggers/cloud_composer.py +302 -46
  182. airflow/providers/google/cloud/triggers/cloud_run.py +2 -2
  183. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +91 -1
  184. airflow/providers/google/cloud/triggers/dataflow.py +122 -0
  185. airflow/providers/google/cloud/triggers/datafusion.py +1 -1
  186. airflow/providers/google/cloud/triggers/dataplex.py +14 -2
  187. airflow/providers/google/cloud/triggers/dataproc.py +122 -52
  188. airflow/providers/google/cloud/triggers/kubernetes_engine.py +45 -27
  189. airflow/providers/google/cloud/triggers/mlengine.py +1 -1
  190. airflow/providers/google/cloud/triggers/pubsub.py +15 -19
  191. airflow/providers/google/cloud/utils/bigquery_get_data.py +1 -1
  192. airflow/providers/google/cloud/utils/credentials_provider.py +1 -1
  193. airflow/providers/google/cloud/utils/field_validator.py +1 -2
  194. airflow/providers/google/common/auth_backend/google_openid.py +4 -4
  195. airflow/providers/google/common/deprecated.py +2 -1
  196. airflow/providers/google/common/hooks/base_google.py +27 -8
  197. airflow/providers/google/common/links/storage.py +0 -22
  198. airflow/providers/google/common/utils/get_secret.py +31 -0
  199. airflow/providers/google/common/utils/id_token_credentials.py +3 -4
  200. airflow/providers/google/firebase/operators/firestore.py +2 -2
  201. airflow/providers/google/get_provider_info.py +56 -52
  202. airflow/providers/google/go_module_utils.py +35 -3
  203. airflow/providers/google/leveldb/hooks/leveldb.py +26 -1
  204. airflow/providers/google/leveldb/operators/leveldb.py +2 -2
  205. airflow/providers/google/marketing_platform/hooks/display_video.py +3 -109
  206. airflow/providers/google/marketing_platform/links/analytics_admin.py +5 -14
  207. airflow/providers/google/marketing_platform/operators/analytics_admin.py +1 -2
  208. airflow/providers/google/marketing_platform/operators/campaign_manager.py +5 -5
  209. airflow/providers/google/marketing_platform/operators/display_video.py +28 -489
  210. airflow/providers/google/marketing_platform/operators/search_ads.py +2 -2
  211. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +2 -2
  212. airflow/providers/google/marketing_platform/sensors/display_video.py +3 -63
  213. airflow/providers/google/suite/hooks/calendar.py +1 -1
  214. airflow/providers/google/suite/hooks/sheets.py +15 -1
  215. airflow/providers/google/suite/operators/sheets.py +8 -3
  216. airflow/providers/google/suite/sensors/drive.py +2 -2
  217. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +2 -2
  218. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  219. airflow/providers/google/suite/transfers/local_to_drive.py +3 -3
  220. airflow/providers/google/suite/transfers/sql_to_sheets.py +5 -4
  221. airflow/providers/google/version_compat.py +15 -1
  222. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/METADATA +92 -48
  223. apache_airflow_providers_google-19.1.0rc1.dist-info/RECORD +331 -0
  224. apache_airflow_providers_google-19.1.0rc1.dist-info/licenses/NOTICE +5 -0
  225. airflow/providers/google/cloud/hooks/automl.py +0 -673
  226. airflow/providers/google/cloud/hooks/life_sciences.py +0 -159
  227. airflow/providers/google/cloud/links/automl.py +0 -193
  228. airflow/providers/google/cloud/operators/automl.py +0 -1362
  229. airflow/providers/google/cloud/operators/life_sciences.py +0 -119
  230. airflow/providers/google/cloud/operators/mlengine.py +0 -112
  231. apache_airflow_providers_google-15.1.0rc1.dist-info/RECORD +0 -321
  232. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/WHEEL +0 -0
  233. {apache_airflow_providers_google-15.1.0rc1.dist-info → apache_airflow_providers_google-19.1.0rc1.dist-info}/entry_points.txt +0 -0
  234. {airflow/providers/google → apache_airflow_providers_google-19.1.0rc1.dist-info/licenses}/LICENSE +0 -0
@@ -21,15 +21,17 @@ from __future__ import annotations
21
21
 
22
22
  import abc
23
23
  from collections.abc import Sequence
24
+ from functools import cached_property
24
25
  from typing import TYPE_CHECKING
25
26
 
26
- from airflow.models import BaseOperator
27
27
  from airflow.providers.google.cloud.hooks.bigquery import BigQueryHook
28
28
  from airflow.providers.google.cloud.utils.bigquery_get_data import bigquery_get_data
29
+ from airflow.providers.google.version_compat import BaseOperator
29
30
 
30
31
  if TYPE_CHECKING:
32
+ from airflow.providers.common.compat.sdk import Context
31
33
  from airflow.providers.common.sql.hooks.sql import DbApiHook
32
- from airflow.utils.context import Context
34
+ from airflow.providers.openlineage.extractors import OperatorLineage
33
35
 
34
36
 
35
37
  class BigQueryToSqlBaseOperator(BaseOperator):
@@ -113,19 +115,22 @@ class BigQueryToSqlBaseOperator(BaseOperator):
113
115
  def persist_links(self, context: Context) -> None:
114
116
  """Persist the connection to the SQL provider."""
115
117
 
116
- def execute(self, context: Context) -> None:
117
- big_query_hook = BigQueryHook(
118
+ @cached_property
119
+ def bigquery_hook(self) -> BigQueryHook:
120
+ return BigQueryHook(
118
121
  gcp_conn_id=self.gcp_conn_id,
119
122
  location=self.location,
120
123
  impersonation_chain=self.impersonation_chain,
121
124
  )
125
+
126
+ def execute(self, context: Context) -> None:
122
127
  self.persist_links(context)
123
128
  sql_hook = self.get_sql_hook()
124
129
  for rows in bigquery_get_data(
125
130
  self.log,
126
131
  self.dataset_id,
127
132
  self.table_id,
128
- big_query_hook,
133
+ self.bigquery_hook,
129
134
  self.batch_size,
130
135
  self.selected_fields,
131
136
  ):
@@ -136,3 +141,97 @@ class BigQueryToSqlBaseOperator(BaseOperator):
136
141
  replace=self.replace,
137
142
  commit_every=self.batch_size,
138
143
  )
144
+
145
+ def get_openlineage_facets_on_complete(self, task_instance) -> OperatorLineage | None:
146
+ """
147
+ Build a generic OpenLineage facet for BigQuery -> SQL transfers.
148
+
149
+ This consolidates nearly identical implementations from child
150
+ operators. Children still provide a concrete SQL hook via
151
+ ``get_sql_hook()`` and may override behavior if needed.
152
+ """
153
+ from airflow.providers.common.compat.openlineage.facet import Dataset
154
+ from airflow.providers.google.cloud.openlineage.utils import (
155
+ BIGQUERY_NAMESPACE,
156
+ get_facets_from_bq_table_for_given_fields,
157
+ get_identity_column_lineage_facet,
158
+ )
159
+ from airflow.providers.openlineage.extractors import OperatorLineage
160
+
161
+ if not self.bigquery_hook:
162
+ self.bigquery_hook = BigQueryHook(
163
+ gcp_conn_id=self.gcp_conn_id,
164
+ location=self.location,
165
+ impersonation_chain=self.impersonation_chain,
166
+ )
167
+
168
+ try:
169
+ if not getattr(self, "source_project_dataset_table", None):
170
+ project_id = self.bigquery_hook.project_id
171
+ self.source_project_dataset_table = f"{project_id}.{self.dataset_id}.{self.table_id}"
172
+
173
+ table_obj = self.bigquery_hook.get_client().get_table(self.source_project_dataset_table)
174
+ except Exception:
175
+ self.log.debug(
176
+ "OpenLineage: could not fetch BigQuery table %s",
177
+ getattr(self, "source_project_dataset_table", None),
178
+ exc_info=True,
179
+ )
180
+ return OperatorLineage()
181
+
182
+ if self.selected_fields:
183
+ if isinstance(self.selected_fields, str):
184
+ bigquery_field_names = list(self.selected_fields)
185
+ else:
186
+ bigquery_field_names = self.selected_fields
187
+ else:
188
+ bigquery_field_names = [f.name for f in getattr(table_obj, "schema", [])]
189
+
190
+ input_dataset = Dataset(
191
+ namespace=BIGQUERY_NAMESPACE,
192
+ name=self.source_project_dataset_table,
193
+ facets=get_facets_from_bq_table_for_given_fields(table_obj, bigquery_field_names),
194
+ )
195
+
196
+ sql_hook = self.get_sql_hook()
197
+ db_info = sql_hook.get_openlineage_database_info(sql_hook.get_conn())
198
+ if db_info is None:
199
+ self.log.debug("OpenLineage: could not get database info from SQL hook %s", type(sql_hook))
200
+ return OperatorLineage()
201
+ namespace = f"{db_info.scheme}://{db_info.authority}"
202
+
203
+ schema_name = None
204
+ if hasattr(sql_hook, "get_openlineage_default_schema"):
205
+ try:
206
+ schema_name = sql_hook.get_openlineage_default_schema()
207
+ except Exception:
208
+ schema_name = None
209
+
210
+ if self.target_table_name and "." in self.target_table_name:
211
+ schema_part, table_part = self.target_table_name.split(".", 1)
212
+ else:
213
+ schema_part = schema_name or ""
214
+ table_part = self.target_table_name or ""
215
+
216
+ if db_info and db_info.scheme == "mysql":
217
+ output_name = f"{self.database}.{table_part}" if self.database else f"{table_part}"
218
+ else:
219
+ if self.database:
220
+ if schema_part:
221
+ output_name = f"{self.database}.{schema_part}.{table_part}"
222
+ else:
223
+ output_name = f"{self.database}.{table_part}"
224
+ else:
225
+ if schema_part:
226
+ output_name = f"{schema_part}.{table_part}"
227
+ else:
228
+ output_name = f"{table_part}"
229
+
230
+ column_lineage_facet = get_identity_column_lineage_facet(
231
+ bigquery_field_names, input_datasets=[input_dataset]
232
+ )
233
+
234
+ output_facets = column_lineage_facet or {}
235
+ output_dataset = Dataset(namespace=namespace, name=output_name, facets=output_facets)
236
+
237
+ return OperatorLineage(inputs=[input_dataset], outputs=[output_dataset])
@@ -21,9 +21,9 @@ from collections.abc import Sequence
21
21
  from tempfile import NamedTemporaryFile
22
22
  from typing import TYPE_CHECKING, Any
23
23
 
24
- from airflow.models import BaseOperator
25
24
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
26
25
  from airflow.providers.google.suite.hooks.calendar import GoogleCalendarHook
26
+ from airflow.providers.google.version_compat import BaseOperator
27
27
 
28
28
  if TYPE_CHECKING:
29
29
  from datetime import datetime
@@ -31,12 +31,12 @@ from uuid import UUID
31
31
  from cassandra.util import Date, OrderedMapSerializedKey, SortedSet, Time
32
32
 
33
33
  from airflow.exceptions import AirflowException
34
- from airflow.models import BaseOperator
35
34
  from airflow.providers.apache.cassandra.hooks.cassandra import CassandraHook
36
35
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
36
+ from airflow.providers.google.version_compat import BaseOperator
37
37
 
38
38
  if TYPE_CHECKING:
39
- from airflow.utils.context import Context
39
+ from airflow.providers.common.compat.sdk import Context
40
40
 
41
41
  NotSetType = NewType("NotSetType", object)
42
42
  NOT_SET = NotSetType(object())
@@ -26,14 +26,14 @@ from enum import Enum
26
26
  from typing import TYPE_CHECKING, Any
27
27
 
28
28
  from airflow.exceptions import AirflowException
29
- from airflow.models import BaseOperator
30
29
  from airflow.providers.facebook.ads.hooks.ads import FacebookAdsReportingHook
31
30
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
31
+ from airflow.providers.google.version_compat import BaseOperator
32
32
 
33
33
  if TYPE_CHECKING:
34
34
  from facebook_business.adobjects.adsinsights import AdsInsights
35
35
 
36
- from airflow.utils.context import Context
36
+ from airflow.providers.common.compat.sdk import Context
37
37
 
38
38
 
39
39
  class FlushAction(Enum):
@@ -208,7 +208,7 @@ class FacebookAdsReportToGcsOperator(BaseOperator):
208
208
 
209
209
  def _flush_rows(self, converted_rows: list[Any] | None, object_name: str):
210
210
  if converted_rows:
211
- headers = converted_rows[0].keys()
211
+ headers = self.fields
212
212
  with tempfile.NamedTemporaryFile("w", suffix=".csv") as csvfile:
213
213
  writer = csv.DictWriter(csvfile, fieldnames=headers)
214
214
  writer.writeheader()
@@ -38,18 +38,18 @@ from google.cloud.bigquery.table import EncryptionConfiguration, Table, TableRef
38
38
 
39
39
  from airflow.configuration import conf
40
40
  from airflow.exceptions import AirflowException
41
- from airflow.models import BaseOperator
42
41
  from airflow.providers.google.cloud.hooks.bigquery import BigQueryHook, BigQueryJob
43
42
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
44
43
  from airflow.providers.google.cloud.links.bigquery import BigQueryTableLink
45
44
  from airflow.providers.google.cloud.triggers.bigquery import BigQueryInsertJobTrigger
46
45
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
46
+ from airflow.providers.google.version_compat import BaseOperator
47
47
  from airflow.utils.helpers import merge_dicts
48
48
 
49
49
  if TYPE_CHECKING:
50
50
  from google.api_core.retry import Retry
51
51
 
52
- from airflow.utils.context import Context
52
+ from airflow.providers.common.compat.sdk import Context
53
53
 
54
54
  ALLOWED_FORMATS = [
55
55
  "CSV",
@@ -144,6 +144,9 @@ class GCSToBigQueryOperator(BaseOperator):
144
144
  partition by field, type and expiration as per API specifications.
145
145
  Note that 'field' is not available in concurrency with
146
146
  dataset.table$partition.
147
+ Ignored if 'range_partitioning' is set.
148
+ :param range_partitioning: configure optional range partitioning fields i.e.
149
+ partition by field and integer interval as per API specifications.
147
150
  :param cluster_fields: Request that the result of this load be stored sorted
148
151
  by one or more columns. BigQuery supports clustering for both partitioned and
149
152
  non-partitioned tables. The order of columns given determines the sort order.
@@ -219,6 +222,7 @@ class GCSToBigQueryOperator(BaseOperator):
219
222
  src_fmt_configs=None,
220
223
  external_table=False,
221
224
  time_partitioning=None,
225
+ range_partitioning=None,
222
226
  cluster_fields=None,
223
227
  autodetect=True,
224
228
  encryption_configuration=None,
@@ -246,6 +250,10 @@ class GCSToBigQueryOperator(BaseOperator):
246
250
  src_fmt_configs = {}
247
251
  if time_partitioning is None:
248
252
  time_partitioning = {}
253
+ if range_partitioning is None:
254
+ range_partitioning = {}
255
+ if range_partitioning and time_partitioning:
256
+ raise ValueError("Only one of time_partitioning or range_partitioning can be set.")
249
257
  self.bucket = bucket
250
258
  self.source_objects = source_objects
251
259
  self.schema_object = schema_object
@@ -283,6 +291,7 @@ class GCSToBigQueryOperator(BaseOperator):
283
291
  self.schema_update_options = schema_update_options
284
292
  self.src_fmt_configs = src_fmt_configs
285
293
  self.time_partitioning = time_partitioning
294
+ self.range_partitioning = range_partitioning
286
295
  self.cluster_fields = cluster_fields
287
296
  self.autodetect = autodetect
288
297
  self.encryption_configuration = encryption_configuration
@@ -337,8 +346,9 @@ class GCSToBigQueryOperator(BaseOperator):
337
346
  job_id=self.job_id,
338
347
  dag_id=self.dag_id,
339
348
  task_id=self.task_id,
340
- logical_date=context["logical_date"],
349
+ logical_date=None,
341
350
  configuration=self.configuration,
351
+ run_after=hook.get_run_after_or_logical_date(context),
342
352
  force_rerun=self.force_rerun,
343
353
  )
344
354
 
@@ -373,7 +383,6 @@ class GCSToBigQueryOperator(BaseOperator):
373
383
 
374
384
  BigQueryTableLink.persist(
375
385
  context=context,
376
- task_instance=self,
377
386
  dataset_id=table_obj_api_repr["tableReference"]["datasetId"],
378
387
  project_id=table_obj_api_repr["tableReference"]["projectId"],
379
388
  table_id=table_obj_api_repr["tableReference"]["tableId"],
@@ -430,7 +439,6 @@ class GCSToBigQueryOperator(BaseOperator):
430
439
  table = job_configuration[job_type][table_prop]
431
440
  persist_kwargs = {
432
441
  "context": context,
433
- "task_instance": self,
434
442
  "table_id": table,
435
443
  }
436
444
  if not isinstance(table, str):
@@ -547,6 +555,7 @@ class GCSToBigQueryOperator(BaseOperator):
547
555
  "quote",
548
556
  "encoding",
549
557
  "preserveAsciiControlCharacters",
558
+ "columnNameCharacterMap",
550
559
  ],
551
560
  "googleSheetsOptions": ["skipLeadingRows"],
552
561
  }
@@ -581,9 +590,11 @@ class GCSToBigQueryOperator(BaseOperator):
581
590
  table_obj_api_repr = table.to_api_repr()
582
591
 
583
592
  self.log.info("Creating external table: %s", self.destination_project_dataset_table)
584
- self.hook.create_empty_table(
593
+ self.hook.create_table(
585
594
  table_resource=table_obj_api_repr,
586
595
  project_id=self.project_id or self.hook.project_id,
596
+ dataset_id=table.dataset_id,
597
+ table_id=table.table_id,
587
598
  location=self.location,
588
599
  exists_ok=True,
589
600
  )
@@ -628,6 +639,8 @@ class GCSToBigQueryOperator(BaseOperator):
628
639
  )
629
640
  if self.time_partitioning:
630
641
  self.configuration["load"].update({"timePartitioning": self.time_partitioning})
642
+ if self.range_partitioning:
643
+ self.configuration["load"].update({"rangePartitioning": self.range_partitioning})
631
644
 
632
645
  if self.cluster_fields:
633
646
  self.configuration["load"].update({"clustering": {"fields": self.cluster_fields}})
@@ -636,12 +649,6 @@ class GCSToBigQueryOperator(BaseOperator):
636
649
  self.configuration["load"]["schema"] = {"fields": self.schema_fields}
637
650
 
638
651
  if self.schema_update_options:
639
- if self.write_disposition not in ["WRITE_APPEND", "WRITE_TRUNCATE"]:
640
- raise ValueError(
641
- "schema_update_options is only "
642
- "allowed if write_disposition is "
643
- "'WRITE_APPEND' or 'WRITE_TRUNCATE'."
644
- )
645
652
  # To provide backward compatibility
646
653
  self.schema_update_options = list(self.schema_update_options or [])
647
654
  self.log.info("Adding experimental 'schemaUpdateOptions': %s", self.schema_update_options)
@@ -672,6 +679,7 @@ class GCSToBigQueryOperator(BaseOperator):
672
679
  "quote",
673
680
  "encoding",
674
681
  "preserveAsciiControlCharacters",
682
+ "columnNameCharacterMap",
675
683
  ],
676
684
  "DATASTORE_BACKUP": ["projectionFields"],
677
685
  "NEWLINE_DELIMITED_JSON": ["autodetect", "ignoreUnknownValues"],
@@ -24,13 +24,13 @@ from collections.abc import Sequence
24
24
  from typing import TYPE_CHECKING
25
25
 
26
26
  from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
27
- from airflow.models import BaseOperator
28
27
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
28
+ from airflow.providers.google.version_compat import BaseOperator
29
29
 
30
30
  WILDCARD = "*"
31
31
 
32
32
  if TYPE_CHECKING:
33
- from airflow.utils.context import Context
33
+ from airflow.providers.common.compat.sdk import Context
34
34
 
35
35
 
36
36
  class GCSToGCSOperator(BaseOperator):
@@ -20,12 +20,14 @@ from collections.abc import Sequence
20
20
  from typing import TYPE_CHECKING
21
21
 
22
22
  from airflow.exceptions import AirflowException
23
- from airflow.models import BaseOperator
24
- from airflow.models.xcom import MAX_XCOM_SIZE
25
23
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
24
+ from airflow.providers.google.version_compat import BaseOperator
26
25
 
27
26
  if TYPE_CHECKING:
28
- from airflow.utils.context import Context
27
+ from airflow.providers.common.compat.sdk import Context
28
+
29
+ # MAX XCOM Size is 48KB, check discussion: https://github.com/apache/airflow/pull/1618#discussion_r68249677
30
+ MAX_XCOM_SIZE = 49344
29
31
 
30
32
 
31
33
  class GCSToLocalFilesystemOperator(BaseOperator):
@@ -26,14 +26,14 @@ from tempfile import NamedTemporaryFile
26
26
  from typing import TYPE_CHECKING
27
27
 
28
28
  from airflow.exceptions import AirflowException
29
- from airflow.models import BaseOperator
30
29
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
30
+ from airflow.providers.google.version_compat import BaseOperator
31
31
  from airflow.providers.sftp.hooks.sftp import SFTPHook
32
32
 
33
33
  WILDCARD = "*"
34
34
 
35
35
  if TYPE_CHECKING:
36
- from airflow.utils.context import Context
36
+ from airflow.providers.common.compat.sdk import Context
37
37
 
38
38
 
39
39
  class GCSToSFTPOperator(BaseOperator):
@@ -80,7 +80,9 @@ class GCSToSFTPOperator(BaseOperator):
80
80
  :param destination_path: The sftp remote path. This is the specified directory path for
81
81
  uploading to the SFTP server.
82
82
  :param keep_directory_structure: (Optional) When set to False the path of the file
83
- on the bucket is recreated within path passed in destination_path.
83
+ on the bucket is recreated within path passed in destination_path.
84
+ :param create_intermediate_dirs: (Optional) When set to True the intermediate directories
85
+ in the specified file path will be created.
84
86
  :param move_object: When move object is True, the object is moved instead
85
87
  of copied to the new location. This is the equivalent of a mv command
86
88
  as opposed to a cp command.
@@ -112,6 +114,7 @@ class GCSToSFTPOperator(BaseOperator):
112
114
  source_object: str,
113
115
  destination_path: str,
114
116
  keep_directory_structure: bool = True,
117
+ create_intermediate_dirs: bool = True,
115
118
  move_object: bool = False,
116
119
  gcp_conn_id: str = "google_cloud_default",
117
120
  sftp_conn_id: str = "ssh_default",
@@ -124,6 +127,7 @@ class GCSToSFTPOperator(BaseOperator):
124
127
  self.source_object = source_object
125
128
  self.destination_path = destination_path
126
129
  self.keep_directory_structure = keep_directory_structure
130
+ self.create_intermediate_dirs = create_intermediate_dirs
127
131
  self.move_object = move_object
128
132
  self.gcp_conn_id = gcp_conn_id
129
133
  self.sftp_conn_id = sftp_conn_id
@@ -190,7 +194,9 @@ class GCSToSFTPOperator(BaseOperator):
190
194
  )
191
195
 
192
196
  dir_path = os.path.dirname(destination_path)
193
- sftp_hook.create_directory(dir_path)
197
+
198
+ if self.create_intermediate_dirs:
199
+ sftp_hook.create_directory(dir_path)
194
200
 
195
201
  with NamedTemporaryFile("w") as tmp:
196
202
  gcs_hook.download(
@@ -19,12 +19,12 @@ from __future__ import annotations
19
19
  from collections.abc import Sequence
20
20
  from typing import TYPE_CHECKING
21
21
 
22
- from airflow.models import BaseOperator
23
22
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
24
23
  from airflow.providers.google.suite.hooks.drive import GoogleDriveHook
24
+ from airflow.providers.google.version_compat import BaseOperator
25
25
 
26
26
  if TYPE_CHECKING:
27
- from airflow.utils.context import Context
27
+ from airflow.providers.common.compat.sdk import Context
28
28
 
29
29
 
30
30
  class GoogleDriveToGCSOperator(BaseOperator):
@@ -99,3 +99,7 @@ class GoogleDriveToGCSOperator(BaseOperator):
99
99
  bucket_name=self.bucket_name, object_name=self.object_name
100
100
  ) as file:
101
101
  gdrive_hook.download_file(file_id=file_metadata["id"], file_handle=file)
102
+
103
+ def dry_run(self):
104
+ """Perform a dry run of the operator."""
105
+ return None
@@ -19,11 +19,11 @@ from __future__ import annotations
19
19
  from collections.abc import Sequence
20
20
  from typing import TYPE_CHECKING
21
21
 
22
- from airflow.models import BaseOperator
23
22
  from airflow.providers.google.suite.hooks.drive import GoogleDriveHook
23
+ from airflow.providers.google.version_compat import BaseOperator
24
24
 
25
25
  if TYPE_CHECKING:
26
- from airflow.utils.context import Context
26
+ from airflow.providers.common.compat.sdk import Context
27
27
 
28
28
 
29
29
  class GoogleDriveToLocalOperator(BaseOperator):
@@ -0,0 +1,193 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ """This module contains operator to move data from HTTP endpoint to GCS."""
19
+
20
+ from __future__ import annotations
21
+
22
+ from functools import cached_property
23
+ from typing import TYPE_CHECKING, Any
24
+
25
+ from airflow.providers.google.cloud.hooks.gcs import GCSHook
26
+ from airflow.providers.google.version_compat import BaseOperator
27
+ from airflow.providers.http.hooks.http import HttpHook
28
+
29
+ if TYPE_CHECKING:
30
+ from collections.abc import Sequence
31
+
32
+ from requests.auth import AuthBase
33
+
34
+ from airflow.providers.common.compat.sdk import Context
35
+
36
+
37
+ class HttpToGCSOperator(BaseOperator):
38
+ """
39
+ Calls an endpoint on an HTTP system to execute an action and store the result in GCS.
40
+
41
+ :param http_conn_id: The :ref:`http connection<howto/connection:http>` to run
42
+ the operator against
43
+ :param endpoint: The relative part of the full url. (templated)
44
+ :param method: The HTTP method to use, default = "POST"
45
+ :param data: The data to pass. POST-data in POST/PUT and params
46
+ in the URL for a GET request. (templated)
47
+ :param headers: The HTTP headers to be added to the GET request
48
+ :param response_check: A check against the 'requests' response object.
49
+ The callable takes the response object as the first positional argument
50
+ and optionally any number of keyword arguments available in the context dictionary.
51
+ It should return True for 'pass' and False otherwise.
52
+ :param response_filter: A function allowing you to manipulate the response
53
+ text. e.g response_filter=lambda response: json.loads(response.text).
54
+ The callable takes the response object as the first positional argument
55
+ and optionally any number of keyword arguments available in the context dictionary.
56
+ :param extra_options: Extra options for the 'requests' library, see the
57
+ 'requests' documentation (options to modify timeout, ssl, etc.)
58
+ :param log_response: Log the response (default: False)
59
+ :param auth_type: The auth type for the service
60
+ :param tcp_keep_alive: Enable TCP Keep Alive for the connection.
61
+ :param tcp_keep_alive_idle: The TCP Keep Alive Idle parameter (corresponds to ``socket.TCP_KEEPIDLE``).
62
+ :param tcp_keep_alive_count: The TCP Keep Alive count parameter (corresponds to ``socket.TCP_KEEPCNT``)
63
+ :param tcp_keep_alive_interval: The TCP Keep Alive interval parameter (corresponds to
64
+ ``socket.TCP_KEEPINTVL``)
65
+ :param gcp_conn_id: The connection ID to use when fetching connection info.
66
+ :param impersonation_chain: Optional service account to impersonate using short-term credentials,
67
+ or chained list of accounts required to get the access_token of the last account in the list,
68
+ which will be impersonated in the request. If set as a string,
69
+ the account must grant the originating account the Service Account Token Creator IAM role.
70
+ If set as a sequence, the identities from the list must grant Service Account Token Creator IAM role to the directly preceding identity,
71
+ with first account from the list granting this role to the originating account.
72
+ :param bucket_name: The bucket to upload to.
73
+ :param object_name: The object name to set when uploading the file.
74
+ :param mime_type: The file mime type set when uploading the file.
75
+ :param gzip: Option to compress local file or file data for upload
76
+ :param encoding: bytes encoding for file data if provided as string
77
+ :param chunk_size: Blob chunk size.
78
+ :param timeout: Request timeout in seconds.
79
+ :param num_max_attempts: Number of attempts to try to upload the file.
80
+ :param metadata: The metadata to be uploaded with the file.
81
+ :param cache_contro: Cache-Control metadata field.
82
+ :param user_project: The identifier of the Google Cloud project to bill for the request. Required for Requester Pays buckets.
83
+ """
84
+
85
+ template_fields: Sequence[str] = (
86
+ "http_conn_id",
87
+ "endpoint",
88
+ "data",
89
+ "headers",
90
+ "gcp_conn_id",
91
+ "bucket_name",
92
+ "object_name",
93
+ )
94
+ template_fields_renderers = {"headers": "json", "data": "py"}
95
+ template_ext: Sequence[str] = ()
96
+ ui_color = "#f4a460"
97
+
98
+ def __init__(
99
+ self,
100
+ *,
101
+ endpoint: str | None = None,
102
+ method: str = "GET",
103
+ data: Any = None,
104
+ headers: dict[str, str] | None = None,
105
+ extra_options: dict[str, Any] | None = None,
106
+ http_conn_id: str = "http_default",
107
+ log_response: bool = False,
108
+ auth_type: type[AuthBase] | None = None,
109
+ tcp_keep_alive: bool = True,
110
+ tcp_keep_alive_idle: int = 120,
111
+ tcp_keep_alive_count: int = 20,
112
+ tcp_keep_alive_interval: int = 30,
113
+ gcp_conn_id: str = "google_cloud_default",
114
+ impersonation_chain: str | Sequence[str] | None = None,
115
+ bucket_name: str,
116
+ object_name: str,
117
+ mime_type: str | None = None,
118
+ gzip: bool = False,
119
+ encoding: str | None = None,
120
+ chunk_size: int | None = None,
121
+ timeout: int | None = None,
122
+ num_max_attempts: int = 3,
123
+ metadata: dict | None = None,
124
+ cache_control: str | None = None,
125
+ user_project: str | None = None,
126
+ **kwargs,
127
+ ):
128
+ super().__init__(**kwargs)
129
+ self.http_conn_id = http_conn_id
130
+ self.method = method
131
+ self.endpoint = endpoint
132
+ self.headers = headers or {}
133
+ self.data = data or {}
134
+ self.extra_options = extra_options or {}
135
+ self.log_response = log_response
136
+ self.auth_type = auth_type
137
+ self.tcp_keep_alive = tcp_keep_alive
138
+ self.tcp_keep_alive_idle = tcp_keep_alive_idle
139
+ self.tcp_keep_alive_count = tcp_keep_alive_count
140
+ self.tcp_keep_alive_interval = tcp_keep_alive_interval
141
+ self.gcp_conn_id = gcp_conn_id
142
+ self.impersonation_chain = impersonation_chain
143
+ self.bucket_name = bucket_name
144
+ self.object_name = object_name
145
+ self.mime_type = mime_type
146
+ self.gzip = gzip
147
+ self.encoding = encoding
148
+ self.chunk_size = chunk_size
149
+ self.timeout = timeout
150
+ self.num_max_attempts = num_max_attempts
151
+ self.metadata = metadata
152
+ self.cache_control = cache_control
153
+ self.user_project = user_project
154
+
155
+ @cached_property
156
+ def http_hook(self) -> HttpHook:
157
+ """Create and return an HttpHook."""
158
+ return HttpHook(
159
+ self.method,
160
+ http_conn_id=self.http_conn_id,
161
+ auth_type=self.auth_type,
162
+ tcp_keep_alive=self.tcp_keep_alive,
163
+ tcp_keep_alive_idle=self.tcp_keep_alive_idle,
164
+ tcp_keep_alive_count=self.tcp_keep_alive_count,
165
+ tcp_keep_alive_interval=self.tcp_keep_alive_interval,
166
+ )
167
+
168
+ @cached_property
169
+ def gcs_hook(self) -> GCSHook:
170
+ """Create and return an GCSHook."""
171
+ return GCSHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain)
172
+
173
+ def execute(self, context: Context):
174
+ self.log.info("Calling HTTP method")
175
+ response = self.http_hook.run(
176
+ endpoint=self.endpoint, data=self.data, headers=self.headers, extra_options=self.extra_options
177
+ )
178
+
179
+ self.log.info("Uploading to GCS")
180
+ self.gcs_hook.upload(
181
+ data=response.content,
182
+ bucket_name=self.bucket_name,
183
+ object_name=self.object_name,
184
+ mime_type=self.mime_type,
185
+ gzip=self.gzip,
186
+ encoding=self.encoding or response.encoding,
187
+ chunk_size=self.chunk_size,
188
+ timeout=self.timeout,
189
+ num_max_attempts=self.num_max_attempts,
190
+ metadata=self.metadata,
191
+ cache_control=self.cache_control,
192
+ user_project=self.user_project,
193
+ )
@@ -24,11 +24,11 @@ from collections.abc import Sequence
24
24
  from glob import glob
25
25
  from typing import TYPE_CHECKING
26
26
 
27
- from airflow.models import BaseOperator
28
27
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
28
+ from airflow.providers.google.version_compat import BaseOperator
29
29
 
30
30
  if TYPE_CHECKING:
31
- from airflow.utils.context import Context
31
+ from airflow.providers.common.compat.sdk import Context
32
32
 
33
33
 
34
34
  class LocalFilesystemToGCSOperator(BaseOperator):
@@ -67,7 +67,7 @@ class MSSQLToGCSOperator(BaseSQLToGCSOperator):
67
67
 
68
68
  ui_color = "#e0a98c"
69
69
 
70
- type_map = {2: "BOOLEAN", 3: "INTEGER", 4: "TIMESTAMP", 5: "NUMERIC"}
70
+ type_map = {2: "BOOL", 3: "INTEGER", 4: "TIMESTAMP", 5: "NUMERIC"}
71
71
 
72
72
  def __init__(
73
73
  self,