apache-airflow-providers-google 16.0.0a1__py3-none-any.whl → 16.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.
- airflow/providers/google/__init__.py +1 -1
- airflow/providers/google/ads/hooks/ads.py +43 -5
- airflow/providers/google/ads/operators/ads.py +1 -1
- airflow/providers/google/ads/transfers/ads_to_gcs.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +63 -77
- airflow/providers/google/cloud/hooks/cloud_sql.py +8 -4
- airflow/providers/google/cloud/hooks/datacatalog.py +9 -1
- airflow/providers/google/cloud/hooks/dataflow.py +2 -2
- airflow/providers/google/cloud/hooks/dataplex.py +1 -1
- airflow/providers/google/cloud/hooks/dataprep.py +4 -1
- airflow/providers/google/cloud/hooks/gcs.py +5 -5
- airflow/providers/google/cloud/hooks/looker.py +10 -1
- airflow/providers/google/cloud/hooks/mlengine.py +2 -1
- airflow/providers/google/cloud/hooks/secret_manager.py +102 -10
- airflow/providers/google/cloud/hooks/spanner.py +2 -2
- airflow/providers/google/cloud/hooks/translate.py +1 -1
- airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py +0 -36
- airflow/providers/google/cloud/hooks/vertex_ai/feature_store.py +307 -7
- airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +44 -80
- airflow/providers/google/cloud/hooks/vertex_ai/ray.py +11 -2
- airflow/providers/google/cloud/hooks/vision.py +2 -2
- airflow/providers/google/cloud/links/alloy_db.py +0 -46
- airflow/providers/google/cloud/links/base.py +75 -11
- airflow/providers/google/cloud/links/bigquery.py +0 -47
- airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
- airflow/providers/google/cloud/links/bigtable.py +0 -48
- airflow/providers/google/cloud/links/cloud_build.py +0 -73
- airflow/providers/google/cloud/links/cloud_functions.py +0 -33
- airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
- airflow/providers/google/cloud/links/cloud_run.py +27 -0
- airflow/providers/google/cloud/links/cloud_sql.py +0 -33
- airflow/providers/google/cloud/links/cloud_storage_transfer.py +16 -43
- airflow/providers/google/cloud/links/cloud_tasks.py +6 -25
- airflow/providers/google/cloud/links/compute.py +0 -58
- airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
- airflow/providers/google/cloud/links/datacatalog.py +23 -54
- airflow/providers/google/cloud/links/dataflow.py +0 -34
- airflow/providers/google/cloud/links/dataform.py +0 -64
- airflow/providers/google/cloud/links/datafusion.py +1 -96
- airflow/providers/google/cloud/links/dataplex.py +0 -154
- airflow/providers/google/cloud/links/dataprep.py +0 -24
- airflow/providers/google/cloud/links/dataproc.py +14 -90
- airflow/providers/google/cloud/links/datastore.py +0 -31
- airflow/providers/google/cloud/links/kubernetes_engine.py +5 -59
- airflow/providers/google/cloud/links/life_sciences.py +0 -19
- airflow/providers/google/cloud/links/managed_kafka.py +0 -70
- airflow/providers/google/cloud/links/mlengine.py +0 -70
- airflow/providers/google/cloud/links/pubsub.py +0 -32
- airflow/providers/google/cloud/links/spanner.py +0 -33
- airflow/providers/google/cloud/links/stackdriver.py +0 -30
- airflow/providers/google/cloud/links/translate.py +16 -186
- airflow/providers/google/cloud/links/vertex_ai.py +8 -224
- airflow/providers/google/cloud/links/workflows.py +0 -52
- airflow/providers/google/cloud/log/gcs_task_handler.py +4 -4
- airflow/providers/google/cloud/operators/alloy_db.py +69 -54
- airflow/providers/google/cloud/operators/automl.py +16 -14
- airflow/providers/google/cloud/operators/bigquery.py +49 -25
- airflow/providers/google/cloud/operators/bigquery_dts.py +2 -4
- airflow/providers/google/cloud/operators/bigtable.py +35 -6
- airflow/providers/google/cloud/operators/cloud_base.py +21 -1
- airflow/providers/google/cloud/operators/cloud_build.py +74 -31
- airflow/providers/google/cloud/operators/cloud_composer.py +34 -35
- airflow/providers/google/cloud/operators/cloud_memorystore.py +68 -42
- airflow/providers/google/cloud/operators/cloud_run.py +9 -1
- airflow/providers/google/cloud/operators/cloud_sql.py +11 -15
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +0 -2
- airflow/providers/google/cloud/operators/compute.py +7 -39
- airflow/providers/google/cloud/operators/datacatalog.py +156 -20
- airflow/providers/google/cloud/operators/dataflow.py +37 -14
- airflow/providers/google/cloud/operators/dataform.py +14 -4
- airflow/providers/google/cloud/operators/datafusion.py +4 -12
- airflow/providers/google/cloud/operators/dataplex.py +180 -96
- airflow/providers/google/cloud/operators/dataprep.py +0 -4
- airflow/providers/google/cloud/operators/dataproc.py +10 -16
- airflow/providers/google/cloud/operators/dataproc_metastore.py +95 -87
- airflow/providers/google/cloud/operators/datastore.py +21 -5
- airflow/providers/google/cloud/operators/dlp.py +3 -26
- airflow/providers/google/cloud/operators/functions.py +15 -6
- airflow/providers/google/cloud/operators/gcs.py +1 -7
- airflow/providers/google/cloud/operators/kubernetes_engine.py +53 -92
- airflow/providers/google/cloud/operators/life_sciences.py +0 -1
- airflow/providers/google/cloud/operators/managed_kafka.py +106 -51
- airflow/providers/google/cloud/operators/mlengine.py +0 -1
- airflow/providers/google/cloud/operators/pubsub.py +4 -5
- airflow/providers/google/cloud/operators/spanner.py +0 -4
- airflow/providers/google/cloud/operators/speech_to_text.py +0 -1
- airflow/providers/google/cloud/operators/stackdriver.py +0 -8
- airflow/providers/google/cloud/operators/tasks.py +0 -11
- airflow/providers/google/cloud/operators/text_to_speech.py +0 -1
- airflow/providers/google/cloud/operators/translate.py +37 -13
- airflow/providers/google/cloud/operators/translate_speech.py +0 -1
- airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +31 -18
- airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +28 -8
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +38 -25
- airflow/providers/google/cloud/operators/vertex_ai/dataset.py +69 -7
- airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +42 -8
- airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +531 -0
- airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +93 -117
- airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +10 -8
- airflow/providers/google/cloud/operators/vertex_ai/model_service.py +56 -10
- airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +29 -6
- airflow/providers/google/cloud/operators/vertex_ai/ray.py +9 -6
- airflow/providers/google/cloud/operators/workflows.py +1 -9
- airflow/providers/google/cloud/sensors/bigquery.py +1 -1
- airflow/providers/google/cloud/sensors/bigquery_dts.py +6 -1
- airflow/providers/google/cloud/sensors/bigtable.py +15 -3
- airflow/providers/google/cloud/sensors/cloud_composer.py +6 -1
- airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +6 -1
- airflow/providers/google/cloud/sensors/dataflow.py +3 -3
- airflow/providers/google/cloud/sensors/dataform.py +6 -1
- airflow/providers/google/cloud/sensors/datafusion.py +6 -1
- airflow/providers/google/cloud/sensors/dataplex.py +6 -1
- airflow/providers/google/cloud/sensors/dataprep.py +6 -1
- airflow/providers/google/cloud/sensors/dataproc.py +6 -1
- airflow/providers/google/cloud/sensors/dataproc_metastore.py +6 -1
- airflow/providers/google/cloud/sensors/gcs.py +9 -3
- airflow/providers/google/cloud/sensors/looker.py +6 -1
- airflow/providers/google/cloud/sensors/pubsub.py +8 -3
- airflow/providers/google/cloud/sensors/tasks.py +6 -1
- airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +6 -1
- airflow/providers/google/cloud/sensors/workflows.py +6 -1
- airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +10 -7
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -2
- airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +0 -1
- airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -1
- airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +1 -2
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/gcs_to_local.py +1 -1
- airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -1
- airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +5 -1
- airflow/providers/google/cloud/transfers/gdrive_to_local.py +1 -1
- airflow/providers/google/cloud/transfers/http_to_gcs.py +193 -0
- airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/s3_to_gcs.py +11 -5
- airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -1
- airflow/providers/google/cloud/transfers/sheets_to_gcs.py +2 -2
- airflow/providers/google/cloud/transfers/sql_to_gcs.py +1 -1
- airflow/providers/google/cloud/triggers/bigquery.py +32 -5
- airflow/providers/google/cloud/triggers/dataproc.py +62 -10
- airflow/providers/google/cloud/utils/field_validator.py +1 -2
- airflow/providers/google/common/auth_backend/google_openid.py +2 -1
- airflow/providers/google/common/deprecated.py +2 -1
- airflow/providers/google/common/hooks/base_google.py +7 -3
- airflow/providers/google/common/links/storage.py +0 -22
- airflow/providers/google/firebase/operators/firestore.py +1 -1
- airflow/providers/google/get_provider_info.py +14 -16
- airflow/providers/google/leveldb/hooks/leveldb.py +30 -1
- airflow/providers/google/leveldb/operators/leveldb.py +1 -1
- airflow/providers/google/marketing_platform/links/analytics_admin.py +3 -6
- airflow/providers/google/marketing_platform/operators/analytics_admin.py +0 -1
- airflow/providers/google/marketing_platform/operators/campaign_manager.py +4 -4
- airflow/providers/google/marketing_platform/operators/display_video.py +6 -6
- airflow/providers/google/marketing_platform/operators/search_ads.py +1 -1
- airflow/providers/google/marketing_platform/sensors/campaign_manager.py +6 -1
- airflow/providers/google/marketing_platform/sensors/display_video.py +6 -1
- airflow/providers/google/suite/operators/sheets.py +3 -3
- airflow/providers/google/suite/sensors/drive.py +6 -1
- airflow/providers/google/suite/transfers/gcs_to_gdrive.py +1 -1
- airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
- airflow/providers/google/suite/transfers/local_to_drive.py +1 -1
- airflow/providers/google/version_compat.py +28 -0
- {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/METADATA +35 -35
- {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/RECORD +171 -170
- airflow/providers/google/cloud/links/automl.py +0 -193
- {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-16.0.0a1.dist-info → apache_airflow_providers_google-16.1.0rc1.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__ = "
|
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.
|
36
|
-
from google.ads.googleads.
|
37
|
-
from google.ads.googleads.
|
38
|
-
from google.ads.googleads.
|
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,
|
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
|
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 =
|
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
|
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
|
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
|
303
|
-
|
349
|
+
if df_type == "polars":
|
350
|
+
return self._get_polars_df(sql, parameters, dialect, **kwargs)
|
304
351
|
|
305
|
-
|
352
|
+
if df_type == "pandas":
|
353
|
+
return self._get_pandas_df(sql, parameters, dialect, **kwargs)
|
306
354
|
|
307
|
-
|
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,
|
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
|
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
|
-
|
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,
|
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
|
-
|
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
|
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
|