text: # 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.
  
  import logging
  
  import ibm_boto3
  
  
  logger = logging.getLogger(__name__)
  
  
  class ResourceMeta(object):
      """
      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_name
  
          if identifiers is None:
              identifiers = []
          #: (``list``) List of identifier names
          self.identifiers = identifiers
  
          #: (:py:class:`~ibm_botocore.client.BaseClient`) Low-level Botocore client
          self.client = client
          #: (``dict``) Loaded resource data attributes
          self.data = data
  
          # The resource model for that resource
          self.resource_model = resource_model
  
      def __repr__(self):
          return 'ResourceMeta(\'{0}\', identifiers={1})'.format(
              self.service_name, self.identifiers)
  
      def __eq__(self, other):
          # Two metas are equal if their components are all equal
          if other.__class__.__name__ != self.__class__.__name__:
              return False
  
          return self.__dict__ == other.__dict__
  
      def copy(self):
          """
          Create a copy of this metadata object.
          """
          params = self.__dict__.copy()
          service_name = params.pop('service_name')
          return ResourceMeta(service_name, **params)
  
  
  class ServiceResource(object):
      """
      A base class for resources.
  
      :type client: ibm_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 passed
          if kwargs.get('client') is not None:
              self.meta.client = kwargs.get('client')
          else:
              self.meta.client = ibm_boto3.client(self.meta.service_name)
  
          # Allow setting identifiers as positional arguments in the order
          # in which they were defined in the ResourceJSON.
          for i, value in enumerate(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``.
          for name, value in kwargs.items():
              if name == 'client':
                  continue
  
              if name not in self.meta.identifiers:
                  raise ValueError('Unknown keyword argument: {0}'.format(name))
  
              setattr(self, '_' + name, value)
  
          # Validate that all identifiers have been set.
          for identifier in self.meta.identifiers:
              if getattr(self, identifier) is None:
                  raise ValueError(
                      'Required parameter {0} not set'.format(identifier))
  
      def __repr__(self):
          identifiers = []
          for identifier in self.meta.identifiers:
              identifiers.append('{0}={1}'.format(
                  identifier, repr(getattr(self, identifier))))
          return "{0}({1})".format(
              self.__class__.__name__,
              ', '.join(identifiers),
          )
  
      def __eq__(self, other):
          # Should be instances of the same resource class
          if other.__class__.__name__ != self.__class__.__name__:
              return False
  
          # Each of the identifiers should have the same value in both
          # instances, e.g. two buckets need the same name to be equal.
          for identifier in self.meta.identifiers:
              if getattr(self, identifier) != getattr(other, identifier):
                  return False
  
          return True
  
      def __hash__(self):
          identifiers = []
          for identifier in self.meta.identifiers:
              identifiers.append(getattr(self, identifier))
          return hash((self.__class__.__name__, tuple(identifiers)))
  