@@ -49,16 +49,21 @@ def _get_meaning(value_pb, is_list=False):
4949 """
5050 meaning = None
5151 if is_list :
52+
53+ values = (
54+ value_pb ._pb .array_value .values
55+ if hasattr (value_pb , "_pb" )
56+ else value_pb .array_value .values
57+ )
58+
5259 # An empty list will have no values, hence no shared meaning
5360 # set among them.
54- if len (value_pb . array_value . values ) == 0 :
61+ if len (values ) == 0 :
5562 return None
5663
5764 # We check among all the meanings, some of which may be None,
5865 # the rest which may be enum/int values.
59- all_meanings = [
60- _get_meaning (sub_value_pb ) for sub_value_pb in value_pb .array_value .values
61- ]
66+ all_meanings = [_get_meaning (sub_value_pb ) for sub_value_pb in values ]
6267 unique_meanings = set (all_meanings )
6368 if len (unique_meanings ) == 1 :
6469 # If there is a unique meaning, we preserve it.
@@ -119,11 +124,8 @@ def entity_from_protobuf(pb):
119124 :rtype: :class:`google.cloud.datastore.entity.Entity`
120125 :returns: The entity derived from the protobuf.
121126 """
122-
123- if not getattr (pb , "_pb" , False ):
124- # Coerce raw pb type into proto-plus pythonic type.
125- proto_pb = entity_pb2 .Entity (pb )
126- pb = pb
127+ if not isinstance (pb , entity_pb2 .Entity ):
128+ proto_pb = entity_pb2 .Entity .wrap (pb )
127129 else :
128130 proto_pb = pb
129131 pb = pb ._pb
@@ -152,7 +154,7 @@ def entity_from_protobuf(pb):
152154 if is_list and len (value ) > 0 :
153155 exclude_values = set (
154156 value_pb .exclude_from_indexes
155- for value_pb in value_pb .array_value .values
157+ for value_pb in value_pb ._pb . array_value .values
156158 )
157159 if len (exclude_values ) != 1 :
158160 raise ValueError (
@@ -402,33 +404,36 @@ def _get_value_from_value_pb(value):
402404 """
403405 if not getattr (value , "_pb" , False ):
404406 # Coerce raw pb type into proto-plus pythonic type.
405- value = entity_pb2 .Value (value )
407+ value = entity_pb2 .Value . wrap (value )
406408
407409 value_type = value ._pb .WhichOneof ("value_type" )
408410
409411 if value_type == "timestamp_value" :
412+ # Do not access `._pb` here, as that returns a Timestamp proto,
413+ # but this should return a Pythonic `DatetimeWithNanoseconds` value,
414+ # which is found at `value.timestamp_value`
410415 result = value .timestamp_value
411416
412417 elif value_type == "key_value" :
413- result = key_from_protobuf (value .key_value )
418+ result = key_from_protobuf (value ._pb . key_value )
414419
415420 elif value_type == "boolean_value" :
416- result = value .boolean_value
421+ result = value ._pb . boolean_value
417422
418423 elif value_type == "double_value" :
419- result = value .double_value
424+ result = value ._pb . double_value
420425
421426 elif value_type == "integer_value" :
422- result = value .integer_value
427+ result = value ._pb . integer_value
423428
424429 elif value_type == "string_value" :
425- result = value .string_value
430+ result = value ._pb . string_value
426431
427432 elif value_type == "blob_value" :
428- result = value .blob_value
433+ result = value ._pb . blob_value
429434
430435 elif value_type == "entity_value" :
431- result = entity_from_protobuf (value .entity_value )
436+ result = entity_from_protobuf (value ._pb . entity_value )
432437
433438 elif value_type == "array_value" :
434439 result = [
@@ -437,7 +442,7 @@ def _get_value_from_value_pb(value):
437442
438443 elif value_type == "geo_point_value" :
439444 result = GeoPoint (
440- value .geo_point_value .latitude , value .geo_point_value .longitude ,
445+ value ._pb . geo_point_value .latitude , value . _pb .geo_point_value .longitude ,
441446 )
442447
443448 elif value_type == "null_value" :
0 commit comments