We use cookies and similar tools to enhance your experience, provide our services, deliver relevant advertising, and make improvements. Approved third parties also use these tools to help us deliver advertising and provide certain site features.
Customize cookie preferences
We use cookies and similar tools (collectively, "cookies") for the following purposes.
Essential
Essential cookies are necessary to provide our site and services and cannot be deactivated. They are usually set in response to your actions on the site, such as setting your privacy preferences, signing in, or filling in forms.
Performance
Performance cookies provide anonymous statistics about how customers navigate our site so we can improve site experience and performance. Approved third parties may perform analytics on our behalf, but they cannot use the data for their own purposes.
Allowed
Functional
Functional cookies help us provide useful site features, remember your preferences, and display relevant content. Approved third parties may set these cookies to provide certain site features. If you do not allow these cookies, then some or all of these services may not function properly.
Allowed
Advertising
Advertising cookies may be set through our site by us or our advertising partners and help us deliver relevant marketing content. If you do not allow these cookies, you will experience less relevant advertising.
Allowed
Blocking some types of cookies may impact your experience of our sites. You may review and change your choices at any time by clicking Cookie preferences in the footer of this site. We and selected third-parties use cookies or similar technologies as specified in the AWS Cookie Notice.
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.## Licensed under the Apache License, Version 2.0 (the "License"). You# may not use this file except in compliance with the License. A copy of# the License is located at## https://aws.amazon.com/apache2.0/## or in the "license" file accompanying this file. This file is# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF# ANY KIND, either express or implied. See the License for the specific# language governing permissions and limitations under the License.importreimportjmespathfrombotocoreimportxform_namefrom..exceptionsimportResourceLoadExceptionINDEX_RE=re.compile(r'\[(.*)\]$')
[docs]defget_data_member(parent,path):""" Get a data member from a parent using a JMESPath search query, loading the parent if required. If the parent cannot be loaded and no data is present then an exception is raised. :type parent: ServiceResource :param parent: The resource instance to which contains data we are interested in. :type path: string :param path: The JMESPath expression to query :raises ResourceLoadException: When no data is present and the resource cannot be loaded. :returns: The queried data or ``None``. """# Ensure the parent has its data loaded, if possible.ifparent.meta.dataisNone:ifhasattr(parent,'load'):parent.load()else:raiseResourceLoadException(f'{parent.__class__.__name__} has no load method!')returnjmespath.search(path,parent.meta.data)
[docs]defcreate_request_parameters(parent,request_model,params=None,index=None):""" Handle request parameters that can be filled in from identifiers, resource data members or constants. By passing ``params``, you can invoke this method multiple times and build up a parameter dict over time, which is particularly useful for reverse JMESPath expressions that append to lists. :type parent: ServiceResource :param parent: The resource instance to which this action is attached. :type request_model: :py:class:`~boto3.resources.model.Request` :param request_model: The action request model. :type params: dict :param params: If set, then add to this existing dict. It is both edited in-place and returned. :type index: int :param index: The position of an item within a list :rtype: dict :return: Pre-filled parameters to be sent to the request operation. """ifparamsisNone:params={}forparaminrequest_model.params:source=param.sourcetarget=param.targetifsource=='identifier':# Resource identifier, e.g. queue.urlvalue=getattr(parent,xform_name(param.name))elifsource=='data':# If this is a data member then it may incur a load# action before returning the value.value=get_data_member(parent,param.path)elifsourcein['string','integer','boolean']:# These are hard-coded values in the definitionvalue=param.valueelifsource=='input':# This is provided by the user, so ignore it herecontinueelse:raiseNotImplementedError(f'Unsupported source type: {source}')build_param_structure(params,target,value,index)returnparams
[docs]defbuild_param_structure(params,target,value,index=None):""" This method provides a basic reverse JMESPath implementation that lets you go from a JMESPath-like string to a possibly deeply nested object. The ``params`` are mutated in-place, so subsequent calls can modify the same element by its index. >>> build_param_structure(params, 'test[0]', 1) >>> print(params) {'test': [1]} >>> build_param_structure(params, 'foo.bar[0].baz', 'hello world') >>> print(params) {'test': [1], 'foo': {'bar': [{'baz': 'hello, world'}]}} """pos=paramsparts=target.split('.')# First, split into parts like 'foo', 'bar[0]', 'baz' and process# each piece. It can either be a list or a dict, depending on if# an index like `[0]` is present. We detect this via a regular# expression, and keep track of where we are in params via the# pos variable, walking down to the last item. Once there, we# set the value.fori,partinenumerate(parts):# Is it indexing an array?result=INDEX_RE.search(part)ifresult:ifresult.group(1):ifresult.group(1)=='*':part=part[:-3]else:# We have an explicit indexindex=int(result.group(1))part=part[:-len(str(index)+'[]')]else:# Index will be set after we know the proper part# name and that it's a list instance.index=Nonepart=part[:-2]ifpartnotinposornotisinstance(pos[part],list):pos[part]=[]# This means we should append, e.g. 'foo[]'ifindexisNone:index=len(pos[part])whilelen(pos[part])<=index:# Assume it's a dict until we set the final value belowpos[part].append({})# Last item? Set the value, otherwise set the new positionifi==len(parts)-1:pos[part][index]=valueelse:# The new pos is the *item* in the array, not the array!pos=pos[part][index]else:ifpartnotinpos:pos[part]={}# Last item? Set the value, otherwise set the new positionifi==len(parts)-1:pos[part]=valueelse:pos=pos[part]