apache-airflow-providers-google 10.23.0rc1__py3-none-any.whl → 10.24.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.
- airflow/providers/google/__init__.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +0 -4
- airflow/providers/google/cloud/hooks/dataflow.py +14 -5
- airflow/providers/google/cloud/hooks/dataproc.py +11 -0
- airflow/providers/google/cloud/hooks/gcs.py +24 -19
- airflow/providers/google/cloud/log/gcs_task_handler.py +1 -6
- airflow/providers/google/cloud/operators/automl.py +7 -1
- airflow/providers/google/cloud/operators/dataflow.py +2 -0
- airflow/providers/google/cloud/operators/dataproc.py +123 -15
- airflow/providers/google/cloud/operators/speech_to_text.py +8 -9
- airflow/providers/google/cloud/operators/translate_speech.py +8 -7
- airflow/providers/google/cloud/sensors/pubsub.py +21 -3
- airflow/providers/google/cloud/triggers/pubsub.py +16 -16
- airflow/providers/google/get_provider_info.py +6 -1
- {apache_airflow_providers_google-10.23.0rc1.dist-info → apache_airflow_providers_google-10.24.0.dist-info}/METADATA +15 -16
- {apache_airflow_providers_google-10.23.0rc1.dist-info → apache_airflow_providers_google-10.24.0.dist-info}/RECORD +18 -18
- {apache_airflow_providers_google-10.23.0rc1.dist-info → apache_airflow_providers_google-10.24.0.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-10.23.0rc1.dist-info → apache_airflow_providers_google-10.24.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__ = "10.
|
32
|
+
__version__ = "10.24.0"
|
33
33
|
|
34
34
|
if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
|
35
35
|
"2.8.0"
|
@@ -2418,10 +2418,6 @@ class BigQueryHook(GoogleBaseHook, DbApiHook):
|
|
2418
2418
|
f"{var_print(var_name)}Expect format of (<project.|<project:)<dataset>.<table>, "
|
2419
2419
|
f"got {table_input}"
|
2420
2420
|
)
|
2421
|
-
|
2422
|
-
# Exclude partition from the table name
|
2423
|
-
table_id = table_id.split("$")[0]
|
2424
|
-
|
2425
2421
|
if project_id is None:
|
2426
2422
|
if var_name is not None:
|
2427
2423
|
self.log.info(
|
@@ -1124,18 +1124,17 @@ class DataflowHook(GoogleBaseHook):
|
|
1124
1124
|
|
1125
1125
|
return safe_job_name
|
1126
1126
|
|
1127
|
-
@_fallback_to_location_from_variables
|
1128
1127
|
@_fallback_to_project_id_from_variables
|
1129
1128
|
@GoogleBaseHook.fallback_to_default_project_id
|
1130
1129
|
def is_job_dataflow_running(
|
1131
1130
|
self,
|
1132
1131
|
name: str,
|
1133
1132
|
project_id: str,
|
1134
|
-
location: str =
|
1133
|
+
location: str | None = None,
|
1135
1134
|
variables: dict | None = None,
|
1136
1135
|
) -> bool:
|
1137
1136
|
"""
|
1138
|
-
Check if
|
1137
|
+
Check if job is still running in dataflow.
|
1139
1138
|
|
1140
1139
|
:param name: The name of the job.
|
1141
1140
|
:param project_id: Optional, the Google Cloud project ID in which to start a job.
|
@@ -1145,11 +1144,21 @@ class DataflowHook(GoogleBaseHook):
|
|
1145
1144
|
"""
|
1146
1145
|
if variables:
|
1147
1146
|
warnings.warn(
|
1148
|
-
"The variables parameter has been deprecated. You should pass
|
1149
|
-
"the
|
1147
|
+
"The variables parameter has been deprecated. You should pass project_id using "
|
1148
|
+
"the project_id parameter.",
|
1150
1149
|
AirflowProviderDeprecationWarning,
|
1151
1150
|
stacklevel=4,
|
1152
1151
|
)
|
1152
|
+
|
1153
|
+
if location is None:
|
1154
|
+
location = DEFAULT_DATAFLOW_LOCATION
|
1155
|
+
warnings.warn(
|
1156
|
+
"The location argument will be become mandatory in future versions, "
|
1157
|
+
f"currently, it defaults to {DEFAULT_DATAFLOW_LOCATION}, please set the location explicitly.",
|
1158
|
+
AirflowProviderDeprecationWarning,
|
1159
|
+
stacklevel=4,
|
1160
|
+
)
|
1161
|
+
|
1153
1162
|
jobs_controller = _DataflowJobsController(
|
1154
1163
|
dataflow=self.get_conn(),
|
1155
1164
|
project_number=project_id,
|
@@ -59,6 +59,10 @@ if TYPE_CHECKING:
|
|
59
59
|
from google.type.interval_pb2 import Interval
|
60
60
|
|
61
61
|
|
62
|
+
class DataprocResourceIsNotReadyError(AirflowException):
|
63
|
+
"""Raise when resource is not ready for create Dataproc cluster."""
|
64
|
+
|
65
|
+
|
62
66
|
class DataProcJobBuilder:
|
63
67
|
"""A helper class for building Dataproc job."""
|
64
68
|
|
@@ -281,6 +285,8 @@ class DataprocHook(GoogleBaseHook):
|
|
281
285
|
return operation.result(timeout=timeout, retry=result_retry)
|
282
286
|
except Exception:
|
283
287
|
error = operation.exception(timeout=timeout)
|
288
|
+
if self.check_error_for_resource_is_not_ready_msg(error.message):
|
289
|
+
raise DataprocResourceIsNotReadyError(error.message)
|
284
290
|
raise AirflowException(error)
|
285
291
|
|
286
292
|
@GoogleBaseHook.fallback_to_default_project_id
|
@@ -1192,6 +1198,11 @@ class DataprocHook(GoogleBaseHook):
|
|
1192
1198
|
|
1193
1199
|
return result
|
1194
1200
|
|
1201
|
+
def check_error_for_resource_is_not_ready_msg(self, error_msg: str) -> bool:
|
1202
|
+
"""Check that reason of error is resource is not ready."""
|
1203
|
+
key_words = ["The resource", "is not ready"]
|
1204
|
+
return all([word in error_msg for word in key_words])
|
1205
|
+
|
1195
1206
|
|
1196
1207
|
class DataprocAsyncHook(GoogleBaseHook):
|
1197
1208
|
"""
|
@@ -59,6 +59,7 @@ if TYPE_CHECKING:
|
|
59
59
|
|
60
60
|
from aiohttp import ClientSession
|
61
61
|
from google.api_core.retry import Retry
|
62
|
+
from google.cloud.storage.blob import Blob
|
62
63
|
|
63
64
|
|
64
65
|
RT = TypeVar("RT")
|
@@ -597,11 +598,7 @@ class GCSHook(GoogleBaseHook):
|
|
597
598
|
:param object_name: The name of the blob to get updated time from the Google cloud
|
598
599
|
storage bucket.
|
599
600
|
"""
|
600
|
-
|
601
|
-
bucket = client.bucket(bucket_name)
|
602
|
-
blob = bucket.get_blob(blob_name=object_name)
|
603
|
-
if blob is None:
|
604
|
-
raise ValueError(f"Object ({object_name}) not found in Bucket ({bucket_name})")
|
601
|
+
blob = self._get_blob(bucket_name, object_name)
|
605
602
|
return blob.updated
|
606
603
|
|
607
604
|
def is_updated_after(self, bucket_name: str, object_name: str, ts: datetime) -> bool:
|
@@ -957,19 +954,35 @@ class GCSHook(GoogleBaseHook):
|
|
957
954
|
break
|
958
955
|
return ids
|
959
956
|
|
960
|
-
def
|
957
|
+
def _get_blob(self, bucket_name: str, object_name: str) -> Blob:
|
961
958
|
"""
|
962
|
-
Get
|
959
|
+
Get a blob object in Google Cloud Storage.
|
963
960
|
|
964
961
|
:param bucket_name: The Google Cloud Storage bucket where the blob_name is.
|
965
962
|
:param object_name: The name of the object to check in the Google
|
966
963
|
cloud storage bucket_name.
|
967
964
|
|
968
965
|
"""
|
969
|
-
self.log.info("Checking the file size of object: %s in bucket_name: %s", object_name, bucket_name)
|
970
966
|
client = self.get_conn()
|
971
967
|
bucket = client.bucket(bucket_name)
|
972
968
|
blob = bucket.get_blob(blob_name=object_name)
|
969
|
+
|
970
|
+
if blob is None:
|
971
|
+
raise ValueError(f"Object ({object_name}) not found in Bucket ({bucket_name})")
|
972
|
+
|
973
|
+
return blob
|
974
|
+
|
975
|
+
def get_size(self, bucket_name: str, object_name: str) -> int:
|
976
|
+
"""
|
977
|
+
Get the size of a file in Google Cloud Storage.
|
978
|
+
|
979
|
+
:param bucket_name: The Google Cloud Storage bucket where the blob_name is.
|
980
|
+
:param object_name: The name of the object to check in the Google
|
981
|
+
cloud storage bucket_name.
|
982
|
+
|
983
|
+
"""
|
984
|
+
self.log.info("Checking the file size of object: %s in bucket_name: %s", object_name, bucket_name)
|
985
|
+
blob = self._get_blob(bucket_name, object_name)
|
973
986
|
blob_size = blob.size
|
974
987
|
self.log.info("The file size of %s is %s bytes.", object_name, blob_size)
|
975
988
|
return blob_size
|
@@ -987,9 +1000,7 @@ class GCSHook(GoogleBaseHook):
|
|
987
1000
|
object_name,
|
988
1001
|
bucket_name,
|
989
1002
|
)
|
990
|
-
|
991
|
-
bucket = client.bucket(bucket_name)
|
992
|
-
blob = bucket.get_blob(blob_name=object_name)
|
1003
|
+
blob = self._get_blob(bucket_name, object_name)
|
993
1004
|
blob_crc32c = blob.crc32c
|
994
1005
|
self.log.info("The crc32c checksum of %s is %s", object_name, blob_crc32c)
|
995
1006
|
return blob_crc32c
|
@@ -1003,9 +1014,7 @@ class GCSHook(GoogleBaseHook):
|
|
1003
1014
|
storage bucket_name.
|
1004
1015
|
"""
|
1005
1016
|
self.log.info("Retrieving the MD5 hash of object: %s in bucket: %s", object_name, bucket_name)
|
1006
|
-
|
1007
|
-
bucket = client.bucket(bucket_name)
|
1008
|
-
blob = bucket.get_blob(blob_name=object_name)
|
1017
|
+
blob = self._get_blob(bucket_name, object_name)
|
1009
1018
|
blob_md5hash = blob.md5_hash
|
1010
1019
|
self.log.info("The md5Hash of %s is %s", object_name, blob_md5hash)
|
1011
1020
|
return blob_md5hash
|
@@ -1019,11 +1028,7 @@ class GCSHook(GoogleBaseHook):
|
|
1019
1028
|
:return: The metadata associated with the object
|
1020
1029
|
"""
|
1021
1030
|
self.log.info("Retrieving the metadata dict of object (%s) in bucket (%s)", object_name, bucket_name)
|
1022
|
-
|
1023
|
-
bucket = client.bucket(bucket_name)
|
1024
|
-
blob = bucket.get_blob(blob_name=object_name)
|
1025
|
-
if blob is None:
|
1026
|
-
raise ValueError("Object (%s) not found in bucket (%s)", object_name, bucket_name)
|
1031
|
+
blob = self._get_blob(bucket_name, object_name)
|
1027
1032
|
blob_metadata = blob.metadata
|
1028
1033
|
if blob_metadata:
|
1029
1034
|
self.log.info("Retrieved metadata of object (%s) with %s fields", object_name, len(blob_metadata))
|
@@ -129,12 +129,7 @@ class GCSTaskHandler(FileTaskHandler, LoggingMixin):
|
|
129
129
|
)
|
130
130
|
|
131
131
|
def set_context(self, ti: TaskInstance, *, identifier: str | None = None) -> None:
|
132
|
-
|
133
|
-
# after Airflow 2.8 can always pass `identifier`
|
134
|
-
if getattr(super(), "supports_task_context_logging", False):
|
135
|
-
super().set_context(ti, identifier=identifier)
|
136
|
-
else:
|
137
|
-
super().set_context(ti)
|
132
|
+
super().set_context(ti, identifier=identifier)
|
138
133
|
# Log relative path is used to construct local and remote
|
139
134
|
# log path to upload log files into GCS and read from the
|
140
135
|
# remote location.
|
@@ -34,7 +34,7 @@ from google.cloud.automl_v1beta1 import (
|
|
34
34
|
TableSpec,
|
35
35
|
)
|
36
36
|
|
37
|
-
from airflow.exceptions import AirflowException
|
37
|
+
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
38
38
|
from airflow.providers.google.cloud.hooks.automl import CloudAutoMLHook
|
39
39
|
from airflow.providers.google.cloud.hooks.vertex_ai.prediction_service import PredictionServiceHook
|
40
40
|
from airflow.providers.google.cloud.links.translate import (
|
@@ -45,6 +45,7 @@ from airflow.providers.google.cloud.links.translate import (
|
|
45
45
|
TranslationLegacyModelTrainLink,
|
46
46
|
)
|
47
47
|
from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
|
48
|
+
from airflow.providers.google.common.deprecated import deprecated
|
48
49
|
from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
|
49
50
|
|
50
51
|
if TYPE_CHECKING:
|
@@ -338,6 +339,11 @@ class AutoMLPredictOperator(GoogleCloudBaseOperator):
|
|
338
339
|
return PredictResponse.to_dict(result)
|
339
340
|
|
340
341
|
|
342
|
+
@deprecated(
|
343
|
+
planned_removal_date="January 01, 2025",
|
344
|
+
use_instead="airflow.providers.google.cloud.operators.vertex_ai.batch_prediction_job",
|
345
|
+
category=AirflowProviderDeprecationWarning,
|
346
|
+
)
|
341
347
|
class AutoMLBatchPredictOperator(GoogleCloudBaseOperator):
|
342
348
|
"""
|
343
349
|
Perform a batch prediction on Google Cloud AutoML.
|
@@ -432,11 +432,13 @@ class DataflowCreateJavaJobOperator(GoogleCloudBaseOperator):
|
|
432
432
|
is_running = self.dataflow_hook.is_job_dataflow_running(
|
433
433
|
name=self.job_name,
|
434
434
|
variables=pipeline_options,
|
435
|
+
location=self.location,
|
435
436
|
)
|
436
437
|
while is_running and self.check_if_running == CheckJobRunning.WaitForRun:
|
437
438
|
is_running = self.dataflow_hook.is_job_dataflow_running(
|
438
439
|
name=self.job_name,
|
439
440
|
variables=pipeline_options,
|
441
|
+
location=self.location,
|
440
442
|
)
|
441
443
|
if not is_running:
|
442
444
|
pipeline_options["jobName"] = job_name
|
@@ -40,7 +40,11 @@ from google.cloud.dataproc_v1 import Batch, Cluster, ClusterStatus, JobStatus
|
|
40
40
|
|
41
41
|
from airflow.configuration import conf
|
42
42
|
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
43
|
-
from airflow.providers.google.cloud.hooks.dataproc import
|
43
|
+
from airflow.providers.google.cloud.hooks.dataproc import (
|
44
|
+
DataprocHook,
|
45
|
+
DataProcJobBuilder,
|
46
|
+
DataprocResourceIsNotReadyError,
|
47
|
+
)
|
44
48
|
from airflow.providers.google.cloud.hooks.gcs import GCSHook
|
45
49
|
from airflow.providers.google.cloud.links.dataproc import (
|
46
50
|
DATAPROC_BATCH_LINK,
|
@@ -593,6 +597,8 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
593
597
|
:param delete_on_error: If true the cluster will be deleted if created with ERROR state. Default
|
594
598
|
value is true.
|
595
599
|
:param use_if_exists: If true use existing cluster
|
600
|
+
:param num_retries_if_resource_is_not_ready: Optional. The number of retry for cluster creation request
|
601
|
+
when resource is not ready error appears.
|
596
602
|
:param request_id: Optional. A unique id used to identify the request. If the server receives two
|
597
603
|
``DeleteClusterRequest`` requests with the same id, then the second request will be ignored and the
|
598
604
|
first ``google.longrunning.Operation`` created and stored in the backend is returned.
|
@@ -639,6 +645,7 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
639
645
|
request_id: str | None = None,
|
640
646
|
delete_on_error: bool = True,
|
641
647
|
use_if_exists: bool = True,
|
648
|
+
num_retries_if_resource_is_not_ready: int = 0,
|
642
649
|
retry: AsyncRetry | _MethodDefault | Retry = DEFAULT,
|
643
650
|
timeout: float = 1 * 60 * 60,
|
644
651
|
metadata: Sequence[tuple[str, str]] = (),
|
@@ -695,6 +702,7 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
695
702
|
self.virtual_cluster_config = virtual_cluster_config
|
696
703
|
self.deferrable = deferrable
|
697
704
|
self.polling_interval_seconds = polling_interval_seconds
|
705
|
+
self.num_retries_if_resource_is_not_ready = num_retries_if_resource_is_not_ready
|
698
706
|
|
699
707
|
def _create_cluster(self, hook: DataprocHook):
|
700
708
|
return hook.create_cluster(
|
@@ -729,20 +737,26 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
729
737
|
return
|
730
738
|
self.log.info("Cluster is in ERROR state")
|
731
739
|
self.log.info("Gathering diagnostic information.")
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
self.
|
744
|
-
|
745
|
-
|
740
|
+
try:
|
741
|
+
operation = hook.diagnose_cluster(
|
742
|
+
region=self.region, cluster_name=self.cluster_name, project_id=self.project_id
|
743
|
+
)
|
744
|
+
operation.result()
|
745
|
+
gcs_uri = str(operation.operation.response.value)
|
746
|
+
self.log.info(
|
747
|
+
"Diagnostic information for cluster %s available at: %s", self.cluster_name, gcs_uri
|
748
|
+
)
|
749
|
+
except Exception as diagnose_error:
|
750
|
+
self.log.info("Some error occurred when trying to diagnose cluster.")
|
751
|
+
self.log.exception(diagnose_error)
|
752
|
+
finally:
|
753
|
+
if self.delete_on_error:
|
754
|
+
self._delete_cluster(hook)
|
755
|
+
# The delete op is asynchronous and can cause further failure if the cluster finishes
|
756
|
+
# deleting between catching AlreadyExists and checking state
|
757
|
+
self._wait_for_cluster_in_deleting_state(hook)
|
758
|
+
raise AirflowException("Cluster was created in an ERROR state then deleted.")
|
759
|
+
raise AirflowException("Cluster was created but is in ERROR state")
|
746
760
|
|
747
761
|
def _wait_for_cluster_in_deleting_state(self, hook: DataprocHook) -> None:
|
748
762
|
time_left = self.timeout
|
@@ -780,6 +794,16 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
780
794
|
)
|
781
795
|
return hook.wait_for_operation(timeout=self.timeout, result_retry=self.retry, operation=op)
|
782
796
|
|
797
|
+
def _retry_cluster_creation(self, hook: DataprocHook):
|
798
|
+
self.log.info("Retrying creation process for Cluster %s", self.cluster_name)
|
799
|
+
self._delete_cluster(hook)
|
800
|
+
self._wait_for_cluster_in_deleting_state(hook)
|
801
|
+
self.log.info("Starting a new creation for Cluster %s", self.cluster_name)
|
802
|
+
operation = self._create_cluster(hook)
|
803
|
+
cluster = hook.wait_for_operation(timeout=self.timeout, result_retry=self.retry, operation=operation)
|
804
|
+
self.log.info("Cluster created.")
|
805
|
+
return Cluster.to_dict(cluster)
|
806
|
+
|
783
807
|
def execute(self, context: Context) -> dict:
|
784
808
|
self.log.info("Creating cluster: %s", self.cluster_name)
|
785
809
|
hook = DataprocHook(gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain)
|
@@ -829,6 +853,25 @@ class DataprocCreateClusterOperator(GoogleCloudBaseOperator):
|
|
829
853
|
raise
|
830
854
|
self.log.info("Cluster already exists.")
|
831
855
|
cluster = self._get_cluster(hook)
|
856
|
+
except DataprocResourceIsNotReadyError as resource_not_ready_error:
|
857
|
+
if self.num_retries_if_resource_is_not_ready:
|
858
|
+
attempt = self.num_retries_if_resource_is_not_ready
|
859
|
+
while attempt > 0:
|
860
|
+
attempt -= 1
|
861
|
+
try:
|
862
|
+
cluster = self._retry_cluster_creation(hook)
|
863
|
+
except DataprocResourceIsNotReadyError:
|
864
|
+
continue
|
865
|
+
else:
|
866
|
+
return cluster
|
867
|
+
self.log.info(
|
868
|
+
"Retrying Cluster %s creation because of resource not ready was unsuccessful.",
|
869
|
+
self.cluster_name,
|
870
|
+
)
|
871
|
+
if self.delete_on_error:
|
872
|
+
self._delete_cluster(hook)
|
873
|
+
self._wait_for_cluster_in_deleting_state(hook)
|
874
|
+
raise resource_not_ready_error
|
832
875
|
except AirflowException as ae:
|
833
876
|
# There still could be a cluster created here in an ERROR state which
|
834
877
|
# should be deleted immediately rather than consuming another retry attempt
|
@@ -2948,6 +2991,8 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
2948
2991
|
:param request_id: Optional. A unique id used to identify the request. If the server receives two
|
2949
2992
|
``CreateBatchRequest`` requests with the same id, then the second request will be ignored and
|
2950
2993
|
the first ``google.longrunning.Operation`` created and stored in the backend is returned.
|
2994
|
+
:param num_retries_if_resource_is_not_ready: Optional. The number of retry for cluster creation request
|
2995
|
+
when resource is not ready error appears.
|
2951
2996
|
:param retry: A retry object used to retry requests. If ``None`` is specified, requests will not be
|
2952
2997
|
retried.
|
2953
2998
|
:param result_retry: Result retry object used to retry requests. Is used to decrease delay between
|
@@ -2988,6 +3033,7 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
2988
3033
|
batch: dict | Batch,
|
2989
3034
|
batch_id: str | None = None,
|
2990
3035
|
request_id: str | None = None,
|
3036
|
+
num_retries_if_resource_is_not_ready: int = 0,
|
2991
3037
|
retry: Retry | _MethodDefault = DEFAULT,
|
2992
3038
|
timeout: float | None = None,
|
2993
3039
|
metadata: Sequence[tuple[str, str]] = (),
|
@@ -3007,6 +3053,7 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
3007
3053
|
self.batch = batch
|
3008
3054
|
self.batch_id = batch_id
|
3009
3055
|
self.request_id = request_id
|
3056
|
+
self.num_retries_if_resource_is_not_ready = num_retries_if_resource_is_not_ready
|
3010
3057
|
self.retry = retry
|
3011
3058
|
self.result_retry = result_retry
|
3012
3059
|
self.timeout = timeout
|
@@ -3028,6 +3075,14 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
3028
3075
|
if self.batch_id:
|
3029
3076
|
batch_id = self.batch_id
|
3030
3077
|
self.log.info("Starting batch %s", batch_id)
|
3078
|
+
# Persist the link earlier so users can observe the progress
|
3079
|
+
DataprocBatchLink.persist(
|
3080
|
+
context=context,
|
3081
|
+
operator=self,
|
3082
|
+
project_id=self.project_id,
|
3083
|
+
region=self.region,
|
3084
|
+
batch_id=self.batch_id,
|
3085
|
+
)
|
3031
3086
|
else:
|
3032
3087
|
self.log.info("Starting batch. The batch ID will be generated since it was not provided.")
|
3033
3088
|
|
@@ -3091,6 +3146,15 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
3091
3146
|
timeout=self.timeout,
|
3092
3147
|
metadata=self.metadata,
|
3093
3148
|
)
|
3149
|
+
if self.num_retries_if_resource_is_not_ready and self.hook.check_error_for_resource_is_not_ready_msg(
|
3150
|
+
batch.state_message
|
3151
|
+
):
|
3152
|
+
attempt = self.num_retries_if_resource_is_not_ready
|
3153
|
+
while attempt > 0:
|
3154
|
+
attempt -= 1
|
3155
|
+
batch, batch_id = self.retry_batch_creation(batch_id)
|
3156
|
+
if not self.hook.check_error_for_resource_is_not_ready_msg(batch.state_message):
|
3157
|
+
break
|
3094
3158
|
|
3095
3159
|
self.handle_batch_status(context, batch.state, batch_id, batch.state_message)
|
3096
3160
|
return Batch.to_dict(batch)
|
@@ -3133,6 +3197,50 @@ class DataprocCreateBatchOperator(GoogleCloudBaseOperator):
|
|
3133
3197
|
raise AirflowException(f"Batch job {batch_id} unspecified. Driver logs: {link}")
|
3134
3198
|
self.log.info("Batch job %s completed. Driver logs: %s", batch_id, link)
|
3135
3199
|
|
3200
|
+
def retry_batch_creation(
|
3201
|
+
self,
|
3202
|
+
previous_batch_id: str,
|
3203
|
+
):
|
3204
|
+
self.log.info("Retrying creation process for batch_id %s", self.batch_id)
|
3205
|
+
self.log.info("Deleting previous failed Batch")
|
3206
|
+
self.hook.delete_batch(
|
3207
|
+
batch_id=previous_batch_id,
|
3208
|
+
region=self.region,
|
3209
|
+
project_id=self.project_id,
|
3210
|
+
retry=self.retry,
|
3211
|
+
timeout=self.timeout,
|
3212
|
+
metadata=self.metadata,
|
3213
|
+
)
|
3214
|
+
self.log.info("Starting a new creation for batch_id %s", self.batch_id)
|
3215
|
+
try:
|
3216
|
+
self.operation = self.hook.create_batch(
|
3217
|
+
region=self.region,
|
3218
|
+
project_id=self.project_id,
|
3219
|
+
batch=self.batch,
|
3220
|
+
batch_id=self.batch_id,
|
3221
|
+
request_id=self.request_id,
|
3222
|
+
retry=self.retry,
|
3223
|
+
timeout=self.timeout,
|
3224
|
+
metadata=self.metadata,
|
3225
|
+
)
|
3226
|
+
except AlreadyExists:
|
3227
|
+
self.log.info("Batch with given id already exists.")
|
3228
|
+
self.log.info("Attaching to the job %s if it is still running.", self.batch_id)
|
3229
|
+
else:
|
3230
|
+
batch_id = self.operation.metadata.batch.split("/")[-1]
|
3231
|
+
self.log.info("The batch %s was created.", batch_id)
|
3232
|
+
|
3233
|
+
self.log.info("Waiting for the completion of batch job %s", batch_id)
|
3234
|
+
batch = self.hook.wait_for_batch(
|
3235
|
+
batch_id=batch_id,
|
3236
|
+
region=self.region,
|
3237
|
+
project_id=self.project_id,
|
3238
|
+
retry=self.retry,
|
3239
|
+
timeout=self.timeout,
|
3240
|
+
metadata=self.metadata,
|
3241
|
+
)
|
3242
|
+
return batch, batch_id
|
3243
|
+
|
3136
3244
|
|
3137
3245
|
class DataprocDeleteBatchOperator(GoogleCloudBaseOperator):
|
3138
3246
|
"""
|
@@ -113,15 +113,14 @@ class CloudSpeechToTextRecognizeSpeechOperator(GoogleCloudBaseOperator):
|
|
113
113
|
gcp_conn_id=self.gcp_conn_id,
|
114
114
|
impersonation_chain=self.impersonation_chain,
|
115
115
|
)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
116
|
+
if self.audio.uri:
|
117
|
+
FileDetailsLink.persist(
|
118
|
+
context=context,
|
119
|
+
task_instance=self,
|
120
|
+
# Slice from: "gs://{BUCKET_NAME}/{FILE_NAME}" to: "{BUCKET_NAME}/{FILE_NAME}"
|
121
|
+
uri=self.audio.uri[5:],
|
122
|
+
project_id=self.project_id or hook.project_id,
|
123
|
+
)
|
125
124
|
response = hook.recognize_speech(
|
126
125
|
config=self.config, audio=self.audio, retry=self.retry, timeout=self.timeout
|
127
126
|
)
|
@@ -169,7 +169,14 @@ class CloudTranslateSpeechOperator(GoogleCloudBaseOperator):
|
|
169
169
|
raise AirflowException(
|
170
170
|
f"Wrong response '{recognize_dict}' returned - it should contain {key} field"
|
171
171
|
)
|
172
|
-
|
172
|
+
if self.audio.uri:
|
173
|
+
FileDetailsLink.persist(
|
174
|
+
context=context,
|
175
|
+
task_instance=self,
|
176
|
+
# Slice from: "gs://{BUCKET_NAME}/{FILE_NAME}" to: "{BUCKET_NAME}/{FILE_NAME}"
|
177
|
+
uri=self.audio.uri[5:],
|
178
|
+
project_id=self.project_id or translate_hook.project_id,
|
179
|
+
)
|
173
180
|
try:
|
174
181
|
translation = translate_hook.translate(
|
175
182
|
values=transcript,
|
@@ -179,12 +186,6 @@ class CloudTranslateSpeechOperator(GoogleCloudBaseOperator):
|
|
179
186
|
model=self.model,
|
180
187
|
)
|
181
188
|
self.log.info("Translated output: %s", translation)
|
182
|
-
FileDetailsLink.persist(
|
183
|
-
context=context,
|
184
|
-
task_instance=self,
|
185
|
-
uri=self.audio["uri"][5:],
|
186
|
-
project_id=self.project_id or translate_hook.project_id,
|
187
|
-
)
|
188
189
|
return translation
|
189
190
|
except ValueError as e:
|
190
191
|
self.log.error("An error has been thrown from translate speech method:")
|
@@ -22,6 +22,7 @@ from __future__ import annotations
|
|
22
22
|
from datetime import timedelta
|
23
23
|
from typing import TYPE_CHECKING, Any, Callable, Sequence
|
24
24
|
|
25
|
+
from google.cloud import pubsub_v1
|
25
26
|
from google.cloud.pubsub_v1.types import ReceivedMessage
|
26
27
|
|
27
28
|
from airflow.configuration import conf
|
@@ -34,6 +35,10 @@ if TYPE_CHECKING:
|
|
34
35
|
from airflow.utils.context import Context
|
35
36
|
|
36
37
|
|
38
|
+
class PubSubMessageTransformException(AirflowException):
|
39
|
+
"""Raise when messages failed to convert pubsub received format."""
|
40
|
+
|
41
|
+
|
37
42
|
class PubSubPullSensor(BaseSensorOperator):
|
38
43
|
"""
|
39
44
|
Pulls messages from a PubSub subscription and passes them through XCom.
|
@@ -170,7 +175,6 @@ class PubSubPullSensor(BaseSensorOperator):
|
|
170
175
|
subscription=self.subscription,
|
171
176
|
max_messages=self.max_messages,
|
172
177
|
ack_messages=self.ack_messages,
|
173
|
-
messages_callback=self.messages_callback,
|
174
178
|
poke_interval=self.poke_interval,
|
175
179
|
gcp_conn_id=self.gcp_conn_id,
|
176
180
|
impersonation_chain=self.impersonation_chain,
|
@@ -178,14 +182,28 @@ class PubSubPullSensor(BaseSensorOperator):
|
|
178
182
|
method_name="execute_complete",
|
179
183
|
)
|
180
184
|
|
181
|
-
def execute_complete(self, context:
|
182
|
-
"""
|
185
|
+
def execute_complete(self, context: Context, event: dict[str, str | list[str]]) -> Any:
|
186
|
+
"""If messages_callback is provided, execute it; otherwise, return immediately with trigger event message."""
|
183
187
|
if event["status"] == "success":
|
184
188
|
self.log.info("Sensor pulls messages: %s", event["message"])
|
189
|
+
if self.messages_callback:
|
190
|
+
received_messages = self._convert_to_received_messages(event["message"])
|
191
|
+
_return_value = self.messages_callback(received_messages, context)
|
192
|
+
return _return_value
|
193
|
+
|
185
194
|
return event["message"]
|
186
195
|
self.log.info("Sensor failed: %s", event["message"])
|
187
196
|
raise AirflowException(event["message"])
|
188
197
|
|
198
|
+
def _convert_to_received_messages(self, messages: Any) -> list[ReceivedMessage]:
|
199
|
+
try:
|
200
|
+
received_messages = [pubsub_v1.types.ReceivedMessage(msg) for msg in messages]
|
201
|
+
return received_messages
|
202
|
+
except Exception as e:
|
203
|
+
raise PubSubMessageTransformException(
|
204
|
+
f"Error converting triggerer event message back to received message format: {e}"
|
205
|
+
)
|
206
|
+
|
189
207
|
def _default_message_callback(
|
190
208
|
self,
|
191
209
|
pulled_messages: list[ReceivedMessage],
|
@@ -19,16 +19,14 @@
|
|
19
19
|
from __future__ import annotations
|
20
20
|
|
21
21
|
import asyncio
|
22
|
-
from
|
22
|
+
from functools import cached_property
|
23
|
+
from typing import Any, AsyncIterator, Sequence
|
24
|
+
|
25
|
+
from google.cloud.pubsub_v1.types import ReceivedMessage
|
23
26
|
|
24
27
|
from airflow.providers.google.cloud.hooks.pubsub import PubSubAsyncHook
|
25
28
|
from airflow.triggers.base import BaseTrigger, TriggerEvent
|
26
29
|
|
27
|
-
if TYPE_CHECKING:
|
28
|
-
from google.cloud.pubsub_v1.types import ReceivedMessage
|
29
|
-
|
30
|
-
from airflow.utils.context import Context
|
31
|
-
|
32
30
|
|
33
31
|
class PubsubPullTrigger(BaseTrigger):
|
34
32
|
"""
|
@@ -41,11 +39,6 @@ class PubsubPullTrigger(BaseTrigger):
|
|
41
39
|
:param ack_messages: If True, each message will be acknowledged
|
42
40
|
immediately rather than by any downstream tasks
|
43
41
|
:param gcp_conn_id: Reference to google cloud connection id
|
44
|
-
:param messages_callback: (Optional) Callback to process received messages.
|
45
|
-
Its return value will be saved to XCom.
|
46
|
-
If you are pulling large messages, you probably want to provide a custom callback.
|
47
|
-
If not provided, the default implementation will convert `ReceivedMessage` objects
|
48
|
-
into JSON-serializable dicts using `google.protobuf.json_format.MessageToDict` function.
|
49
42
|
:param poke_interval: polling period in seconds to check for the status
|
50
43
|
:param impersonation_chain: Optional service account to impersonate using short-term
|
51
44
|
credentials, or chained list of accounts required to get the access_token
|
@@ -64,7 +57,6 @@ class PubsubPullTrigger(BaseTrigger):
|
|
64
57
|
max_messages: int,
|
65
58
|
ack_messages: bool,
|
66
59
|
gcp_conn_id: str,
|
67
|
-
messages_callback: Callable[[list[ReceivedMessage], Context], Any] | None = None,
|
68
60
|
poke_interval: float = 10.0,
|
69
61
|
impersonation_chain: str | Sequence[str] | None = None,
|
70
62
|
):
|
@@ -73,11 +65,9 @@ class PubsubPullTrigger(BaseTrigger):
|
|
73
65
|
self.subscription = subscription
|
74
66
|
self.max_messages = max_messages
|
75
67
|
self.ack_messages = ack_messages
|
76
|
-
self.messages_callback = messages_callback
|
77
68
|
self.poke_interval = poke_interval
|
78
69
|
self.gcp_conn_id = gcp_conn_id
|
79
70
|
self.impersonation_chain = impersonation_chain
|
80
|
-
self.hook = PubSubAsyncHook()
|
81
71
|
|
82
72
|
def serialize(self) -> tuple[str, dict[str, Any]]:
|
83
73
|
"""Serialize PubsubPullTrigger arguments and classpath."""
|
@@ -88,7 +78,6 @@ class PubsubPullTrigger(BaseTrigger):
|
|
88
78
|
"subscription": self.subscription,
|
89
79
|
"max_messages": self.max_messages,
|
90
80
|
"ack_messages": self.ack_messages,
|
91
|
-
"messages_callback": self.messages_callback,
|
92
81
|
"poke_interval": self.poke_interval,
|
93
82
|
"gcp_conn_id": self.gcp_conn_id,
|
94
83
|
"impersonation_chain": self.impersonation_chain,
|
@@ -106,7 +95,10 @@ class PubsubPullTrigger(BaseTrigger):
|
|
106
95
|
):
|
107
96
|
if self.ack_messages:
|
108
97
|
await self.message_acknowledgement(pulled_messages)
|
109
|
-
|
98
|
+
|
99
|
+
messages_json = [ReceivedMessage.to_dict(m) for m in pulled_messages]
|
100
|
+
|
101
|
+
yield TriggerEvent({"status": "success", "message": messages_json})
|
110
102
|
return
|
111
103
|
self.log.info("Sleeping for %s seconds.", self.poke_interval)
|
112
104
|
await asyncio.sleep(self.poke_interval)
|
@@ -121,3 +113,11 @@ class PubsubPullTrigger(BaseTrigger):
|
|
121
113
|
messages=pulled_messages,
|
122
114
|
)
|
123
115
|
self.log.info("Acknowledged ack_ids from subscription %s", self.subscription)
|
116
|
+
|
117
|
+
@cached_property
|
118
|
+
def hook(self) -> PubSubAsyncHook:
|
119
|
+
return PubSubAsyncHook(
|
120
|
+
gcp_conn_id=self.gcp_conn_id,
|
121
|
+
impersonation_chain=self.impersonation_chain,
|
122
|
+
project_id=self.project_id,
|
123
|
+
)
|
@@ -28,8 +28,9 @@ def get_provider_info():
|
|
28
28
|
"name": "Google",
|
29
29
|
"description": "Google services including:\n\n - `Google Ads <https://ads.google.com/>`__\n - `Google Cloud (GCP) <https://cloud.google.com/>`__\n - `Google Firebase <https://firebase.google.com/>`__\n - `Google LevelDB <https://github.com/google/leveldb/>`__\n - `Google Marketing Platform <https://marketingplatform.google.com/>`__\n - `Google Workspace <https://workspace.google.com/>`__ (formerly Google Suite)\n",
|
30
30
|
"state": "ready",
|
31
|
-
"source-date-epoch":
|
31
|
+
"source-date-epoch": 1728485162,
|
32
32
|
"versions": [
|
33
|
+
"10.24.0",
|
33
34
|
"10.23.0",
|
34
35
|
"10.22.0",
|
35
36
|
"10.21.1",
|
@@ -921,6 +922,10 @@ def get_provider_info():
|
|
921
922
|
},
|
922
923
|
],
|
923
924
|
"filesystems": ["airflow.providers.google.cloud.fs.gcs"],
|
925
|
+
"asset-uris": [
|
926
|
+
{"schemes": ["gcp"], "handler": None},
|
927
|
+
{"schemes": ["bigquery"], "handler": "airflow.providers.google.datasets.bigquery.sanitize_uri"},
|
928
|
+
],
|
924
929
|
"dataset-uris": [
|
925
930
|
{"schemes": ["gcp"], "handler": None},
|
926
931
|
{"schemes": ["bigquery"], "handler": "airflow.providers.google.datasets.bigquery.sanitize_uri"},
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: apache-airflow-providers-google
|
3
|
-
Version: 10.
|
3
|
+
Version: 10.24.0
|
4
4
|
Summary: Provider package apache-airflow-providers-google for Apache Airflow
|
5
5
|
Keywords: airflow-provider,google,airflow,integration
|
6
6
|
Author-email: Apache Software Foundation <dev@airflow.apache.org>
|
7
7
|
Maintainer-email: Apache Software Foundation <dev@airflow.apache.org>
|
8
|
-
Requires-Python: ~=3.
|
8
|
+
Requires-Python: ~=3.9
|
9
9
|
Description-Content-Type: text/x-rst
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
11
11
|
Classifier: Environment :: Console
|
@@ -15,16 +15,15 @@ Classifier: Intended Audience :: System Administrators
|
|
15
15
|
Classifier: Framework :: Apache Airflow
|
16
16
|
Classifier: Framework :: Apache Airflow :: Provider
|
17
17
|
Classifier: License :: OSI Approved :: Apache Software License
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
19
18
|
Classifier: Programming Language :: Python :: 3.9
|
20
19
|
Classifier: Programming Language :: Python :: 3.10
|
21
20
|
Classifier: Programming Language :: Python :: 3.11
|
22
21
|
Classifier: Programming Language :: Python :: 3.12
|
23
22
|
Classifier: Topic :: System :: Monitoring
|
24
23
|
Requires-Dist: PyOpenSSL>=23.0.0
|
25
|
-
Requires-Dist: apache-airflow-providers-common-compat>=1.1.
|
26
|
-
Requires-Dist: apache-airflow-providers-common-sql>=1.7.
|
27
|
-
Requires-Dist: apache-airflow>=2.8.
|
24
|
+
Requires-Dist: apache-airflow-providers-common-compat>=1.1.0
|
25
|
+
Requires-Dist: apache-airflow-providers-common-sql>=1.7.2
|
26
|
+
Requires-Dist: apache-airflow>=2.8.0
|
28
27
|
Requires-Dist: asgiref>=3.5.2
|
29
28
|
Requires-Dist: dill>=0.2.3
|
30
29
|
Requires-Dist: gcloud-aio-auth>=5.2.0
|
@@ -87,20 +86,20 @@ Requires-Dist: python-slugify>=7.0.0
|
|
87
86
|
Requires-Dist: sqlalchemy-bigquery>=1.2.1
|
88
87
|
Requires-Dist: sqlalchemy-spanner>=1.6.2
|
89
88
|
Requires-Dist: tenacity>=8.1.0
|
90
|
-
Requires-Dist: apache-airflow-providers-amazon>=2.6.
|
89
|
+
Requires-Dist: apache-airflow-providers-amazon>=2.6.0 ; extra == "amazon"
|
91
90
|
Requires-Dist: apache-airflow-providers-apache-beam ; extra == "apache.beam"
|
92
91
|
Requires-Dist: apache-beam[gcp] ; extra == "apache.beam"
|
93
92
|
Requires-Dist: apache-airflow-providers-apache-cassandra ; extra == "apache.cassandra"
|
94
|
-
Requires-Dist: apache-airflow-providers-cncf-kubernetes>=7.2.
|
93
|
+
Requires-Dist: apache-airflow-providers-cncf-kubernetes>=7.2.0 ; extra == "cncf.kubernetes"
|
95
94
|
Requires-Dist: apache-airflow-providers-common-compat ; extra == "common.compat"
|
96
95
|
Requires-Dist: apache-airflow-providers-common-sql ; extra == "common.sql"
|
97
|
-
Requires-Dist: apache-airflow-providers-facebook>=2.2.
|
96
|
+
Requires-Dist: apache-airflow-providers-facebook>=2.2.0 ; extra == "facebook"
|
98
97
|
Requires-Dist: plyvel ; extra == "leveldb"
|
99
98
|
Requires-Dist: apache-airflow-providers-microsoft-azure ; extra == "microsoft.azure"
|
100
99
|
Requires-Dist: apache-airflow-providers-microsoft-mssql ; extra == "microsoft.mssql"
|
101
100
|
Requires-Dist: apache-airflow-providers-mysql ; extra == "mysql"
|
102
101
|
Requires-Dist: apache-airflow-providers-openlineage ; extra == "openlineage"
|
103
|
-
Requires-Dist: apache-airflow-providers-oracle>=3.1.
|
102
|
+
Requires-Dist: apache-airflow-providers-oracle>=3.1.0 ; extra == "oracle"
|
104
103
|
Requires-Dist: apache-airflow-providers-postgres ; extra == "postgres"
|
105
104
|
Requires-Dist: apache-airflow-providers-presto ; extra == "presto"
|
106
105
|
Requires-Dist: apache-airflow-providers-salesforce ; extra == "salesforce"
|
@@ -108,8 +107,8 @@ Requires-Dist: apache-airflow-providers-sftp ; extra == "sftp"
|
|
108
107
|
Requires-Dist: apache-airflow-providers-ssh ; extra == "ssh"
|
109
108
|
Requires-Dist: apache-airflow-providers-trino ; extra == "trino"
|
110
109
|
Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
|
111
|
-
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-google/10.
|
112
|
-
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-google/10.
|
110
|
+
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-google/10.24.0/changelog.html
|
111
|
+
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-google/10.24.0
|
113
112
|
Project-URL: Slack Chat, https://s.apache.org/airflow-slack
|
114
113
|
Project-URL: Source Code, https://github.com/apache/airflow
|
115
114
|
Project-URL: Twitter, https://twitter.com/ApacheAirflow
|
@@ -178,7 +177,7 @@ Provides-Extra: trino
|
|
178
177
|
|
179
178
|
Package ``apache-airflow-providers-google``
|
180
179
|
|
181
|
-
Release: ``10.
|
180
|
+
Release: ``10.24.0``
|
182
181
|
|
183
182
|
|
184
183
|
Google services including:
|
@@ -198,7 +197,7 @@ This is a provider package for ``google`` provider. All classes for this provide
|
|
198
197
|
are in ``airflow.providers.google`` python package.
|
199
198
|
|
200
199
|
You can find package information and changelog for the provider
|
201
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-google/10.
|
200
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-google/10.24.0/>`_.
|
202
201
|
|
203
202
|
Installation
|
204
203
|
------------
|
@@ -207,7 +206,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
|
|
207
206
|
for the minimum Airflow version supported) via
|
208
207
|
``pip install apache-airflow-providers-google``
|
209
208
|
|
210
|
-
The package supports the following python versions: 3.
|
209
|
+
The package supports the following python versions: 3.9,3.10,3.11,3.12
|
211
210
|
|
212
211
|
Requirements
|
213
212
|
------------
|
@@ -320,4 +319,4 @@ Dependent package
|
|
320
319
|
======================================================================================================================== ====================
|
321
320
|
|
322
321
|
The changelog for the provider package can be found in the
|
323
|
-
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-google/10.
|
322
|
+
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-google/10.24.0/changelog.html>`_.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
airflow/providers/google/LICENSE,sha256=FFb4jd2AXnOOf7XLP04pQW6jbdhG49TxlGY6fFpCV1Y,13609
|
2
|
-
airflow/providers/google/__init__.py,sha256=
|
3
|
-
airflow/providers/google/get_provider_info.py,sha256=
|
2
|
+
airflow/providers/google/__init__.py,sha256=HCd-PmeEVd99eSEuOle0bVEuyyRdbC-TeYHy2An3dqw,1495
|
3
|
+
airflow/providers/google/get_provider_info.py,sha256=gJcV9EN6FkM8I98xA3n0KHMLwDVJxonPO04qrwBVj_E,82205
|
4
4
|
airflow/providers/google/go_module_utils.py,sha256=XVM-IGME6CPgJA8fgDgkusFc4fz3lEghZaZ4elBkv7s,1780
|
5
5
|
airflow/providers/google/ads/.gitignore,sha256=z_qaKzblF2LuVvP-06iDord9JBeyzIlNeJ4bx3LbtGc,167
|
6
6
|
airflow/providers/google/ads/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
|
@@ -23,7 +23,7 @@ airflow/providers/google/cloud/fs/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2x
|
|
23
23
|
airflow/providers/google/cloud/fs/gcs.py,sha256=fJBGhHEE46_U5Rmbs1W0uenvGhECv13CtVSh3z7pM60,2457
|
24
24
|
airflow/providers/google/cloud/hooks/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
|
25
25
|
airflow/providers/google/cloud/hooks/automl.py,sha256=5fp8vZ96at8jH-a4yYipu4FI3J809b2E6XLCOQVhzmY,28959
|
26
|
-
airflow/providers/google/cloud/hooks/bigquery.py,sha256=
|
26
|
+
airflow/providers/google/cloud/hooks/bigquery.py,sha256=iTe6KLIzQWJl4Jp3Mz1KVmPWbRfrl9sOGiaLcVQ7jBs,157603
|
27
27
|
airflow/providers/google/cloud/hooks/bigquery_dts.py,sha256=3wLKj-6tQwWphjwKBLGg1rjoXAAknv0WLh6T3MqsNWA,15228
|
28
28
|
airflow/providers/google/cloud/hooks/bigtable.py,sha256=wReDIbDyQGP8oZIzg0vsfgD6zrLmY-oYghBNCPVPorw,12580
|
29
29
|
airflow/providers/google/cloud/hooks/cloud_batch.py,sha256=FjpR_Av7z8oMnB4Q7S-aPTMO8HZMxAo_1akdHpE7iA8,7809
|
@@ -36,18 +36,18 @@ airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py,sha256=BI
|
|
36
36
|
airflow/providers/google/cloud/hooks/compute.py,sha256=sBpi7oZjJwV4JPkWm3iKw23l7cAjHDET2MU9S8FOc58,40673
|
37
37
|
airflow/providers/google/cloud/hooks/compute_ssh.py,sha256=GTSiuhDFpeN-7n8ggrF-XBaPQ2hfk80tWChGImYGpTo,15689
|
38
38
|
airflow/providers/google/cloud/hooks/datacatalog.py,sha256=KoOcXUE-YhCR81wgHNJQ_YwTr5LYYyoDXTFJWZz_mds,54292
|
39
|
-
airflow/providers/google/cloud/hooks/dataflow.py,sha256
|
39
|
+
airflow/providers/google/cloud/hooks/dataflow.py,sha256=-FtTNvJ5bIEphLwobO4WpxVnV4erUcOEuV9K4p3lkxw,72002
|
40
40
|
airflow/providers/google/cloud/hooks/dataform.py,sha256=fLeYwtFgXTZMhdqFKBzAA9VfsC5eQ92GycbmDApdg6Q,27796
|
41
41
|
airflow/providers/google/cloud/hooks/datafusion.py,sha256=un_0r0fwiLPffNG-9tWN05FVWcx9ogaoLSI5XKUGHIg,26195
|
42
42
|
airflow/providers/google/cloud/hooks/datapipeline.py,sha256=HPNO7tkQeb_N1JQZInZeO-YWZADcNLZZijjtVAKkWcE,2637
|
43
43
|
airflow/providers/google/cloud/hooks/dataplex.py,sha256=hOAQ5gXBE0V6fw5Y_7Q8BymD6_GmFGsc8TPvd4SwJPM,38347
|
44
44
|
airflow/providers/google/cloud/hooks/dataprep.py,sha256=GH46CoEMnc63RoMiJ7aKvsHlGFvsBl_QcRgbmWwJ5tU,12187
|
45
|
-
airflow/providers/google/cloud/hooks/dataproc.py,sha256=
|
45
|
+
airflow/providers/google/cloud/hooks/dataproc.py,sha256=q1kw1AJ1AjSFb2ylljJNHVryycOQMbhB_sxeZ6Yn0PU,84496
|
46
46
|
airflow/providers/google/cloud/hooks/dataproc_metastore.py,sha256=Oh6I6PbawdCb0hkfrFNU4BVbxWangCcjIJdOBAh7q2Q,32152
|
47
47
|
airflow/providers/google/cloud/hooks/datastore.py,sha256=JuXTZqL-FAohbKBHQVYLCS3tY9pvMDjlg-dSphKiyPU,12158
|
48
48
|
airflow/providers/google/cloud/hooks/dlp.py,sha256=U1mnUEIQBcvh0bxf9RgeKLK2gjWx09qGh-hvCDOL_8k,67586
|
49
49
|
airflow/providers/google/cloud/hooks/functions.py,sha256=Zz1MCy_6j4oG-SXeeiVdqo4Ld68pVQg4rIuSm7RrPEo,9290
|
50
|
-
airflow/providers/google/cloud/hooks/gcs.py,sha256=
|
50
|
+
airflow/providers/google/cloud/hooks/gcs.py,sha256=j7SO8bxDh_-sO0XdFvfhOA9RuAw325y-2ef3mnKXKwQ,59974
|
51
51
|
airflow/providers/google/cloud/hooks/gdm.py,sha256=fCTu6SXtyQ3sn56GfIdgj6Myj_cc8UWdFVbYDMRMhZY,4123
|
52
52
|
airflow/providers/google/cloud/hooks/kms.py,sha256=CSIoyXgfZOujEPWOk2bn2bmwcKuDWXCu8eFSvi8MV9w,6574
|
53
53
|
airflow/providers/google/cloud/hooks/kubernetes_engine.py,sha256=VzpGcO8sf7FsAkLniatmvjyRpH_x2DV9cVYsl0ICAt4,24204
|
@@ -110,7 +110,7 @@ airflow/providers/google/cloud/links/translate.py,sha256=p0tHVr_CHPJswCmNheQAnpP
|
|
110
110
|
airflow/providers/google/cloud/links/vertex_ai.py,sha256=T5WGK77wKIPTiHtxKuQXvokArjVQYwZPjX5IgJX1dds,11138
|
111
111
|
airflow/providers/google/cloud/links/workflows.py,sha256=Ux7bwq2fspvSoNT4X3xFXX2SSmp8EuwDyPQsTO-z7bI,3303
|
112
112
|
airflow/providers/google/cloud/log/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
|
113
|
-
airflow/providers/google/cloud/log/gcs_task_handler.py,sha256=
|
113
|
+
airflow/providers/google/cloud/log/gcs_task_handler.py,sha256=LeIK9lF7tpKDCid-AFxEIS23AanCmE92tlPH3NB8efc,10089
|
114
114
|
airflow/providers/google/cloud/log/stackdriver_task_handler.py,sha256=5yh-Zgh2Me5BCrB_Nd52o5RP5gyv-tZjvOG2qnSZuRU,15526
|
115
115
|
airflow/providers/google/cloud/openlineage/BigQueryErrorRunFacet.json,sha256=3whXAY38LjxmQTpCnExiIU1Q1-8dZGtWjiK0A4JQWTA,688
|
116
116
|
airflow/providers/google/cloud/openlineage/BigQueryJobRunFacet.json,sha256=sWvE1o30bCqBBmB19n6wFZyL6BBcc22kCGWe0qcsYBc,850
|
@@ -118,7 +118,7 @@ airflow/providers/google/cloud/openlineage/__init__.py,sha256=9hdXHABrVpkbpjZgUf
|
|
118
118
|
airflow/providers/google/cloud/openlineage/mixins.py,sha256=5blMJ1heK9rMYBWR5p-lBj1y_EA1qJyjfb-fwdBM31k,12908
|
119
119
|
airflow/providers/google/cloud/openlineage/utils.py,sha256=iBeHh68qMumZ1pc-PWRBgQW8sycwmdtkJV-oCvYplPA,5781
|
120
120
|
airflow/providers/google/cloud/operators/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
|
121
|
-
airflow/providers/google/cloud/operators/automl.py,sha256=
|
121
|
+
airflow/providers/google/cloud/operators/automl.py,sha256=2S5gziRfU-3ptHNTHmRMXo9CfQcl8trNqPEqAVCRlZQ,63779
|
122
122
|
airflow/providers/google/cloud/operators/bigquery.py,sha256=l8wLnRdCsH1IGWsxZrdb-YzHlyOssymQo19lnNgxdyA,131077
|
123
123
|
airflow/providers/google/cloud/operators/bigquery_dts.py,sha256=6VJISM4HoMBQ3EQ5nz3zxFk8tfluGA1d2vcUNUlYLPc,17695
|
124
124
|
airflow/providers/google/cloud/operators/bigtable.py,sha256=BnWHnTEscyPbsKWFaSreLr62W68fmHu5loQVZex7LPs,26921
|
@@ -132,13 +132,13 @@ airflow/providers/google/cloud/operators/cloud_sql.py,sha256=VA_RRg_Zv3zo4cKmpEf
|
|
132
132
|
airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py,sha256=YQsVg8pDegEDvsWsZCbGrSqCln3iQyLQErZS_XZTnBo,48066
|
133
133
|
airflow/providers/google/cloud/operators/compute.py,sha256=lFGCacevkKJvAszJhfSLAOfetlsbYrCoImTeWXS5bqw,74607
|
134
134
|
airflow/providers/google/cloud/operators/datacatalog.py,sha256=TY0KZtphd28mNmZF4f3pV-G4-K61nwlOzBok1ZHqG_E,92962
|
135
|
-
airflow/providers/google/cloud/operators/dataflow.py,sha256=
|
135
|
+
airflow/providers/google/cloud/operators/dataflow.py,sha256=xwo0KFuHv85Wo_HESrQd1YsaWt3AKDEoiQ20GkqvOuk,79911
|
136
136
|
airflow/providers/google/cloud/operators/dataform.py,sha256=MkRDkn12gm2PJHOIfCs61N8nTuF3bfrcbWT4zSCXOdI,48745
|
137
137
|
airflow/providers/google/cloud/operators/datafusion.py,sha256=mXBCOhKVfHc1ZudMIT9UgBWL8w9qwBwnxTDWEO-xegA,41557
|
138
138
|
airflow/providers/google/cloud/operators/datapipeline.py,sha256=OuF0RxHpQxqPDjCq3jNpiOTEQHQgL5UXwNo7sk5fpEA,2362
|
139
139
|
airflow/providers/google/cloud/operators/dataplex.py,sha256=IgGwt95uW72IeLi1oHpGk8V0fKyt9apsc4kUpBz_7YQ,91195
|
140
140
|
airflow/providers/google/cloud/operators/dataprep.py,sha256=jTDDgRccd2zIUqGzJebZpbNTJsFdRi5RnMtldXHqiMs,10477
|
141
|
-
airflow/providers/google/cloud/operators/dataproc.py,sha256=
|
141
|
+
airflow/providers/google/cloud/operators/dataproc.py,sha256=GBdojsHucUR1FAo1YG8OSyuBXrQn_HVGwWq5-ciXJl0,156776
|
142
142
|
airflow/providers/google/cloud/operators/dataproc_metastore.py,sha256=mJOqDv4GEqQ7tx32ar-mMsPhIjYC_B1AZyiVDZBKOio,50402
|
143
143
|
airflow/providers/google/cloud/operators/datastore.py,sha256=di00jFy3Z1v0GcmcQ0df8NJ32yxcseOqWuojC4TKdmY,24927
|
144
144
|
airflow/providers/google/cloud/operators/dlp.py,sha256=SQCGml0RIKl0UrvXHIUiOskg5ayTj4F5_4k4rztClvM,120742
|
@@ -151,12 +151,12 @@ airflow/providers/google/cloud/operators/mlengine.py,sha256=AyJJDekzHN65PSRYfVbs
|
|
151
151
|
airflow/providers/google/cloud/operators/natural_language.py,sha256=mVi1R1QXU_aJXEGgyPiQXxAWlmOEInia6DpayxGhRwo,13719
|
152
152
|
airflow/providers/google/cloud/operators/pubsub.py,sha256=oo7nXjlexuLmp_-NHDa0Ko3vn15Sl81iTFfH0MGf-kQ,35508
|
153
153
|
airflow/providers/google/cloud/operators/spanner.py,sha256=Gpzr1LNB3e2zLaOb-LwORR9Vv9tMTDzNIcyV728u7Pw,24938
|
154
|
-
airflow/providers/google/cloud/operators/speech_to_text.py,sha256=
|
154
|
+
airflow/providers/google/cloud/operators/speech_to_text.py,sha256=AcMK8aY9OqVPwWSBfzZJEYB2oZM7C0NaTbvmXJMqwmQ,5696
|
155
155
|
airflow/providers/google/cloud/operators/stackdriver.py,sha256=Tei_f5oodxTp4K-m15U_M98_WhZr3v0JynTzlJHDOws,39205
|
156
156
|
airflow/providers/google/cloud/operators/tasks.py,sha256=zy3kgQkcVLx9a7r1Ojsk5-crVOzmmKC7_dO9WuKTwDY,48427
|
157
157
|
airflow/providers/google/cloud/operators/text_to_speech.py,sha256=y51bA2Ksr8NvaBKFn2dZBV3K04YqAu47yssK86t9MtQ,6956
|
158
158
|
airflow/providers/google/cloud/operators/translate.py,sha256=yYN4IRcRHXllZsChMJd71UDMigdD2iKid9G27jIVOlM,5007
|
159
|
-
airflow/providers/google/cloud/operators/translate_speech.py,sha256=
|
159
|
+
airflow/providers/google/cloud/operators/translate_speech.py,sha256=UjI-quI4IcgDZ_X4925mb9aQiI7yLIi2m4txieowYn4,7935
|
160
160
|
airflow/providers/google/cloud/operators/video_intelligence.py,sha256=NQvEueDegdpPBSqMkJF_qb9x3WeZT7XJL-yE8Sqlz_U,14165
|
161
161
|
airflow/providers/google/cloud/operators/vision.py,sha256=iKEEj33nVLrHUcJr2sE72NC1mAAZ7Gz-_XGdLgO4dqA,67720
|
162
162
|
airflow/providers/google/cloud/operators/workflows.py,sha256=fnyWLqRHz0UYu6AnQKKZIMlfSIg_v5nNbZAt6ASe4fI,28977
|
@@ -187,7 +187,7 @@ airflow/providers/google/cloud/sensors/dataproc.py,sha256=ANSRHFkApFjb-GVt1SBiRw
|
|
187
187
|
airflow/providers/google/cloud/sensors/dataproc_metastore.py,sha256=h4ToV-9FpKqE_4Gsmt7GButSB2hrcthb4JlfFU2o6Ik,5432
|
188
188
|
airflow/providers/google/cloud/sensors/gcs.py,sha256=S6FohDoiQQJPm4DvdW4NVpcGHRdl3HlR-vJuA8pIGzY,24490
|
189
189
|
airflow/providers/google/cloud/sensors/looker.py,sha256=zwtfCjxoowBoR3iuHlVpKzgwuN4ft6WGy2gzojlflvo,3609
|
190
|
-
airflow/providers/google/cloud/sensors/pubsub.py,sha256=
|
190
|
+
airflow/providers/google/cloud/sensors/pubsub.py,sha256=gzo0uaPom-R_FPttRZD1ENX6hFeq_2VD-C9_u-lNRu0,9742
|
191
191
|
airflow/providers/google/cloud/sensors/tasks.py,sha256=Y2t5OYIH98tsIN7G2LwSKnYZsOAUCkLqoOYMdQvYlHc,3485
|
192
192
|
airflow/providers/google/cloud/sensors/workflows.py,sha256=Lsp_F9wYDtC0KtWvoQq0B8oBzFuX1PF3du7abnW2Esc,5133
|
193
193
|
airflow/providers/google/cloud/transfers/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
|
@@ -237,7 +237,7 @@ airflow/providers/google/cloud/triggers/dataproc.py,sha256=xK2tZdS2gZTAqgQEQ9kQ9
|
|
237
237
|
airflow/providers/google/cloud/triggers/gcs.py,sha256=pMjeNOkWHkOyiAxeK-JoyDInUf2VNtefOZxp8K-aNjw,18973
|
238
238
|
airflow/providers/google/cloud/triggers/kubernetes_engine.py,sha256=OWjts1J4TIZWiXPP3GpE2mZTNneTfFAhnK0fpapVcE4,15689
|
239
239
|
airflow/providers/google/cloud/triggers/mlengine.py,sha256=qpOa9Gz8FmHDxXvPWrXO3M7snGbRTq92gy6kGafCUiY,5265
|
240
|
-
airflow/providers/google/cloud/triggers/pubsub.py,sha256=
|
240
|
+
airflow/providers/google/cloud/triggers/pubsub.py,sha256=IbomKaGpO1qbF3bpM7cF7rWY2X6T7D1UttHq08hq1tg,5234
|
241
241
|
airflow/providers/google/cloud/triggers/vertex_ai.py,sha256=IKeVp6p5weU-G_3SgIqwCK__vt_q0NAavgBpWmLfLqI,9932
|
242
242
|
airflow/providers/google/cloud/utils/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
|
243
243
|
airflow/providers/google/cloud/utils/bigquery.py,sha256=nMPUMpfsf-7QQEJG3wo1QqKuPGPwDUwKLGhE9SBjCaI,2145
|
@@ -310,7 +310,7 @@ airflow/providers/google/suite/transfers/gcs_to_gdrive.py,sha256=CxtVhp3wlEOBtjR
|
|
310
310
|
airflow/providers/google/suite/transfers/gcs_to_sheets.py,sha256=4nwXWkTySeBXNuThPxzO7uww_hH6PthpppTeuShn27Q,4363
|
311
311
|
airflow/providers/google/suite/transfers/local_to_drive.py,sha256=ZSK0b1Rd6x_xsP2DVcUzeYu3qoo9Bsp3VmnKyBsFRH8,6105
|
312
312
|
airflow/providers/google/suite/transfers/sql_to_sheets.py,sha256=sORkYSUDArRPnvi8WCiXP7YIXtpAgpEPhf8cqgpu644,5220
|
313
|
-
apache_airflow_providers_google-10.
|
314
|
-
apache_airflow_providers_google-10.
|
315
|
-
apache_airflow_providers_google-10.
|
316
|
-
apache_airflow_providers_google-10.
|
313
|
+
apache_airflow_providers_google-10.24.0.dist-info/entry_points.txt,sha256=Ay1Uo7uHxdXCxWew3CyBHumZ44Ld-iR7AcSR2fY-PLw,102
|
314
|
+
apache_airflow_providers_google-10.24.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
315
|
+
apache_airflow_providers_google-10.24.0.dist-info/METADATA,sha256=E4nXJ-g-KYQRTW388l-AtGr4sy0ckOnUgTIhQ4bXZhY,17191
|
316
|
+
apache_airflow_providers_google-10.24.0.dist-info/RECORD,,
|
File without changes
|