App Engine Python SDK version 1.8.9
[gae.git] / python / google / appengine / datastore / datastore_pbs.py
blobe44b891e35767692687f445a1c1cb4ab42581ec8
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 else:
337 pass
339 def v3_property_to_v4_value(self, v3_property, indexed, v4_value):
340 """Converts a v3 Property to a v4 Value.
342 Args:
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
347 v4_value.Clear()
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_v3_property_value_union_valid(v3_property_value):
357 v3_meaning = None
358 v3_uri_meaning = None
359 elif v3_meaning == entity_pb.Property.NO_MEANING:
360 v3_meaning = None
361 elif not self.__is_v3_property_value_meaning_valid(v3_property_value,
362 v3_meaning):
364 v3_meaning = None
366 is_zlib_value = False
367 if v3_uri_meaning:
368 if v3_uri_meaning == URI_MEANING_ZLIB:
369 if v3_property_value.has_stringvalue():
370 is_zlib_value = True
371 if v3_meaning != entity_pb.Property.BLOB:
373 v3_meaning = entity_pb.Property.BLOB
374 else:
375 pass
376 else:
377 pass
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())
386 v3_meaning = None
387 else:
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.__v3_reference_value_to_v3_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())
404 v3_meaning = None
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:
410 v3_meaning = None
411 else:
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)
416 v3_meaning = None
417 else:
418 v4_value.set_string_value(string_value)
419 else:
421 v4_value.set_blob_value(string_value)
423 if v3_meaning != entity_pb.Property.INDEX_VALUE:
424 v3_meaning = None
427 elif v3_property_value.has_pointvalue():
428 self.__v3_to_v4_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)
432 v3_meaning = None
433 elif v3_property_value.has_uservalue():
434 self.__v3_to_v4_user_entity(v3_property_value.uservalue(),
435 v4_value.mutable_entity_value())
436 v4_value.set_meaning(MEANING_PREDEFINED_ENTITY_USER)
437 else:
438 pass
440 if is_zlib_value:
441 v4_value.set_meaning(MEANING_ZLIB)
442 elif v3_meaning:
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.
454 Args:
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'
461 v3_property.Clear()
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())
466 v4_meaning = None
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():
479 pass
482 else:
483 if v4_value.indexed():
484 v3_property.set_meaning(entity_pb.Property.BYTESTRING)
485 else:
486 v3_property.set_meaning(entity_pb.Property.BLOB)
487 v4_meaning = None
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)
493 v4_meaning = None
494 else:
496 pass
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.
503 Args:
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.__v4_to_v3_property(property_name, is_multi, v4_value,
511 v3_entity.add_property())
512 else:
513 self.__v4_to_v3_property(property_name, is_multi, v4_value,
514 v3_entity.add_raw_property())
516 def __build_name_to_v4_property_map(self, v4_entity):
517 property_map = {}
518 for prop in v4_entity.property_list():
519 property_map[prop.name()] = prop
520 return property_map
522 def __add_v4_property_to_entity(self, v4_entity, property_map, v3_property,
523 indexed):
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.
529 Args:
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]
538 else:
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())
545 else:
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.
552 Args:
553 v4_property: an entity_v4_pb.Property
555 Returns:
556 an integer
558 Raises:
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.
568 Args:
569 v4_property: an entity_v4_pb.Property
571 Returns:
572 a double
574 Raises:
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.
584 Args:
585 v4_property: an entity_v4_pb.Property
587 Returns:
588 a string
590 Throws:
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.
600 Args:
601 name: the property name
602 value: the integer value of the property
603 indexed: whether the value should be indexed
605 Returns:
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)
613 return v4_property
615 def __v4_double_property(self, name, value, indexed):
616 """Creates a single-double-valued v4 Property.
618 Args:
619 name: the property name
620 value: the double value of the property
621 indexed: whether the value should be indexed
623 Returns:
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)
631 return v4_property
633 def __v4_string_property(self, name, value, indexed):
634 """Creates a single-string-valued v4 Property.
636 Args:
637 name: the property name
638 value: the string value of the property
639 indexed: whether the value should be indexed
641 Returns:
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)
649 return v4_property
651 def __v4_to_v3_point_value(self, v4_point_entity, v3_point_value):
652 """Converts a v4 point Entity to a v3 PointValue.
654 Args:
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_v4_property_map(v4_point_entity)
660 v3_point_value.set_x(
661 self.__get_v4_double_value(name_to_v4_property['x']))
662 v3_point_value.set_y(
663 self.__get_v4_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.
668 Args:
669 v3_point_value: an entity_pb.Property_PointValue
670 v4_entity: an entity_v4_pb.Entity to populate
672 v4_entity.Clear()
673 v4_entity.property_list().append(
674 self.__v4_double_property(PROPERTY_NAME_X, v3_point_value.x(), False))
675 v4_entity.property_list().append(
676 self.__v4_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.
681 Args:
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_v4_property_map(v4_user_entity)
688 v3_user_value.set_email(self.__get_v4_string_value(
689 name_to_v4_property[PROPERTY_NAME_EMAIL]))
690 v3_user_value.set_auth_domain(self.__get_v4_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_v4_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_v4_integer_value(
698 name_to_v4_property[PROPERTY_NAME_INTERNAL_ID]))
699 else:
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_v4_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_v4_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.
714 Args:
715 v3_user_value: an entity_pb.Property_UserValue
716 v4_entity: an entity_v4_pb.Entity to populate
718 v4_entity.Clear()
719 v4_entity.property_list().append(
720 self.__v4_string_property(PROPERTY_NAME_EMAIL, v3_user_value.email(),
721 False))
722 v4_entity.property_list().append(self.__v4_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.__v4_integer_property(
728 PROPERTY_NAME_INTERNAL_ID,
729 v3_user_value.gaiaid(),
730 False))
731 if v3_user_value.has_obfuscated_gaiaid():
732 v4_entity.property_list().append(self.__v4_string_property(
733 PROPERTY_NAME_USER_ID,
734 v3_user_value.obfuscated_gaiaid(),
735 False))
736 if v3_user_value.has_federated_identity():
737 v4_entity.property_list().append(self.__v4_string_property(
738 PROPERTY_NAME_FEDERATED_IDENTITY,
739 v3_user_value.federated_identity(),
740 False))
741 if v3_user_value.has_federated_provider():
742 v4_entity.property_list().append(self.__v4_string_property(
743 PROPERTY_NAME_FEDERATED_PROVIDER,
744 v3_user_value.federated_provider(),
745 False))
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."""
760 def ReturnTrue():
761 return True
762 def HasStringValue():
763 return v3_property_value.has_stringvalue()
764 def HasInt64Value():
765 return v3_property_value.has_int64value()
766 def HasPointValue():
767 return v3_property_value.has_pointvalue()
768 def ReturnFalse():
769 return False
770 value_checkers = {
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.
798 Args:
799 v3_ref: an entity_pb.Reference
801 Returns:
802 boolean: True if the last path element specifies an ID or name.
804 path = v3_ref.path()
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.
815 Args:
816 v3_ref: an entity_pb.Reference
817 group: an entity_pb.Path to populate
819 group.Clear()
820 path = v3_ref.path()
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.
827 Args:
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()
833 if v3_ref.has_app():
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.
849 Args:
850 v3_ref_value: an entity_pb.PropertyValue_ReferenceValue
851 v3_ref: an entity_pb.Reference to populate
853 v3_ref.Clear()
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