apache-airflow-providers-amazon 8.25.0rc1__py3-none-any.whl → 8.26.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 (45) hide show
  1. airflow/providers/amazon/__init__.py +1 -1
  2. airflow/providers/amazon/aws/hooks/athena.py +18 -9
  3. airflow/providers/amazon/aws/hooks/athena_sql.py +2 -1
  4. airflow/providers/amazon/aws/hooks/base_aws.py +34 -10
  5. airflow/providers/amazon/aws/hooks/chime.py +2 -1
  6. airflow/providers/amazon/aws/hooks/datasync.py +6 -3
  7. airflow/providers/amazon/aws/hooks/ecr.py +2 -1
  8. airflow/providers/amazon/aws/hooks/ecs.py +12 -6
  9. airflow/providers/amazon/aws/hooks/glacier.py +8 -4
  10. airflow/providers/amazon/aws/hooks/kinesis.py +2 -1
  11. airflow/providers/amazon/aws/hooks/logs.py +4 -2
  12. airflow/providers/amazon/aws/hooks/redshift_cluster.py +24 -12
  13. airflow/providers/amazon/aws/hooks/redshift_data.py +4 -2
  14. airflow/providers/amazon/aws/hooks/redshift_sql.py +6 -3
  15. airflow/providers/amazon/aws/hooks/s3.py +70 -53
  16. airflow/providers/amazon/aws/hooks/sagemaker.py +82 -41
  17. airflow/providers/amazon/aws/hooks/secrets_manager.py +6 -3
  18. airflow/providers/amazon/aws/hooks/sts.py +2 -1
  19. airflow/providers/amazon/aws/operators/athena.py +21 -8
  20. airflow/providers/amazon/aws/operators/batch.py +12 -6
  21. airflow/providers/amazon/aws/operators/datasync.py +2 -1
  22. airflow/providers/amazon/aws/operators/ecs.py +1 -0
  23. airflow/providers/amazon/aws/operators/emr.py +6 -86
  24. airflow/providers/amazon/aws/operators/glue.py +4 -2
  25. airflow/providers/amazon/aws/operators/glue_crawler.py +22 -19
  26. airflow/providers/amazon/aws/operators/neptune.py +2 -1
  27. airflow/providers/amazon/aws/operators/redshift_cluster.py +2 -1
  28. airflow/providers/amazon/aws/operators/sagemaker.py +2 -1
  29. airflow/providers/amazon/aws/sensors/base_aws.py +2 -1
  30. airflow/providers/amazon/aws/sensors/glue_catalog_partition.py +25 -17
  31. airflow/providers/amazon/aws/sensors/glue_crawler.py +16 -12
  32. airflow/providers/amazon/aws/transfers/mongo_to_s3.py +6 -3
  33. airflow/providers/amazon/aws/transfers/s3_to_dynamodb.py +2 -1
  34. airflow/providers/amazon/aws/transfers/s3_to_sql.py +2 -1
  35. airflow/providers/amazon/aws/triggers/ecs.py +3 -1
  36. airflow/providers/amazon/aws/triggers/glue.py +15 -3
  37. airflow/providers/amazon/aws/triggers/glue_crawler.py +8 -1
  38. airflow/providers/amazon/aws/utils/connection_wrapper.py +10 -5
  39. airflow/providers/amazon/aws/utils/mixins.py +2 -1
  40. airflow/providers/amazon/aws/utils/redshift.py +2 -1
  41. airflow/providers/amazon/get_provider_info.py +2 -1
  42. {apache_airflow_providers_amazon-8.25.0rc1.dist-info → apache_airflow_providers_amazon-8.26.0rc1.dist-info}/METADATA +6 -6
  43. {apache_airflow_providers_amazon-8.25.0rc1.dist-info → apache_airflow_providers_amazon-8.26.0rc1.dist-info}/RECORD +45 -45
  44. {apache_airflow_providers_amazon-8.25.0rc1.dist-info → apache_airflow_providers_amazon-8.26.0rc1.dist-info}/WHEEL +0 -0
  45. {apache_airflow_providers_amazon-8.25.0rc1.dist-info → apache_airflow_providers_amazon-8.26.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__ = "8.25.0"
32
+ __version__ = "8.26.0"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.7.0"
@@ -50,7 +50,8 @@ def query_params_to_string(params: dict[str, str | Collection[str]]) -> str:
50
50
 
51
51
 
52
52
  class AthenaHook(AwsBaseHook):
53
- """Interact with Amazon Athena.
53
+ """
54
+ Interact with Amazon Athena.
54
55
 
55
56
  Provide thick wrapper around
56
57
  :external+boto3:py:class:`boto3.client("athena") <Athena.Client>`.
@@ -106,7 +107,8 @@ class AthenaHook(AwsBaseHook):
106
107
  client_request_token: str | None = None,
107
108
  workgroup: str = "primary",
108
109
  ) -> str:
109
- """Run a Trino/Presto query on Athena with provided config.
110
+ """
111
+ Run a Trino/Presto query on Athena with provided config.
110
112
 
111
113
  .. seealso::
112
114
  - :external+boto3:py:meth:`Athena.Client.start_query_execution`
@@ -136,7 +138,8 @@ class AthenaHook(AwsBaseHook):
136
138
  return query_execution_id
137
139
 
138
140
  def get_query_info(self, query_execution_id: str, use_cache: bool = False) -> dict:
139
- """Get information about a single execution of a query.
141
+ """
142
+ Get information about a single execution of a query.
140
143
 
141
144
  .. seealso::
142
145
  - :external+boto3:py:meth:`Athena.Client.get_query_execution`
@@ -152,7 +155,8 @@ class AthenaHook(AwsBaseHook):
152
155
  return response
153
156
 
154
157
  def check_query_status(self, query_execution_id: str, use_cache: bool = False) -> str | None:
155
- """Fetch the state of a submitted query.
158
+ """
159
+ Fetch the state of a submitted query.
156
160
 
157
161
  .. seealso::
158
162
  - :external+boto3:py:meth:`Athena.Client.get_query_execution`
@@ -200,7 +204,8 @@ class AthenaHook(AwsBaseHook):
200
204
  def get_query_results(
201
205
  self, query_execution_id: str, next_token_id: str | None = None, max_results: int = 1000
202
206
  ) -> dict | None:
203
- """Fetch submitted query results.
207
+ """
208
+ Fetch submitted query results.
204
209
 
205
210
  .. seealso::
206
211
  - :external+boto3:py:meth:`Athena.Client.get_query_results`
@@ -234,7 +239,8 @@ class AthenaHook(AwsBaseHook):
234
239
  page_size: int | None = None,
235
240
  starting_token: str | None = None,
236
241
  ) -> PageIterator | None:
237
- """Fetch submitted Athena query results.
242
+ """
243
+ Fetch submitted Athena query results.
238
244
 
239
245
  .. seealso::
240
246
  - :external+boto3:py:class:`Athena.Paginator.GetQueryResults`
@@ -274,7 +280,8 @@ class AthenaHook(AwsBaseHook):
274
280
  def poll_query_status(
275
281
  self, query_execution_id: str, max_polling_attempts: int | None = None, sleep_time: int | None = None
276
282
  ) -> str | None:
277
- """Poll the state of a submitted query until it reaches final state.
283
+ """
284
+ Poll the state of a submitted query until it reaches final state.
278
285
 
279
286
  :param query_execution_id: ID of submitted athena query
280
287
  :param max_polling_attempts: Number of times to poll for query state before function exits
@@ -299,7 +306,8 @@ class AthenaHook(AwsBaseHook):
299
306
  return self.check_query_status(query_execution_id)
300
307
 
301
308
  def get_output_location(self, query_execution_id: str) -> str:
302
- """Get the output location of the query results in S3 URI format.
309
+ """
310
+ Get the output location of the query results in S3 URI format.
303
311
 
304
312
  .. seealso::
305
313
  - :external+boto3:py:meth:`Athena.Client.get_query_execution`
@@ -319,7 +327,8 @@ class AthenaHook(AwsBaseHook):
319
327
  raise
320
328
 
321
329
  def stop_query(self, query_execution_id: str) -> dict:
322
- """Cancel the submitted query.
330
+ """
331
+ Cancel the submitted query.
323
332
 
324
333
  .. seealso::
325
334
  - :external+boto3:py:meth:`Athena.Client.stop_query_execution`
@@ -33,7 +33,8 @@ if TYPE_CHECKING:
33
33
 
34
34
 
35
35
  class AthenaSQLHook(AwsBaseHook, DbApiHook):
36
- """Interact with Amazon Athena.
36
+ """
37
+ Interact with Amazon Athena.
37
38
 
38
39
  Provide wrapper around PyAthena library.
39
40
 
@@ -70,9 +70,23 @@ if TYPE_CHECKING:
70
70
 
71
71
  from airflow.models.connection import Connection # Avoid circular imports.
72
72
 
73
+ _loader = botocore.loaders.Loader()
74
+ """
75
+ botocore data loader to be used with async sessions
76
+
77
+ By default, a botocore session creates and caches an instance of JSONDecoder which
78
+ consumes a lot of memory. This issue was reported here https://github.com/boto/botocore/issues/3078.
79
+ In the context of triggers which use boto sessions, this can result in excessive
80
+ memory usage and as a result reduced capacity on the triggerer. We can reduce
81
+ memory footprint by sharing the loader instance across the sessions.
82
+
83
+ :meta private:
84
+ """
85
+
73
86
 
74
87
  class BaseSessionFactory(LoggingMixin):
75
- """Base AWS Session Factory class.
88
+ """
89
+ Base AWS Session Factory class.
76
90
 
77
91
  This handles synchronous and async boto session creation. It can handle most
78
92
  of the AWS supported authentication methods.
@@ -154,7 +168,9 @@ class BaseSessionFactory(LoggingMixin):
154
168
  def get_async_session(self):
155
169
  from aiobotocore.session import get_session as async_get_session
156
170
 
157
- return async_get_session()
171
+ session = async_get_session()
172
+ session.register_component("data_loader", _loader)
173
+ return session
158
174
 
159
175
  def create_session(
160
176
  self, deferrable: bool = False
@@ -435,7 +451,8 @@ class BaseSessionFactory(LoggingMixin):
435
451
 
436
452
 
437
453
  class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
438
- """Generic class for interact with AWS.
454
+ """
455
+ Generic class for interact with AWS.
439
456
 
440
457
  This class provide a thin wrapper around the boto3 Python library.
441
458
 
@@ -497,7 +514,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
497
514
 
498
515
  @staticmethod
499
516
  def _find_operator_class_name(target_function_name: str) -> str | None:
500
- """Given a frame off the stack, return the name of the class that made the call.
517
+ """
518
+ Given a frame off the stack, return the name of the class that made the call.
501
519
 
502
520
  This method may raise a ValueError or an IndexError. The caller is
503
521
  responsible with catching and handling those.
@@ -547,7 +565,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
547
565
  @staticmethod
548
566
  @return_on_error("00000000-0000-0000-0000-000000000000")
549
567
  def _generate_dag_key() -> str:
550
- """Generate a DAG key.
568
+ """
569
+ Generate a DAG key.
551
570
 
552
571
  The Object Identifier (OID) namespace is used to salt the dag_id value.
553
572
  That salted value is used to generate a SHA-1 hash which, by definition,
@@ -783,7 +802,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
783
802
  return creds
784
803
 
785
804
  def expand_role(self, role: str, region_name: str | None = None) -> str:
786
- """Get the Amazon Resource Name (ARN) for the role.
805
+ """
806
+ Get the Amazon Resource Name (ARN) for the role.
787
807
 
788
808
  If IAM role is already an IAM role ARN, the value is returned unchanged.
789
809
 
@@ -861,7 +881,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
861
881
  }
862
882
 
863
883
  def test_connection(self):
864
- """Test the AWS connection by call AWS STS (Security Token Service) GetCallerIdentity API.
884
+ """
885
+ Test the AWS connection by call AWS STS (Security Token Service) GetCallerIdentity API.
865
886
 
866
887
  .. seealso::
867
888
  https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
@@ -898,7 +919,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
898
919
  deferrable: bool = False,
899
920
  client=None,
900
921
  ) -> Waiter:
901
- """Get a waiter by name.
922
+ """
923
+ Get a waiter by name.
902
924
 
903
925
  First checks if there is a custom waiter with the provided waiter_name and
904
926
  uses that if it exists, otherwise it will check the service client for a
@@ -969,7 +991,8 @@ class AwsGenericHook(BaseHook, Generic[BaseAwsConnection]):
969
991
 
970
992
 
971
993
  class AwsBaseHook(AwsGenericHook[Union[boto3.client, boto3.resource]]):
972
- """Base class for interact with AWS.
994
+ """
995
+ Base class for interact with AWS.
973
996
 
974
997
  This class provide a thin wrapper around the boto3 Python library.
975
998
 
@@ -1128,7 +1151,8 @@ class BaseAsyncSessionFactory(BaseSessionFactory):
1128
1151
  category=AirflowProviderDeprecationWarning,
1129
1152
  )
1130
1153
  class AwsBaseAsyncHook(AwsBaseHook):
1131
- """Interacts with AWS using aiobotocore asynchronously.
1154
+ """
1155
+ Interacts with AWS using aiobotocore asynchronously.
1132
1156
 
1133
1157
  :param aws_conn_id: The Airflow connection used for AWS credentials.
1134
1158
  If this is None or empty then the default botocore behaviour is used. If
@@ -30,7 +30,8 @@ from airflow.providers.http.hooks.http import HttpHook
30
30
 
31
31
 
32
32
  class ChimeWebhookHook(HttpHook):
33
- """Interact with Amazon Chime Webhooks to create notifications.
33
+ """
34
+ Interact with Amazon Chime Webhooks to create notifications.
34
35
 
35
36
  .. warning:: This hook is only designed to work with web hooks and not chat bots.
36
37
 
@@ -136,7 +136,8 @@ class DataSyncHook(AwsBaseHook):
136
136
  def create_task(
137
137
  self, source_location_arn: str, destination_location_arn: str, **create_task_kwargs
138
138
  ) -> str:
139
- """Create a Task between the specified source and destination LocationArns.
139
+ """
140
+ Create a Task between the specified source and destination LocationArns.
140
141
 
141
142
  .. seealso::
142
143
  - :external+boto3:py:meth:`DataSync.Client.create_task`
@@ -155,7 +156,8 @@ class DataSyncHook(AwsBaseHook):
155
156
  return task["TaskArn"]
156
157
 
157
158
  def update_task(self, task_arn: str, **update_task_kwargs) -> None:
158
- """Update a Task.
159
+ """
160
+ Update a Task.
159
161
 
160
162
  .. seealso::
161
163
  - :external+boto3:py:meth:`DataSync.Client.update_task`
@@ -166,7 +168,8 @@ class DataSyncHook(AwsBaseHook):
166
168
  self.get_conn().update_task(TaskArn=task_arn, **update_task_kwargs)
167
169
 
168
170
  def delete_task(self, task_arn: str) -> None:
169
- """Delete a Task.
171
+ """
172
+ Delete a Task.
170
173
 
171
174
  .. seealso::
172
175
  - :external+boto3:py:meth:`DataSync.Client.delete_task`
@@ -70,7 +70,8 @@ class EcrHook(AwsBaseHook):
70
70
  super().__init__(**kwargs)
71
71
 
72
72
  def get_temporary_credentials(self, registry_ids: list[str] | str | None = None) -> list[EcrCredentials]:
73
- """Get temporary credentials for Amazon ECR.
73
+ """
74
+ Get temporary credentials for Amazon ECR.
74
75
 
75
76
  .. seealso::
76
77
  - :external+boto3:py:meth:`ECR.Client.get_authorization_token`
@@ -152,42 +152,48 @@ class EcsProtocol(Protocol):
152
152
  """
153
153
 
154
154
  def run_task(self, **kwargs) -> dict:
155
- """Run a task.
155
+ """
156
+ Run a task.
156
157
 
157
158
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.run_task
158
159
  """
159
160
  ...
160
161
 
161
162
  def get_waiter(self, x: str) -> Waiter:
162
- """Get a waiter.
163
+ """
164
+ Get a waiter.
163
165
 
164
166
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.get_waiter
165
167
  """
166
168
  ...
167
169
 
168
170
  def describe_tasks(self, cluster: str, tasks) -> dict:
169
- """Describe tasks.
171
+ """
172
+ Describe tasks.
170
173
 
171
174
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.describe_tasks
172
175
  """
173
176
  ...
174
177
 
175
178
  def stop_task(self, cluster, task, reason: str) -> dict:
176
- """Stop a task.
179
+ """
180
+ Stop a task.
177
181
 
178
182
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.stop_task
179
183
  """
180
184
  ...
181
185
 
182
186
  def describe_task_definition(self, taskDefinition: str) -> dict:
183
- """Describe a task definition.
187
+ """
188
+ Describe a task definition.
184
189
 
185
190
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.describe_task_definition
186
191
  """
187
192
  ...
188
193
 
189
194
  def list_tasks(self, cluster: str, launchType: str, desiredStatus: str, family: str) -> dict:
190
- """List tasks.
195
+ """
196
+ List tasks.
191
197
 
192
198
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.list_tasks
193
199
  """
@@ -23,7 +23,8 @@ from airflow.providers.amazon.aws.hooks.base_aws import AwsBaseHook
23
23
 
24
24
 
25
25
  class GlacierHook(AwsBaseHook):
26
- """Interact with Amazon Glacier.
26
+ """
27
+ Interact with Amazon Glacier.
27
28
 
28
29
  This is a thin wrapper around
29
30
  :external+boto3:py:class:`boto3.client("glacier") <Glacier.Client>`.
@@ -40,7 +41,8 @@ class GlacierHook(AwsBaseHook):
40
41
  super().__init__(*args, **kwargs)
41
42
 
42
43
  def retrieve_inventory(self, vault_name: str) -> dict[str, Any]:
43
- """Initiate an Amazon Glacier inventory-retrieval job.
44
+ """
45
+ Initiate an Amazon Glacier inventory-retrieval job.
44
46
 
45
47
  .. seealso::
46
48
  - :external+boto3:py:meth:`Glacier.Client.initiate_job`
@@ -55,7 +57,8 @@ class GlacierHook(AwsBaseHook):
55
57
  return response
56
58
 
57
59
  def retrieve_inventory_results(self, vault_name: str, job_id: str) -> dict[str, Any]:
58
- """Retrieve the results of an Amazon Glacier inventory-retrieval job.
60
+ """
61
+ Retrieve the results of an Amazon Glacier inventory-retrieval job.
59
62
 
60
63
  .. seealso::
61
64
  - :external+boto3:py:meth:`Glacier.Client.get_job_output`
@@ -68,7 +71,8 @@ class GlacierHook(AwsBaseHook):
68
71
  return response
69
72
 
70
73
  def describe_job(self, vault_name: str, job_id: str) -> dict[str, Any]:
71
- """Retrieve the status of an Amazon S3 Glacier job.
74
+ """
75
+ Retrieve the status of an Amazon S3 Glacier job.
72
76
 
73
77
  .. seealso::
74
78
  - :external+boto3:py:meth:`Glacier.Client.describe_job`
@@ -45,7 +45,8 @@ class FirehoseHook(AwsBaseHook):
45
45
  super().__init__(*args, **kwargs)
46
46
 
47
47
  def put_records(self, records: Iterable):
48
- """Write batch records to Kinesis Firehose.
48
+ """
49
+ Write batch records to Kinesis Firehose.
49
50
 
50
51
  .. seealso::
51
52
  - :external+boto3:py:meth:`Firehose.Client.put_record_batch`
@@ -158,7 +158,8 @@ class AwsLogsHook(AwsBaseHook):
158
158
  async def describe_log_streams_async(
159
159
  self, log_group: str, stream_prefix: str, order_by: str, count: int
160
160
  ) -> dict[str, Any] | None:
161
- """Async function to get the list of log streams for the specified log group.
161
+ """
162
+ Async function to get the list of log streams for the specified log group.
162
163
 
163
164
  You can list all the log streams or filter the results by prefix. You can also control
164
165
  how the results are ordered.
@@ -193,7 +194,8 @@ class AwsLogsHook(AwsBaseHook):
193
194
  skip: int = 0,
194
195
  start_from_head: bool = True,
195
196
  ) -> AsyncGenerator[Any, dict[str, Any]]:
196
- """Yield all the available items in a single log stream.
197
+ """
198
+ Yield all the available items in a single log stream.
197
199
 
198
200
  :param log_group: The name of the log group.
199
201
  :param log_stream_name: The name of the specific stream.
@@ -27,7 +27,8 @@ from airflow.providers.amazon.aws.hooks.base_aws import AwsBaseAsyncHook, AwsBas
27
27
 
28
28
 
29
29
  class RedshiftHook(AwsBaseHook):
30
- """Interact with Amazon Redshift.
30
+ """
31
+ Interact with Amazon Redshift.
31
32
 
32
33
  This is a thin wrapper around
33
34
  :external+boto3:py:class:`boto3.client("redshift") <Redshift.Client>`.
@@ -53,7 +54,8 @@ class RedshiftHook(AwsBaseHook):
53
54
  master_user_password: str,
54
55
  params: dict[str, Any],
55
56
  ) -> dict[str, Any]:
56
- """Create a new cluster with the specified parameters.
57
+ """
58
+ Create a new cluster with the specified parameters.
57
59
 
58
60
  .. seealso::
59
61
  - :external+boto3:py:meth:`Redshift.Client.create_cluster`
@@ -80,7 +82,8 @@ class RedshiftHook(AwsBaseHook):
80
82
 
81
83
  # TODO: Wrap create_cluster_snapshot
82
84
  def cluster_status(self, cluster_identifier: str) -> str:
83
- """Get status of a cluster.
85
+ """
86
+ Get status of a cluster.
84
87
 
85
88
  .. seealso::
86
89
  - :external+boto3:py:meth:`Redshift.Client.describe_clusters`
@@ -101,7 +104,8 @@ class RedshiftHook(AwsBaseHook):
101
104
  skip_final_cluster_snapshot: bool = True,
102
105
  final_cluster_snapshot_identifier: str | None = None,
103
106
  ):
104
- """Delete a cluster and optionally create a snapshot.
107
+ """
108
+ Delete a cluster and optionally create a snapshot.
105
109
 
106
110
  .. seealso::
107
111
  - :external+boto3:py:meth:`Redshift.Client.delete_cluster`
@@ -120,7 +124,8 @@ class RedshiftHook(AwsBaseHook):
120
124
  return response["Cluster"] if response["Cluster"] else None
121
125
 
122
126
  def describe_cluster_snapshots(self, cluster_identifier: str) -> list[str] | None:
123
- """List snapshots for a cluster.
127
+ """
128
+ List snapshots for a cluster.
124
129
 
125
130
  .. seealso::
126
131
  - :external+boto3:py:meth:`Redshift.Client.describe_cluster_snapshots`
@@ -136,7 +141,8 @@ class RedshiftHook(AwsBaseHook):
136
141
  return snapshots
137
142
 
138
143
  def restore_from_cluster_snapshot(self, cluster_identifier: str, snapshot_identifier: str) -> str:
139
- """Restore a cluster from its snapshot.
144
+ """
145
+ Restore a cluster from its snapshot.
140
146
 
141
147
  .. seealso::
142
148
  - :external+boto3:py:meth:`Redshift.Client.restore_from_cluster_snapshot`
@@ -156,7 +162,8 @@ class RedshiftHook(AwsBaseHook):
156
162
  retention_period: int = -1,
157
163
  tags: list[Any] | None = None,
158
164
  ) -> str:
159
- """Create a snapshot of a cluster.
165
+ """
166
+ Create a snapshot of a cluster.
160
167
 
161
168
  .. seealso::
162
169
  - :external+boto3:py:meth:`Redshift.Client.create_cluster_snapshot`
@@ -178,7 +185,8 @@ class RedshiftHook(AwsBaseHook):
178
185
  return response["Snapshot"] if response["Snapshot"] else None
179
186
 
180
187
  def get_cluster_snapshot_status(self, snapshot_identifier: str):
181
- """Get Redshift cluster snapshot status.
188
+ """
189
+ Get Redshift cluster snapshot status.
182
190
 
183
191
  If cluster snapshot not found, *None* is returned.
184
192
 
@@ -210,7 +218,8 @@ class RedshiftAsyncHook(AwsBaseAsyncHook):
210
218
  super().__init__(*args, **kwargs)
211
219
 
212
220
  async def cluster_status(self, cluster_identifier: str, delete_operation: bool = False) -> dict[str, Any]:
213
- """Get the cluster status.
221
+ """
222
+ Get the cluster status.
214
223
 
215
224
  :param cluster_identifier: unique identifier of a cluster
216
225
  :param delete_operation: whether the method has been called as part of delete cluster operation
@@ -228,7 +237,8 @@ class RedshiftAsyncHook(AwsBaseAsyncHook):
228
237
  return {"status": "error", "message": str(error)}
229
238
 
230
239
  async def pause_cluster(self, cluster_identifier: str, poll_interval: float = 5.0) -> dict[str, Any]:
231
- """Pause the cluster.
240
+ """
241
+ Pause the cluster.
232
242
 
233
243
  :param cluster_identifier: unique identifier of a cluster
234
244
  :param poll_interval: polling period in seconds to check for the status
@@ -255,7 +265,8 @@ class RedshiftAsyncHook(AwsBaseAsyncHook):
255
265
  cluster_identifier: str,
256
266
  polling_period_seconds: float = 5.0,
257
267
  ) -> dict[str, Any]:
258
- """Resume the cluster.
268
+ """
269
+ Resume the cluster.
259
270
 
260
271
  :param cluster_identifier: unique identifier of a cluster
261
272
  :param polling_period_seconds: polling period in seconds to check for the status
@@ -284,7 +295,8 @@ class RedshiftAsyncHook(AwsBaseAsyncHook):
284
295
  flag: asyncio.Event,
285
296
  delete_operation: bool = False,
286
297
  ) -> dict[str, Any]:
287
- """Check for expected Redshift cluster state.
298
+ """
299
+ Check for expected Redshift cluster state.
288
300
 
289
301
  :param cluster_identifier: unique identifier of a cluster
290
302
  :param expected_state: expected_state example("available", "pausing", "paused"")
@@ -231,7 +231,8 @@ class RedshiftDataHook(AwsGenericHook["RedshiftDataAPIServiceClient"]):
231
231
  return pk_columns or None
232
232
 
233
233
  async def is_still_running(self, statement_id: str) -> bool:
234
- """Async function to check whether the query is still running.
234
+ """
235
+ Async function to check whether the query is still running.
235
236
 
236
237
  :param statement_id: the UUID of the statement
237
238
  """
@@ -240,7 +241,8 @@ class RedshiftDataHook(AwsGenericHook["RedshiftDataAPIServiceClient"]):
240
241
  return desc["Status"] in RUNNING_STATES
241
242
 
242
243
  async def check_query_is_finished_async(self, statement_id: str) -> bool:
243
- """Async function to check statement is finished.
244
+ """
245
+ Async function to check statement is finished.
244
246
 
245
247
  It takes statement_id, makes async connection to redshift data to get the query status
246
248
  by statement_id and returns the query status.
@@ -39,7 +39,8 @@ if TYPE_CHECKING:
39
39
 
40
40
 
41
41
  class RedshiftSQLHook(DbApiHook):
42
- """Execute statements against Amazon Redshift.
42
+ """
43
+ Execute statements against Amazon Redshift.
43
44
 
44
45
  This hook requires the redshift_conn_id connection.
45
46
 
@@ -103,7 +104,8 @@ class RedshiftSQLHook(DbApiHook):
103
104
  return conn_params
104
105
 
105
106
  def get_iam_token(self, conn: Connection) -> tuple[str, str, int]:
106
- """Retrieve a temporary password to connect to Redshift.
107
+ """
108
+ Retrieve a temporary password to connect to Redshift.
107
109
 
108
110
  Port is required. If none is provided, default is used for each service.
109
111
  """
@@ -177,7 +179,8 @@ class RedshiftSQLHook(DbApiHook):
177
179
  return create_engine(self.get_uri(), **engine_kwargs)
178
180
 
179
181
  def get_table_primary_key(self, table: str, schema: str | None = "public") -> list[str] | None:
180
- """Get the table's primary key.
182
+ """
183
+ Get the table's primary key.
181
184
 
182
185
  :param table: Name of the target table
183
186
  :param schema: Name of the target schema, public by default