apache-airflow-providers-google 15.0.1rc1__py3-none-any.whl → 15.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airflow/providers/google/__init__.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +3 -5
- airflow/providers/google/cloud/hooks/cloud_batch.py +3 -4
- airflow/providers/google/cloud/hooks/cloud_sql.py +34 -41
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +1 -1
- airflow/providers/google/cloud/hooks/compute_ssh.py +2 -3
- airflow/providers/google/cloud/hooks/dataflow.py +11 -6
- airflow/providers/google/cloud/hooks/datafusion.py +3 -4
- airflow/providers/google/cloud/hooks/dataprep.py +1 -1
- airflow/providers/google/cloud/hooks/dlp.py +1 -1
- airflow/providers/google/cloud/hooks/gcs.py +5 -6
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +1 -2
- airflow/providers/google/cloud/hooks/managed_kafka.py +1 -1
- airflow/providers/google/cloud/hooks/mlengine.py +4 -6
- airflow/providers/google/cloud/hooks/stackdriver.py +4 -6
- airflow/providers/google/cloud/hooks/vision.py +1 -2
- airflow/providers/google/cloud/openlineage/mixins.py +2 -3
- airflow/providers/google/cloud/operators/alloy_db.py +1 -2
- airflow/providers/google/cloud/operators/automl.py +5 -5
- airflow/providers/google/cloud/operators/bigquery.py +24 -26
- airflow/providers/google/cloud/operators/cloud_batch.py +13 -15
- airflow/providers/google/cloud/operators/cloud_build.py +1 -2
- airflow/providers/google/cloud/operators/cloud_composer.py +24 -28
- airflow/providers/google/cloud/operators/cloud_run.py +12 -13
- airflow/providers/google/cloud/operators/cloud_sql.py +42 -49
- airflow/providers/google/cloud/operators/compute.py +9 -10
- airflow/providers/google/cloud/operators/dataproc.py +23 -26
- airflow/providers/google/cloud/operators/functions.py +5 -7
- airflow/providers/google/cloud/operators/kubernetes_engine.py +1 -2
- airflow/providers/google/cloud/operators/spanner.py +29 -33
- airflow/providers/google/cloud/sensors/cloud_composer.py +3 -5
- airflow/providers/google/cloud/sensors/dataflow.py +1 -1
- airflow/providers/google/cloud/sensors/dataproc.py +5 -5
- airflow/providers/google/cloud/sensors/gcs.py +15 -16
- airflow/providers/google/cloud/sensors/looker.py +3 -3
- airflow/providers/google/cloud/sensors/pubsub.py +13 -14
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +7 -8
- airflow/providers/google/cloud/transfers/cassandra_to_gcs.py +16 -20
- airflow/providers/google/cloud/transfers/facebook_ads_to_gcs.py +1 -2
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +14 -16
- airflow/providers/google/cloud/transfers/postgres_to_gcs.py +2 -3
- airflow/providers/google/cloud/utils/bigquery.py +5 -7
- airflow/providers/google/cloud/utils/dataform.py +1 -1
- airflow/providers/google/common/hooks/base_google.py +1 -1
- airflow/providers/google/common/hooks/operation_helpers.py +1 -2
- airflow/providers/google/common/utils/id_token_credentials.py +1 -1
- airflow/providers/google/leveldb/hooks/leveldb.py +4 -5
- {apache_airflow_providers_google-15.0.1rc1.dist-info → apache_airflow_providers_google-15.1.0.dist-info}/METADATA +9 -9
- {apache_airflow_providers_google-15.0.1rc1.dist-info → apache_airflow_providers_google-15.1.0.dist-info}/RECORD +51 -51
- {apache_airflow_providers_google-15.0.1rc1.dist-info → apache_airflow_providers_google-15.1.0.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-15.0.1rc1.dist-info → apache_airflow_providers_google-15.1.0.dist-info}/entry_points.txt +0 -0
@@ -168,20 +168,19 @@ class PubSubPullSensor(BaseSensorOperator):
|
|
168
168
|
if not self.deferrable:
|
169
169
|
super().execute(context)
|
170
170
|
return self._return_value
|
171
|
-
|
172
|
-
self.
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
)
|
171
|
+
self.defer(
|
172
|
+
timeout=timedelta(seconds=self.timeout),
|
173
|
+
trigger=PubsubPullTrigger(
|
174
|
+
project_id=self.project_id,
|
175
|
+
subscription=self.subscription,
|
176
|
+
max_messages=self.max_messages,
|
177
|
+
ack_messages=self.ack_messages,
|
178
|
+
poke_interval=self.poke_interval,
|
179
|
+
gcp_conn_id=self.gcp_conn_id,
|
180
|
+
impersonation_chain=self.impersonation_chain,
|
181
|
+
),
|
182
|
+
method_name="execute_complete",
|
183
|
+
)
|
185
184
|
|
186
185
|
def execute_complete(self, context: Context, event: dict[str, str | list[str]]) -> Any:
|
187
186
|
"""If messages_callback is provided, execute it; otherwise, return immediately with trigger event message."""
|
@@ -241,14 +241,13 @@ class BigQueryToGCSOperator(BaseOperator):
|
|
241
241
|
f"want to force rerun it consider setting `force_rerun=True`."
|
242
242
|
f"Or, if you want to reattach in this scenario add {job.state} to `reattach_states`"
|
243
243
|
)
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
self._handle_job_error(job)
|
244
|
+
# Job already reached state DONE
|
245
|
+
if job.state == "DONE":
|
246
|
+
raise AirflowException("Job is already in state DONE. Can not reattach to this job.")
|
247
|
+
|
248
|
+
# We are reattaching to a job
|
249
|
+
self.log.info("Reattaching to existing Job in state %s", job.state)
|
250
|
+
self._handle_job_error(job)
|
252
251
|
|
253
252
|
self.job_id = job.job_id
|
254
253
|
conf = job.to_api_repr()["configuration"]["extract"]["sourceTable"]
|
@@ -261,29 +261,27 @@ class CassandraToGCSOperator(BaseOperator):
|
|
261
261
|
"""Convert value to BQ type."""
|
262
262
|
if not value or isinstance(value, (str, int, float, bool, dict)):
|
263
263
|
return value
|
264
|
-
|
264
|
+
if isinstance(value, bytes):
|
265
265
|
return b64encode(value).decode("ascii")
|
266
|
-
|
266
|
+
if isinstance(value, UUID):
|
267
267
|
if self.encode_uuid:
|
268
268
|
return b64encode(value.bytes).decode("ascii")
|
269
|
-
else:
|
270
|
-
return str(value)
|
271
|
-
elif isinstance(value, (datetime, Date)):
|
272
269
|
return str(value)
|
273
|
-
|
270
|
+
if isinstance(value, (datetime, Date)):
|
271
|
+
return str(value)
|
272
|
+
if isinstance(value, Decimal):
|
274
273
|
return float(value)
|
275
|
-
|
274
|
+
if isinstance(value, Time):
|
276
275
|
return str(value).split(".")[0]
|
277
|
-
|
276
|
+
if isinstance(value, (list, SortedSet)):
|
278
277
|
return self.convert_array_types(value)
|
279
|
-
|
278
|
+
if hasattr(value, "_fields"):
|
280
279
|
return self.convert_user_type(value)
|
281
|
-
|
280
|
+
if isinstance(value, tuple):
|
282
281
|
return self.convert_tuple_type(value)
|
283
|
-
|
282
|
+
if isinstance(value, OrderedMapSerializedKey):
|
284
283
|
return self.convert_map_type(value)
|
285
|
-
|
286
|
-
raise AirflowException(f"Unexpected value: {value}")
|
284
|
+
raise AirflowException(f"Unexpected value: {value}")
|
287
285
|
|
288
286
|
def convert_array_types(self, value: list[Any] | SortedSet) -> list[Any]:
|
289
287
|
"""Map convert_value over array."""
|
@@ -376,19 +374,17 @@ class CassandraToGCSOperator(BaseOperator):
|
|
376
374
|
"""Convert type to equivalent BQ type."""
|
377
375
|
if cls.is_simple_type(type_):
|
378
376
|
return CassandraToGCSOperator.CQL_TYPE_MAP[type_.cassname]
|
379
|
-
|
377
|
+
if cls.is_record_type(type_):
|
380
378
|
return "RECORD"
|
381
|
-
|
379
|
+
if cls.is_array_type(type_):
|
382
380
|
return cls.get_bq_type(type_.subtypes[0])
|
383
|
-
|
384
|
-
raise AirflowException("Not a supported type_: " + type_.cassname)
|
381
|
+
raise AirflowException("Not a supported type_: " + type_.cassname)
|
385
382
|
|
386
383
|
@classmethod
|
387
384
|
def get_bq_mode(cls, type_: Any) -> str:
|
388
385
|
"""Convert type to equivalent BQ mode."""
|
389
386
|
if cls.is_array_type(type_) or type_.cassname == "MapType":
|
390
387
|
return "REPEATED"
|
391
|
-
|
388
|
+
if cls.is_record_type(type_) or cls.is_simple_type(type_):
|
392
389
|
return "NULLABLE"
|
393
|
-
|
394
|
-
raise AirflowException("Not a supported type_: " + type_.cassname)
|
390
|
+
raise AirflowException("Not a supported type_: " + type_.cassname)
|
@@ -157,8 +157,7 @@ class FacebookAdsReportToGcsOperator(BaseOperator):
|
|
157
157
|
def _generate_rows_with_action(self, type_check: bool):
|
158
158
|
if type_check and self.upload_as_account:
|
159
159
|
return {FlushAction.EXPORT_EVERY_ACCOUNT: []}
|
160
|
-
|
161
|
-
return {FlushAction.EXPORT_ONCE: []}
|
160
|
+
return {FlushAction.EXPORT_ONCE: []}
|
162
161
|
|
163
162
|
def _prepare_rows_for_upload(
|
164
163
|
self,
|
@@ -58,6 +58,7 @@ ALLOWED_FORMATS = [
|
|
58
58
|
"GOOGLE_SHEETS",
|
59
59
|
"DATASTORE_BACKUP",
|
60
60
|
"PARQUET",
|
61
|
+
"ORC",
|
61
62
|
]
|
62
63
|
|
63
64
|
|
@@ -262,8 +263,7 @@ class GCSToBigQueryOperator(BaseOperator):
|
|
262
263
|
f"{source_format} is not a valid source format. "
|
263
264
|
f"Please use one of the following types: {ALLOWED_FORMATS}."
|
264
265
|
)
|
265
|
-
|
266
|
-
self.source_format = source_format.upper()
|
266
|
+
self.source_format = source_format.upper()
|
267
267
|
self.compression = compression
|
268
268
|
self.create_disposition = create_disposition
|
269
269
|
self.skip_leading_rows = skip_leading_rows
|
@@ -406,14 +406,13 @@ class GCSToBigQueryOperator(BaseOperator):
|
|
406
406
|
f"want to force rerun it consider setting `force_rerun=True`."
|
407
407
|
f"Or, if you want to reattach in this scenario add {job.state} to `reattach_states`"
|
408
408
|
)
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
raise AirflowException("Job is already in state DONE. Can not reattach to this job.")
|
409
|
+
# Job already reached state DONE
|
410
|
+
if job.state == "DONE":
|
411
|
+
raise AirflowException("Job is already in state DONE. Can not reattach to this job.")
|
413
412
|
|
414
|
-
|
415
|
-
|
416
|
-
|
413
|
+
# We are reattaching to a job
|
414
|
+
self.log.info("Reattaching to existing Job in state %s", job.state)
|
415
|
+
self._handle_job_error(job)
|
417
416
|
|
418
417
|
job_types = {
|
419
418
|
LoadJob._JOB_TYPE: ["sourceTable", "destinationTable"],
|
@@ -506,8 +505,7 @@ class GCSToBigQueryOperator(BaseOperator):
|
|
506
505
|
f"Could not determine MAX value in column {self.max_id_key} "
|
507
506
|
f"since the default value of 'string_field_n' was set by BQ"
|
508
507
|
)
|
509
|
-
|
510
|
-
raise AirflowException(e.message)
|
508
|
+
raise AirflowException(e.message)
|
511
509
|
if rows:
|
512
510
|
for row in rows:
|
513
511
|
max_id = row[0] if row[0] else 0
|
@@ -644,11 +642,10 @@ class GCSToBigQueryOperator(BaseOperator):
|
|
644
642
|
"allowed if write_disposition is "
|
645
643
|
"'WRITE_APPEND' or 'WRITE_TRUNCATE'."
|
646
644
|
)
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
self.configuration["load"]["schemaUpdateOptions"] = self.schema_update_options
|
645
|
+
# To provide backward compatibility
|
646
|
+
self.schema_update_options = list(self.schema_update_options or [])
|
647
|
+
self.log.info("Adding experimental 'schemaUpdateOptions': %s", self.schema_update_options)
|
648
|
+
self.configuration["load"]["schemaUpdateOptions"] = self.schema_update_options
|
652
649
|
|
653
650
|
if self.max_bad_records:
|
654
651
|
self.configuration["load"]["maxBadRecords"] = self.max_bad_records
|
@@ -680,6 +677,7 @@ class GCSToBigQueryOperator(BaseOperator):
|
|
680
677
|
"NEWLINE_DELIMITED_JSON": ["autodetect", "ignoreUnknownValues"],
|
681
678
|
"PARQUET": ["autodetect", "ignoreUnknownValues"],
|
682
679
|
"AVRO": ["useAvroLogicalTypes"],
|
680
|
+
"ORC": ["autodetect"],
|
683
681
|
}
|
684
682
|
|
685
683
|
valid_configs = src_fmt_to_configs_mapping[self.source_format]
|
@@ -57,9 +57,8 @@ class _PostgresServerSideCursorDecorator:
|
|
57
57
|
def __next__(self):
|
58
58
|
if self.rows:
|
59
59
|
return self.rows.pop()
|
60
|
-
|
61
|
-
|
62
|
-
return next(self.cursor)
|
60
|
+
self.initialized = True
|
61
|
+
return next(self.cursor)
|
63
62
|
|
64
63
|
@property
|
65
64
|
def description(self):
|
@@ -27,16 +27,15 @@ def bq_cast(string_field: str, bq_type: str) -> None | int | float | bool | str:
|
|
27
27
|
"""
|
28
28
|
if string_field is None:
|
29
29
|
return None
|
30
|
-
|
30
|
+
if bq_type == "INTEGER":
|
31
31
|
return int(string_field)
|
32
|
-
|
32
|
+
if bq_type in ("FLOAT", "TIMESTAMP"):
|
33
33
|
return float(string_field)
|
34
|
-
|
34
|
+
if bq_type == "BOOLEAN":
|
35
35
|
if string_field not in ["true", "false"]:
|
36
36
|
raise ValueError(f"{string_field} must have value 'true' or 'false'")
|
37
37
|
return string_field == "true"
|
38
|
-
|
39
|
-
return string_field
|
38
|
+
return string_field
|
40
39
|
|
41
40
|
|
42
41
|
def convert_job_id(job_id: str | list[str], project_id: str, location: str | None) -> Any:
|
@@ -51,5 +50,4 @@ def convert_job_id(job_id: str | list[str], project_id: str, location: str | Non
|
|
51
50
|
location = location or "US"
|
52
51
|
if isinstance(job_id, list):
|
53
52
|
return [f"{project_id}:{location}:{i}" for i in job_id]
|
54
|
-
|
55
|
-
return f"{project_id}:{location}:{job_id}"
|
53
|
+
return f"{project_id}:{location}:{job_id}"
|
@@ -202,7 +202,7 @@ def make_initialization_workspace_flow(
|
|
202
202
|
def define_default_location(region: str) -> DataformLocations:
|
203
203
|
if "us" in region:
|
204
204
|
return DataformLocations.US
|
205
|
-
|
205
|
+
if "europe" in region:
|
206
206
|
return DataformLocations.EUROPE
|
207
207
|
|
208
208
|
regions_mapping: Mapping[str, DataformLocations] = {}
|
@@ -156,7 +156,7 @@ T = TypeVar("T", bound=Callable)
|
|
156
156
|
RT = TypeVar("RT")
|
157
157
|
|
158
158
|
|
159
|
-
def get_field(extras: dict, field_name: str):
|
159
|
+
def get_field(extras: dict, field_name: str) -> str | None:
|
160
160
|
"""Get field from extra, first checking short name, then for backcompat we check for prefixed name."""
|
161
161
|
if field_name.startswith("extra__"):
|
162
162
|
raise ValueError(
|
@@ -22,7 +22,6 @@ from __future__ import annotations
|
|
22
22
|
from typing import TYPE_CHECKING
|
23
23
|
|
24
24
|
from google.api_core.exceptions import GoogleAPICallError
|
25
|
-
from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
|
26
25
|
|
27
26
|
from airflow.exceptions import AirflowException
|
28
27
|
|
@@ -38,7 +37,7 @@ class OperationHelper:
|
|
38
37
|
@staticmethod
|
39
38
|
def wait_for_operation_result(
|
40
39
|
operation: Operation,
|
41
|
-
timeout: int | None
|
40
|
+
timeout: int | None = None,
|
42
41
|
polling: Retry | None = None,
|
43
42
|
retry: Retry | None = None,
|
44
43
|
) -> Message:
|
@@ -111,7 +111,7 @@ def _load_credentials_from_file(
|
|
111
111
|
|
112
112
|
return current_credentials
|
113
113
|
|
114
|
-
|
114
|
+
if credential_type == _SERVICE_ACCOUNT_TYPE:
|
115
115
|
try:
|
116
116
|
return service_account.IDTokenCredentials.from_service_account_info(
|
117
117
|
info, target_audience=target_audience
|
@@ -96,18 +96,17 @@ class LevelDBHook(BaseHook):
|
|
96
96
|
if not value:
|
97
97
|
raise ValueError("Please provide `value`!")
|
98
98
|
return self.put(key, value)
|
99
|
-
|
99
|
+
if command == "get":
|
100
100
|
return self.get(key)
|
101
|
-
|
101
|
+
if command == "delete":
|
102
102
|
return self.delete(key)
|
103
|
-
|
103
|
+
if command == "write_batch":
|
104
104
|
if not keys:
|
105
105
|
raise ValueError("Please provide `keys`!")
|
106
106
|
if not values:
|
107
107
|
raise ValueError("Please provide `values`!")
|
108
108
|
return self.write_batch(keys, values)
|
109
|
-
|
110
|
-
raise LevelDBHookException("Unknown command for LevelDB hook")
|
109
|
+
raise LevelDBHookException("Unknown command for LevelDB hook")
|
111
110
|
|
112
111
|
def put(self, key: bytes, value: bytes):
|
113
112
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: apache-airflow-providers-google
|
3
|
-
Version: 15.0
|
3
|
+
Version: 15.1.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>
|
@@ -20,9 +20,9 @@ Classifier: Programming Language :: Python :: 3.10
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
22
22
|
Classifier: Topic :: System :: Monitoring
|
23
|
-
Requires-Dist: apache-airflow>=2.9.
|
24
|
-
Requires-Dist: apache-airflow-providers-common-compat>=1.4.
|
25
|
-
Requires-Dist: apache-airflow-providers-common-sql>=1.20.
|
23
|
+
Requires-Dist: apache-airflow>=2.9.0
|
24
|
+
Requires-Dist: apache-airflow-providers-common-compat>=1.4.0
|
25
|
+
Requires-Dist: apache-airflow-providers-common-sql>=1.20.0
|
26
26
|
Requires-Dist: asgiref>=3.5.2
|
27
27
|
Requires-Dist: dill>=0.2.3
|
28
28
|
Requires-Dist: gcloud-aio-auth>=5.2.0
|
@@ -108,8 +108,8 @@ Requires-Dist: apache-airflow-providers-sftp ; extra == "sftp"
|
|
108
108
|
Requires-Dist: apache-airflow-providers-ssh ; extra == "ssh"
|
109
109
|
Requires-Dist: apache-airflow-providers-trino ; extra == "trino"
|
110
110
|
Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
|
111
|
-
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-google/15.0
|
112
|
-
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-google/15.0
|
111
|
+
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-google/15.1.0/changelog.html
|
112
|
+
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-google/15.1.0
|
113
113
|
Project-URL: Mastodon, https://fosstodon.org/@airflow
|
114
114
|
Project-URL: Slack Chat, https://s.apache.org/airflow-slack
|
115
115
|
Project-URL: Source Code, https://github.com/apache/airflow
|
@@ -158,7 +158,7 @@ Provides-Extra: trino
|
|
158
158
|
|
159
159
|
Package ``apache-airflow-providers-google``
|
160
160
|
|
161
|
-
Release: ``15.0
|
161
|
+
Release: ``15.1.0``
|
162
162
|
|
163
163
|
|
164
164
|
Google services including:
|
@@ -178,7 +178,7 @@ This is a provider package for ``google`` provider. All classes for this provide
|
|
178
178
|
are in ``airflow.providers.google`` python package.
|
179
179
|
|
180
180
|
You can find package information and changelog for the provider
|
181
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-google/15.0
|
181
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-google/15.1.0/>`_.
|
182
182
|
|
183
183
|
Installation
|
184
184
|
------------
|
@@ -302,5 +302,5 @@ Dependent package
|
|
302
302
|
======================================================================================================================== ====================
|
303
303
|
|
304
304
|
The changelog for the provider package can be found in the
|
305
|
-
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-google/15.0
|
305
|
+
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-google/15.1.0/changelog.html>`_.
|
306
306
|
|