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())
339 def v3_property_to_v4_value(self
, v3_property
, indexed
, v4_value
):
340 """Converts a v3 Property to a v4 Value.
343 v3_property: an entity_pb.Property
344 indexed: whether the v3 property is indexed
345 v4_value: an entity_v4_pb.Value to populate
348 v3_property_value
= v3_property
.value()
349 v3_meaning
= v3_property
.meaning()
350 v3_uri_meaning
= None
351 if v3_property
.meaning_uri():
352 v3_uri_meaning
= v3_property
.meaning_uri()
354 if not self
.__is
_v
3_property
_value
_union
_valid
(v3_property_value
):
358 v3_uri_meaning
= None
359 elif v3_meaning
== entity_pb
.Property
.NO_MEANING
:
361 elif not self
.__is
_v
3_property
_value
_meaning
_valid
(v3_property_value
,
366 is_zlib_value
= False
368 if v3_uri_meaning
== URI_MEANING_ZLIB
:
369 if v3_property_value
.has_stringvalue():
371 if v3_meaning
!= entity_pb
.Property
.BLOB
:
373 v3_meaning
= entity_pb
.Property
.BLOB
380 if v3_property_value
.has_booleanvalue():
381 v4_value
.set_boolean_value(v3_property_value
.booleanvalue())
382 elif v3_property_value
.has_int64value():
383 if v3_meaning
== entity_pb
.Property
.GD_WHEN
:
384 v4_value
.set_timestamp_microseconds_value(
385 v3_property_value
.int64value())
388 v4_value
.set_integer_value(v3_property_value
.int64value())
389 elif v3_property_value
.has_doublevalue():
390 v4_value
.set_double_value(v3_property_value
.doublevalue())
391 elif v3_property_value
.has_referencevalue():
392 v3_ref
= entity_pb
.Reference()
393 self
.__v
3_reference
_value
_to
_v
3_reference
(
394 v3_property_value
.referencevalue(), v3_ref
)
395 self
.v3_to_v4_key(v3_ref
, v4_value
.mutable_key_value())
396 elif v3_property_value
.has_stringvalue():
397 if v3_meaning
== entity_pb
.Property
.ENTITY_PROTO
:
398 serialized_entity_v3
= v3_property_value
.stringvalue()
399 v3_entity
= entity_pb
.EntityProto()
402 v3_entity
.ParsePartialFromString(serialized_entity_v3
)
403 self
.v3_to_v4_entity(v3_entity
, v4_value
.mutable_entity_value())
405 elif (v3_meaning
== entity_pb
.Property
.BLOB
406 or v3_meaning
== entity_pb
.Property
.BYTESTRING
):
407 v4_value
.set_blob_value(v3_property_value
.stringvalue())
409 if indexed
or v3_meaning
== entity_pb
.Property
.BLOB
:
412 string_value
= v3_property_value
.stringvalue()
413 if is_valid_utf8(string_value
):
414 if v3_meaning
== entity_pb
.Property
.BLOBKEY
:
415 v4_value
.set_blob_key_value(string_value
)
418 v4_value
.set_string_value(string_value
)
421 v4_value
.set_blob_value(string_value
)
423 if v3_meaning
!= entity_pb
.Property
.INDEX_VALUE
:
427 elif v3_property_value
.has_pointvalue():
428 self
.__v
3_to
_v
4_point
_entity
(v3_property_value
.pointvalue(),
429 v4_value
.mutable_entity_value())
430 if v3_meaning
!= entity_pb
.Property
.GEORSS_POINT
:
431 v4_value
.set_meaning(MEANING_PREDEFINED_ENTITY_POINT
)
433 elif v3_property_value
.has_uservalue():
434 self
.__v
3_to
_v
4_user
_entity
(v3_property_value
.uservalue(),
435 v4_value
.mutable_entity_value())
436 v4_value
.set_meaning(MEANING_PREDEFINED_ENTITY_USER
)
441 v4_value
.set_meaning(MEANING_ZLIB
)
443 v4_value
.set_meaning(v3_meaning
)
446 if indexed
!= v4_value
.indexed():
447 v4_value
.set_indexed(indexed
)
449 def __v4_to_v3_property(self
, property_name
, is_multi
, v4_value
, v3_property
):
450 """Converts info from a v4 Property to a v3 Property.
452 v4_value must not have a list_value.
455 property_name: the name of the property
456 is_multi: whether the property contains multiple values
457 v4_value: an entity_v4_pb.Value
458 v3_property: an entity_pb.Property to populate
460 assert not v4_value
.list_value_list(), 'v4 list_value not convertable to v3'
462 v3_property
.set_name(property_name
)
463 v3_property
.set_multiple(is_multi
)
464 self
.v4_value_to_v3_property_value(v4_value
, v3_property
.mutable_value())
467 if v4_value
.has_meaning():
468 v4_meaning
= v4_value
.meaning()
470 if v4_value
.has_timestamp_microseconds_value():
471 v3_property
.set_meaning(entity_pb
.Property
.GD_WHEN
)
472 elif v4_value
.has_blob_key_value():
473 v3_property
.set_meaning(entity_pb
.Property
.BLOBKEY
)
474 elif v4_value
.has_blob_value():
475 if v4_meaning
== MEANING_ZLIB
:
476 v3_property
.set_meaning_uri(URI_MEANING_ZLIB
)
477 if v4_meaning
== entity_pb
.Property
.BYTESTRING
:
478 if v4_value
.indexed():
483 if v4_value
.indexed():
484 v3_property
.set_meaning(entity_pb
.Property
.BYTESTRING
)
486 v3_property
.set_meaning(entity_pb
.Property
.BLOB
)
488 elif v4_value
.has_entity_value():
489 if v4_meaning
!= MEANING_GEORSS_POINT
:
490 if (v4_meaning
!= MEANING_PREDEFINED_ENTITY_POINT
491 and v4_meaning
!= MEANING_PREDEFINED_ENTITY_USER
):
492 v3_property
.set_meaning(entity_pb
.Property
.ENTITY_PROTO
)
497 if v4_meaning
is not None:
498 v3_property
.set_meaning(v4_meaning
)
500 def __add_v3_property(self
, property_name
, is_multi
, v4_value
, v3_entity
):
501 """Adds a v3 Property to an Entity based on information from a v4 Property.
504 property_name: the name of the property
505 is_multi: whether the property contains multiple values
506 v4_value: an entity_v4_pb.Value
507 v3_entity: an entity_pb.EntityProto
509 if v4_value
.indexed():
510 self
.__v
4_to
_v
3_property
(property_name
, is_multi
, v4_value
,
511 v3_entity
.add_property())
513 self
.__v
4_to
_v
3_property
(property_name
, is_multi
, v4_value
,
514 v3_entity
.add_raw_property())
516 def __build_name_to_v4_property_map(self
, v4_entity
):
518 for prop
in v4_entity
.property_list():
519 property_map
[prop
.name()] = prop
522 def __add_v4_property_to_entity(self
, v4_entity
, property_map
, v3_property
,
524 """Adds a v4 Property to an entity or modifies an existing one.
526 property_map is used to track of properties that have already been added.
527 The same dict should be used for all of an entity's properties.
530 v4_entity: an entity_v4_pb.Entity
531 property_map: a dict of name -> v4_property
532 v3_property: an entity_pb.Property to convert to v4 and add to the dict
533 indexed: whether the property is indexed
535 property_name
= v3_property
.name()
536 if property_name
in property_map
:
537 v4_property
= property_map
[property_name
]
539 v4_property
= v4_entity
.add_property()
540 v4_property
.set_name(property_name
)
541 property_map
[property_name
] = v4_property
542 if v3_property
.multiple():
543 self
.v3_property_to_v4_value(v3_property
, indexed
,
544 v4_property
.mutable_value().add_list_value())
546 self
.v3_property_to_v4_value(v3_property
, indexed
,
547 v4_property
.mutable_value())
549 def __get_v4_integer_value(self
, v4_property
):
550 """Returns an integer value from a v4 Property.
553 v4_property: an entity_v4_pb.Property
559 InvalidConversionError: if the property doesn't contain an integer value
561 check_conversion(v4_property
.value().has_integer_value(),
562 'Property does not contain an integer value.')
563 return v4_property
.value().integer_value()
565 def __get_v4_double_value(self
, v4_property
):
566 """Returns a double value from a v4 Property.
569 v4_property: an entity_v4_pb.Property
575 InvalidConversionError: if the property doesn't contain a double value
577 check_conversion(v4_property
.value().has_double_value(),
578 'Property does not contain a double value.')
579 return v4_property
.value().double_value()
581 def __get_v4_string_value(self
, v4_property
):
582 """Returns an string value from a v4 Property.
585 v4_property: an entity_v4_pb.Property
591 InvalidConversionError: if the property doesn't contain a string value
593 check_conversion(v4_property
.value().has_string_value(),
594 'Property does not contain a string value.')
595 return v4_property
.value().string_value()
597 def __v4_integer_property(self
, name
, value
, indexed
):
598 """Creates a single-integer-valued v4 Property.
601 name: the property name
602 value: the integer value of the property
603 indexed: whether the value should be indexed
606 an entity_v4_pb.Property
608 v4_property
= entity_v4_pb
.Property()
609 v4_property
.set_name(name
)
610 v4_value
= v4_property
.mutable_value()
611 v4_value
.set_indexed(indexed
)
612 v4_value
.set_integer_value(value
)
615 def __v4_double_property(self
, name
, value
, indexed
):
616 """Creates a single-double-valued v4 Property.
619 name: the property name
620 value: the double value of the property
621 indexed: whether the value should be indexed
624 an entity_v4_pb.Property
626 v4_property
= entity_v4_pb
.Property()
627 v4_property
.set_name(name
)
628 v4_value
= v4_property
.mutable_value()
629 v4_value
.set_indexed(indexed
)
630 v4_value
.set_double_value(value
)
633 def __v4_string_property(self
, name
, value
, indexed
):
634 """Creates a single-string-valued v4 Property.
637 name: the property name
638 value: the string value of the property
639 indexed: whether the value should be indexed
642 an entity_v4_pb.Property
644 v4_property
= entity_v4_pb
.Property()
645 v4_property
.set_name(name
)
646 v4_value
= v4_property
.mutable_value()
647 v4_value
.set_indexed(indexed
)
648 v4_value
.set_string_value(value
)
651 def __v4_to_v3_point_value(self
, v4_point_entity
, v3_point_value
):
652 """Converts a v4 point Entity to a v3 PointValue.
655 v4_point_entity: an entity_v4_pb.Entity representing a point
656 v3_point_value: an entity_pb.Property_PointValue to populate
658 v3_point_value
.Clear()
659 name_to_v4_property
= self
.__build
_name
_to
_v
4_property
_map
(v4_point_entity
)
660 v3_point_value
.set_x(
661 self
.__get
_v
4_double
_value
(name_to_v4_property
['x']))
662 v3_point_value
.set_y(
663 self
.__get
_v
4_double
_value
(name_to_v4_property
['y']))
665 def __v3_to_v4_point_entity(self
, v3_point_value
, v4_entity
):
666 """Converts a v3 UserValue to a v4 user Entity.
669 v3_point_value: an entity_pb.Property_PointValue
670 v4_entity: an entity_v4_pb.Entity to populate
673 v4_entity
.property_list().append(
674 self
.__v
4_double
_property
(PROPERTY_NAME_X
, v3_point_value
.x(), False))
675 v4_entity
.property_list().append(
676 self
.__v
4_double
_property
(PROPERTY_NAME_Y
, v3_point_value
.y(), False))
678 def __v4_to_v3_user_value(self
, v4_user_entity
, v3_user_value
):
679 """Converts a v4 user Entity to a v3 UserValue.
682 v4_user_entity: an entity_v4_pb.Entity representing a user
683 v3_user_value: an entity_pb.Property_UserValue to populate
685 v3_user_value
.Clear()
686 name_to_v4_property
= self
.__build
_name
_to
_v
4_property
_map
(v4_user_entity
)
688 v3_user_value
.set_email(self
.__get
_v
4_string
_value
(
689 name_to_v4_property
[PROPERTY_NAME_EMAIL
]))
690 v3_user_value
.set_auth_domain(self
.__get
_v
4_string
_value
(
691 name_to_v4_property
[PROPERTY_NAME_AUTH_DOMAIN
]))
692 if PROPERTY_NAME_USER_ID
in name_to_v4_property
:
693 v3_user_value
.set_obfuscated_gaiaid(
694 self
.__get
_v
4_string
_value
(
695 name_to_v4_property
[PROPERTY_NAME_USER_ID
]))
696 if PROPERTY_NAME_INTERNAL_ID
in name_to_v4_property
:
697 v3_user_value
.set_gaiaid(self
.__get
_v
4_integer
_value
(
698 name_to_v4_property
[PROPERTY_NAME_INTERNAL_ID
]))
701 v3_user_value
.set_gaiaid(0)
702 if PROPERTY_NAME_FEDERATED_IDENTITY
in name_to_v4_property
:
703 v3_user_value
.set_federated_identity(
704 self
.__get
_v
4_string
_value
(name_to_v4_property
[
705 PROPERTY_NAME_FEDERATED_IDENTITY
]))
706 if PROPERTY_NAME_FEDERATED_PROVIDER
in name_to_v4_property
:
707 v3_user_value
.set_federated_provider(
708 self
.__get
_v
4_string
_value
(name_to_v4_property
[
709 PROPERTY_NAME_FEDERATED_PROVIDER
]))
711 def __v3_to_v4_user_entity(self
, v3_user_value
, v4_entity
):
712 """Converts a v3 UserValue to a v4 user Entity.
715 v3_user_value: an entity_pb.Property_UserValue
716 v4_entity: an entity_v4_pb.Entity to populate
719 v4_entity
.property_list().append(
720 self
.__v
4_string
_property
(PROPERTY_NAME_EMAIL
, v3_user_value
.email(),
722 v4_entity
.property_list().append(self
.__v
4_string
_property
(
723 PROPERTY_NAME_AUTH_DOMAIN
,
724 v3_user_value
.auth_domain(), False))
726 if v3_user_value
.gaiaid() != 0:
727 v4_entity
.property_list().append(self
.__v
4_integer
_property
(
728 PROPERTY_NAME_INTERNAL_ID
,
729 v3_user_value
.gaiaid(),
731 if v3_user_value
.has_obfuscated_gaiaid():
732 v4_entity
.property_list().append(self
.__v
4_string
_property
(
733 PROPERTY_NAME_USER_ID
,
734 v3_user_value
.obfuscated_gaiaid(),
736 if v3_user_value
.has_federated_identity():
737 v4_entity
.property_list().append(self
.__v
4_string
_property
(
738 PROPERTY_NAME_FEDERATED_IDENTITY
,
739 v3_user_value
.federated_identity(),
741 if v3_user_value
.has_federated_provider():
742 v4_entity
.property_list().append(self
.__v
4_string
_property
(
743 PROPERTY_NAME_FEDERATED_PROVIDER
,
744 v3_user_value
.federated_provider(),
747 def __is_v3_property_value_union_valid(self
, v3_property_value
):
748 """Returns True if the v3 PropertyValue's union is valid."""
749 num_sub_values
= (v3_property_value
.has_booleanvalue()
750 + v3_property_value
.has_int64value()
751 + v3_property_value
.has_doublevalue()
752 + v3_property_value
.has_referencevalue()
753 + v3_property_value
.has_stringvalue()
754 + v3_property_value
.has_pointvalue()
755 + v3_property_value
.has_uservalue())
756 return num_sub_values
<= 1
758 def __is_v3_property_value_meaning_valid(self
, v3_property_value
, v3_meaning
):
759 """Returns True if the v3 PropertyValue's type value matches its meaning."""
762 def HasStringValue():
763 return v3_property_value
.has_stringvalue()
765 return v3_property_value
.has_int64value()
767 return v3_property_value
.has_pointvalue()
771 entity_pb
.Property
.NO_MEANING
: ReturnTrue
,
772 entity_pb
.Property
.INDEX_VALUE
: ReturnTrue
,
773 entity_pb
.Property
.BLOB
: HasStringValue
,
774 entity_pb
.Property
.TEXT
: HasStringValue
,
775 entity_pb
.Property
.BYTESTRING
: HasStringValue
,
776 entity_pb
.Property
.ATOM_CATEGORY
: HasStringValue
,
777 entity_pb
.Property
.ATOM_LINK
: HasStringValue
,
778 entity_pb
.Property
.ATOM_TITLE
: HasStringValue
,
779 entity_pb
.Property
.ATOM_CONTENT
: HasStringValue
,
780 entity_pb
.Property
.ATOM_SUMMARY
: HasStringValue
,
781 entity_pb
.Property
.ATOM_AUTHOR
: HasStringValue
,
782 entity_pb
.Property
.GD_EMAIL
: HasStringValue
,
783 entity_pb
.Property
.GD_IM
: HasStringValue
,
784 entity_pb
.Property
.GD_PHONENUMBER
: HasStringValue
,
785 entity_pb
.Property
.GD_POSTALADDRESS
: HasStringValue
,
786 entity_pb
.Property
.BLOBKEY
: HasStringValue
,
787 entity_pb
.Property
.ENTITY_PROTO
: HasStringValue
,
788 entity_pb
.Property
.GD_WHEN
: HasInt64Value
,
789 entity_pb
.Property
.GD_RATING
: HasInt64Value
,
790 entity_pb
.Property
.GEORSS_POINT
: HasPointValue
,
792 default
= ReturnFalse
793 return value_checkers
.get(v3_meaning
, default
)()
795 def __v3_reference_has_id_or_name(self
, v3_ref
):
796 """Determines if a v3 Reference specifies an ID or name.
799 v3_ref: an entity_pb.Reference
802 boolean: True if the last path element specifies an ID or name.
805 assert path
.element_size() >= 1
806 last_element
= path
.element(path
.element_size() - 1)
807 return last_element
.has_id() or last_element
.has_name()
809 def v3_reference_to_group(self
, v3_ref
, group
):
810 """Converts a v3 Reference to a v3 Path representing the entity group.
812 The entity group is represented as an entity_pb.Path containing only the
813 first element in the provided Reference.
816 v3_ref: an entity_pb.Reference
817 group: an entity_pb.Path to populate
821 assert path
.element_size() >= 1
822 group
.add_element().CopyFrom(path
.element(0))
824 def v3_reference_to_v3_property_value(self
, v3_ref
, v3_property_value
):
825 """Converts a v3 Reference to a v3 PropertyValue.
828 v3_ref: an entity_pb.Reference
829 v3_property_value: an entity_pb.PropertyValue to populate
831 v3_property_value
.Clear()
832 reference_value
= v3_property_value
.mutable_referencevalue()
834 reference_value
.set_app(v3_ref
.app())
835 if v3_ref
.has_name_space():
836 reference_value
.set_name_space(v3_ref
.name_space())
837 for v3_path_element
in v3_ref
.path().element_list():
838 v3_ref_value_path_element
= reference_value
.add_pathelement()
839 if v3_path_element
.has_type():
840 v3_ref_value_path_element
.set_type(v3_path_element
.type())
841 if v3_path_element
.has_id():
842 v3_ref_value_path_element
.set_id(v3_path_element
.id())
843 if v3_path_element
.has_name():
844 v3_ref_value_path_element
.set_name(v3_path_element
.name())
846 def __v3_reference_value_to_v3_reference(self
, v3_ref_value
, v3_ref
):
847 """Converts a v3 ReferenceValue to a v3 Reference.
850 v3_ref_value: an entity_pb.PropertyValue_ReferenceValue
851 v3_ref: an entity_pb.Reference to populate
854 if v3_ref_value
.has_app():
855 v3_ref
.set_app(v3_ref_value
.app())
856 if v3_ref_value
.has_name_space():
857 v3_ref
.set_name_space(v3_ref_value
.name_space())
858 for v3_ref_value_path_element
in v3_ref_value
.pathelement_list():
859 v3_path_element
= v3_ref
.mutable_path().add_element()
860 if v3_ref_value_path_element
.has_type():
861 v3_path_element
.set_type(v3_ref_value_path_element
.type())
862 if v3_ref_value_path_element
.has_id():
863 v3_path_element
.set_id(v3_ref_value_path_element
.id())
864 if v3_ref_value_path_element
.has_name():
865 v3_path_element
.set_name(v3_ref_value_path_element
.name())
869 __entity_converter
= _EntityConverter()
872 def get_entity_converter():
873 """Returns a converter for v3 and v4 entities and keys."""
874 return __entity_converter