in boto3/resources/response.py [0:0]
def __call__(self, parent, params, response):
"""
:type parent: ServiceResource
:param parent: The resource instance to which this action is attached.
:type params: dict
:param params: Request parameters sent to the service.
:type response: dict
:param response: Low-level operation response.
"""
resource_name = self.resource_model.type
json_definition = self.service_context.resource_json_definitions.get(
resource_name)
# Load the new resource class that will result from this action.
resource_cls = self.factory.load_from_definition(
resource_name=resource_name,
single_resource_json_definition=json_definition,
service_context=self.service_context
)
raw_response = response
search_response = None
# Anytime a path is defined, it means the response contains the
# resource's attributes, so resource_data gets set here. It
# eventually ends up in resource.meta.data, which is where
# the attribute properties look for data.
if self.search_path:
search_response = jmespath.search(self.search_path, raw_response)
# First, we parse all the identifiers, then create the individual
# response resources using them. Any identifiers that are lists
# will have one item consumed from the front of the list for each
# resource that is instantiated. Items which are not a list will
# be set as the same value on each new resource instance.
identifiers = dict(build_identifiers(
self.resource_model.identifiers, parent, params,
raw_response))
# If any of the identifiers is a list, then the response is plural
plural = [v for v in identifiers.values() if isinstance(v, list)]
if plural:
response = []
# The number of items in an identifier that is a list will
# determine how many resource instances to create.
for i in range(len(plural[0])):
# Response item data is *only* available if a search path
# was given. This prevents accidentally loading unrelated
# data that may be in the response.
response_item = None
if search_response:
response_item = search_response[i]
response.append(
self.handle_response_item(resource_cls, parent,
identifiers, response_item))
elif all_not_none(identifiers.values()):
# All identifiers must always exist, otherwise the resource
# cannot be instantiated.
response = self.handle_response_item(
resource_cls, parent, identifiers, search_response)
else:
# The response should be empty, but that may mean an
# empty dict, list, or None based on whether we make
# a remote service call and what shape it is expected
# to return.
response = None
if self.operation_name is not None:
# A remote service call was made, so try and determine
# its shape.
response = build_empty_response(
self.search_path, self.operation_name,
self.service_context.service_model)
return response