Source code for gcloud.datastore.helpers

"""Helper methods for dealing with Cloud Datastore's Protobuf API."""
import calendar
from datetime import datetime, timedelta

import pytz

from gcloud.datastore.key import Key


[docs]def get_protobuf_attribute_and_value(val): """Given a value, return the protobuf attribute name and proper value. The Protobuf API uses different attribute names based on value types rather than inferring the type. This method simply determines the proper attribute name based on the type of the value provided and returns the attribute name as well as a properly formatted value. Certain value types need to be coerced into a different type (such as a `datetime.datetime` into an integer timestamp, or a `gcloud.datastore.key.Key` into a Protobuf representation. This method handles that for you. For example: >>> get_protobuf_attribute_and_value(1234) ('integer_value', 1234) >>> get_protobuf_attribute_and_value('my_string') ('string_value', 'my_string') :type val: `datetime.datetime`, :class:`gcloud.datastore.key.Key`, bool, float, integer, string :param val: The value to be scrutinized. :returns: A tuple of the attribute name and proper value type. """ if isinstance(val, datetime): name = 'timestamp_microseconds' # If the datetime is naive (no timezone), consider that it was # intended to be UTC and replace the tzinfo to that effect. if not val.tzinfo: val = val.replace(tzinfo=pytz.utc) # Regardless of what timezone is on the value, convert it to UTC. val = val.astimezone(pytz.utc) # Convert the datetime to a microsecond timestamp. value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond elif isinstance(val, Key): name, value = 'key', val.to_protobuf() elif isinstance(val, bool): name, value = 'boolean', val elif isinstance(val, float): name, value = 'double', val elif isinstance(val, (int, long)): name, value = 'integer', val elif isinstance(val, basestring): name, value = 'string', val return name + '_value', value
[docs]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