Index: third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
diff --git a/third_party/protobuf/python/google/protobuf/internal/well_known_types.py b/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
index d3de98319009dc0256a9767b2b7977c6fbe3f107..7c5dffd0fc53d4728647c1e8551aa9d676782c8d 100644 |
--- a/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
+++ b/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
@@ -34,6 +34,7 @@ This files defines well known classes which need extra maintenance including: |
- Any |
- Duration |
- FieldMask |
+ - Struct |
- Timestamp |
""" |
@@ -41,6 +42,7 @@ __author__ = 'jieluo@google.com (Jie Luo)' |
from datetime import datetime |
from datetime import timedelta |
+import six |
from google.protobuf.descriptor import FieldDescriptor |
@@ -64,9 +66,12 @@ class ParseError(Error): |
class Any(object): |
"""Class for Any Message type.""" |
- def Pack(self, msg): |
+ def Pack(self, msg, type_url_prefix='type.googleapis.com/'): |
"""Packs the specified message into current Any message.""" |
- self.type_url = 'type.googleapis.com/%s' % msg.DESCRIPTOR.full_name |
+ if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/': |
+ self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) |
+ else: |
+ self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) |
self.value = msg.SerializeToString() |
def Unpack(self, msg): |
@@ -77,10 +82,14 @@ class Any(object): |
msg.ParseFromString(self.value) |
return True |
+ def TypeName(self): |
+ """Returns the protobuf type name of the inner message.""" |
+ # Only last part is to be used: b/25630112 |
+ return self.type_url.split('/')[-1] |
+ |
def Is(self, descriptor): |
"""Checks if this Any represents the given protobuf type.""" |
- # Only last part is to be used: b/25630112 |
- return self.type_url.split('/')[-1] == descriptor.full_name |
+ return self.TypeName() == descriptor.full_name |
class Timestamp(object): |
@@ -614,9 +623,102 @@ def _AddFieldPaths(node, prefix, field_mask): |
_AddFieldPaths(node[name], child_path, field_mask) |
+_INT_OR_FLOAT = six.integer_types + (float,) |
+ |
+ |
+def _SetStructValue(struct_value, value): |
+ if value is None: |
+ struct_value.null_value = 0 |
+ elif isinstance(value, bool): |
+ # Note: this check must come before the number check because in Python |
+ # True and False are also considered numbers. |
+ struct_value.bool_value = value |
+ elif isinstance(value, six.string_types): |
+ struct_value.string_value = value |
+ elif isinstance(value, _INT_OR_FLOAT): |
+ struct_value.number_value = value |
+ else: |
+ raise ValueError('Unexpected type') |
+ |
+ |
+def _GetStructValue(struct_value): |
+ which = struct_value.WhichOneof('kind') |
+ if which == 'struct_value': |
+ return struct_value.struct_value |
+ elif which == 'null_value': |
+ return None |
+ elif which == 'number_value': |
+ return struct_value.number_value |
+ elif which == 'string_value': |
+ return struct_value.string_value |
+ elif which == 'bool_value': |
+ return struct_value.bool_value |
+ elif which == 'list_value': |
+ return struct_value.list_value |
+ elif which is None: |
+ raise ValueError('Value not set') |
+ |
+ |
+class Struct(object): |
+ """Class for Struct message type.""" |
+ |
+ __slots__ = [] |
+ |
+ def __getitem__(self, key): |
+ return _GetStructValue(self.fields[key]) |
+ |
+ def __setitem__(self, key, value): |
+ _SetStructValue(self.fields[key], value) |
+ |
+ def get_or_create_list(self, key): |
+ """Returns a list for this key, creating if it didn't exist already.""" |
+ return self.fields[key].list_value |
+ |
+ def get_or_create_struct(self, key): |
+ """Returns a struct for this key, creating if it didn't exist already.""" |
+ return self.fields[key].struct_value |
+ |
+ # TODO(haberman): allow constructing/merging from dict. |
+ |
+ |
+class ListValue(object): |
+ """Class for ListValue message type.""" |
+ |
+ def __len__(self): |
+ return len(self.values) |
+ |
+ def append(self, value): |
+ _SetStructValue(self.values.add(), value) |
+ |
+ def extend(self, elem_seq): |
+ for value in elem_seq: |
+ self.append(value) |
+ |
+ def __getitem__(self, index): |
+ """Retrieves item by the specified index.""" |
+ return _GetStructValue(self.values.__getitem__(index)) |
+ |
+ def __setitem__(self, index, value): |
+ _SetStructValue(self.values.__getitem__(index), value) |
+ |
+ def items(self): |
+ for i in range(len(self)): |
+ yield self[i] |
+ |
+ def add_struct(self): |
+ """Appends and returns a struct value as the next value in the list.""" |
+ return self.values.add().struct_value |
+ |
+ def add_list(self): |
+ """Appends and returns a list value as the next value in the list.""" |
+ return self.values.add().list_value |
+ |
+ |
WKTBASES = { |
'google.protobuf.Any': Any, |
'google.protobuf.Duration': Duration, |
'google.protobuf.FieldMask': FieldMask, |
+ 'google.protobuf.ListValue': ListValue, |
+ 'google.protobuf.Struct': Struct, |
'google.protobuf.Timestamp': Timestamp, |
} |