Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/boto3/resources/action.py: 27%
70 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
1# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"). You
4# may not use this file except in compliance with the License. A copy of
5# the License is located at
6#
7# https://aws.amazon.com/apache2.0/
8#
9# or in the "license" file accompanying this file. This file is
10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11# ANY KIND, either express or implied. See the License for the specific
12# language governing permissions and limitations under the License.
14import logging
16from botocore import xform_name
18from boto3.docs.docstring import ActionDocstring
19from boto3.utils import inject_attribute
21from .model import Action
22from .params import create_request_parameters
23from .response import RawHandler, ResourceHandler
25logger = logging.getLogger(__name__)
28class ServiceAction:
29 """
30 A class representing a callable action on a resource, for example
31 ``sqs.get_queue_by_name(...)`` or ``s3.Bucket('foo').delete()``.
32 The action may construct parameters from existing resource identifiers
33 and may return either a raw response or a new resource instance.
35 :type action_model: :py:class`~boto3.resources.model.Action`
36 :param action_model: The action model.
38 :type factory: ResourceFactory
39 :param factory: The factory that created the resource class to which
40 this action is attached.
42 :type service_context: :py:class:`~boto3.utils.ServiceContext`
43 :param service_context: Context about the AWS service
44 """
46 def __init__(self, action_model, factory=None, service_context=None):
47 self._action_model = action_model
49 # In the simplest case we just return the response, but if a
50 # resource is defined, then we must create these before returning.
51 resource_response_model = action_model.resource
52 if resource_response_model:
53 self._response_handler = ResourceHandler(
54 search_path=resource_response_model.path,
55 factory=factory,
56 resource_model=resource_response_model,
57 service_context=service_context,
58 operation_name=action_model.request.operation,
59 )
60 else:
61 self._response_handler = RawHandler(action_model.path)
63 def __call__(self, parent, *args, **kwargs):
64 """
65 Perform the action's request operation after building operation
66 parameters and build any defined resources from the response.
68 :type parent: :py:class:`~boto3.resources.base.ServiceResource`
69 :param parent: The resource instance to which this action is attached.
70 :rtype: dict or ServiceResource or list(ServiceResource)
71 :return: The response, either as a raw dict or resource instance(s).
72 """
73 operation_name = xform_name(self._action_model.request.operation)
75 # First, build predefined params and then update with the
76 # user-supplied kwargs, which allows overriding the pre-built
77 # params if needed.
78 params = create_request_parameters(parent, self._action_model.request)
79 params.update(kwargs)
81 logger.debug(
82 'Calling %s:%s with %r',
83 parent.meta.service_name,
84 operation_name,
85 params,
86 )
88 response = getattr(parent.meta.client, operation_name)(*args, **params)
90 logger.debug('Response: %r', response)
92 return self._response_handler(parent, params, response)
95class BatchAction(ServiceAction):
96 """
97 An action which operates on a batch of items in a collection, typically
98 a single page of results from the collection's underlying service
99 operation call. For example, this allows you to delete up to 999
100 S3 objects in a single operation rather than calling ``.delete()`` on
101 each one individually.
103 :type action_model: :py:class`~boto3.resources.model.Action`
104 :param action_model: The action model.
106 :type factory: ResourceFactory
107 :param factory: The factory that created the resource class to which
108 this action is attached.
110 :type service_context: :py:class:`~boto3.utils.ServiceContext`
111 :param service_context: Context about the AWS service
112 """
114 def __call__(self, parent, *args, **kwargs):
115 """
116 Perform the batch action's operation on every page of results
117 from the collection.
119 :type parent:
120 :py:class:`~boto3.resources.collection.ResourceCollection`
121 :param parent: The collection iterator to which this action
122 is attached.
123 :rtype: list(dict)
124 :return: A list of low-level response dicts from each call.
125 """
126 service_name = None
127 client = None
128 responses = []
129 operation_name = xform_name(self._action_model.request.operation)
131 # Unlike the simple action above, a batch action must operate
132 # on batches (or pages) of items. So we get each page, construct
133 # the necessary parameters and call the batch operation.
134 for page in parent.pages():
135 params = {}
136 for index, resource in enumerate(page):
137 # There is no public interface to get a service name
138 # or low-level client from a collection, so we get
139 # these from the first resource in the collection.
140 if service_name is None:
141 service_name = resource.meta.service_name
142 if client is None:
143 client = resource.meta.client
145 create_request_parameters(
146 resource,
147 self._action_model.request,
148 params=params,
149 index=index,
150 )
152 if not params:
153 # There are no items, no need to make a call.
154 break
156 params.update(kwargs)
158 logger.debug(
159 'Calling %s:%s with %r', service_name, operation_name, params
160 )
162 response = getattr(client, operation_name)(*args, **params)
164 logger.debug('Response: %r', response)
166 responses.append(self._response_handler(parent, params, response))
168 return responses
171class WaiterAction:
172 """
173 A class representing a callable waiter action on a resource, for example
174 ``s3.Bucket('foo').wait_until_bucket_exists()``.
175 The waiter action may construct parameters from existing resource
176 identifiers.
178 :type waiter_model: :py:class`~boto3.resources.model.Waiter`
179 :param waiter_model: The action waiter.
180 :type waiter_resource_name: string
181 :param waiter_resource_name: The name of the waiter action for the
182 resource. It usually begins with a
183 ``wait_until_``
184 """
186 def __init__(self, waiter_model, waiter_resource_name):
187 self._waiter_model = waiter_model
188 self._waiter_resource_name = waiter_resource_name
190 def __call__(self, parent, *args, **kwargs):
191 """
192 Perform the wait operation after building operation
193 parameters.
195 :type parent: :py:class:`~boto3.resources.base.ServiceResource`
196 :param parent: The resource instance to which this action is attached.
197 """
198 client_waiter_name = xform_name(self._waiter_model.waiter_name)
200 # First, build predefined params and then update with the
201 # user-supplied kwargs, which allows overriding the pre-built
202 # params if needed.
203 params = create_request_parameters(parent, self._waiter_model)
204 params.update(kwargs)
206 logger.debug(
207 'Calling %s:%s with %r',
208 parent.meta.service_name,
209 self._waiter_resource_name,
210 params,
211 )
213 client = parent.meta.client
214 waiter = client.get_waiter(client_waiter_name)
215 response = waiter.wait(**params)
217 logger.debug('Response: %r', response)
220class CustomModeledAction:
221 """A custom, modeled action to inject into a resource."""
223 def __init__(self, action_name, action_model, function, event_emitter):
224 """
225 :type action_name: str
226 :param action_name: The name of the action to inject, e.g.
227 'delete_tags'
229 :type action_model: dict
230 :param action_model: A JSON definition of the action, as if it were
231 part of the resource model.
233 :type function: function
234 :param function: The function to perform when the action is called.
235 The first argument should be 'self', which will be the resource
236 the function is to be called on.
238 :type event_emitter: :py:class:`botocore.hooks.BaseEventHooks`
239 :param event_emitter: The session event emitter.
240 """
241 self.name = action_name
242 self.model = action_model
243 self.function = function
244 self.emitter = event_emitter
246 def inject(self, class_attributes, service_context, event_name, **kwargs):
247 resource_name = event_name.rsplit(".")[-1]
248 action = Action(self.name, self.model, {})
249 self.function.__name__ = self.name
250 self.function.__doc__ = ActionDocstring(
251 resource_name=resource_name,
252 event_emitter=self.emitter,
253 action_model=action,
254 service_model=service_context.service_model,
255 include_signature=False,
256 )
257 inject_attribute(class_attributes, self.name, self.function)