apache-airflow-providers-google 16.0.0rc1__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.
Files changed (166) hide show
  1. airflow/providers/google/__init__.py +1 -1
  2. airflow/providers/google/ads/hooks/ads.py +9 -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 +2 -3
  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 +2 -2
  12. airflow/providers/google/cloud/hooks/looker.py +5 -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/feature_store.py +307 -7
  18. airflow/providers/google/cloud/hooks/vertex_ai/generative_model.py +43 -14
  19. airflow/providers/google/cloud/hooks/vertex_ai/ray.py +11 -2
  20. airflow/providers/google/cloud/hooks/vision.py +2 -2
  21. airflow/providers/google/cloud/links/alloy_db.py +0 -46
  22. airflow/providers/google/cloud/links/base.py +75 -11
  23. airflow/providers/google/cloud/links/bigquery.py +0 -47
  24. airflow/providers/google/cloud/links/bigquery_dts.py +0 -20
  25. airflow/providers/google/cloud/links/bigtable.py +0 -48
  26. airflow/providers/google/cloud/links/cloud_build.py +0 -73
  27. airflow/providers/google/cloud/links/cloud_functions.py +0 -33
  28. airflow/providers/google/cloud/links/cloud_memorystore.py +0 -58
  29. airflow/providers/google/cloud/links/cloud_run.py +1 -33
  30. airflow/providers/google/cloud/links/cloud_sql.py +0 -33
  31. airflow/providers/google/cloud/links/cloud_storage_transfer.py +16 -43
  32. airflow/providers/google/cloud/links/cloud_tasks.py +6 -25
  33. airflow/providers/google/cloud/links/compute.py +0 -58
  34. airflow/providers/google/cloud/links/data_loss_prevention.py +0 -169
  35. airflow/providers/google/cloud/links/datacatalog.py +23 -54
  36. airflow/providers/google/cloud/links/dataflow.py +0 -34
  37. airflow/providers/google/cloud/links/dataform.py +0 -64
  38. airflow/providers/google/cloud/links/datafusion.py +1 -96
  39. airflow/providers/google/cloud/links/dataplex.py +0 -154
  40. airflow/providers/google/cloud/links/dataprep.py +0 -24
  41. airflow/providers/google/cloud/links/dataproc.py +14 -90
  42. airflow/providers/google/cloud/links/datastore.py +0 -31
  43. airflow/providers/google/cloud/links/kubernetes_engine.py +5 -59
  44. airflow/providers/google/cloud/links/life_sciences.py +0 -19
  45. airflow/providers/google/cloud/links/managed_kafka.py +0 -70
  46. airflow/providers/google/cloud/links/mlengine.py +0 -70
  47. airflow/providers/google/cloud/links/pubsub.py +0 -32
  48. airflow/providers/google/cloud/links/spanner.py +0 -33
  49. airflow/providers/google/cloud/links/stackdriver.py +0 -30
  50. airflow/providers/google/cloud/links/translate.py +16 -186
  51. airflow/providers/google/cloud/links/vertex_ai.py +8 -224
  52. airflow/providers/google/cloud/links/workflows.py +0 -52
  53. airflow/providers/google/cloud/operators/alloy_db.py +69 -54
  54. airflow/providers/google/cloud/operators/automl.py +16 -14
  55. airflow/providers/google/cloud/operators/bigquery.py +0 -15
  56. airflow/providers/google/cloud/operators/bigquery_dts.py +2 -4
  57. airflow/providers/google/cloud/operators/bigtable.py +35 -6
  58. airflow/providers/google/cloud/operators/cloud_base.py +21 -1
  59. airflow/providers/google/cloud/operators/cloud_build.py +74 -31
  60. airflow/providers/google/cloud/operators/cloud_composer.py +34 -35
  61. airflow/providers/google/cloud/operators/cloud_memorystore.py +68 -42
  62. airflow/providers/google/cloud/operators/cloud_run.py +0 -1
  63. airflow/providers/google/cloud/operators/cloud_sql.py +11 -15
  64. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +0 -2
  65. airflow/providers/google/cloud/operators/compute.py +7 -39
  66. airflow/providers/google/cloud/operators/datacatalog.py +156 -20
  67. airflow/providers/google/cloud/operators/dataflow.py +37 -14
  68. airflow/providers/google/cloud/operators/dataform.py +14 -4
  69. airflow/providers/google/cloud/operators/datafusion.py +4 -12
  70. airflow/providers/google/cloud/operators/dataplex.py +180 -96
  71. airflow/providers/google/cloud/operators/dataprep.py +0 -4
  72. airflow/providers/google/cloud/operators/dataproc.py +10 -16
  73. airflow/providers/google/cloud/operators/dataproc_metastore.py +95 -87
  74. airflow/providers/google/cloud/operators/datastore.py +21 -5
  75. airflow/providers/google/cloud/operators/dlp.py +3 -26
  76. airflow/providers/google/cloud/operators/functions.py +15 -6
  77. airflow/providers/google/cloud/operators/gcs.py +0 -7
  78. airflow/providers/google/cloud/operators/kubernetes_engine.py +50 -7
  79. airflow/providers/google/cloud/operators/life_sciences.py +0 -1
  80. airflow/providers/google/cloud/operators/managed_kafka.py +106 -51
  81. airflow/providers/google/cloud/operators/mlengine.py +0 -1
  82. airflow/providers/google/cloud/operators/pubsub.py +2 -4
  83. airflow/providers/google/cloud/operators/spanner.py +0 -4
  84. airflow/providers/google/cloud/operators/speech_to_text.py +0 -1
  85. airflow/providers/google/cloud/operators/stackdriver.py +0 -8
  86. airflow/providers/google/cloud/operators/tasks.py +0 -11
  87. airflow/providers/google/cloud/operators/text_to_speech.py +0 -1
  88. airflow/providers/google/cloud/operators/translate.py +37 -13
  89. airflow/providers/google/cloud/operators/translate_speech.py +0 -1
  90. airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py +31 -18
  91. airflow/providers/google/cloud/operators/vertex_ai/batch_prediction_job.py +28 -8
  92. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +38 -25
  93. airflow/providers/google/cloud/operators/vertex_ai/dataset.py +69 -7
  94. airflow/providers/google/cloud/operators/vertex_ai/endpoint_service.py +42 -8
  95. airflow/providers/google/cloud/operators/vertex_ai/feature_store.py +531 -0
  96. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +93 -25
  97. airflow/providers/google/cloud/operators/vertex_ai/hyperparameter_tuning_job.py +10 -8
  98. airflow/providers/google/cloud/operators/vertex_ai/model_service.py +56 -10
  99. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +25 -6
  100. airflow/providers/google/cloud/operators/vertex_ai/ray.py +9 -6
  101. airflow/providers/google/cloud/operators/workflows.py +1 -9
  102. airflow/providers/google/cloud/sensors/bigquery.py +1 -1
  103. airflow/providers/google/cloud/sensors/bigquery_dts.py +6 -1
  104. airflow/providers/google/cloud/sensors/bigtable.py +15 -3
  105. airflow/providers/google/cloud/sensors/cloud_composer.py +6 -1
  106. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +6 -1
  107. airflow/providers/google/cloud/sensors/dataflow.py +3 -3
  108. airflow/providers/google/cloud/sensors/dataform.py +6 -1
  109. airflow/providers/google/cloud/sensors/datafusion.py +6 -1
  110. airflow/providers/google/cloud/sensors/dataplex.py +6 -1
  111. airflow/providers/google/cloud/sensors/dataprep.py +6 -1
  112. airflow/providers/google/cloud/sensors/dataproc.py +6 -1
  113. airflow/providers/google/cloud/sensors/dataproc_metastore.py +6 -1
  114. airflow/providers/google/cloud/sensors/gcs.py +9 -3
  115. airflow/providers/google/cloud/sensors/looker.py +6 -1
  116. airflow/providers/google/cloud/sensors/pubsub.py +8 -3
  117. airflow/providers/google/cloud/sensors/tasks.py +6 -1
  118. airflow/providers/google/cloud/sensors/vertex_ai/feature_store.py +6 -1
  119. airflow/providers/google/cloud/sensors/workflows.py +6 -1
  120. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +1 -1
  121. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +1 -1
  122. airflow/providers/google/cloud/transfers/bigquery_to_bigquery.py +1 -2
  123. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +1 -2
  124. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +0 -1
  125. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -1
  126. airflow/providers/google/cloud/transfers/calendar_to_gcs.py +1 -1
  127. airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +1 -1
  128. airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +1 -1
  129. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +1 -2
  130. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +1 -1
  131. airflow/providers/google/cloud/transfers/gcs_to_local.py +1 -1
  132. airflow/providers/google/cloud/transfers/gcs_to_sftp.py +1 -1
  133. airflow/providers/google/cloud/transfers/gdrive_to_gcs.py +5 -1
  134. airflow/providers/google/cloud/transfers/gdrive_to_local.py +1 -1
  135. airflow/providers/google/cloud/transfers/http_to_gcs.py +1 -1
  136. airflow/providers/google/cloud/transfers/local_to_gcs.py +1 -1
  137. airflow/providers/google/cloud/transfers/salesforce_to_gcs.py +1 -1
  138. airflow/providers/google/cloud/transfers/sftp_to_gcs.py +1 -1
  139. airflow/providers/google/cloud/transfers/sheets_to_gcs.py +2 -2
  140. airflow/providers/google/cloud/transfers/sql_to_gcs.py +1 -1
  141. airflow/providers/google/cloud/utils/field_validator.py +1 -2
  142. airflow/providers/google/common/auth_backend/google_openid.py +2 -1
  143. airflow/providers/google/common/deprecated.py +2 -1
  144. airflow/providers/google/common/hooks/base_google.py +7 -3
  145. airflow/providers/google/common/links/storage.py +0 -22
  146. airflow/providers/google/firebase/operators/firestore.py +1 -1
  147. airflow/providers/google/get_provider_info.py +0 -11
  148. airflow/providers/google/leveldb/hooks/leveldb.py +5 -1
  149. airflow/providers/google/leveldb/operators/leveldb.py +1 -1
  150. airflow/providers/google/marketing_platform/links/analytics_admin.py +3 -6
  151. airflow/providers/google/marketing_platform/operators/analytics_admin.py +0 -1
  152. airflow/providers/google/marketing_platform/operators/campaign_manager.py +4 -4
  153. airflow/providers/google/marketing_platform/operators/display_video.py +6 -6
  154. airflow/providers/google/marketing_platform/operators/search_ads.py +1 -1
  155. airflow/providers/google/marketing_platform/sensors/campaign_manager.py +6 -1
  156. airflow/providers/google/marketing_platform/sensors/display_video.py +6 -1
  157. airflow/providers/google/suite/operators/sheets.py +3 -3
  158. airflow/providers/google/suite/sensors/drive.py +6 -1
  159. airflow/providers/google/suite/transfers/gcs_to_gdrive.py +1 -1
  160. airflow/providers/google/suite/transfers/gcs_to_sheets.py +1 -1
  161. airflow/providers/google/suite/transfers/local_to_drive.py +1 -1
  162. airflow/providers/google/version_compat.py +28 -0
  163. {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/METADATA +19 -20
  164. {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/RECORD +166 -166
  165. {apache_airflow_providers_google-16.0.0rc1.dist-info → apache_airflow_providers_google-16.1.0rc1.dist-info}/WHEEL +0 -0
  166. {apache_airflow_providers_google-16.0.0rc1.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__ = "16.0.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):
@@ -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, overload
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
@@ -57,7 +57,6 @@ from googleapiclient.discovery import build
57
57
  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
- from typing_extensions import Literal
61
60
 
62
61
  from airflow.exceptions import (
63
62
  AirflowException,
@@ -89,7 +88,7 @@ if TYPE_CHECKING:
89
88
 
90
89
  log = logging.getLogger(__name__)
91
90
 
92
- BigQueryJob = Union[CopyJob, QueryJob, LoadJob, ExtractJob]
91
+ BigQueryJob = CopyJob | QueryJob | LoadJob | ExtractJob
93
92
 
94
93
 
95
94
  class BigQueryHook(GoogleBaseHook, DbApiHook):
@@ -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
@@ -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:
@@ -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
@@ -47,6 +47,10 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
47
47
  See https://cloud.google.com/secret-manager
48
48
  """
49
49
 
50
+ def __init__(self, location: str | None = None, **kwargs) -> None:
51
+ super().__init__(**kwargs)
52
+ self.location = location
53
+
50
54
  @cached_property
51
55
  def client(self):
52
56
  """
@@ -54,7 +58,16 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
54
58
 
55
59
  :return: Secret Manager client.
56
60
  """
57
- return SecretManagerServiceClient(credentials=self.get_credentials(), client_info=CLIENT_INFO)
61
+ if self.location is not None:
62
+ return SecretManagerServiceClient(
63
+ credentials=self.get_credentials(),
64
+ client_info=CLIENT_INFO,
65
+ client_options={"api_endpoint": f"secretmanager.{self.location}.rep.googleapis.com"},
66
+ )
67
+ return SecretManagerServiceClient(
68
+ credentials=self.get_credentials(),
69
+ client_info=CLIENT_INFO,
70
+ )
58
71
 
59
72
  def get_conn(self) -> SecretManagerServiceClient:
60
73
  """
@@ -64,6 +77,60 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
64
77
  """
65
78
  return self.client
66
79
 
80
+ def _get_parent(self, project_id: str, location: str | None = None) -> str:
81
+ """
82
+ Return parent path.
83
+
84
+ :param project_id: Required. ID of the GCP project that owns the job.
85
+ :param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
86
+ For more details : https://cloud.google.com/secret-manager/docs/locations
87
+
88
+ :return: Parent path.
89
+ """
90
+ _location = location or self.location
91
+ if _location is not None:
92
+ return self.client.common_location_path(project_id, _location)
93
+ return self.client.common_project_path(project_id)
94
+
95
+ def _get_secret_path(self, project_id: str, secret_id: str, location: str | None = None) -> str:
96
+ """
97
+ Return secret path.
98
+
99
+ :param project_id: Required. ID of the GCP project that owns the job.
100
+ :param secret_id: Required. Secret ID for which path is required.
101
+ :param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
102
+ For more details : https://cloud.google.com/secret-manager/docs/locations
103
+
104
+ :return: Parent path.
105
+ """
106
+ _location = location or self.location
107
+ if _location is not None:
108
+ # Google's client library does not provide a method to construct regional secret paths, so constructing manually.
109
+ return f"projects/{project_id}/locations/{_location}/secrets/{secret_id}"
110
+ return self.client.secret_path(project_id, secret_id)
111
+
112
+ def _get_secret_version_path(
113
+ self, project_id: str, secret_id: str, secret_version: str, location: str | None = None
114
+ ) -> str:
115
+ """
116
+ Return secret version path.
117
+
118
+ :param project_id: Required. ID of the GCP project that owns the job.
119
+ :param secret_id: Required. Secret ID for which path is required.
120
+ :param secret_version: Required. Secret version for which path is required.
121
+ :param location: Optional. Target location. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
122
+ For more details : https://cloud.google.com/secret-manager/docs/locations
123
+
124
+ :return: Parent path.
125
+ """
126
+ _location = location or self.location
127
+ if _location is not None:
128
+ # Google's client library does not provide a method to construct regional secret version paths, so constructing manually.
129
+ return (
130
+ f"projects/{project_id}/locations/{_location}/secrets/{secret_id}/versions/{secret_version}"
131
+ )
132
+ return self.client.secret_version_path(project_id, secret_id, secret_version)
133
+
67
134
  @GoogleBaseHook.fallback_to_default_project_id
68
135
  def create_secret(
69
136
  self,
@@ -73,6 +140,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
73
140
  retry: Retry | _MethodDefault = DEFAULT,
74
141
  timeout: float | None = None,
75
142
  metadata: Sequence[tuple[str, str]] = (),
143
+ location: str | None = None,
76
144
  ) -> Secret:
77
145
  """
78
146
  Create a secret.
@@ -88,12 +156,20 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
88
156
  :param retry: Optional. Designation of what errors, if any, should be retried.
89
157
  :param timeout: Optional. The timeout for this request.
90
158
  :param metadata: Optional. Strings which should be sent along with the request as metadata.
159
+ :param location: Optional. Location where secret should be created. Used for creating regional secret. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
160
+ For more details : https://cloud.google.com/secret-manager/docs/locations
91
161
  :return: Secret object.
92
162
  """
93
- _secret = secret or {"replication": {"automatic": {}}}
163
+ if not secret:
164
+ _secret: dict | Secret = {}
165
+ if (location or self.location) is None:
166
+ _secret["replication"] = {"automatic": {}}
167
+ else:
168
+ _secret = secret
169
+
94
170
  response = self.client.create_secret(
95
171
  request={
96
- "parent": f"projects/{project_id}",
172
+ "parent": self._get_parent(project_id, location),
97
173
  "secret_id": secret_id,
98
174
  "secret": _secret,
99
175
  },
@@ -113,6 +189,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
113
189
  retry: Retry | _MethodDefault = DEFAULT,
114
190
  timeout: float | None = None,
115
191
  metadata: Sequence[tuple[str, str]] = (),
192
+ location: str | None = None,
116
193
  ) -> SecretVersion:
117
194
  """
118
195
  Add a version to the secret.
@@ -128,11 +205,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
128
205
  :param retry: Optional. Designation of what errors, if any, should be retried.
129
206
  :param timeout: Optional. The timeout for this request.
130
207
  :param metadata: Optional. Strings which should be sent along with the request as metadata.
208
+ :param location: Optional. Location where secret is located. Used for adding version to regional secret. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
209
+ For more details : https://cloud.google.com/secret-manager/docs/locations
131
210
  :return: Secret version object.
132
211
  """
133
212
  response = self.client.add_secret_version(
134
213
  request={
135
- "parent": f"projects/{project_id}/secrets/{secret_id}",
214
+ "parent": self._get_secret_path(project_id, secret_id, location),
136
215
  "payload": secret_payload,
137
216
  },
138
217
  retry=retry,
@@ -152,6 +231,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
152
231
  retry: Retry | _MethodDefault = DEFAULT,
153
232
  timeout: float | None = None,
154
233
  metadata: Sequence[tuple[str, str]] = (),
234
+ location: str | None = None,
155
235
  ) -> ListSecretsPager:
156
236
  """
157
237
  List secrets.
@@ -168,11 +248,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
168
248
  :param retry: Optional. Designation of what errors, if any, should be retried.
169
249
  :param timeout: Optional. The timeout for this request.
170
250
  :param metadata: Optional. Strings which should be sent along with the request as metadata.
251
+ :param location: Optional. The regional secrets stored in the provided location will be listed. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
252
+ For more details : https://cloud.google.com/secret-manager/docs/locations
171
253
  :return: Secret List object.
172
254
  """
173
255
  response = self.client.list_secrets(
174
256
  request={
175
- "parent": f"projects/{project_id}",
257
+ "parent": self._get_parent(project_id, location),
176
258
  "page_size": page_size,
177
259
  "page_token": page_token,
178
260
  "filter": secret_filter,
@@ -185,18 +267,22 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
185
267
  return response
186
268
 
187
269
  @GoogleBaseHook.fallback_to_default_project_id
188
- def secret_exists(self, project_id: str, secret_id: str) -> bool:
270
+ def secret_exists(self, project_id: str, secret_id: str, location: str | None = None) -> bool:
189
271
  """
190
272
  Check whether secret exists.
191
273
 
192
274
  :param project_id: Required. ID of the GCP project that owns the job.
193
275
  If set to ``None`` or missing, the default project_id from the GCP connection is used.
194
276
  :param secret_id: Required. ID of the secret to find.
277
+ :param location: Optional. Location where secret is expected to be stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
278
+ For more details : https://cloud.google.com/secret-manager/docs/locations
195
279
  :return: True if the secret exists, False otherwise.
196
280
  """
197
281
  secret_filter = f"name:{secret_id}"
198
- secret_name = self.client.secret_path(project_id, secret_id)
199
- for secret in self.list_secrets(project_id=project_id, page_size=100, secret_filter=secret_filter):
282
+ secret_name = self._get_secret_path(project_id, secret_id, location)
283
+ for secret in self.list_secrets(
284
+ project_id=project_id, page_size=100, secret_filter=secret_filter, location=location
285
+ ):
200
286
  if secret.name.split("/")[-1] == secret_id:
201
287
  self.log.info("Secret %s exists.", secret_name)
202
288
  return True
@@ -212,6 +298,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
212
298
  retry: Retry | _MethodDefault = DEFAULT,
213
299
  timeout: float | None = None,
214
300
  metadata: Sequence[tuple[str, str]] = (),
301
+ location: str | None = None,
215
302
  ) -> AccessSecretVersionResponse:
216
303
  """
217
304
  Access a secret version.
@@ -227,11 +314,13 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
227
314
  :param retry: Optional. Designation of what errors, if any, should be retried.
228
315
  :param timeout: Optional. The timeout for this request.
229
316
  :param metadata: Optional. Strings which should be sent along with the request as metadata.
317
+ :param location: Optional. Location where secret is stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used
318
+ For more details : https://cloud.google.com/secret-manager/docs/locations
230
319
  :return: Access secret version response object.
231
320
  """
232
321
  response = self.client.access_secret_version(
233
322
  request={
234
- "name": self.client.secret_version_path(project_id, secret_id, secret_version),
323
+ "name": self._get_secret_version_path(project_id, secret_id, secret_version, location),
235
324
  },
236
325
  retry=retry,
237
326
  timeout=timeout,
@@ -248,6 +337,7 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
248
337
  retry: Retry | _MethodDefault = DEFAULT,
249
338
  timeout: float | None = None,
250
339
  metadata: Sequence[tuple[str, str]] = (),
340
+ location: str | None = None,
251
341
  ) -> None:
252
342
  """
253
343
  Delete a secret.
@@ -262,9 +352,11 @@ class GoogleCloudSecretManagerHook(GoogleBaseHook):
262
352
  :param retry: Optional. Designation of what errors, if any, should be retried.
263
353
  :param timeout: Optional. The timeout for this request.
264
354
  :param metadata: Optional. Strings which should be sent along with the request as metadata.
355
+ :param location: Optional. Location where secret is stored regionally. If set to ``None`` or missing, the location provided for GoogleCloudSecretHook instantiation is used.
356
+ For more details : https://cloud.google.com/secret-manager/docs/locations
265
357
  :return: Access secret version response object.
266
358
  """
267
- name = self.client.secret_path(project_id, secret_id)
359
+ name = self._get_secret_path(project_id, secret_id, location)
268
360
  self.client.delete_secret(
269
361
  request={"name": name},
270
362
  retry=retry,
@@ -19,8 +19,8 @@
19
19
 
20
20
  from __future__ import annotations
21
21
 
22
- from collections.abc import Sequence
23
- from typing import TYPE_CHECKING, Callable, NamedTuple
22
+ from collections.abc import Callable, Sequence
23
+ from typing import TYPE_CHECKING, NamedTuple
24
24
 
25
25
  from google.api_core.exceptions import AlreadyExists, GoogleAPICallError
26
26
  from google.cloud.spanner_v1.client import Client
@@ -429,7 +429,7 @@ class TranslateHook(GoogleBaseHook, OperationHelper):
429
429
  project_id: str,
430
430
  location: str,
431
431
  retry: Retry | _MethodDefault = DEFAULT,
432
- timeout: float | _MethodDefault = DEFAULT,
432
+ timeout: float | None | _MethodDefault = DEFAULT,
433
433
  metadata: Sequence[tuple[str, str]] = (),
434
434
  ) -> automl_translation.Dataset:
435
435
  """