text: import logging
  import types
  from google.cloud import datastore
  from pymacaron_core.swagger.apipool import ApiPool
  from pymacaron.exceptions import PyMacaronException
  from pymacaron.monitor import monitor
  
  
  log = logging.getLogger(__name__)
  
  
  db = None
  
  
  GCLOUD_CLIENT = None
  
  
  # Exception raised if no item found
  class DatastoreItemNotFound(PyMacaronException):
      pass
  
  
  # keep a mapping of entity name to which pymacaron object class to instantiate
  # it into
  
  model_to_persistent_class = {}
  
  class PersistentSwaggerObject():
  
      @staticmethod
      def setup(childclass):
          """setup() is called to initialize persistence against a given Entity (aka
          table). The following class attributes must be set in the child class of
          PersistentSwaggerObject:
  
          * 'api_name': Name of the swagger api in which the searialized model is defined
  
          * 'model_name': Name of the swagger data model being serialized
  
          * 'table_name': Name of the Datastore Entity being serialized to
  
          * 'primary_key': The main indexing property of that Entity
  
          * 'secondary_keys': All other Entity properties that Datastore should
            build index for. Any property that is not the primary_key or in secondary_keys will be
            excluded form indexing.
  
          * 'gcloud_creds_path': Path to the gcloud crendential file in JSON format
  
          setup() sets the child class's attributes:
  
          * 'api': The pymacaron-core.swagger.api.API instance describing the API
            in which the serialized object is defined.
  
          * 'model': The constructor class for the Pymacaron Model being serialized.
          """
  
          if not hasattr(childclass, 'api'):
              api_name = getattr(childclass, 'api_name')
              model_name = getattr(childclass, 'model_name')
              table_name = getattr(childclass, 'table_name')
              primary_key = getattr(childclass, 'primary_key')
              secondary_keys = getattr(childclass, 'secondary_keys')
              gcloud_creds_path = getattr(childclass, 'gcloud_creds_path')
  
              assert api_name
              assert model_name
              assert table_name
              assert primary_key
              assert secondary_keys is not None
              assert gcloud_creds_path
  
              log.info("Initializing %s with api_name=%s, model_name=%s, table_name=%s, primary_key=%s, secondary_keys=%s, gcloud_creds_path=%s" % (
                  childclass.__name__,
                  api_name,
                  model_name,
                  table_name,
                  primary_key,
                  secondary_keys,
                  gcloud_creds_path,
              ))
  
              global model_to_persistent_class
              model_to_persistent_class[model_name] = childclass
  
              api = getattr(ApiPool, api_name)
              model = getattr(getattr(api, 'model'), model_name)
  
              setattr(childclass, 'api', api)
              setattr(childclass, 'model', model)
  
  
      @classmethod
      def load_from_db(childclass, key_value):
  
          PersistentSwaggerObject.setup(childclass)
  
          result = None
          with monitor(kind='Datastore', method='load_from_db'):
              client = datastore.Client.from_service_account_json(childclass.gcloud_creds_path)
              k = client.key(childclass.table_name, key_value)
              result = client.get(k)
  
          log.debug("load_from_db gave result: %s" % result)
          if result is None:
              raise DatastoreItemNotFound("Entities %s has no item with %s=%s" % (childclass.table_name, childclass.primary_key, key_value))
  
          return childclass.to_model(result)
  
  
      @classmethod
      def import_childclass(self, object):
          components = object.__persistence_class__.split('.')
          mod = __import__(components[0])
          for comp in components[1:]:
              mod = getattr(mod, comp)
          return mod
  
  
      def save_to_db(self):
          global model_to_persistent_class
  
          # Do we need to run setup on the persistence class?
          if self.__class__.__name__ not in model_to_persistent_class:
              c = PersistentSwaggerObject.import_childclass(self)
              c.setup(c)
  
          childclass = model_to_persistent_class[self.__class__.__name__]
  
          j = childclass.api.model_to_json(self)
  
          with monitor(kind='Datastore', method='save_to_db'):
              client = datastore.Client.from_service_account_json(childclass.gcloud_creds_path)
  
              # Figure out which keys not to index
              index_keys = childclass.secondary_keys + [childclass.primary_key]
              exclude_from_indexes = [k for k in list(j.keys()) if k not in index_keys]
  
              key_value = getattr(self, childclass.primary_key)
              assert key_value is not None
              key = client.key(childclass.table_name, key_value)
  
              entity = datastore.Entity(key=key, exclude_from_indexes=exclude_from_indexes)
              entity.update(j)
  
              client.put(entity)
  
  
      @classmethod
      def to_model(childclass, item):
          PersistentSwaggerObject.setup(childclass)
  
          if '__persistence_class__' in item:
              del item['__persistence_class__']
  
          # Convert from python dict to Swagger object
          item = childclass.api.json_to_model(childclass.model_name, item)
  
          # Monkey-patch this model so we can store it later
          item.save_to_db = types.MethodType(childclass.save_to_db, item)
  
          return item
  