Ejemplo n.º 1
0
    def commit(self):
        """Commits the transaction.

    This is called automatically upon exiting a with statement,
    however it can be called explicitly
    if you don't want to use a context manager.

    This method has necessary side-effects:

    - Sets the current connection's transaction reference to None.
    - Sets the current transaction's ID to None.
    - Updates paths for any keys that needed an automatically generated ID.
    """
        # It's possible that they called commit() already, in which case
        # we shouldn't do any committing of our own.
        if self.connection().transaction():
            result = self.connection().commit(self.dataset().id(), self.mutation())

            # For any of the auto-id entities, make sure we update their keys.
            for i, entity in enumerate(self._auto_id_entities):
                key_pb = result.insert_auto_id_key[i]
                key = Key.from_protobuf(key_pb)
                entity.key(entity.key().path(key.path()))

        # Tell the connection that the transaction is over.
        self.connection().transaction(None)

        # Clear our own ID in case this gets accidentally reused.
        self._id = None
Ejemplo n.º 2
0
    def commit(self):
        """Commits the transaction.

    This is called automatically upon exiting a with statement,
    however it can be called explicitly
    if you don't want to use a context manager.

    This method has necessary side-effects:

    - Sets the current connection's transaction reference to None.
    - Sets the current transaction's ID to None.
    - Updates paths for any keys that needed an automatically generated ID.
    """
        # It's possible that they called commit() already, in which case
        # we shouldn't do any committing of our own.
        if self.connection().transaction():
            result = self.connection().commit(self.dataset().id(),
                                              self.mutation())

            # For any of the auto-id entities, make sure we update their keys.
            for i, entity in enumerate(self._auto_id_entities):
                key_pb = result.insert_auto_id_key[i]
                key = Key.from_protobuf(key_pb)
                entity.key(entity.key().path(key.path()))

        # Tell the connection that the transaction is over.
        self.connection().transaction(None)

        # Clear our own ID in case this gets accidentally reused.
        self._id = None
Ejemplo n.º 3
0
    def save(self):
        """Save the entity in the Cloud Datastore.

        :rtype: :class:`gcloud.datastore.entity.Entity`
        :returns: The entity with a possibly updated Key.
        """
        # pylint: disable=maybe-no-member
        key_pb = self.dataset().connection().save_entity(
            dataset_id=self.dataset().id(),
            key_pb=self.key().to_protobuf(), properties=dict(self))
        # pylint: enable=maybe-no-member

        # If we are in a transaction and the current entity needs an
        # automatically assigned ID, tell the transaction where to put that.
        transaction = self.dataset().connection().transaction()
        # pylint: disable=maybe-no-member
        if transaction and self.key().is_partial():
            transaction.add_auto_id_entity(self)
        # pylint: enable=maybe-no-member

        if isinstance(key_pb, datastore_pb.Key):
            updated_key = Key.from_protobuf(key_pb)
            # Update the path (which may have been altered).
            # pylint: disable=maybe-no-member
            key = self.key().path(updated_key.path())
            # pylint: enable=maybe-no-member
            self.key(key)

        return self
Ejemplo n.º 4
0
def _get_value_from_protobuf(pb):
    """Given a protobuf for a Property, get the correct value.

    The Cloud Datastore Protobuf API returns a Property Protobuf
    which has one value set and the rest blank.
    This function retrieves the the one value provided.

    Some work is done to coerce the return value into a more useful type
    (particularly in the case of a timestamp value, or a key value).

    :type pb: :class:`gcloud.datastore.datastore_v1_pb2.Property`
    :param pb: The Property Protobuf.

    :returns: The value provided by the Protobuf.
    """

    if pb.value.HasField('timestamp_microseconds_value'):
        microseconds = pb.value.timestamp_microseconds_value
        naive = (datetime.utcfromtimestamp(0) +
                 timedelta(microseconds=microseconds))
        return naive.replace(tzinfo=pytz.utc)

    elif pb.value.HasField('key_value'):
        return Key.from_protobuf(pb.value.key_value)

    elif pb.value.HasField('boolean_value'):
        return pb.value.boolean_value

    elif pb.value.HasField('double_value'):
        return pb.value.double_value

    elif pb.value.HasField('integer_value'):
        return pb.value.integer_value

    elif pb.value.HasField('string_value'):
        return pb.value.string_value

    elif pb.value.HasField('entity_value'):
        return Entity.from_protobuf(pb.value.entity_value)

    else:
        return None
Ejemplo n.º 5
0
    def from_protobuf(cls, pb, dataset=None):
        """Factory method for creating an entity based on a protobuf.

    The protobuf should be one returned from the Cloud Datastore Protobuf API.

    :type key: :class:`gcloud.datastore.datastore_v1_pb2.Entity`
    :param key: The Protobuf representing the entity.

    :returns: The :class:`Entity` derived from the :class:`gcloud.datastore.datastore_v1_pb2.Entity`.
    """

        # This is here to avoid circular imports.
        from gcloud.datastore import helpers

        key = Key.from_protobuf(pb.key, dataset=dataset)
        entity = cls.from_key(key)

        for property_pb in pb.property:
            value = helpers.get_value_from_protobuf(property_pb)
            entity[property_pb.name] = value

        return entity
Ejemplo n.º 6
0
def get_value_from_protobuf(pb):
  """Given a protobuf for a Property, get the correct value.

  The Cloud Datastore Protobuf API returns a Property Protobuf
  which has one value set and the rest blank.
  This method retrieves the the one value provided.

  Some work is done to coerce the return value into a more useful type
  (particularly in the case of a timestamp value, or a key value).

  :type pb: :class:`gcloud.datastore.datastore_v1_pb2.Property`
  :param pb: The Property Protobuf.

  :returns: The value provided by the Protobuf.
  """

  if pb.value.HasField('timestamp_microseconds_value'):
    microseconds = pb.value.timestamp_microseconds_value
    return (datetime.utcfromtimestamp(0) +
            timedelta(microseconds=microseconds))

  elif pb.value.HasField('key_value'):
    return Key.from_protobuf(pb.value.key_value)

  elif pb.value.HasField('boolean_value'):
    return pb.value.boolean_value

  elif pb.value.HasField('double_value'):
    return pb.value.double_value

  elif pb.value.HasField('integer_value'):
    return pb.value.integer_value

  elif pb.value.HasField('string_value'):
    return pb.value.string_value

  else:
    # TODO(jjg): Should we raise a ValueError here?
    return None
Ejemplo n.º 7
0
    def from_protobuf(cls, pb, dataset=None):
        """Factory method for creating an entity based on a protobuf.

    The protobuf should be one returned from the Cloud Datastore Protobuf API.

    :type key: :class:`gcloud.datastore.datastore_v1_pb2.Entity`
    :param key: The Protobuf representing the entity.

    :returns: The :class:`Entity` derived from the :class:`gcloud.datastore.datastore_v1_pb2.Entity`.
    """

        # This is here to avoid circular imports.
        from gcloud.datastore import helpers

        key = Key.from_protobuf(pb.key, dataset=dataset)
        entity = cls.from_key(key)

        for property_pb in pb.property:
            value = helpers.get_value_from_protobuf(property_pb)
            entity[property_pb.name] = value

        return entity
Ejemplo n.º 8
0
    def save(self):
        """Save the entity in the Cloud Datastore.

    :rtype: :class:`gcloud.datastore.entity.Entity`
    :returns: The entity with a possibly updated Key.
    """
        key_pb = self.dataset().connection().save_entity(
            dataset_id=self.dataset().id(),
            key_pb=self.key().to_protobuf(),
            properties=dict(self))

        # If we are in a transaction and the current entity needs an
        # automatically assigned ID, tell the transaction where to put that.
        transaction = self.dataset().connection().transaction()
        if transaction and self.key().is_partial():
            transaction.add_auto_id_entity(self)

        if isinstance(key_pb, datastore_pb.Key):
            updated_key = Key.from_protobuf(key_pb)
            # Update the path (which may have been altered).
            key = self.key().path(updated_key.path())
            self.key(key)

        return self