# 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.importloggingimportboto3logger=logging.getLogger(__name__)
[docs]classResourceMeta:""" An object containing metadata about a resource. """def__init__(self,service_name,identifiers=None,client=None,data=None,resource_model=None,):#: (``string``) The service name, e.g. 's3'self.service_name=service_nameifidentifiersisNone:identifiers=[]#: (``list``) List of identifier namesself.identifiers=identifiers#: (:py:class:`~botocore.client.BaseClient`) Low-level Botocore clientself.client=client#: (``dict``) Loaded resource data attributesself.data=data# The resource model for that resourceself.resource_model=resource_modeldef__repr__(self):returnf'ResourceMeta(\'{self.service_name}\', identifiers={self.identifiers})'def__eq__(self,other):# Two metas are equal if their components are all equalifother.__class__.__name__!=self.__class__.__name__:returnFalsereturnself.__dict__==other.__dict__
[docs]defcopy(self):""" Create a copy of this metadata object. """params=self.__dict__.copy()service_name=params.pop('service_name')returnResourceMeta(service_name,**params)
[docs]classServiceResource:""" A base class for resources. :type client: botocore.client :param client: A low-level Botocore client instance """meta=None""" Stores metadata about this resource instance, such as the ``service_name``, the low-level ``client`` and any cached ``data`` from when the instance was hydrated. For example:: # Get a low-level client from a resource instance client = resource.meta.client response = client.operation(Param='foo') # Print the resource instance's service short name print(resource.meta.service_name) See :py:class:`ResourceMeta` for more information. """def__init__(self,*args,**kwargs):# Always work on a copy of meta, otherwise we would affect other# instances of the same subclass.self.meta=self.meta.copy()# Create a default client if none was passedifkwargs.get('client')isnotNone:self.meta.client=kwargs.get('client')else:self.meta.client=boto3.client(self.meta.service_name)# Allow setting identifiers as positional arguments in the order# in which they were defined in the ResourceJSON.fori,valueinenumerate(args):setattr(self,'_'+self.meta.identifiers[i],value)# Allow setting identifiers via keyword arguments. Here we need# extra logic to ignore other keyword arguments like ``client``.forname,valueinkwargs.items():ifname=='client':continueifnamenotinself.meta.identifiers:raiseValueError(f'Unknown keyword argument: {name}')setattr(self,'_'+name,value)# Validate that all identifiers have been set.foridentifierinself.meta.identifiers:ifgetattr(self,identifier)isNone:raiseValueError(f'Required parameter {identifier} not set')def__repr__(self):identifiers=[]foridentifierinself.meta.identifiers:identifiers.append(f'{identifier}={repr(getattr(self,identifier))}')return"{}({})".format(self.__class__.__name__,', '.join(identifiers),)def__eq__(self,other):# Should be instances of the same resource classifother.__class__.__name__!=self.__class__.__name__:returnFalse# Each of the identifiers should have the same value in both# instances, e.g. two buckets need the same name to be equal.foridentifierinself.meta.identifiers:ifgetattr(self,identifier)!=getattr(other,identifier):returnFalsereturnTruedef__hash__(self):identifiers=[]foridentifierinself.meta.identifiers:identifiers.append(getattr(self,identifier))returnhash((self.__class__.__name__,tuple(identifiers)))