App Engine Python SDK version 1.9.13
[gae.git] / python / google / appengine / datastore / datastore_pbs.py
blob323897fb5ff8edad94c69c1289dcc1e117af0434
1 #!/usr/bin/env python
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.
24 """
41 from google.appengine.datastore import entity_pb
43 from google.appengine.datastore import entity_v4_pb
47 MEANING_ATOM_CATEGORY = 1
48 MEANING_URL = 2
49 MEANING_ATOM_TITLE = 3
50 MEANING_ATOM_CONTENT = 4
51 MEANING_ATOM_SUMMARY = 5
52 MEANING_ATOM_AUTHOR = 6
53 MEANING_GD_EMAIL = 8
54 MEANING_GEORSS_POINT = 9
55 MEANING_GD_IM = 10
56 MEANING_GD_PHONENUMBER = 11
57 MEANING_GD_POSTALADDRESS = 12
58 MEANING_PERCENT = 13
59 MEANING_TEXT = 15
60 MEANING_BYTESTRING = 16
61 MEANING_INDEX_ONLY = 18
62 MEANING_PREDEFINED_ENTITY_USER = 20
63 MEANING_PREDEFINED_ENTITY_POINT = 21
64 MEANING_ZLIB = 22
67 URI_MEANING_ZLIB = 'ZLIB'
71 MAX_URL_CHARS = 2038
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
83 PROPERTY_NAME_X = 'x'
84 PROPERTY_NAME_Y = 'y'
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__'
97 DEFAULT_GAIA_ID = 0
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.
108 Args:
109 v4_key: an entity_v4_pb.Key
111 Returns:
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()
120 else:
121 id_or_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.
129 Args:
130 v4_key: an entity_v4_pb.Key
132 Returns:
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):
141 try:
142 s.decode('utf-8')
143 return True
144 except UnicodeDecodeError:
145 return False
148 def check_conversion(condition, message):
149 """Asserts a conversion condition and raises an error if it's not met.
151 Args:
152 condition: (boolean) condition to enforce
153 message: error message
155 Raises:
156 InvalidConversionError: if condition is not met
158 if not condition:
159 raise InvalidConversionError(message)
163 class InvalidConversionError(Exception):
164 """Raised when conversion fails."""
165 pass
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.
174 Args:
175 v4_key: an entity_v4_pb.Key
176 v3_ref: an entity_pb.Reference to populate
178 v3_ref.Clear()
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.
195 Args:
196 v4_keys: a list of entity_v4_pb.Key objects
198 Returns:
199 a list of entity_pb.Reference objects
201 v3_refs = []
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)
206 return v3_refs
208 def v3_to_v4_key(self, v3_ref, v4_key):
209 """Converts a v3 Reference to a v4 Key.
211 Args:
212 v3_ref: an entity_pb.Reference
213 v4_key: an entity_v4_pb.Key to populate
215 v4_key.Clear()
216 if not v3_ref.app():
217 return
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.
232 Args:
233 v3_refs: a list of entity_pb.Reference objects
235 Returns:
236 a list of entity_v4_pb.Key objects
238 v4_keys = []
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)
243 return v4_keys
245 def v4_to_v3_entity(self, v4_entity, v3_entity):
246 """Converts a v4 Entity to a v3 EntityProto.
248 Args:
249 v4_entity: an entity_v4_pb.Entity
250 v3_entity: an entity_pb.EntityProto to populate
252 v3_entity.Clear()
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_v3_property(property_name, True, v4_sub_value, v3_entity)
259 else:
260 self.__add_v3_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())
266 else:
269 pass
271 def v3_to_v4_entity(self, v3_entity, v4_entity):
272 """Converts a v3 EntityProto to a v4 Entity.
274 Args:
275 v3_entity: an entity_pb.EntityProto
276 v4_entity: an entity_v4_pb.Proto to populate
278 v4_entity.Clear()
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()
287 v4_properties = {}
288 for v3_property in v3_entity.property_list():
289 self.__add_v4_property_to_entity(v4_entity, v4_properties, v3_property,
290 True)
291 for v3_property in v3_entity.raw_property_list():
292 self.__add_v4_property_to_entity(v4_entity, v4_properties, v3_property,
293 False)
295 def v4_value_to_v3_property_value(self, v4_value, v3_value):
296 """Converts a v4 Value to a v3 PropertyValue.
298 Args:
299 v4_value: an entity_v4_pb.Value
300 v3_value: an entity_pb.PropertyValue to populate
302 v3_value.Clear()
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.__v4_to_v3_point_value(v4_entity_value,
327 v3_value.mutable_pointvalue())
328 elif v4_meaning == MEANING_PREDEFINED_ENTITY_USER:
329 self.__v4_to_v3_user_value(v4_entity_value,
330 v3_value.mutable_uservalue())
331 else:
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())
339 else:
341 pass
343 def v3_property_to_v4_value(self, v3_property, indexed, v4_value):
344 """Converts a v3 Property to a v4 Value.
346 Args:
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
351 v4_value.Clear()
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_v3_property_value_union_valid(v3_property_value):
361 v3_meaning = None
362 v3_uri_meaning = None
363 elif v3_meaning == entity_pb.Property.NO_MEANING:
364 v3_meaning = None
365 elif not self.__is_v3_property_value_meaning_valid(v3_property_value,
366 v3_meaning):
368 v3_meaning = None
370 is_zlib_value = False
371 if v3_uri_meaning:
372 if v3_uri_meaning == URI_MEANING_ZLIB:
373 if v3_property_value.has_stringvalue():
374 is_zlib_value = True
375 if v3_meaning != entity_pb.Property.BLOB:
377 v3_meaning = entity_pb.Property.BLOB
378 else:
379 pass
380 else:
381 pass
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())
390 v3_meaning = None
391 else:
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.__v3_reference_value_to_v3_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())
408 v3_meaning = None
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:
414 v3_meaning = None
415 else:
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)
420 v3_meaning = None
421 else:
422 v4_value.set_string_value(string_value)
423 else:
425 v4_value.set_blob_value(string_value)
427 if v3_meaning != entity_pb.Property.INDEX_VALUE:
428 v3_meaning = None
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())
436 else:
437 self.__v3_to_v4_point_entity(v3_property_value.pointvalue(),
438 v4_value.mutable_entity_value())
439 v4_value.set_meaning(MEANING_PREDEFINED_ENTITY_POINT)
441 v3_meaning = None
442 elif v3_property_value.has_uservalue():
443 self.__v3_to_v4_user_entity(v3_property_value.uservalue(),
444 v4_value.mutable_entity_value())
445 v4_value.set_meaning(MEANING_PREDEFINED_ENTITY_USER)
446 v3_meaning = None
447 else:
448 pass
450 if is_zlib_value:
451 v4_value.set_meaning(MEANING_ZLIB)
452 elif v3_meaning:
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.
464 Args:
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'
471 v3_property.Clear()
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())
476 v4_meaning = None
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():
489 pass
492 else:
493 if v4_value.indexed():
494 v3_property.set_meaning(entity_pb.Property.BYTESTRING)
495 else:
496 v3_property.set_meaning(entity_pb.Property.BLOB)
497 v4_meaning = None
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)
503 v4_meaning = None
504 elif v4_value.has_geo_point_value():
505 v3_property.set_meaning(MEANING_GEORSS_POINT)
506 else:
508 pass
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.
515 Args:
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.__v4_to_v3_property(property_name, is_multi, v4_value,
523 v3_entity.add_property())
524 else:
525 self.__v4_to_v3_property(property_name, is_multi, v4_value,
526 v3_entity.add_raw_property())
528 def __build_name_to_v4_property_map(self, v4_entity):
529 property_map = {}
530 for prop in v4_entity.property_list():
531 property_map[prop.name()] = prop
532 return property_map
534 def __add_v4_property_to_entity(self, v4_entity, property_map, v3_property,
535 indexed):
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.
541 Args:
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]
550 else:
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())
557 else:
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.
564 Args:
565 v4_property: an entity_v4_pb.Property
567 Returns:
568 an integer
570 Raises:
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.
580 Args:
581 v4_property: an entity_v4_pb.Property
583 Returns:
584 a double
586 Raises:
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.
596 Args:
597 v4_property: an entity_v4_pb.Property
599 Returns:
600 a string
602 Throws:
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.
612 Args:
613 name: the property name
614 value: the integer value of the property
615 indexed: whether the value should be indexed
617 Returns:
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)
625 return v4_property
627 def __v4_double_property(self, name, value, indexed):
628 """Creates a single-double-valued v4 Property.
630 Args:
631 name: the property name
632 value: the double value of the property
633 indexed: whether the value should be indexed
635 Returns:
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)
643 return v4_property
645 def __v4_string_property(self, name, value, indexed):
646 """Creates a single-string-valued v4 Property.
648 Args:
649 name: the property name
650 value: the string value of the property
651 indexed: whether the value should be indexed
653 Returns:
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)
661 return v4_property
663 def __v4_to_v3_point_value(self, v4_point_entity, v3_point_value):
664 """Converts a v4 point Entity to a v3 PointValue.
666 Args:
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_v4_property_map(v4_point_entity)
672 v3_point_value.set_x(
673 self.__get_v4_double_value(name_to_v4_property['x']))
674 v3_point_value.set_y(
675 self.__get_v4_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.
680 Args:
681 v3_point_value: an entity_pb.Property_PointValue
682 v4_entity: an entity_v4_pb.Entity to populate
684 v4_entity.Clear()
685 v4_entity.property_list().append(
686 self.__v4_double_property(PROPERTY_NAME_X, v3_point_value.x(), False))
687 v4_entity.property_list().append(
688 self.__v4_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.
693 Args:
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_v4_property_map(v4_user_entity)
700 v3_user_value.set_email(self.__get_v4_string_value(
701 name_to_v4_property[PROPERTY_NAME_EMAIL]))
702 v3_user_value.set_auth_domain(self.__get_v4_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_v4_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_v4_integer_value(
710 name_to_v4_property[PROPERTY_NAME_INTERNAL_ID]))
711 else:
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_v4_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_v4_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.
726 Args:
727 v3_user_value: an entity_pb.Property_UserValue
728 v4_entity: an entity_v4_pb.Entity to populate
730 v4_entity.Clear()
731 v4_entity.property_list().append(
732 self.__v4_string_property(PROPERTY_NAME_EMAIL, v3_user_value.email(),
733 False))
734 v4_entity.property_list().append(self.__v4_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.__v4_integer_property(
740 PROPERTY_NAME_INTERNAL_ID,
741 v3_user_value.gaiaid(),
742 False))
743 if v3_user_value.has_obfuscated_gaiaid():
744 v4_entity.property_list().append(self.__v4_string_property(
745 PROPERTY_NAME_USER_ID,
746 v3_user_value.obfuscated_gaiaid(),
747 False))
748 if v3_user_value.has_federated_identity():
749 v4_entity.property_list().append(self.__v4_string_property(
750 PROPERTY_NAME_FEDERATED_IDENTITY,
751 v3_user_value.federated_identity(),
752 False))
753 if v3_user_value.has_federated_provider():
754 v4_entity.property_list().append(self.__v4_string_property(
755 PROPERTY_NAME_FEDERATED_PROVIDER,
756 v3_user_value.federated_provider(),
757 False))
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."""
772 def ReturnTrue():
773 return True
774 def HasStringValue():
775 return v3_property_value.has_stringvalue()
776 def HasInt64Value():
777 return v3_property_value.has_int64value()
778 def HasPointValue():
779 return v3_property_value.has_pointvalue()
780 def ReturnFalse():
781 return False
782 value_checkers = {
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.
810 Args:
811 v3_ref: an entity_pb.Reference
813 Returns:
814 boolean: True if the last path element specifies an ID or name.
816 path = v3_ref.path()
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.
827 Args:
828 v3_ref: an entity_pb.Reference
829 group: an entity_pb.Path to populate
831 group.Clear()
832 path = v3_ref.path()
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.
839 Args:
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()
845 if v3_ref.has_app():
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.
861 Args:
862 v3_ref_value: an entity_pb.PropertyValue_ReferenceValue
863 v3_ref: an entity_pb.Reference to populate
865 v3_ref.Clear()
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