apache-airflow-providers-google 12.0.0rc2__py3-none-any.whl → 14.0.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 (163) hide show
  1. airflow/providers/google/LICENSE +0 -52
  2. airflow/providers/google/__init__.py +1 -1
  3. airflow/providers/google/ads/hooks/ads.py +27 -13
  4. airflow/providers/google/ads/transfers/ads_to_gcs.py +18 -4
  5. airflow/providers/google/assets/bigquery.py +17 -0
  6. airflow/providers/google/cloud/_internal_client/secret_manager_client.py +2 -3
  7. airflow/providers/google/cloud/hooks/alloy_db.py +736 -8
  8. airflow/providers/google/cloud/hooks/automl.py +10 -4
  9. airflow/providers/google/cloud/hooks/bigquery.py +125 -22
  10. airflow/providers/google/cloud/hooks/bigquery_dts.py +8 -8
  11. airflow/providers/google/cloud/hooks/bigtable.py +2 -3
  12. airflow/providers/google/cloud/hooks/cloud_batch.py +3 -4
  13. airflow/providers/google/cloud/hooks/cloud_build.py +4 -5
  14. airflow/providers/google/cloud/hooks/cloud_composer.py +3 -4
  15. airflow/providers/google/cloud/hooks/cloud_memorystore.py +3 -4
  16. airflow/providers/google/cloud/hooks/cloud_run.py +3 -4
  17. airflow/providers/google/cloud/hooks/cloud_sql.py +7 -3
  18. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +119 -7
  19. airflow/providers/google/cloud/hooks/compute.py +3 -3
  20. airflow/providers/google/cloud/hooks/datacatalog.py +3 -4
  21. airflow/providers/google/cloud/hooks/dataflow.py +12 -12
  22. airflow/providers/google/cloud/hooks/dataform.py +2 -3
  23. airflow/providers/google/cloud/hooks/datafusion.py +2 -2
  24. airflow/providers/google/cloud/hooks/dataplex.py +1032 -11
  25. airflow/providers/google/cloud/hooks/dataproc.py +4 -5
  26. airflow/providers/google/cloud/hooks/dataproc_metastore.py +3 -4
  27. airflow/providers/google/cloud/hooks/dlp.py +3 -4
  28. airflow/providers/google/cloud/hooks/gcs.py +7 -6
  29. airflow/providers/google/cloud/hooks/kms.py +2 -3
  30. airflow/providers/google/cloud/hooks/kubernetes_engine.py +8 -8
  31. airflow/providers/google/cloud/hooks/life_sciences.py +1 -1
  32. airflow/providers/google/cloud/hooks/managed_kafka.py +482 -0
  33. airflow/providers/google/cloud/hooks/natural_language.py +2 -3
  34. airflow/providers/google/cloud/hooks/os_login.py +2 -3
  35. airflow/providers/google/cloud/hooks/pubsub.py +6 -6
  36. airflow/providers/google/cloud/hooks/secret_manager.py +2 -3
  37. airflow/providers/google/cloud/hooks/spanner.py +2 -2
  38. airflow/providers/google/cloud/hooks/speech_to_text.py +2 -3
  39. airflow/providers/google/cloud/hooks/stackdriver.py +4 -4
  40. airflow/providers/google/cloud/hooks/tasks.py +3 -4
  41. airflow/providers/google/cloud/hooks/text_to_speech.py +2 -3
  42. airflow/providers/google/cloud/hooks/translate.py +236 -5
  43. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +9 -4
  44. airflow/providers/google/cloud/hooks/vertex_ai/batch_prediction_job.py +3 -4
  45. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +4 -5
  46. airflow/providers/google/cloud/hooks/vertex_ai/dataset.py +3 -4
  47. airflow/providers/google/cloud/hooks/vertex_ai/endpoint_service.py +2 -3
  48. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +3 -4
  49. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +1 -181
  50. airflow/providers/google/cloud/hooks/vertex_ai/hyperparameter_tuning_job.py +3 -4
  51. airflow/providers/google/cloud/hooks/vertex_ai/model_service.py +2 -3
  52. airflow/providers/google/cloud/hooks/vertex_ai/pipeline_job.py +3 -4
  53. airflow/providers/google/cloud/hooks/vertex_ai/prediction_service.py +2 -3
  54. airflow/providers/google/cloud/hooks/video_intelligence.py +2 -3
  55. airflow/providers/google/cloud/hooks/vision.py +3 -4
  56. airflow/providers/google/cloud/hooks/workflows.py +2 -3
  57. airflow/providers/google/cloud/links/alloy_db.py +46 -0
  58. airflow/providers/google/cloud/links/bigquery.py +25 -0
  59. airflow/providers/google/cloud/links/dataplex.py +172 -2
  60. airflow/providers/google/cloud/links/kubernetes_engine.py +1 -2
  61. airflow/providers/google/cloud/links/managed_kafka.py +104 -0
  62. airflow/providers/google/cloud/links/translate.py +28 -0
  63. airflow/providers/google/cloud/log/gcs_task_handler.py +3 -3
  64. airflow/providers/google/cloud/log/stackdriver_task_handler.py +11 -10
  65. airflow/providers/google/cloud/openlineage/facets.py +67 -0
  66. airflow/providers/google/cloud/openlineage/mixins.py +438 -173
  67. airflow/providers/google/cloud/openlineage/utils.py +394 -61
  68. airflow/providers/google/cloud/operators/alloy_db.py +980 -69
  69. airflow/providers/google/cloud/operators/automl.py +83 -245
  70. airflow/providers/google/cloud/operators/bigquery.py +377 -74
  71. airflow/providers/google/cloud/operators/bigquery_dts.py +126 -13
  72. airflow/providers/google/cloud/operators/bigtable.py +1 -3
  73. airflow/providers/google/cloud/operators/cloud_base.py +1 -2
  74. airflow/providers/google/cloud/operators/cloud_batch.py +2 -4
  75. airflow/providers/google/cloud/operators/cloud_build.py +3 -5
  76. airflow/providers/google/cloud/operators/cloud_composer.py +5 -7
  77. airflow/providers/google/cloud/operators/cloud_memorystore.py +4 -6
  78. airflow/providers/google/cloud/operators/cloud_run.py +6 -5
  79. airflow/providers/google/cloud/operators/cloud_sql.py +20 -8
  80. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +62 -8
  81. airflow/providers/google/cloud/operators/compute.py +3 -4
  82. airflow/providers/google/cloud/operators/datacatalog.py +9 -11
  83. airflow/providers/google/cloud/operators/dataflow.py +1 -112
  84. airflow/providers/google/cloud/operators/dataform.py +3 -5
  85. airflow/providers/google/cloud/operators/datafusion.py +1 -1
  86. airflow/providers/google/cloud/operators/dataplex.py +2046 -7
  87. airflow/providers/google/cloud/operators/dataproc.py +102 -17
  88. airflow/providers/google/cloud/operators/dataproc_metastore.py +7 -9
  89. airflow/providers/google/cloud/operators/dlp.py +17 -19
  90. airflow/providers/google/cloud/operators/gcs.py +14 -17
  91. airflow/providers/google/cloud/operators/kubernetes_engine.py +2 -2
  92. airflow/providers/google/cloud/operators/managed_kafka.py +788 -0
  93. airflow/providers/google/cloud/operators/natural_language.py +3 -5
  94. airflow/providers/google/cloud/operators/pubsub.py +39 -7
  95. airflow/providers/google/cloud/operators/speech_to_text.py +3 -5
  96. airflow/providers/google/cloud/operators/stackdriver.py +3 -5
  97. airflow/providers/google/cloud/operators/tasks.py +4 -6
  98. airflow/providers/google/cloud/operators/text_to_speech.py +2 -4
  99. airflow/providers/google/cloud/operators/translate.py +414 -5
  100. airflow/providers/google/cloud/operators/translate_speech.py +2 -4
  101. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +9 -8
  102. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +4 -6
  103. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +6 -8
  104. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +4 -6
  105. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +4 -6
  106. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +0 -322
  107. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +4 -6
  108. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +4 -6
  109. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +4 -6
  110. airflow/providers/google/cloud/operators/video_intelligence.py +3 -5
  111. airflow/providers/google/cloud/operators/vision.py +4 -6
  112. airflow/providers/google/cloud/operators/workflows.py +5 -7
  113. airflow/providers/google/cloud/secrets/secret_manager.py +1 -2
  114. airflow/providers/google/cloud/sensors/bigquery_dts.py +3 -5
  115. airflow/providers/google/cloud/sensors/bigtable.py +2 -3
  116. airflow/providers/google/cloud/sensors/cloud_composer.py +32 -8
  117. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +39 -1
  118. airflow/providers/google/cloud/sensors/dataplex.py +4 -6
  119. airflow/providers/google/cloud/sensors/dataproc.py +2 -3
  120. airflow/providers/google/cloud/sensors/dataproc_metastore.py +1 -2
  121. airflow/providers/google/cloud/sensors/gcs.py +2 -4
  122. airflow/providers/google/cloud/sensors/pubsub.py +2 -3
  123. airflow/providers/google/cloud/sensors/workflows.py +3 -5
  124. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +5 -5
  125. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +10 -12
  126. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -1
  127. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +36 -4
  128. airflow/providers/google/cloud/transfers/mssql_to_gcs.py +27 -2
  129. airflow/providers/google/cloud/transfers/mysql_to_gcs.py +27 -2
  130. airflow/providers/google/cloud/transfers/postgres_to_gcs.py +27 -2
  131. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +34 -5
  132. airflow/providers/google/cloud/transfers/sql_to_gcs.py +15 -0
  133. airflow/providers/google/cloud/transfers/trino_to_gcs.py +25 -2
  134. airflow/providers/google/cloud/triggers/bigquery_dts.py +1 -2
  135. airflow/providers/google/cloud/triggers/cloud_batch.py +1 -2
  136. airflow/providers/google/cloud/triggers/cloud_build.py +1 -2
  137. airflow/providers/google/cloud/triggers/cloud_composer.py +13 -3
  138. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +102 -4
  139. airflow/providers/google/cloud/triggers/dataflow.py +2 -3
  140. airflow/providers/google/cloud/triggers/dataplex.py +1 -2
  141. airflow/providers/google/cloud/triggers/dataproc.py +2 -3
  142. airflow/providers/google/cloud/triggers/kubernetes_engine.py +1 -1
  143. airflow/providers/google/cloud/triggers/pubsub.py +1 -2
  144. airflow/providers/google/cloud/triggers/vertex_ai.py +7 -8
  145. airflow/providers/google/cloud/utils/credentials_provider.py +15 -8
  146. airflow/providers/google/cloud/utils/external_token_supplier.py +1 -0
  147. airflow/providers/google/common/auth_backend/google_openid.py +4 -4
  148. airflow/providers/google/common/consts.py +1 -2
  149. airflow/providers/google/common/hooks/base_google.py +8 -7
  150. airflow/providers/google/get_provider_info.py +186 -134
  151. airflow/providers/google/marketing_platform/hooks/analytics_admin.py +2 -3
  152. airflow/providers/google/marketing_platform/hooks/search_ads.py +1 -1
  153. airflow/providers/google/marketing_platform/operators/analytics_admin.py +5 -7
  154. {apache_airflow_providers_google-12.0.0rc2.dist-info → apache_airflow_providers_google-14.0.0rc1.dist-info}/METADATA +40 -57
  155. {apache_airflow_providers_google-12.0.0rc2.dist-info → apache_airflow_providers_google-14.0.0rc1.dist-info}/RECORD +157 -159
  156. airflow/providers/google/cloud/example_dags/example_facebook_ads_to_gcs.py +0 -141
  157. airflow/providers/google/cloud/example_dags/example_looker.py +0 -64
  158. airflow/providers/google/cloud/example_dags/example_presto_to_gcs.py +0 -194
  159. airflow/providers/google/cloud/example_dags/example_salesforce_to_gcs.py +0 -129
  160. airflow/providers/google/marketing_platform/example_dags/__init__.py +0 -16
  161. airflow/providers/google/marketing_platform/example_dags/example_display_video.py +0 -213
  162. {apache_airflow_providers_google-12.0.0rc2.dist-info → apache_airflow_providers_google-14.0.0rc1.dist-info}/WHEEL +0 -0
  163. {apache_airflow_providers_google-12.0.0rc2.dist-info → apache_airflow_providers_google-14.0.0rc1.dist-info}/entry_points.txt +0 -0
@@ -29,6 +29,10 @@ from collections.abc import Sequence
29
29
  from functools import cached_property
30
30
  from typing import TYPE_CHECKING
31
31
 
32
+ from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
33
+ from airflow.providers.google.common.consts import CLIENT_INFO
34
+ from airflow.providers.google.common.deprecated import deprecated
35
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
32
36
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
33
37
  from google.cloud.automl_v1beta1 import (
34
38
  AutoMlClient,
@@ -43,10 +47,6 @@ from google.cloud.automl_v1beta1 import (
43
47
  PredictResponse,
44
48
  )
45
49
 
46
- from airflow.exceptions import AirflowException
47
- from airflow.providers.google.common.consts import CLIENT_INFO
48
- from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
49
-
50
50
  if TYPE_CHECKING:
51
51
  from google.api_core.operation import Operation
52
52
  from google.api_core.retry import Retry
@@ -58,6 +58,12 @@ if TYPE_CHECKING:
58
58
  from google.protobuf.field_mask_pb2 import FieldMask
59
59
 
60
60
 
61
+ @deprecated(
62
+ planned_removal_date="September 30, 2025",
63
+ use_instead="airflow.providers.google.cloud.hooks.vertex_ai.auto_ml.AutoMLHook, "
64
+ "airflow.providers.google.cloud.hooks.translate.TranslateHook",
65
+ category=AirflowProviderDeprecationWarning,
66
+ )
61
67
  class CloudAutoMLHook(GoogleBaseHook):
62
68
  """
63
69
  Google Cloud AutoML hook.
@@ -33,25 +33,6 @@ from typing import TYPE_CHECKING, Any, NoReturn, Union, cast
33
33
 
34
34
  from aiohttp import ClientSession as ClientSession
35
35
  from gcloud.aio.bigquery import Job, Table as Table_async
36
- from google.cloud.bigquery import (
37
- DEFAULT_RETRY,
38
- Client,
39
- CopyJob,
40
- ExtractJob,
41
- LoadJob,
42
- QueryJob,
43
- SchemaField,
44
- UnknownJob,
45
- )
46
- from google.cloud.bigquery.dataset import AccessEntry, Dataset, DatasetListItem, DatasetReference
47
- from google.cloud.bigquery.retry import DEFAULT_JOB_RETRY
48
- from google.cloud.bigquery.table import (
49
- Row,
50
- RowIterator,
51
- Table,
52
- TableReference,
53
- )
54
- from google.cloud.exceptions import NotFound
55
36
  from googleapiclient.discovery import build
56
37
  from pandas_gbq import read_gbq
57
38
  from pandas_gbq.gbq import GbqConnector # noqa: F401 used in ``airflow.contrib.hooks.bigquery``
@@ -59,6 +40,7 @@ from requests import Session
59
40
  from sqlalchemy import create_engine
60
41
 
61
42
  from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
43
+ from airflow.providers.common.compat.lineage.hook import get_hook_lineage_collector
62
44
  from airflow.providers.common.sql.hooks.sql import DbApiHook
63
45
  from airflow.providers.google.cloud.utils.bigquery import bq_cast
64
46
  from airflow.providers.google.cloud.utils.credentials_provider import _get_scopes
@@ -73,9 +55,30 @@ from airflow.providers.google.common.hooks.base_google import (
73
55
  from airflow.utils.hashlib_wrapper import md5
74
56
  from airflow.utils.helpers import convert_camel_to_snake
75
57
  from airflow.utils.log.logging_mixin import LoggingMixin
58
+ from google.cloud.bigquery import (
59
+ DEFAULT_RETRY,
60
+ Client,
61
+ CopyJob,
62
+ ExtractJob,
63
+ LoadJob,
64
+ QueryJob,
65
+ SchemaField,
66
+ UnknownJob,
67
+ )
68
+ from google.cloud.bigquery.dataset import AccessEntry, Dataset, DatasetListItem, DatasetReference
69
+ from google.cloud.bigquery.retry import DEFAULT_JOB_RETRY
70
+ from google.cloud.bigquery.table import (
71
+ Row,
72
+ RowIterator,
73
+ Table,
74
+ TableListItem,
75
+ TableReference,
76
+ )
77
+ from google.cloud.exceptions import NotFound
76
78
 
77
79
  if TYPE_CHECKING:
78
80
  import pandas as pd
81
+
79
82
  from google.api_core.page_iterator import HTTPIterator
80
83
  from google.api_core.retry import Retry
81
84
 
@@ -344,6 +347,11 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
344
347
  except NotFound:
345
348
  return False
346
349
 
350
+ @deprecated(
351
+ planned_removal_date="July 30, 2025",
352
+ use_instead="airflow.providers.google.cloud.hooks.bigquery.BigQueryHook.create_table",
353
+ category=AirflowProviderDeprecationWarning,
354
+ )
347
355
  @GoogleBaseHook.fallback_to_default_project_id
348
356
  def create_empty_table(
349
357
  self,
@@ -454,9 +462,85 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
454
462
  table_id=table_id,
455
463
  )
456
464
  table = Table.from_api_repr(table_resource)
457
- return self.get_client(project_id=project_id, location=location).create_table(
465
+ result = self.get_client(project_id=project_id, location=location).create_table(
458
466
  table=table, exists_ok=exists_ok, retry=retry
459
467
  )
468
+ get_hook_lineage_collector().add_output_asset(
469
+ context=self,
470
+ scheme="bigquery",
471
+ asset_kwargs={
472
+ "project_id": result.project,
473
+ "dataset_id": result.dataset_id,
474
+ "table_id": result.table_id,
475
+ },
476
+ )
477
+ return result
478
+
479
+ @GoogleBaseHook.fallback_to_default_project_id
480
+ def create_table(
481
+ self,
482
+ dataset_id: str,
483
+ table_id: str,
484
+ table_resource: dict[str, Any] | Table | TableReference | TableListItem,
485
+ location: str | None = None,
486
+ project_id: str = PROVIDE_PROJECT_ID,
487
+ exists_ok: bool = True,
488
+ schema_fields: list | None = None,
489
+ retry: Retry = DEFAULT_RETRY,
490
+ timeout: float | None = None,
491
+ ) -> Table:
492
+ """
493
+ Create a new, empty table in the dataset.
494
+
495
+ :param project_id: Optional. The project to create the table into.
496
+ :param dataset_id: Required. The dataset to create the table into.
497
+ :param table_id: Required. The Name of the table to be created.
498
+ :param table_resource: Required. Table resource as described in documentation:
499
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#Table
500
+ If ``table`` is a reference, an empty table is created with the specified ID. The dataset that
501
+ the table belongs to must already exist.
502
+ :param schema_fields: Optional. If set, the schema field list as defined here:
503
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#configuration.load.schema
504
+
505
+ .. code-block:: python
506
+
507
+ schema_fields = [
508
+ {"name": "emp_name", "type": "STRING", "mode": "REQUIRED"},
509
+ {"name": "salary", "type": "INTEGER", "mode": "NULLABLE"},
510
+ ]
511
+ :param location: Optional. The location used for the operation.
512
+ :param exists_ok: Optional. If ``True``, ignore "already exists" errors when creating the table.
513
+ :param retry: Optional. A retry object used to retry requests. If `None` is specified, requests
514
+ will not be retried.
515
+ :param timeout: Optional. The amount of time, in seconds, to wait for the request to complete.
516
+ Note that if `retry` is specified, the timeout applies to each individual attempt.
517
+ """
518
+ _table_resource: dict[str, Any] = {}
519
+ if isinstance(table_resource, Table):
520
+ _table_resource = Table.from_api_repr(table_resource) # type: ignore
521
+ if schema_fields:
522
+ _table_resource["schema"] = {"fields": schema_fields}
523
+ table_resource_final = {**table_resource, **_table_resource} # type: ignore
524
+ table_resource = self._resolve_table_reference(
525
+ table_resource=table_resource_final,
526
+ project_id=project_id,
527
+ dataset_id=dataset_id,
528
+ table_id=table_id,
529
+ )
530
+ table = Table.from_api_repr(table_resource)
531
+ result = self.get_client(project_id=project_id, location=location).create_table(
532
+ table=table, exists_ok=exists_ok, retry=retry, timeout=timeout
533
+ )
534
+ get_hook_lineage_collector().add_output_asset(
535
+ context=self,
536
+ scheme="bigquery",
537
+ asset_kwargs={
538
+ "project_id": result.project,
539
+ "dataset_id": result.dataset_id,
540
+ "table_id": result.table_id,
541
+ },
542
+ )
543
+ return result
460
544
 
461
545
  @GoogleBaseHook.fallback_to_default_project_id
462
546
  def create_empty_dataset(
@@ -617,6 +701,15 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
617
701
  self.log.info("Updating table: %s", table_resource["tableReference"])
618
702
  table_object = self.get_client(project_id=project_id).update_table(table=table, fields=fields)
619
703
  self.log.info("Table %s.%s.%s updated successfully", project_id, dataset_id, table_id)
704
+ get_hook_lineage_collector().add_output_asset(
705
+ context=self,
706
+ scheme="bigquery",
707
+ asset_kwargs={
708
+ "project_id": table_object.project,
709
+ "dataset_id": table_object.dataset_id,
710
+ "table_id": table_object.table_id,
711
+ },
712
+ )
620
713
  return table_object.to_api_repr()
621
714
 
622
715
  @GoogleBaseHook.fallback_to_default_project_id
@@ -879,8 +972,8 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
879
972
  table = self.update_table(table_resource=table_resource)
880
973
  else:
881
974
  self.log.info("Table %s:%s.%s does not exist. creating.", project_id, dataset_id, table_id)
882
- table = self.create_empty_table(
883
- table_resource=table_resource, project_id=project_id
975
+ table = self.create_table(
976
+ dataset_id=dataset_id, table_id=table_id, table_resource=table_resource, project_id=project_id
884
977
  ).to_api_repr()
885
978
  return table
886
979
 
@@ -908,6 +1001,16 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
908
1001
  not_found_ok=not_found_ok,
909
1002
  )
910
1003
  self.log.info("Deleted table %s", table_id)
1004
+ table_ref = TableReference.from_string(table_id, default_project=project_id)
1005
+ get_hook_lineage_collector().add_input_asset(
1006
+ context=self,
1007
+ scheme="bigquery",
1008
+ asset_kwargs={
1009
+ "project_id": table_ref.project,
1010
+ "dataset_id": table_ref.dataset_id,
1011
+ "table_id": table_ref.table_id,
1012
+ },
1013
+ )
911
1014
 
912
1015
  @GoogleBaseHook.fallback_to_default_project_id
913
1016
  def list_rows(
@@ -23,6 +23,12 @@ from collections.abc import Sequence
23
23
  from copy import copy
24
24
  from typing import TYPE_CHECKING
25
25
 
26
+ from airflow.providers.google.common.consts import CLIENT_INFO
27
+ from airflow.providers.google.common.hooks.base_google import (
28
+ PROVIDE_PROJECT_ID,
29
+ GoogleBaseAsyncHook,
30
+ GoogleBaseHook,
31
+ )
26
32
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
27
33
  from google.cloud.bigquery_datatransfer_v1 import DataTransferServiceAsyncClient, DataTransferServiceClient
28
34
  from google.cloud.bigquery_datatransfer_v1.types import (
@@ -31,17 +37,11 @@ from google.cloud.bigquery_datatransfer_v1.types import (
31
37
  TransferRun,
32
38
  )
33
39
 
34
- from airflow.providers.google.common.consts import CLIENT_INFO
35
- from airflow.providers.google.common.hooks.base_google import (
36
- PROVIDE_PROJECT_ID,
37
- GoogleBaseAsyncHook,
38
- GoogleBaseHook,
39
- )
40
-
41
40
  if TYPE_CHECKING:
41
+ from googleapiclient.discovery import Resource
42
+
42
43
  from google.api_core.retry import Retry
43
44
  from google.api_core.retry_async import AsyncRetry
44
- from googleapiclient.discovery import Resource
45
45
 
46
46
 
47
47
  def get_object_id(obj: dict) -> str:
@@ -22,14 +22,13 @@ from __future__ import annotations
22
22
  from collections.abc import Sequence
23
23
  from typing import TYPE_CHECKING
24
24
 
25
+ from airflow.providers.google.common.consts import CLIENT_INFO
26
+ from airflow.providers.google.common.hooks.base_google import GoogleBaseHook
25
27
  from google.cloud.bigtable import Client, enums
26
28
  from google.cloud.bigtable.cluster import Cluster
27
29
  from google.cloud.bigtable.instance import Instance
28
30
  from google.cloud.bigtable.table import ClusterState, Table
29
31
 
30
- from airflow.providers.google.common.consts import CLIENT_INFO
31
- from airflow.providers.google.common.hooks.base_google import GoogleBaseHook
32
-
33
32
  if TYPE_CHECKING:
34
33
  import enum
35
34
 
@@ -23,6 +23,9 @@ import time
23
23
  from collections.abc import Iterable, Sequence
24
24
  from typing import TYPE_CHECKING
25
25
 
26
+ from airflow.exceptions import AirflowException
27
+ from airflow.providers.google.common.consts import CLIENT_INFO
28
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
26
29
  from google.cloud.batch import ListJobsRequest, ListTasksRequest
27
30
  from google.cloud.batch_v1 import (
28
31
  BatchServiceAsyncClient,
@@ -33,10 +36,6 @@ from google.cloud.batch_v1 import (
33
36
  Task,
34
37
  )
35
38
 
36
- from airflow.exceptions import AirflowException
37
- from airflow.providers.google.common.consts import CLIENT_INFO
38
- from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
39
-
40
39
  if TYPE_CHECKING:
41
40
  from google.api_core import operation
42
41
  from google.cloud.batch_v1.services.batch_service import pagers
@@ -22,15 +22,14 @@ from __future__ import annotations
22
22
  from collections.abc import Sequence
23
23
  from typing import TYPE_CHECKING
24
24
 
25
- from google.api_core.client_options import ClientOptions
26
- from google.api_core.exceptions import AlreadyExists
27
- from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
28
- from google.cloud.devtools.cloudbuild_v1 import CloudBuildAsyncClient, CloudBuildClient, GetBuildRequest
29
-
30
25
  from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
31
26
  from airflow.providers.google.common.consts import CLIENT_INFO
32
27
  from airflow.providers.google.common.deprecated import deprecated
33
28
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
29
+ from google.api_core.client_options import ClientOptions
30
+ from google.api_core.exceptions import AlreadyExists
31
+ from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
32
+ from google.cloud.devtools.cloudbuild_v1 import CloudBuildAsyncClient, CloudBuildClient, GetBuildRequest
34
33
 
35
34
  if TYPE_CHECKING:
36
35
  from google.api_core.operation import Operation
@@ -22,6 +22,9 @@ import time
22
22
  from collections.abc import MutableSequence, Sequence
23
23
  from typing import TYPE_CHECKING
24
24
 
25
+ from airflow.exceptions import AirflowException
26
+ from airflow.providers.google.common.consts import CLIENT_INFO
27
+ from airflow.providers.google.common.hooks.base_google import GoogleBaseHook
25
28
  from google.api_core.client_options import ClientOptions
26
29
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
27
30
  from google.cloud.orchestration.airflow.service_v1 import (
@@ -31,10 +34,6 @@ from google.cloud.orchestration.airflow.service_v1 import (
31
34
  PollAirflowCommandResponse,
32
35
  )
33
36
 
34
- from airflow.exceptions import AirflowException
35
- from airflow.providers.google.common.consts import CLIENT_INFO
36
- from airflow.providers.google.common.hooks.base_google import GoogleBaseHook
37
-
38
37
  if TYPE_CHECKING:
39
38
  from google.api_core.operation import Operation
40
39
  from google.api_core.operation_async import AsyncOperation
@@ -31,6 +31,9 @@ from __future__ import annotations
31
31
  from collections.abc import Sequence
32
32
  from typing import TYPE_CHECKING
33
33
 
34
+ from airflow import version
35
+ from airflow.exceptions import AirflowException
36
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
34
37
  from google.api_core import path_template
35
38
  from google.api_core.exceptions import NotFound
36
39
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
@@ -44,10 +47,6 @@ from google.cloud.redis_v1 import (
44
47
  OutputConfig,
45
48
  )
46
49
 
47
- from airflow import version
48
- from airflow.exceptions import AirflowException
49
- from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
50
-
51
50
  if TYPE_CHECKING:
52
51
  from google.api_core.retry import Retry
53
52
  from google.protobuf.field_mask_pb2 import FieldMask
@@ -21,6 +21,9 @@ import itertools
21
21
  from collections.abc import Iterable, Sequence
22
22
  from typing import TYPE_CHECKING, Any
23
23
 
24
+ from airflow.exceptions import AirflowException
25
+ from airflow.providers.google.common.consts import CLIENT_INFO
26
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
24
27
  from google.cloud.run_v2 import (
25
28
  CreateJobRequest,
26
29
  CreateServiceRequest,
@@ -40,10 +43,6 @@ from google.cloud.run_v2 import (
40
43
  )
41
44
  from google.longrunning import operations_pb2 # type: ignore[attr-defined]
42
45
 
43
- from airflow.exceptions import AirflowException
44
- from airflow.providers.google.common.consts import CLIENT_INFO
45
- from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
46
-
47
46
  if TYPE_CHECKING:
48
47
  from google.api_core import operation
49
48
  from google.api_core.operation_async import AsyncOperation
@@ -64,9 +64,11 @@ from airflow.providers.google.common.hooks.base_google import (
64
64
  from airflow.utils.log.logging_mixin import LoggingMixin
65
65
 
66
66
  if TYPE_CHECKING:
67
- from google.cloud.secretmanager_v1 import AccessSecretVersionResponse
68
67
  from requests import Session
69
68
 
69
+ from airflow.providers.common.sql.hooks.sql import DbApiHook
70
+ from google.cloud.secretmanager_v1 import AccessSecretVersionResponse
71
+
70
72
  UNIX_PATH_MAX = 108
71
73
 
72
74
  # Time to sleep between active checks of the operation results
@@ -573,6 +575,8 @@ class CloudSqlProxyRunner(LoggingMixin):
573
575
  processor = os.uname().machine
574
576
  if processor == "x86_64":
575
577
  processor = "amd64"
578
+ elif processor == "aarch64":
579
+ processor = "arm64"
576
580
  if not self.sql_proxy_version:
577
581
  download_url = CLOUD_SQL_PROXY_DOWNLOAD_URL.format(system, processor)
578
582
  else:
@@ -1146,7 +1150,7 @@ class CloudSQLDatabaseHook(BaseHook):
1146
1150
  gcp_conn_id=self.gcp_conn_id,
1147
1151
  )
1148
1152
 
1149
- def get_database_hook(self, connection: Connection) -> BaseHook:
1153
+ def get_database_hook(self, connection: Connection) -> DbApiHook:
1150
1154
  """
1151
1155
  Retrieve database hook.
1152
1156
 
@@ -1156,7 +1160,7 @@ class CloudSQLDatabaseHook(BaseHook):
1156
1160
  if self.database_type == "postgres":
1157
1161
  from airflow.providers.postgres.hooks.postgres import PostgresHook
1158
1162
 
1159
- db_hook: BaseHook = PostgresHook(connection=connection, database=self.database)
1163
+ db_hook: DbApiHook = PostgresHook(connection=connection, database=self.database)
1160
1164
  else:
1161
1165
  from airflow.providers.mysql.hooks.mysql import MySqlHook
1162
1166
 
@@ -36,12 +36,6 @@ from copy import deepcopy
36
36
  from datetime import timedelta
37
37
  from typing import TYPE_CHECKING, Any
38
38
 
39
- from google.cloud.storage_transfer_v1 import (
40
- ListTransferJobsRequest,
41
- StorageTransferServiceAsyncClient,
42
- TransferJob,
43
- TransferOperation,
44
- )
45
39
  from googleapiclient.discovery import Resource, build
46
40
  from googleapiclient.errors import HttpError
47
41
 
@@ -52,12 +46,21 @@ from airflow.providers.google.common.hooks.base_google import (
52
46
  GoogleBaseAsyncHook,
53
47
  GoogleBaseHook,
54
48
  )
49
+ from google.api_core import protobuf_helpers
50
+ from google.cloud.storage_transfer_v1 import (
51
+ ListTransferJobsRequest,
52
+ StorageTransferServiceAsyncClient,
53
+ TransferJob,
54
+ TransferOperation,
55
+ )
55
56
 
56
57
  if TYPE_CHECKING:
58
+ from proto import Message
59
+
57
60
  from google.cloud.storage_transfer_v1.services.storage_transfer_service.pagers import (
58
61
  ListTransferJobsAsyncPager,
59
62
  )
60
- from proto import Message
63
+ from google.longrunning import operations_pb2 # type: ignore[attr-defined]
61
64
 
62
65
  log = logging.getLogger(__name__)
63
66
 
@@ -596,3 +599,112 @@ class CloudDataTransferServiceAsyncHook(GoogleBaseAsyncHook):
596
599
  operation = TransferOperation.deserialize(response_operation.metadata.value)
597
600
  return operation
598
601
  return None
602
+
603
+ async def list_transfer_operations(
604
+ self,
605
+ request_filter: dict | None = None,
606
+ **kwargs,
607
+ ) -> list[TransferOperation]:
608
+ """
609
+ Get a transfer operation in Google Storage Transfer Service.
610
+
611
+ :param request_filter: (Required) A request filter, as described in
612
+ https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/list#body.QUERY_PARAMETERS.filter
613
+ With one additional improvement:
614
+ :return: transfer operation
615
+
616
+ The ``project_id`` parameter is optional if you have a project ID
617
+ defined in the connection. See: :doc:`/connections/gcp`
618
+ """
619
+ # To preserve backward compatibility
620
+ # TODO: remove one day
621
+ if request_filter is None:
622
+ if "filter" in kwargs:
623
+ request_filter = kwargs["filter"]
624
+ if not isinstance(request_filter, dict):
625
+ raise ValueError(f"The request_filter should be dict and is {type(request_filter)}")
626
+ warnings.warn(
627
+ "Use 'request_filter' instead of 'filter'",
628
+ AirflowProviderDeprecationWarning,
629
+ stacklevel=2,
630
+ )
631
+ else:
632
+ raise TypeError(
633
+ "list_transfer_operations missing 1 required positional argument: 'request_filter'"
634
+ )
635
+
636
+ conn = await self.get_conn()
637
+
638
+ request_filter = await self._inject_project_id(request_filter, FILTER, FILTER_PROJECT_ID)
639
+
640
+ operations: list[operations_pb2.Operation] = []
641
+
642
+ response = await conn.list_operations(
643
+ request={
644
+ "name": TRANSFER_OPERATIONS,
645
+ "filter": json.dumps(request_filter),
646
+ }
647
+ )
648
+
649
+ while response is not None:
650
+ operations.extend(response.operations)
651
+ response = (
652
+ await conn.list_operations(
653
+ request={
654
+ "name": TRANSFER_OPERATIONS,
655
+ "filter": json.dumps(request_filter),
656
+ "page_token": response.next_page_token,
657
+ }
658
+ )
659
+ if response.next_page_token
660
+ else None
661
+ )
662
+
663
+ transfer_operations = [
664
+ protobuf_helpers.from_any_pb(TransferOperation, op.metadata) for op in operations
665
+ ]
666
+
667
+ return transfer_operations
668
+
669
+ async def _inject_project_id(self, body: dict, param_name: str, target_key: str) -> dict:
670
+ body = deepcopy(body)
671
+ body[target_key] = body.get(target_key, self.project_id)
672
+ if not body.get(target_key):
673
+ raise AirflowException(
674
+ f"The project id must be passed either as `{target_key}` key in `{param_name}` "
675
+ f"parameter or as project_id extra in Google Cloud connection definition. Both are not set!"
676
+ )
677
+ return body
678
+
679
+ @staticmethod
680
+ async def operations_contain_expected_statuses(
681
+ operations: list[TransferOperation], expected_statuses: set[str] | str
682
+ ) -> bool:
683
+ """
684
+ Check whether an operation exists with the expected status.
685
+
686
+ :param operations: (Required) List of transfer operations to check.
687
+ :param expected_statuses: (Required) The expected status. See:
688
+ https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferOperations#Status
689
+ :return: If there is an operation with the expected state in the
690
+ operation list, returns true,
691
+ :raises AirflowException: If it encounters operations with state FAILED
692
+ or ABORTED in the list.
693
+ """
694
+ expected_statuses_set = (
695
+ {expected_statuses} if isinstance(expected_statuses, str) else set(expected_statuses)
696
+ )
697
+ if not operations:
698
+ return False
699
+
700
+ current_statuses = {operation.status.name for operation in operations}
701
+
702
+ if len(current_statuses - expected_statuses_set) != len(current_statuses):
703
+ return True
704
+
705
+ if len(NEGATIVE_STATUSES - current_statuses) != len(NEGATIVE_STATUSES):
706
+ raise AirflowException(
707
+ f"An unexpected operation status was encountered. "
708
+ f"Expected: {', '.join(expected_statuses_set)}"
709
+ )
710
+ return False
@@ -23,13 +23,13 @@ import time
23
23
  from collections.abc import Sequence
24
24
  from typing import TYPE_CHECKING, Any
25
25
 
26
- from google.cloud.compute_v1.services.instance_group_managers import InstanceGroupManagersClient
27
- from google.cloud.compute_v1.services.instance_templates import InstanceTemplatesClient
28
- from google.cloud.compute_v1.services.instances import InstancesClient
29
26
  from googleapiclient.discovery import build
30
27
 
31
28
  from airflow.exceptions import AirflowException
32
29
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
30
+ from google.cloud.compute_v1.services.instance_group_managers import InstanceGroupManagersClient
31
+ from google.cloud.compute_v1.services.instance_templates import InstanceTemplatesClient
32
+ from google.cloud.compute_v1.services.instances import InstancesClient
33
33
 
34
34
  if TYPE_CHECKING:
35
35
  from google.api_core.retry import Retry
@@ -19,6 +19,9 @@ from __future__ import annotations
19
19
  from collections.abc import Sequence
20
20
  from typing import TYPE_CHECKING
21
21
 
22
+ from airflow.exceptions import AirflowException
23
+ from airflow.providers.google.common.consts import CLIENT_INFO
24
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
22
25
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
23
26
  from google.cloud import datacatalog
24
27
  from google.cloud.datacatalog import (
@@ -32,10 +35,6 @@ from google.cloud.datacatalog import (
32
35
  TagTemplateField,
33
36
  )
34
37
 
35
- from airflow.exceptions import AirflowException
36
- from airflow.providers.google.common.consts import CLIENT_INFO
37
- from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
38
-
39
38
  if TYPE_CHECKING:
40
39
  from google.api_core.retry import Retry
41
40
  from google.protobuf.field_mask_pb2 import FieldMask
@@ -31,6 +31,18 @@ from collections.abc import Generator, Sequence
31
31
  from copy import deepcopy
32
32
  from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast
33
33
 
34
+ from googleapiclient.discovery import Resource, build
35
+
36
+ from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
37
+ from airflow.providers.apache.beam.hooks.beam import BeamHook, BeamRunnerType, beam_options_to_args
38
+ from airflow.providers.google.common.deprecated import deprecated
39
+ from airflow.providers.google.common.hooks.base_google import (
40
+ PROVIDE_PROJECT_ID,
41
+ GoogleBaseAsyncHook,
42
+ GoogleBaseHook,
43
+ )
44
+ from airflow.utils.log.logging_mixin import LoggingMixin
45
+ from airflow.utils.timeout import timeout
34
46
  from google.cloud.dataflow_v1beta3 import (
35
47
  GetJobRequest,
36
48
  Job,
@@ -47,18 +59,6 @@ from google.cloud.dataflow_v1beta3.types import (
47
59
  JobMetrics,
48
60
  )
49
61
  from google.cloud.dataflow_v1beta3.types.jobs import ListJobsRequest
50
- from googleapiclient.discovery import Resource, build
51
-
52
- from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
53
- from airflow.providers.apache.beam.hooks.beam import BeamHook, BeamRunnerType, beam_options_to_args
54
- from airflow.providers.google.common.deprecated import deprecated
55
- from airflow.providers.google.common.hooks.base_google import (
56
- PROVIDE_PROJECT_ID,
57
- GoogleBaseAsyncHook,
58
- GoogleBaseHook,
59
- )
60
- from airflow.utils.log.logging_mixin import LoggingMixin
61
- from airflow.utils.timeout import timeout
62
62
 
63
63
  if TYPE_CHECKING:
64
64
  from google.cloud.dataflow_v1beta3.services.jobs_v1_beta3.pagers import ListJobsAsyncPager