apache-airflow-providers-google 16.0.0a1__py3-none-any.whl → 16.1.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 (172) hide show
  1. airflow/providers/google/__init__.py +1 -1
  2. airflow/providers/google/ads/hooks/ads.py +43 -5
  3. airflow/providers/google/ads/operators/ads.py +1 -1
  4. airflow/providers/google/ads/transfers/ads_to_gcs.py +1 -1
  5. airflow/providers/google/cloud/hooks/bigquery.py +63 -77
  6. airflow/providers/google/cloud/hooks/cloud_sql.py +8 -4
  7. airflow/providers/google/cloud/hooks/datacatalog.py +9 -1
  8. airflow/providers/google/cloud/hooks/dataflow.py +2 -2
  9. airflow/providers/google/cloud/hooks/dataplex.py +1 -1
  10. airflow/providers/google/cloud/hooks/dataprep.py +4 -1
  11. airflow/providers/google/cloud/hooks/gcs.py +5 -5
  12. airflow/providers/google/cloud/hooks/looker.py +10 -1
  13. airflow/providers/google/cloud/hooks/mlengine.py +2 -1
  14. airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
  15. airflow/providers/google/cloud/hooks/spanner.py +2 -2
  16. airflow/providers/google/cloud/hooks/translate.py +1 -1
  17. airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +0 -36
  18. airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +307 -7
  19. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +44 -80
  20. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +11 -2
  21. airflow/providers/google/cloud/hooks/vision.py +2 -2
  22. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  23. airflow/providers/google/cloud/links/base.py +75 -11
  24. airflow/providers/google/cloud/links/bigquery.py +0 -47
  25. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  26. airflow/providers/google/cloud/links/bigtable.py +0 -48
  27. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  28. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  29. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  30. airflow/providers/google/cloud/links/cloud_run.py +27 -0
  31. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  32. airflow/providers/google/cloud/links/cloud_storage_transfer.py +16 -43
  33. airflow/providers/google/cloud/links/cloud_tasks.py +6 -25
  34. airflow/providers/google/cloud/links/compute.py +0 -58
  35. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  36. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  37. airflow/providers/google/cloud/links/dataflow.py +0 -34
  38. airflow/providers/google/cloud/links/dataform.py +0 -64
  39. airflow/providers/google/cloud/links/datafusion.py +1 -96
  40. airflow/providers/google/cloud/links/dataplex.py +0 -154
  41. airflow/providers/google/cloud/links/dataprep.py +0 -24
  42. airflow/providers/google/cloud/links/dataproc.py +14 -90
  43. airflow/providers/google/cloud/links/datastore.py +0 -31
  44. airflow/providers/google/cloud/links/kubernetes_engine.py +5 -59
  45. airflow/providers/google/cloud/links/life_sciences.py +0 -19
  46. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  47. airflow/providers/google/cloud/links/mlengine.py +0 -70
  48. airflow/providers/google/cloud/links/pubsub.py +0 -32
  49. airflow/providers/google/cloud/links/spanner.py +0 -33
  50. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  51. airflow/providers/google/cloud/links/translate.py +16 -186
  52. airflow/providers/google/cloud/links/vertex_ai.py +8 -224
  53. airflow/providers/google/cloud/links/workflows.py +0 -52
  54. airflow/providers/google/cloud/log/gcs_task_handler.py +4 -4
  55. airflow/providers/google/cloud/operators/alloy_db.py +69 -54
  56. airflow/providers/google/cloud/operators/automl.py +16 -14
  57. airflow/providers/google/cloud/operators/bigquery.py +49 -25
  58. airflow/providers/google/cloud/operators/bigquery_dts.py +2 -4
  59. airflow/providers/google/cloud/operators/bigtable.py +35 -6
  60. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  61. airflow/providers/google/cloud/operators/cloud_build.py +74 -31
  62. airflow/providers/google/cloud/operators/cloud_composer.py +34 -35
  63. airflow/providers/google/cloud/operators/cloud_memorystore.py +68 -42
  64. airflow/providers/google/cloud/operators/cloud_run.py +9 -1
  65. airflow/providers/google/cloud/operators/cloud_sql.py +11 -15
  66. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +0 -2
  67. airflow/providers/google/cloud/operators/compute.py +7 -39
  68. airflow/providers/google/cloud/operators/datacatalog.py +156 -20
  69. airflow/providers/google/cloud/operators/dataflow.py +37 -14
  70. airflow/providers/google/cloud/operators/dataform.py +14 -4
  71. airflow/providers/google/cloud/operators/datafusion.py +4 -12
  72. airflow/providers/google/cloud/operators/dataplex.py +180 -96
  73. airflow/providers/google/cloud/operators/dataprep.py +0 -4
  74. airflow/providers/google/cloud/operators/dataproc.py +10 -16
  75. airflow/providers/google/cloud/operators/dataproc_metastore.py +95 -87
  76. airflow/providers/google/cloud/operators/datastore.py +21 -5
  77. airflow/providers/google/cloud/operators/dlp.py +3 -26
  78. airflow/providers/google/cloud/operators/functions.py +15 -6
  79. airflow/providers/google/cloud/operators/gcs.py +1 -7
  80. airflow/providers/google/cloud/operators/kubernetes_engine.py +53 -92
  81. airflow/providers/google/cloud/operators/life_sciences.py +0 -1
  82. airflow/providers/google/cloud/operators/managed_kafka.py +106 -51
  83. airflow/providers/google/cloud/operators/mlengine.py +0 -1
  84. airflow/providers/google/cloud/operators/pubsub.py +4 -5
  85. airflow/providers/google/cloud/operators/spanner.py +0 -4
  86. airflow/providers/google/cloud/operators/speech_to_text.py +0 -1
  87. airflow/providers/google/cloud/operators/stackdriver.py +0 -8
  88. airflow/providers/google/cloud/operators/tasks.py +0 -11
  89. airflow/providers/google/cloud/operators/text_to_speech.py +0 -1
  90. airflow/providers/google/cloud/operators/translate.py +37 -13
  91. airflow/providers/google/cloud/operators/translate_speech.py +0 -1
  92. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +31 -18
  93. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +28 -8
  94. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +38 -25
  95. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +69 -7
  96. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +42 -8
  97. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +531 -0
  98. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +93 -117
  99. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +10 -8
  100. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +56 -10
  101. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +29 -6
  102. airflow/providers/google/cloud/operators/vertex_ai/ray.py +9 -6
  103. airflow/providers/google/cloud/operators/workflows.py +1 -9
  104. airflow/providers/google/cloud/sensors/bigquery.py +1 -1
  105. airflow/providers/google/cloud/sensors/bigquery_dts.py +6 -1
  106. airflow/providers/google/cloud/sensors/bigtable.py +15 -3
  107. airflow/providers/google/cloud/sensors/cloud_composer.py +6 -1
  108. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +6 -1
  109. airflow/providers/google/cloud/sensors/dataflow.py +3 -3
  110. airflow/providers/google/cloud/sensors/dataform.py +6 -1
  111. airflow/providers/google/cloud/sensors/datafusion.py +6 -1
  112. airflow/providers/google/cloud/sensors/dataplex.py +6 -1
  113. airflow/providers/google/cloud/sensors/dataprep.py +6 -1
  114. airflow/providers/google/cloud/sensors/dataproc.py +6 -1
  115. airflow/providers/google/cloud/sensors/dataproc_metastore.py +6 -1
  116. airflow/providers/google/cloud/sensors/gcs.py +9 -3
  117. airflow/providers/google/cloud/sensors/looker.py +6 -1
  118. airflow/providers/google/cloud/sensors/pubsub.py +8 -3
  119. airflow/providers/google/cloud/sensors/tasks.py +6 -1
  120. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +6 -1
  121. airflow/providers/google/cloud/sensors/workflows.py +6 -1
  122. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +1 -1
  123. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +1 -1
  124. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +10 -7
  125. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -2
  126. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +0 -1
  127. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -1
  128. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  129. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +1 -1
  130. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +2 -2
  131. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +1 -2
  132. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -1
  133. airflow/providers/google/cloud/transfers/gcs_to_local.py +1 -1
  134. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -1
  135. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +5 -1
  136. airflow/providers/google/cloud/transfers/gdrive_to_local.py +1 -1
  137. airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
  138. airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -1
  139. airflow/providers/google/cloud/transfers/s3_to_gcs.py +11 -5
  140. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +1 -1
  141. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -1
  142. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +2 -2
  143. airflow/providers/google/cloud/transfers/sql_to_gcs.py +1 -1
  144. airflow/providers/google/cloud/triggers/bigquery.py +32 -5
  145. airflow/providers/google/cloud/triggers/dataproc.py +62 -10
  146. airflow/providers/google/cloud/utils/field_validator.py +1 -2
  147. airflow/providers/google/common/auth_backend/google_openid.py +2 -1
  148. airflow/providers/google/common/deprecated.py +2 -1
  149. airflow/providers/google/common/hooks/base_google.py +7 -3
  150. airflow/providers/google/common/links/storage.py +0 -22
  151. airflow/providers/google/firebase/operators/firestore.py +1 -1
  152. airflow/providers/google/get_provider_info.py +14 -16
  153. airflow/providers/google/leveldb/hooks/leveldb.py +30 -1
  154. airflow/providers/google/leveldb/operators/leveldb.py +1 -1
  155. airflow/providers/google/marketing_platform/links/analytics_admin.py +3 -6
  156. airflow/providers/google/marketing_platform/operators/analytics_admin.py +0 -1
  157. airflow/providers/google/marketing_platform/operators/campaign_manager.py +4 -4
  158. airflow/providers/google/marketing_platform/operators/display_video.py +6 -6
  159. airflow/providers/google/marketing_platform/operators/search_ads.py +1 -1
  160. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +6 -1
  161. airflow/providers/google/marketing_platform/sensors/display_video.py +6 -1
  162. airflow/providers/google/suite/operators/sheets.py +3 -3
  163. airflow/providers/google/suite/sensors/drive.py +6 -1
  164. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +1 -1
  165. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  166. airflow/providers/google/suite/transfers/local_to_drive.py +1 -1
  167. airflow/providers/google/version_compat.py +28 -0
  168. {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/METADATA +35 -35
  169. {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/RECORD +171 -170
  170. airflow/providers/google/cloud/links/automl.py +0 -193
  171. {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/WHEEL +0 -0
  172. {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0.dist-info}/entry_points.txt +0 -0
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "15.1.0"
32
+ __version__ = "16.1.0"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.10.0"
@@ -28,14 +28,18 @@ from google.ads.googleads.errors import GoogleAdsException
28
28
  from google.auth.exceptions import GoogleAuthError
29
29
 
30
30
  from airflow.exceptions import AirflowException
31
- from airflow.hooks.base import BaseHook
32
31
  from airflow.providers.google.common.hooks.base_google import get_field
33
32
 
33
+ try:
34
+ from airflow.sdk import BaseHook
35
+ except ImportError:
36
+ from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
37
+
34
38
  if TYPE_CHECKING:
35
- from google.ads.googleads.v19.services.services.customer_service import CustomerServiceClient
36
- from google.ads.googleads.v19.services.services.google_ads_service import GoogleAdsServiceClient
37
- from google.ads.googleads.v19.services.services.google_ads_service.pagers import SearchPager
38
- from google.ads.googleads.v19.services.types.google_ads_service import GoogleAdsRow
39
+ from google.ads.googleads.v20.services.services.customer_service import CustomerServiceClient
40
+ from google.ads.googleads.v20.services.services.google_ads_service import GoogleAdsServiceClient
41
+ from google.ads.googleads.v20.services.services.google_ads_service.pagers import SearchPager
42
+ from google.ads.googleads.v20.services.types.google_ads_service import GoogleAdsRow
39
43
 
40
44
 
41
45
  class GoogleAdsHook(BaseHook):
@@ -101,6 +105,40 @@ class GoogleAdsHook(BaseHook):
101
105
  :param api_version: The Google Ads API version to use.
102
106
  """
103
107
 
108
+ conn_name_attr = "google_ads_conn_id"
109
+ default_conn_name = "google_ads_default"
110
+ conn_type = "google_ads"
111
+ hook_name = "Google Ads"
112
+
113
+ @classmethod
114
+ def get_connection_form_widgets(cls) -> dict[str, Any]:
115
+ """Return connection widgets to add to Google Ads connection form."""
116
+ from flask_appbuilder.fieldwidgets import BS3PasswordFieldWidget, BS3TextFieldWidget
117
+ from flask_babel import lazy_gettext
118
+ from wtforms import PasswordField, StringField
119
+
120
+ return {
121
+ "developer_token": StringField(lazy_gettext("Developer token"), widget=BS3TextFieldWidget()),
122
+ "client_id": StringField(lazy_gettext("OAuth2 Client ID"), widget=BS3TextFieldWidget()),
123
+ "client_secret": PasswordField(
124
+ lazy_gettext("OAuth2 Client Secret"), widget=BS3PasswordFieldWidget()
125
+ ),
126
+ "refresh_token": PasswordField(
127
+ lazy_gettext("OAuth2 Refresh Token"), widget=BS3PasswordFieldWidget()
128
+ ),
129
+ }
130
+
131
+ @classmethod
132
+ def get_ui_field_behaviour(cls) -> dict[str, Any]:
133
+ """Return custom UI field behaviour for Google Ads connection."""
134
+ return {
135
+ "hidden_fields": ["host", "login", "schema", "port"],
136
+ "relabeling": {},
137
+ "placeholders": {
138
+ "password": "Leave blank (optional)",
139
+ },
140
+ }
141
+
104
142
  def __init__(
105
143
  self,
106
144
  api_version: str | None = None,
@@ -24,9 +24,9 @@ from collections.abc import Sequence
24
24
  from tempfile import NamedTemporaryFile
25
25
  from typing import TYPE_CHECKING
26
26
 
27
- from airflow.models import BaseOperator
28
27
  from airflow.providers.google.ads.hooks.ads import GoogleAdsHook
29
28
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
29
+ from airflow.providers.google.version_compat import BaseOperator
30
30
 
31
31
  if TYPE_CHECKING:
32
32
  from airflow.utils.context import Context
@@ -22,9 +22,9 @@ from operator import attrgetter
22
22
  from tempfile import NamedTemporaryFile
23
23
  from typing import TYPE_CHECKING
24
24
 
25
- from airflow.models import BaseOperator
26
25
  from airflow.providers.google.ads.hooks.ads import GoogleAdsHook
27
26
  from airflow.providers.google.cloud.hooks.gcs import GCSHook
27
+ from airflow.providers.google.version_compat import BaseOperator
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  from airflow.utils.context import Context
@@ -29,7 +29,7 @@ import uuid
29
29
  from collections.abc import Iterable, Mapping, Sequence
30
30
  from copy import deepcopy
31
31
  from datetime import datetime, timedelta
32
- from typing import TYPE_CHECKING, Any, NoReturn, Union, cast
32
+ from typing import TYPE_CHECKING, Any, Literal, NoReturn, cast, overload
33
33
 
34
34
  from aiohttp import ClientSession as ClientSession
35
35
  from gcloud.aio.bigquery import Job, Table as Table_async
@@ -58,7 +58,11 @@ from pandas_gbq import read_gbq
58
58
  from pandas_gbq.gbq import GbqConnector # noqa: F401 used in ``airflow.contrib.hooks.bigquery``
59
59
  from sqlalchemy import create_engine
60
60
 
61
- from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
61
+ from airflow.exceptions import (
62
+ AirflowException,
63
+ AirflowOptionalProviderFeatureException,
64
+ AirflowProviderDeprecationWarning,
65
+ )
62
66
  from airflow.providers.common.compat.lineage.hook import get_hook_lineage_collector
63
67
  from airflow.providers.common.sql.hooks.sql import DbApiHook
64
68
  from airflow.providers.google.cloud.utils.bigquery import bq_cast
@@ -77,13 +81,14 @@ from airflow.utils.log.logging_mixin import LoggingMixin
77
81
 
78
82
  if TYPE_CHECKING:
79
83
  import pandas as pd
84
+ import polars as pl
80
85
  from google.api_core.page_iterator import HTTPIterator
81
86
  from google.api_core.retry import Retry
82
87
  from requests import Session
83
88
 
84
89
  log = logging.getLogger(__name__)
85
90
 
86
- BigQueryJob = Union[CopyJob, QueryJob, LoadJob, ExtractJob]
91
+ BigQueryJob = CopyJob | QueryJob | LoadJob | ExtractJob
87
92
 
88
93
 
89
94
  class BigQueryHook(GoogleBaseHook, DbApiHook):
@@ -275,15 +280,57 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
275
280
  """
276
281
  raise NotImplementedError()
277
282
 
278
- def get_pandas_df(
283
+ def _get_pandas_df(
279
284
  self,
280
285
  sql: str,
281
286
  parameters: Iterable | Mapping[str, Any] | None = None,
282
287
  dialect: str | None = None,
283
288
  **kwargs,
284
289
  ) -> pd.DataFrame:
290
+ if dialect is None:
291
+ dialect = "legacy" if self.use_legacy_sql else "standard"
292
+
293
+ credentials, project_id = self.get_credentials_and_project_id()
294
+
295
+ return read_gbq(sql, project_id=project_id, dialect=dialect, credentials=credentials, **kwargs)
296
+
297
+ def _get_polars_df(self, sql, parameters=None, dialect=None, **kwargs) -> pl.DataFrame:
298
+ try:
299
+ import polars as pl
300
+ except ImportError:
301
+ raise AirflowOptionalProviderFeatureException(
302
+ "Polars is not installed. Please install it with `pip install polars`."
303
+ )
304
+
305
+ if dialect is None:
306
+ dialect = "legacy" if self.use_legacy_sql else "standard"
307
+
308
+ credentials, project_id = self.get_credentials_and_project_id()
309
+
310
+ pandas_df = read_gbq(sql, project_id=project_id, dialect=dialect, credentials=credentials, **kwargs)
311
+ return pl.from_pandas(pandas_df)
312
+
313
+ @overload
314
+ def get_df(
315
+ self, sql, parameters=None, dialect=None, *, df_type: Literal["pandas"] = "pandas", **kwargs
316
+ ) -> pd.DataFrame: ...
317
+
318
+ @overload
319
+ def get_df(
320
+ self, sql, parameters=None, dialect=None, *, df_type: Literal["polars"], **kwargs
321
+ ) -> pl.DataFrame: ...
322
+
323
+ def get_df(
324
+ self,
325
+ sql,
326
+ parameters=None,
327
+ dialect=None,
328
+ *,
329
+ df_type: Literal["pandas", "polars"] = "pandas",
330
+ **kwargs,
331
+ ) -> pd.DataFrame | pl.DataFrame:
285
332
  """
286
- Get a Pandas DataFrame for the BigQuery results.
333
+ Get a DataFrame for the BigQuery results.
287
334
 
288
335
  The DbApiHook method must be overridden because Pandas doesn't support
289
336
  PEP 249 connections, except for SQLite.
@@ -299,12 +346,19 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
299
346
  defaults to use `self.use_legacy_sql` if not specified
300
347
  :param kwargs: (optional) passed into pandas_gbq.read_gbq method
301
348
  """
302
- if dialect is None:
303
- dialect = "legacy" if self.use_legacy_sql else "standard"
349
+ if df_type == "polars":
350
+ return self._get_polars_df(sql, parameters, dialect, **kwargs)
304
351
 
305
- credentials, project_id = self.get_credentials_and_project_id()
352
+ if df_type == "pandas":
353
+ return self._get_pandas_df(sql, parameters, dialect, **kwargs)
306
354
 
307
- return read_gbq(sql, project_id=project_id, dialect=dialect, credentials=credentials, **kwargs)
355
+ @deprecated(
356
+ planned_removal_date="November 30, 2025",
357
+ use_instead="airflow.providers.google.cloud.hooks.bigquery.BigQueryHook.get_df",
358
+ category=AirflowProviderDeprecationWarning,
359
+ )
360
+ def get_pandas_df(self, sql, parameters=None, dialect=None, **kwargs):
361
+ return self._get_pandas_df(sql, parameters, dialect, **kwargs)
308
362
 
309
363
  @GoogleBaseHook.fallback_to_default_project_id
310
364
  def table_exists(self, dataset_id: str, table_id: str, project_id: str) -> bool:
@@ -1937,74 +1991,6 @@ def _escape(s: str) -> str:
1937
1991
  return e
1938
1992
 
1939
1993
 
1940
- @deprecated(
1941
- planned_removal_date="April 01, 2025",
1942
- use_instead="airflow.providers.google.cloud.hooks.bigquery.BigQueryHook.split_tablename",
1943
- category=AirflowProviderDeprecationWarning,
1944
- )
1945
- def split_tablename(
1946
- table_input: str, default_project_id: str, var_name: str | None = None
1947
- ) -> tuple[str, str, str]:
1948
- if "." not in table_input:
1949
- raise ValueError(f"Expected table name in the format of <dataset>.<table>. Got: {table_input}")
1950
-
1951
- if not default_project_id:
1952
- raise ValueError("INTERNAL: No default project is specified")
1953
-
1954
- def var_print(var_name):
1955
- if var_name is None:
1956
- return ""
1957
- return f"Format exception for {var_name}: "
1958
-
1959
- if table_input.count(".") + table_input.count(":") > 3:
1960
- raise ValueError(f"{var_print(var_name)}Use either : or . to specify project got {table_input}")
1961
- cmpt = table_input.rsplit(":", 1)
1962
- project_id = None
1963
- rest = table_input
1964
- if len(cmpt) == 1:
1965
- project_id = None
1966
- rest = cmpt[0]
1967
- elif len(cmpt) == 2 and cmpt[0].count(":") <= 1:
1968
- if cmpt[-1].count(".") != 2:
1969
- project_id = cmpt[0]
1970
- rest = cmpt[1]
1971
- else:
1972
- raise ValueError(
1973
- f"{var_print(var_name)}Expect format of (<project:)<dataset>.<table>, got {table_input}"
1974
- )
1975
-
1976
- cmpt = rest.split(".")
1977
- if len(cmpt) == 3:
1978
- if project_id:
1979
- raise ValueError(f"{var_print(var_name)}Use either : or . to specify project")
1980
- project_id = cmpt[0]
1981
- dataset_id = cmpt[1]
1982
- table_id = cmpt[2]
1983
-
1984
- elif len(cmpt) == 2:
1985
- dataset_id = cmpt[0]
1986
- table_id = cmpt[1]
1987
- else:
1988
- raise ValueError(
1989
- f"{var_print(var_name)}Expect format of (<project.|<project:)<dataset>.<table>, got {table_input}"
1990
- )
1991
-
1992
- # Exclude partition from the table name
1993
- table_id = table_id.split("$")[0]
1994
-
1995
- if project_id is None:
1996
- if var_name is not None:
1997
- log.info(
1998
- 'Project is not included in %s: %s; using project "%s"',
1999
- var_name,
2000
- table_input,
2001
- default_project_id,
2002
- )
2003
- project_id = default_project_id
2004
-
2005
- return project_id, dataset_id, table_id
2006
-
2007
-
2008
1994
  def _cleanse_time_partitioning(
2009
1995
  destination_dataset_table: str | None, time_partitioning_in: dict | None
2010
1996
  ) -> dict: # if it is a partitioned table ($ is in the table name) add partition load option
@@ -38,7 +38,7 @@ from inspect import signature
38
38
  from pathlib import Path
39
39
  from subprocess import PIPE, Popen
40
40
  from tempfile import NamedTemporaryFile, _TemporaryFileWrapper, gettempdir
41
- from typing import TYPE_CHECKING, Any
41
+ from typing import TYPE_CHECKING, Any, cast
42
42
  from urllib.parse import quote_plus
43
43
 
44
44
  import httpx
@@ -50,7 +50,6 @@ from googleapiclient.errors import HttpError
50
50
  # Number of retries - used by googleapiclient method calls to perform retries
51
51
  # For requests that are "retriable"
52
52
  from airflow.exceptions import AirflowException
53
- from airflow.hooks.base import BaseHook
54
53
  from airflow.models import Connection
55
54
  from airflow.providers.google.cloud.hooks.secret_manager import (
56
55
  GoogleCloudSecretManagerHook,
@@ -61,6 +60,11 @@ from airflow.providers.google.common.hooks.base_google import (
61
60
  GoogleBaseHook,
62
61
  get_field,
63
62
  )
63
+
64
+ try:
65
+ from airflow.sdk import BaseHook
66
+ except ImportError:
67
+ from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
64
68
  from airflow.utils.log.logging_mixin import LoggingMixin
65
69
 
66
70
  if TYPE_CHECKING:
@@ -847,8 +851,8 @@ class CloudSQLDatabaseHook(BaseHook):
847
851
  self.user = self._get_iam_db_login()
848
852
  self.password = self._generate_login_token(service_account=self.cloudsql_connection.login)
849
853
  else:
850
- self.user = self.cloudsql_connection.login
851
- self.password = self.cloudsql_connection.password
854
+ self.user = cast("str", self.cloudsql_connection.login)
855
+ self.password = cast("str", self.cloudsql_connection.password)
852
856
  self.public_ip = self.cloudsql_connection.host
853
857
  self.public_port = self.cloudsql_connection.port
854
858
  self.ssl_cert = ssl_cert
@@ -32,8 +32,9 @@ from google.cloud.datacatalog import (
32
32
  TagTemplateField,
33
33
  )
34
34
 
35
- from airflow.exceptions import AirflowException
35
+ from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
36
36
  from airflow.providers.google.common.consts import CLIENT_INFO
37
+ from airflow.providers.google.common.deprecated import deprecated
37
38
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
38
39
 
39
40
  if TYPE_CHECKING:
@@ -41,6 +42,13 @@ if TYPE_CHECKING:
41
42
  from google.protobuf.field_mask_pb2 import FieldMask
42
43
 
43
44
 
45
+ @deprecated(
46
+ planned_removal_date="January 30, 2026",
47
+ use_instead="airflow.providers.google.cloud.hooks.dataplex.DataplexHook",
48
+ reason="The Data Catalog will be discontinued on January 30, 2026 "
49
+ "in favor of Dataplex Universal Catalog.",
50
+ category=AirflowProviderDeprecationWarning,
51
+ )
44
52
  class CloudDataCatalogHook(GoogleBaseHook):
45
53
  """
46
54
  Hook for Google Cloud Data Catalog Service.
@@ -27,9 +27,9 @@ import subprocess
27
27
  import time
28
28
  import uuid
29
29
  import warnings
30
- from collections.abc import Generator, Sequence
30
+ from collections.abc import Callable, Generator, Sequence
31
31
  from copy import deepcopy
32
- from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast
32
+ from typing import TYPE_CHECKING, Any, TypeVar, cast
33
33
 
34
34
  from google.cloud.dataflow_v1beta3 import (
35
35
  GetJobRequest,
@@ -515,7 +515,7 @@ class DataplexHook(GoogleBaseHook, OperationHelper):
515
515
  fields are non-required and omitted in the request body, their values are emptied.
516
516
  :param allow_missing: Optional. If set to true and entry doesn't exist, the service will create it.
517
517
  :param delete_missing_aspects: Optional. If set to true and the aspect_keys specify aspect
518
- ranges, the service deletes any existing aspects from that range that weren't provided
518
+ ranges, the service deletes any existing aspects from that range that were not provided
519
519
  in the request.
520
520
  :param aspect_keys: Optional. The map keys of the Aspects which the service should modify.
521
521
  It supports the following syntax:
@@ -28,7 +28,10 @@ import requests
28
28
  from requests import HTTPError
29
29
  from tenacity import retry, stop_after_attempt, wait_exponential
30
30
 
31
- from airflow.hooks.base import BaseHook
31
+ try:
32
+ from airflow.sdk import BaseHook
33
+ except ImportError:
34
+ from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
32
35
 
33
36
 
34
37
  def _get_field(extras: dict, field_name: str) -> str | None:
@@ -26,12 +26,12 @@ import os
26
26
  import shutil
27
27
  import time
28
28
  import warnings
29
- from collections.abc import Generator, Sequence
29
+ from collections.abc import Callable, Generator, Sequence
30
30
  from contextlib import contextmanager
31
31
  from functools import partial
32
32
  from io import BytesIO
33
33
  from tempfile import NamedTemporaryFile
34
- from typing import IO, TYPE_CHECKING, Any, Callable, TypeVar, cast, overload
34
+ from typing import IO, TYPE_CHECKING, Any, TypeVar, cast, overload
35
35
  from urllib.parse import urlsplit
36
36
 
37
37
  from gcloud.aio.storage import Storage
@@ -549,13 +549,13 @@ class GCSHook(GoogleBaseHook):
549
549
  if cache_control:
550
550
  blob.cache_control = cache_control
551
551
 
552
- if filename and data:
552
+ if filename is not None and data is not None:
553
553
  raise ValueError(
554
554
  "'filename' and 'data' parameter provided. Please "
555
555
  "specify a single parameter, either 'filename' for "
556
556
  "local file uploads or 'data' for file content uploads."
557
557
  )
558
- if filename:
558
+ if filename is not None:
559
559
  if not mime_type:
560
560
  mime_type = "application/octet-stream"
561
561
  if gzip:
@@ -575,7 +575,7 @@ class GCSHook(GoogleBaseHook):
575
575
  if gzip:
576
576
  os.remove(filename)
577
577
  self.log.info("File %s uploaded to %s in %s bucket", filename, object_name, bucket_name)
578
- elif data:
578
+ elif data is not None:
579
579
  if not mime_type:
580
580
  mime_type = "text/plain"
581
581
  if gzip:
@@ -29,7 +29,11 @@ from looker_sdk.sdk.api40 import methods as methods40
29
29
  from packaging.version import parse as parse_version
30
30
 
31
31
  from airflow.exceptions import AirflowException
32
- from airflow.hooks.base import BaseHook
32
+
33
+ try:
34
+ from airflow.sdk import BaseHook
35
+ except ImportError:
36
+ from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
33
37
  from airflow.version import version
34
38
 
35
39
  if TYPE_CHECKING:
@@ -39,6 +43,11 @@ if TYPE_CHECKING:
39
43
  class LookerHook(BaseHook):
40
44
  """Hook for Looker APIs."""
41
45
 
46
+ conn_name_attr = "looker_conn_id"
47
+ default_conn_name = "looker_default"
48
+ conn_type = "gcp_looker"
49
+ hook_name = "Google Looker"
50
+
42
51
  def __init__(
43
52
  self,
44
53
  looker_conn_id: str,
@@ -23,7 +23,8 @@ import contextlib
23
23
  import logging
24
24
  import random
25
25
  import time
26
- from typing import TYPE_CHECKING, Callable
26
+ from collections.abc import Callable
27
+ from typing import TYPE_CHECKING
27
28
 
28
29
  from aiohttp import ClientSession
29
30
  from gcloud.aio.auth import AioSession, Token