3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
21 """Utilities for converting between v3 and v4 datastore protocol buffers.
23 This module is internal and should not be used by client applications.
41 from google
.appengine
.datastore
import entity_pb
43 from google
.appengine
.datastore
import entity_v4_pb
47 MEANING_ATOM_CATEGORY
= 1
49 MEANING_ATOM_TITLE
= 3
50 MEANING_ATOM_CONTENT
= 4
51 MEANING_ATOM_SUMMARY
= 5
52 MEANING_ATOM_AUTHOR
= 6
54 MEANING_GEORSS_POINT
= 9
56 MEANING_GD_PHONENUMBER
= 11
57 MEANING_GD_POSTALADDRESS
= 12
60 MEANING_BYTESTRING
= 16
61 MEANING_INDEX_ONLY
= 18
62 MEANING_PREDEFINED_ENTITY_USER
= 20
63 MEANING_PREDEFINED_ENTITY_POINT
= 21
67 URI_MEANING_ZLIB
= 'ZLIB'
72 MAX_INDEXED_STRING_CHARS
= 500
73 MAX_INDEXED_BLOB_BYTES
= 500
74 MAX_PARTITION_ID_LENGTH
= 100
75 MAX_DATASET_ID_SECTION_LENGTH
= 100
79 MAX_DATASET_ID_LENGTH
= MAX_DATASET_ID_SECTION_LENGTH
* 3 + 2
80 MAX_KEY_PATH_LENGTH
= 100
87 PROPERTY_NAME_EMAIL
= 'email'
88 PROPERTY_NAME_AUTH_DOMAIN
= 'auth_domain'
89 PROPERTY_NAME_USER_ID
= 'user_id'
90 PROPERTY_NAME_INTERNAL_ID
= 'internal_id'
91 PROPERTY_NAME_FEDERATED_IDENTITY
= 'federated_identity'
92 PROPERTY_NAME_FEDERATED_PROVIDER
= 'federated_provider'
95 PROPERTY_NAME_KEY
= '__key__'
100 def v4_key_to_string(v4_key
):
101 """Generates a string representing a key's path.
103 The output makes no effort to qualify special characters in strings.
105 The key need not be valid, but if any of the key path elements have
106 both a name and an ID the name is ignored.
109 v4_key: an entity_v4_pb.Key
112 a string representing the key's path
114 path_element_strings
= []
115 for path_element
in v4_key
.path_element_list():
116 if path_element
.has_id():
117 id_or_name
= str(path_element
.id())
118 elif path_element
.has_name():
119 id_or_name
= path_element
.name()
122 path_element_strings
.append('%s: %s' % (path_element
.kind(), id_or_name
))
123 return '[%s]' % ', '.join(path_element_strings
)
126 def is_complete_v4_key(v4_key
):
127 """Returns True if a key specifies an ID or name, False otherwise.
130 v4_key: an entity_v4_pb.Key
133 True if the key specifies an ID or name, False otherwise.
135 assert len(v4_key
.path_element_list()) >= 1
136 last_element
= v4_key
.path_element(len(v4_key
.path_element_list()) - 1)
137 return last_element
.has_id() or last_element
.has_name()
140 def is_valid_utf8(s
):
144 except UnicodeDecodeError:
148 def check_conversion(condition
, message
):
149 """Asserts a conversion condition and raises an error if it's not met.
152 condition: (boolean) condition to enforce
153 message: error message
156 InvalidConversionError: if condition is not met
159 raise InvalidConversionError(message
)
163 class InvalidConversionError(Exception):
164 """Raised when conversion fails."""
168 class _EntityConverter(object):
169 """Converter for entities and keys."""
171 def v4_to_v3_reference(self
, v4_key
, v3_ref
):
172 """Converts a v4 Key to a v3 Reference.
175 v4_key: an entity_v4_pb.Key
176 v3_ref: an entity_pb.Reference to populate
179 if v4_key
.has_partition_id():
180 if v4_key
.partition_id().has_dataset_id():
181 v3_ref
.set_app(v4_key
.partition_id().dataset_id())
182 if v4_key
.partition_id().has_namespace():
183 v3_ref
.set_name_space(v4_key
.partition_id().namespace())
184 for v4_element
in v4_key
.path_element_list():
185 v3_element
= v3_ref
.mutable_path().add_element()
186 v3_element
.set_type(v4_element
.kind())
187 if v4_element
.has_id():
188 v3_element
.set_id(v4_element
.id())
189 if v4_element
.has_name():
190 v3_element
.set_name(v4_element
.name())
192 def v4_to_v3_references(self
, v4_keys
):
193 """Converts a list of v4 Keys to a list of v3 References.
196 v4_keys: a list of entity_v4_pb.Key objects
199 a list of entity_pb.Reference objects
202 for v4_key
in v4_keys
:
203 v3_ref
= entity_pb
.Reference()
204 self
.v4_to_v3_reference(v4_key
, v3_ref
)
205 v3_refs
.append(v3_ref
)
208 def v3_to_v4_key(self
, v3_ref
, v4_key
):
209 """Converts a v3 Reference to a v4 Key.
212 v3_ref: an entity_pb.Reference
213 v4_key: an entity_v4_pb.Key to populate
218 v4_key
.mutable_partition_id().set_dataset_id(v3_ref
.app())
219 if v3_ref
.name_space():
220 v4_key
.mutable_partition_id().set_namespace(v3_ref
.name_space())
221 for v3_element
in v3_ref
.path().element_list():
222 v4_element
= v4_key
.add_path_element()
223 v4_element
.set_kind(v3_element
.type())
224 if v3_element
.has_id():
225 v4_element
.set_id(v3_element
.id())
226 if v3_element
.has_name():
227 v4_element
.set_name(v3_element
.name())
229 def v3_to_v4_keys(self
, v3_refs
):
230 """Converts a list of v3 References to a list of v4 Keys.
233 v3_refs: a list of entity_pb.Reference objects
236 a list of entity_v4_pb.Key objects
239 for v3_ref
in v3_refs
:
240 v4_key
= entity_v4_pb
.Key()
241 self
.v3_to_v4_key(v3_ref
, v4_key
)
242 v4_keys
.append(v4_key
)
245 def v4_to_v3_entity(self
, v4_entity
, v3_entity
):
246 """Converts a v4 Entity to a v3 EntityProto.
249 v4_entity: an entity_v4_pb.Entity
250 v3_entity: an entity_pb.EntityProto to populate
253 for v4_property
in v4_entity
.property_list():
254 property_name
= v4_property
.name()
255 v4_value
= v4_property
.value()
256 if v4_value
.list_value_list():
257 for v4_sub_value
in v4_value
.list_value_list():
258 self
.__add
_v
3_property
(property_name
, True, v4_sub_value
, v3_entity
)
260 self
.__add
_v
3_property
(property_name
, False, v4_value
, v3_entity
)
261 if v4_entity
.has_key():
262 v4_key
= v4_entity
.key()
263 self
.v4_to_v3_reference(v4_key
, v3_entity
.mutable_key())
264 v3_ref
= v3_entity
.key()
265 self
.v3_reference_to_group(v3_ref
, v3_entity
.mutable_entity_group())
271 def v3_to_v4_entity(self
, v3_entity
, v4_entity
):
272 """Converts a v3 EntityProto to a v4 Entity.
275 v3_entity: an entity_pb.EntityProto
276 v4_entity: an entity_v4_pb.Proto to populate
279 self
.v3_to_v4_key(v3_entity
.key(), v4_entity
.mutable_key())
280 if not v3_entity
.key().has_app():
282 v4_entity
.clear_key()
288 for v3_property
in v3_entity
.property_list():
289 self
.__add
_v
4_property
_to
_entity
(v4_entity
, v4_properties
, v3_property
,
291 for v3_property
in v3_entity
.raw_property_list():
292 self
.__add
_v
4_property
_to
_entity
(v4_entity
, v4_properties
, v3_property
,
295 def v4_value_to_v3_property_value(self
, v4_value
, v3_value
):
296 """Converts a v4 Value to a v3 PropertyValue.
299 v4_value: an entity_v4_pb.Value
300 v3_value: an entity_pb.PropertyValue to populate
303 if v4_value
.has_boolean_value():
304 v3_value
.set_booleanvalue(v4_value
.boolean_value())
305 elif v4_value
.has_integer_value():
306 v3_value
.set_int64value(v4_value
.integer_value())
307 elif v4_value
.has_double_value():
308 v3_value
.set_doublevalue(v4_value
.double_value())
309 elif v4_value
.has_timestamp_microseconds_value():
310 v3_value
.set_int64value(v4_value
.timestamp_microseconds_value())
311 elif v4_value
.has_key_value():
312 v3_ref
= entity_pb
.Reference()
313 self
.v4_to_v3_reference(v4_value
.key_value(), v3_ref
)
314 self
.v3_reference_to_v3_property_value(v3_ref
, v3_value
)
315 elif v4_value
.has_blob_key_value():
316 v3_value
.set_stringvalue(v4_value
.blob_key_value())
317 elif v4_value
.has_string_value():
318 v3_value
.set_stringvalue(v4_value
.string_value())
319 elif v4_value
.has_blob_value():
320 v3_value
.set_stringvalue(v4_value
.blob_value())
321 elif v4_value
.has_entity_value():
322 v4_entity_value
= v4_value
.entity_value()
323 v4_meaning
= v4_value
.meaning()
324 if (v4_meaning
== MEANING_GEORSS_POINT
325 or v4_meaning
== MEANING_PREDEFINED_ENTITY_POINT
):
326 self
.__v
4_to
_v
3_point
_value
(v4_entity_value
,
327 v3_value
.mutable_pointvalue())
328 elif v4_meaning
== MEANING_PREDEFINED_ENTITY_USER
:
329 self
.__v
4_to
_v
3_user
_value
(v4_entity_value
,
330 v3_value
.mutable_uservalue())
332 v3_entity_value
= entity_pb
.EntityProto()
333 self
.v4_to_v3_entity(v4_entity_value
, v3_entity_value
)
334 v3_value
.set_stringvalue(v3_entity_value
.SerializePartialToString())
335 elif v4_value
.has_geo_point_value():
336 point_value
= v3_value
.mutable_pointvalue()
337 point_value
.set_x(v4_value
.geo_point_value().latitude())
338 point_value
.set_y(v4_value
.geo_point_value().longitude())
343 def v3_property_to_v4_value(self
, v3_property
, indexed
, v4_value
):
344 """Converts a v3 Property to a v4 Value.
347 v3_property: an entity_pb.Property
348 indexed: whether the v3 property is indexed
349 v4_value: an entity_v4_pb.Value to populate
352 v3_property_value
= v3_property
.value()
353 v3_meaning
= v3_property
.meaning()
354 v3_uri_meaning
= None
355 if v3_property
.meaning_uri():
356 v3_uri_meaning
= v3_property
.meaning_uri()
358 if not self
.__is
_v
3_property
_value
_union
_valid
(v3_property_value
):
362 v3_uri_meaning
= None
363 elif v3_meaning
== entity_pb
.Property
.NO_MEANING
:
365 elif not self
.__is
_v
3_property
_value
_meaning
_valid
(v3_property_value
,
370 is_zlib_value
= False
372 if v3_uri_meaning
== URI_MEANING_ZLIB
:
373 if v3_property_value
.has_stringvalue():
375 if v3_meaning
!= entity_pb
.Property
.BLOB
:
377 v3_meaning
= entity_pb
.Property
.BLOB
384 if v3_property_value
.has_booleanvalue():
385 v4_value
.set_boolean_value(v3_property_value
.booleanvalue())
386 elif v3_property_value
.has_int64value():
387 if v3_meaning
== entity_pb
.Property
.GD_WHEN
:
388 v4_value
.set_timestamp_microseconds_value(
389 v3_property_value
.int64value())
392 v4_value
.set_integer_value(v3_property_value
.int64value())
393 elif v3_property_value
.has_doublevalue():
394 v4_value
.set_double_value(v3_property_value
.doublevalue())
395 elif v3_property_value
.has_referencevalue():
396 v3_ref
= entity_pb
.Reference()
397 self
.__v
3_reference
_value
_to
_v
3_reference
(
398 v3_property_value
.referencevalue(), v3_ref
)
399 self
.v3_to_v4_key(v3_ref
, v4_value
.mutable_key_value())
400 elif v3_property_value
.has_stringvalue():
401 if v3_meaning
== entity_pb
.Property
.ENTITY_PROTO
:
402 serialized_entity_v3
= v3_property_value
.stringvalue()
403 v3_entity
= entity_pb
.EntityProto()
406 v3_entity
.ParsePartialFromString(serialized_entity_v3
)
407 self
.v3_to_v4_entity(v3_entity
, v4_value
.mutable_entity_value())
409 elif (v3_meaning
== entity_pb
.Property
.BLOB
410 or v3_meaning
== entity_pb
.Property
.BYTESTRING
):
411 v4_value
.set_blob_value(v3_property_value
.stringvalue())
413 if indexed
or v3_meaning
== entity_pb
.Property
.BLOB
:
416 string_value
= v3_property_value
.stringvalue()
417 if is_valid_utf8(string_value
):
418 if v3_meaning
== entity_pb
.Property
.BLOBKEY
:
419 v4_value
.set_blob_key_value(string_value
)
422 v4_value
.set_string_value(string_value
)
425 v4_value
.set_blob_value(string_value
)
427 if v3_meaning
!= entity_pb
.Property
.INDEX_VALUE
:
431 elif v3_property_value
.has_pointvalue():
432 if v3_meaning
== MEANING_GEORSS_POINT
:
433 point_value
= v3_property_value
.pointvalue()
434 v4_value
.mutable_geo_point_value().set_latitude(point_value
.x())
435 v4_value
.mutable_geo_point_value().set_longitude(point_value
.y())
437 self
.__v
3_to
_v
4_point
_entity
(v3_property_value
.pointvalue(),
438 v4_value
.mutable_entity_value())
439 v4_value
.set_meaning(MEANING_PREDEFINED_ENTITY_POINT
)
442 elif v3_property_value
.has_uservalue():
443 self
.__v
3_to
_v
4_user
_entity
(v3_property_value
.uservalue(),
444 v4_value
.mutable_entity_value())
445 v4_value
.set_meaning(MEANING_PREDEFINED_ENTITY_USER
)
451 v4_value
.set_meaning(MEANING_ZLIB
)
453 v4_value
.set_meaning(v3_meaning
)
456 if indexed
!= v4_value
.indexed():
457 v4_value
.set_indexed(indexed
)
459 def __v4_to_v3_property(self
, property_name
, is_multi
, v4_value
, v3_property
):
460 """Converts info from a v4 Property to a v3 Property.
462 v4_value must not have a list_value.
465 property_name: the name of the property
466 is_multi: whether the property contains multiple values
467 v4_value: an entity_v4_pb.Value
468 v3_property: an entity_pb.Property to populate
470 assert not v4_value
.list_value_list(), 'v4 list_value not convertable to v3'
472 v3_property
.set_name(property_name
)
473 v3_property
.set_multiple(is_multi
)
474 self
.v4_value_to_v3_property_value(v4_value
, v3_property
.mutable_value())
477 if v4_value
.has_meaning():
478 v4_meaning
= v4_value
.meaning()
480 if v4_value
.has_timestamp_microseconds_value():
481 v3_property
.set_meaning(entity_pb
.Property
.GD_WHEN
)
482 elif v4_value
.has_blob_key_value():
483 v3_property
.set_meaning(entity_pb
.Property
.BLOBKEY
)
484 elif v4_value
.has_blob_value():
485 if v4_meaning
== MEANING_ZLIB
:
486 v3_property
.set_meaning_uri(URI_MEANING_ZLIB
)
487 if v4_meaning
== entity_pb
.Property
.BYTESTRING
:
488 if v4_value
.indexed():
493 if v4_value
.indexed():
494 v3_property
.set_meaning(entity_pb
.Property
.BYTESTRING
)
496 v3_property
.set_meaning(entity_pb
.Property
.BLOB
)
498 elif v4_value
.has_entity_value():
499 if v4_meaning
!= MEANING_GEORSS_POINT
:
500 if (v4_meaning
!= MEANING_PREDEFINED_ENTITY_POINT
501 and v4_meaning
!= MEANING_PREDEFINED_ENTITY_USER
):
502 v3_property
.set_meaning(entity_pb
.Property
.ENTITY_PROTO
)
504 elif v4_value
.has_geo_point_value():
505 v3_property
.set_meaning(MEANING_GEORSS_POINT
)
509 if v4_meaning
is not None:
510 v3_property
.set_meaning(v4_meaning
)
512 def __add_v3_property(self
, property_name
, is_multi
, v4_value
, v3_entity
):
513 """Adds a v3 Property to an Entity based on information from a v4 Property.
516 property_name: the name of the property
517 is_multi: whether the property contains multiple values
518 v4_value: an entity_v4_pb.Value
519 v3_entity: an entity_pb.EntityProto
521 if v4_value
.indexed():
522 self
.__v
4_to
_v
3_property
(property_name
, is_multi
, v4_value
,
523 v3_entity
.add_property())
525 self
.__v
4_to
_v
3_property
(property_name
, is_multi
, v4_value
,
526 v3_entity
.add_raw_property())
528 def __build_name_to_v4_property_map(self
, v4_entity
):
530 for prop
in v4_entity
.property_list():
531 property_map
[prop
.name()] = prop
534 def __add_v4_property_to_entity(self
, v4_entity
, property_map
, v3_property
,
536 """Adds a v4 Property to an entity or modifies an existing one.
538 property_map is used to track of properties that have already been added.
539 The same dict should be used for all of an entity's properties.
542 v4_entity: an entity_v4_pb.Entity
543 property_map: a dict of name -> v4_property
544 v3_property: an entity_pb.Property to convert to v4 and add to the dict
545 indexed: whether the property is indexed
547 property_name
= v3_property
.name()
548 if property_name
in property_map
:
549 v4_property
= property_map
[property_name
]
551 v4_property
= v4_entity
.add_property()
552 v4_property
.set_name(property_name
)
553 property_map
[property_name
] = v4_property
554 if v3_property
.multiple():
555 self
.v3_property_to_v4_value(v3_property
, indexed
,
556 v4_property
.mutable_value().add_list_value())
558 self
.v3_property_to_v4_value(v3_property
, indexed
,
559 v4_property
.mutable_value())
561 def __get_v4_integer_value(self
, v4_property
):
562 """Returns an integer value from a v4 Property.
565 v4_property: an entity_v4_pb.Property
571 InvalidConversionError: if the property doesn't contain an integer value
573 check_conversion(v4_property
.value().has_integer_value(),
574 'Property does not contain an integer value.')
575 return v4_property
.value().integer_value()
577 def __get_v4_double_value(self
, v4_property
):
578 """Returns a double value from a v4 Property.
581 v4_property: an entity_v4_pb.Property
587 InvalidConversionError: if the property doesn't contain a double value
589 check_conversion(v4_property
.value().has_double_value(),
590 'Property does not contain a double value.')
591 return v4_property
.value().double_value()
593 def __get_v4_string_value(self
, v4_property
):
594 """Returns an string value from a v4 Property.
597 v4_property: an entity_v4_pb.Property
603 InvalidConversionError: if the property doesn't contain a string value
605 check_conversion(v4_property
.value().has_string_value(),
606 'Property does not contain a string value.')
607 return v4_property
.value().string_value()
609 def __v4_integer_property(self
, name
, value
, indexed
):
610 """Creates a single-integer-valued v4 Property.
613 name: the property name
614 value: the integer value of the property
615 indexed: whether the value should be indexed
618 an entity_v4_pb.Property
620 v4_property
= entity_v4_pb
.Property()
621 v4_property
.set_name(name
)
622 v4_value
= v4_property
.mutable_value()
623 v4_value
.set_indexed(indexed
)
624 v4_value
.set_integer_value(value
)
627 def __v4_double_property(self
, name
, value
, indexed
):
628 """Creates a single-double-valued v4 Property.
631 name: the property name
632 value: the double value of the property
633 indexed: whether the value should be indexed
636 an entity_v4_pb.Property
638 v4_property
= entity_v4_pb
.Property()
639 v4_property
.set_name(name
)
640 v4_value
= v4_property
.mutable_value()
641 v4_value
.set_indexed(indexed
)
642 v4_value
.set_double_value(value
)
645 def __v4_string_property(self
, name
, value
, indexed
):
646 """Creates a single-string-valued v4 Property.
649 name: the property name
650 value: the string value of the property
651 indexed: whether the value should be indexed
654 an entity_v4_pb.Property
656 v4_property
= entity_v4_pb
.Property()
657 v4_property
.set_name(name
)
658 v4_value
= v4_property
.mutable_value()
659 v4_value
.set_indexed(indexed
)
660 v4_value
.set_string_value(value
)
663 def __v4_to_v3_point_value(self
, v4_point_entity
, v3_point_value
):
664 """Converts a v4 point Entity to a v3 PointValue.
667 v4_point_entity: an entity_v4_pb.Entity representing a point
668 v3_point_value: an entity_pb.Property_PointValue to populate
670 v3_point_value
.Clear()
671 name_to_v4_property
= self
.__build
_name
_to
_v
4_property
_map
(v4_point_entity
)
672 v3_point_value
.set_x(
673 self
.__get
_v
4_double
_value
(name_to_v4_property
['x']))
674 v3_point_value
.set_y(
675 self
.__get
_v
4_double
_value
(name_to_v4_property
['y']))
677 def __v3_to_v4_point_entity(self
, v3_point_value
, v4_entity
):
678 """Converts a v3 UserValue to a v4 user Entity.
681 v3_point_value: an entity_pb.Property_PointValue
682 v4_entity: an entity_v4_pb.Entity to populate
685 v4_entity
.property_list().append(
686 self
.__v
4_double
_property
(PROPERTY_NAME_X
, v3_point_value
.x(), False))
687 v4_entity
.property_list().append(
688 self
.__v
4_double
_property
(PROPERTY_NAME_Y
, v3_point_value
.y(), False))
690 def __v4_to_v3_user_value(self
, v4_user_entity
, v3_user_value
):
691 """Converts a v4 user Entity to a v3 UserValue.
694 v4_user_entity: an entity_v4_pb.Entity representing a user
695 v3_user_value: an entity_pb.Property_UserValue to populate
697 v3_user_value
.Clear()
698 name_to_v4_property
= self
.__build
_name
_to
_v
4_property
_map
(v4_user_entity
)
700 v3_user_value
.set_email(self
.__get
_v
4_string
_value
(
701 name_to_v4_property
[PROPERTY_NAME_EMAIL
]))
702 v3_user_value
.set_auth_domain(self
.__get
_v
4_string
_value
(
703 name_to_v4_property
[PROPERTY_NAME_AUTH_DOMAIN
]))
704 if PROPERTY_NAME_USER_ID
in name_to_v4_property
:
705 v3_user_value
.set_obfuscated_gaiaid(
706 self
.__get
_v
4_string
_value
(
707 name_to_v4_property
[PROPERTY_NAME_USER_ID
]))
708 if PROPERTY_NAME_INTERNAL_ID
in name_to_v4_property
:
709 v3_user_value
.set_gaiaid(self
.__get
_v
4_integer
_value
(
710 name_to_v4_property
[PROPERTY_NAME_INTERNAL_ID
]))
713 v3_user_value
.set_gaiaid(0)
714 if PROPERTY_NAME_FEDERATED_IDENTITY
in name_to_v4_property
:
715 v3_user_value
.set_federated_identity(
716 self
.__get
_v
4_string
_value
(name_to_v4_property
[
717 PROPERTY_NAME_FEDERATED_IDENTITY
]))
718 if PROPERTY_NAME_FEDERATED_PROVIDER
in name_to_v4_property
:
719 v3_user_value
.set_federated_provider(
720 self
.__get
_v
4_string
_value
(name_to_v4_property
[
721 PROPERTY_NAME_FEDERATED_PROVIDER
]))
723 def __v3_to_v4_user_entity(self
, v3_user_value
, v4_entity
):
724 """Converts a v3 UserValue to a v4 user Entity.
727 v3_user_value: an entity_pb.Property_UserValue
728 v4_entity: an entity_v4_pb.Entity to populate
731 v4_entity
.property_list().append(
732 self
.__v
4_string
_property
(PROPERTY_NAME_EMAIL
, v3_user_value
.email(),
734 v4_entity
.property_list().append(self
.__v
4_string
_property
(
735 PROPERTY_NAME_AUTH_DOMAIN
,
736 v3_user_value
.auth_domain(), False))
738 if v3_user_value
.gaiaid() != 0:
739 v4_entity
.property_list().append(self
.__v
4_integer
_property
(
740 PROPERTY_NAME_INTERNAL_ID
,
741 v3_user_value
.gaiaid(),
743 if v3_user_value
.has_obfuscated_gaiaid():
744 v4_entity
.property_list().append(self
.__v
4_string
_property
(
745 PROPERTY_NAME_USER_ID
,
746 v3_user_value
.obfuscated_gaiaid(),
748 if v3_user_value
.has_federated_identity():
749 v4_entity
.property_list().append(self
.__v
4_string
_property
(
750 PROPERTY_NAME_FEDERATED_IDENTITY
,
751 v3_user_value
.federated_identity(),
753 if v3_user_value
.has_federated_provider():
754 v4_entity
.property_list().append(self
.__v
4_string
_property
(
755 PROPERTY_NAME_FEDERATED_PROVIDER
,
756 v3_user_value
.federated_provider(),
759 def __is_v3_property_value_union_valid(self
, v3_property_value
):
760 """Returns True if the v3 PropertyValue's union is valid."""
761 num_sub_values
= (v3_property_value
.has_booleanvalue()
762 + v3_property_value
.has_int64value()
763 + v3_property_value
.has_doublevalue()
764 + v3_property_value
.has_referencevalue()
765 + v3_property_value
.has_stringvalue()
766 + v3_property_value
.has_pointvalue()
767 + v3_property_value
.has_uservalue())
768 return num_sub_values
<= 1
770 def __is_v3_property_value_meaning_valid(self
, v3_property_value
, v3_meaning
):
771 """Returns True if the v3 PropertyValue's type value matches its meaning."""
774 def HasStringValue():
775 return v3_property_value
.has_stringvalue()
777 return v3_property_value
.has_int64value()
779 return v3_property_value
.has_pointvalue()
783 entity_pb
.Property
.NO_MEANING
: ReturnTrue
,
784 entity_pb
.Property
.INDEX_VALUE
: ReturnTrue
,
785 entity_pb
.Property
.BLOB
: HasStringValue
,
786 entity_pb
.Property
.TEXT
: HasStringValue
,
787 entity_pb
.Property
.BYTESTRING
: HasStringValue
,
788 entity_pb
.Property
.ATOM_CATEGORY
: HasStringValue
,
789 entity_pb
.Property
.ATOM_LINK
: HasStringValue
,
790 entity_pb
.Property
.ATOM_TITLE
: HasStringValue
,
791 entity_pb
.Property
.ATOM_CONTENT
: HasStringValue
,
792 entity_pb
.Property
.ATOM_SUMMARY
: HasStringValue
,
793 entity_pb
.Property
.ATOM_AUTHOR
: HasStringValue
,
794 entity_pb
.Property
.GD_EMAIL
: HasStringValue
,
795 entity_pb
.Property
.GD_IM
: HasStringValue
,
796 entity_pb
.Property
.GD_PHONENUMBER
: HasStringValue
,
797 entity_pb
.Property
.GD_POSTALADDRESS
: HasStringValue
,
798 entity_pb
.Property
.BLOBKEY
: HasStringValue
,
799 entity_pb
.Property
.ENTITY_PROTO
: HasStringValue
,
800 entity_pb
.Property
.GD_WHEN
: HasInt64Value
,
801 entity_pb
.Property
.GD_RATING
: HasInt64Value
,
802 entity_pb
.Property
.GEORSS_POINT
: HasPointValue
,
804 default
= ReturnFalse
805 return value_checkers
.get(v3_meaning
, default
)()
807 def __v3_reference_has_id_or_name(self
, v3_ref
):
808 """Determines if a v3 Reference specifies an ID or name.
811 v3_ref: an entity_pb.Reference
814 boolean: True if the last path element specifies an ID or name.
817 assert path
.element_size() >= 1
818 last_element
= path
.element(path
.element_size() - 1)
819 return last_element
.has_id() or last_element
.has_name()
821 def v3_reference_to_group(self
, v3_ref
, group
):
822 """Converts a v3 Reference to a v3 Path representing the entity group.
824 The entity group is represented as an entity_pb.Path containing only the
825 first element in the provided Reference.
828 v3_ref: an entity_pb.Reference
829 group: an entity_pb.Path to populate
833 assert path
.element_size() >= 1
834 group
.add_element().CopyFrom(path
.element(0))
836 def v3_reference_to_v3_property_value(self
, v3_ref
, v3_property_value
):
837 """Converts a v3 Reference to a v3 PropertyValue.
840 v3_ref: an entity_pb.Reference
841 v3_property_value: an entity_pb.PropertyValue to populate
843 v3_property_value
.Clear()
844 reference_value
= v3_property_value
.mutable_referencevalue()
846 reference_value
.set_app(v3_ref
.app())
847 if v3_ref
.has_name_space():
848 reference_value
.set_name_space(v3_ref
.name_space())
849 for v3_path_element
in v3_ref
.path().element_list():
850 v3_ref_value_path_element
= reference_value
.add_pathelement()
851 if v3_path_element
.has_type():
852 v3_ref_value_path_element
.set_type(v3_path_element
.type())
853 if v3_path_element
.has_id():
854 v3_ref_value_path_element
.set_id(v3_path_element
.id())
855 if v3_path_element
.has_name():
856 v3_ref_value_path_element
.set_name(v3_path_element
.name())
858 def __v3_reference_value_to_v3_reference(self
, v3_ref_value
, v3_ref
):
859 """Converts a v3 ReferenceValue to a v3 Reference.
862 v3_ref_value: an entity_pb.PropertyValue_ReferenceValue
863 v3_ref: an entity_pb.Reference to populate
866 if v3_ref_value
.has_app():
867 v3_ref
.set_app(v3_ref_value
.app())
868 if v3_ref_value
.has_name_space():
869 v3_ref
.set_name_space(v3_ref_value
.name_space())
870 for v3_ref_value_path_element
in v3_ref_value
.pathelement_list():
871 v3_path_element
= v3_ref
.mutable_path().add_element()
872 if v3_ref_value_path_element
.has_type():
873 v3_path_element
.set_type(v3_ref_value_path_element
.type())
874 if v3_ref_value_path_element
.has_id():
875 v3_path_element
.set_id(v3_ref_value_path_element
.id())
876 if v3_ref_value_path_element
.has_name():
877 v3_path_element
.set_name(v3_ref_value_path_element
.name())
881 __entity_converter
= _EntityConverter()
884 def get_entity_converter():
885 """Returns a converter for v3 and v4 entities and keys."""
886 return __entity_converter