| Index: third_party/protobuf/python/google/protobuf/descriptor.py
|
| diff --git a/third_party/protobuf/python/google/protobuf/descriptor.py b/third_party/protobuf/python/google/protobuf/descriptor.py
|
| index eb13eda5ad6029ba9945512ee251f4d13979ce85..5f613c880b8edb003ef4cdcaab70f4a1e834d4b6 100755
|
| --- a/third_party/protobuf/python/google/protobuf/descriptor.py
|
| +++ b/third_party/protobuf/python/google/protobuf/descriptor.py
|
| @@ -1,6 +1,6 @@
|
| # Protocol Buffers - Google's data interchange format
|
| # Copyright 2008 Google Inc. All rights reserved.
|
| -# http://code.google.com/p/protobuf/
|
| +# https://developers.google.com/protocol-buffers/
|
| #
|
| # Redistribution and use in source and binary forms, with or without
|
| # modification, are permitted provided that the following conditions are
|
| @@ -34,15 +34,17 @@ file, in types that make this information accessible in Python.
|
|
|
| __author__ = 'robinson@google.com (Will Robinson)'
|
|
|
| +import six
|
|
|
| from google.protobuf.internal import api_implementation
|
|
|
| -
|
| +_USE_C_DESCRIPTORS = False
|
| if api_implementation.Type() == 'cpp':
|
| - if api_implementation.Version() == 2:
|
| - from google.protobuf.internal.cpp import _message
|
| - else:
|
| - from google.protobuf.internal import cpp_message
|
| + # Used by MakeDescriptor in cpp mode
|
| + import os
|
| + import uuid
|
| + from google.protobuf.pyext import _message
|
| + _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
|
|
|
|
|
| class Error(Exception):
|
| @@ -53,12 +55,29 @@ class TypeTransformationError(Error):
|
| """Error transforming between python proto type and corresponding C++ type."""
|
|
|
|
|
| -class DescriptorBase(object):
|
| +if _USE_C_DESCRIPTORS:
|
| + # This metaclass allows to override the behavior of code like
|
| + # isinstance(my_descriptor, FieldDescriptor)
|
| + # and make it return True when the descriptor is an instance of the extension
|
| + # type written in C++.
|
| + class DescriptorMetaclass(type):
|
| + def __instancecheck__(cls, obj):
|
| + if super(DescriptorMetaclass, cls).__instancecheck__(obj):
|
| + return True
|
| + if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
|
| + return True
|
| + return False
|
| +else:
|
| + # The standard metaclass; nothing changes.
|
| + DescriptorMetaclass = type
|
| +
|
| +
|
| +class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
|
|
|
| """Descriptors base class.
|
|
|
| This class is the base of all descriptor classes. It provides common options
|
| - related functionaility.
|
| + related functionality.
|
|
|
| Attributes:
|
| has_options: True if the descriptor has non-default options. Usually it
|
| @@ -68,6 +87,11 @@ class DescriptorBase(object):
|
| avoid some bootstrapping issues.
|
| """
|
|
|
| + if _USE_C_DESCRIPTORS:
|
| + # The class, or tuple of classes, that are considered as "virtual
|
| + # subclasses" of this descriptor class.
|
| + _C_DESCRIPTOR_CLASS = ()
|
| +
|
| def __init__(self, options, options_class_name):
|
| """Initialize the descriptor given its options message and the name of the
|
| class of the options message. The name of the class is required in case
|
| @@ -194,6 +218,9 @@ class Descriptor(_NestedDescriptorBase):
|
| fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor
|
| objects as in |fields|, but indexed by "name" attribute in each
|
| FieldDescriptor.
|
| + fields_by_camelcase_name: (dict str -> FieldDescriptor) Same
|
| + FieldDescriptor objects as in |fields|, but indexed by
|
| + "camelcase_name" attribute in each FieldDescriptor.
|
|
|
| nested_types: (list of Descriptors) Descriptor references
|
| for all protocol message types nested within this one.
|
| @@ -217,16 +244,33 @@ class Descriptor(_NestedDescriptorBase):
|
|
|
| is_extendable: Does this type define any extension ranges?
|
|
|
| - options: (descriptor_pb2.MessageOptions) Protocol message options or None
|
| - to use default message options.
|
| + oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields
|
| + in this message.
|
| + oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|,
|
| + but indexed by "name" attribute.
|
|
|
| file: (FileDescriptor) Reference to file descriptor.
|
| """
|
|
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.Descriptor
|
| +
|
| + def __new__(cls, name, full_name, filename, containing_type, fields,
|
| + nested_types, enum_types, extensions, options=None,
|
| + is_extendable=True, extension_ranges=None, oneofs=None,
|
| + file=None, serialized_start=None, serialized_end=None,
|
| + syntax=None):
|
| + _message.Message._CheckCalledFromGeneratedFile()
|
| + return _message.default_pool.FindMessageTypeByName(full_name)
|
| +
|
| + # NOTE(tmarek): The file argument redefining a builtin is nothing we can
|
| + # fix right now since we don't know how many clients already rely on the
|
| + # name of the argument.
|
| def __init__(self, name, full_name, filename, containing_type, fields,
|
| nested_types, enum_types, extensions, options=None,
|
| - is_extendable=True, extension_ranges=None, file=None,
|
| - serialized_start=None, serialized_end=None):
|
| + is_extendable=True, extension_ranges=None, oneofs=None,
|
| + file=None, serialized_start=None, serialized_end=None,
|
| + syntax=None): # pylint:disable=redefined-builtin
|
| """Arguments to __init__() are as described in the description
|
| of Descriptor fields above.
|
|
|
| @@ -236,7 +280,7 @@ class Descriptor(_NestedDescriptorBase):
|
| super(Descriptor, self).__init__(
|
| options, 'MessageOptions', name, full_name, file,
|
| containing_type, serialized_start=serialized_start,
|
| - serialized_end=serialized_start)
|
| + serialized_end=serialized_end)
|
|
|
| # We have fields in addition to fields_by_name and fields_by_number,
|
| # so that:
|
| @@ -248,8 +292,11 @@ class Descriptor(_NestedDescriptorBase):
|
| field.containing_type = self
|
| self.fields_by_number = dict((f.number, f) for f in fields)
|
| self.fields_by_name = dict((f.name, f) for f in fields)
|
| + self._fields_by_camelcase_name = None
|
|
|
| self.nested_types = nested_types
|
| + for nested_type in nested_types:
|
| + nested_type.containing_type = self
|
| self.nested_types_by_name = dict((t.name, t) for t in nested_types)
|
|
|
| self.enum_types = enum_types
|
| @@ -265,9 +312,18 @@ class Descriptor(_NestedDescriptorBase):
|
| self.extensions_by_name = dict((f.name, f) for f in extensions)
|
| self.is_extendable = is_extendable
|
| self.extension_ranges = extension_ranges
|
| -
|
| - self._serialized_start = serialized_start
|
| - self._serialized_end = serialized_end
|
| + self.oneofs = oneofs if oneofs is not None else []
|
| + self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
|
| + for oneof in self.oneofs:
|
| + oneof.containing_type = self
|
| + self.syntax = syntax or "proto2"
|
| +
|
| + @property
|
| + def fields_by_camelcase_name(self):
|
| + if self._fields_by_camelcase_name is None:
|
| + self._fields_by_camelcase_name = dict(
|
| + (f.camelcase_name, f) for f in self.fields)
|
| + return self._fields_by_camelcase_name
|
|
|
| def EnumValueName(self, enum, value):
|
| """Returns the string name of an enum value.
|
| @@ -317,6 +373,7 @@ class FieldDescriptor(DescriptorBase):
|
| name: (str) Name of this field, exactly as it appears in .proto.
|
| full_name: (str) Name of this field, including containing scope. This is
|
| particularly relevant for extensions.
|
| + camelcase_name: (str) Camelcase name of this field.
|
| index: (int) Dense, 0-indexed index giving the order that this
|
| field textually appears within its message in the .proto file.
|
| number: (int) Tag number declared for this field in the .proto file.
|
| @@ -353,6 +410,9 @@ class FieldDescriptor(DescriptorBase):
|
|
|
| options: (descriptor_pb2.FieldOptions) Protocol message field options or
|
| None to use default field options.
|
| +
|
| + containing_oneof: (OneofDescriptor) If the field is a member of a oneof
|
| + union, contains its descriptor. Otherwise, None.
|
| """
|
|
|
| # Must be consistent with C++ FieldDescriptor::Type enum in
|
| @@ -425,10 +485,29 @@ class FieldDescriptor(DescriptorBase):
|
| LABEL_REPEATED = 3
|
| MAX_LABEL = 3
|
|
|
| + # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
|
| + # and kLastReservedNumber in descriptor.h
|
| + MAX_FIELD_NUMBER = (1 << 29) - 1
|
| + FIRST_RESERVED_FIELD_NUMBER = 19000
|
| + LAST_RESERVED_FIELD_NUMBER = 19999
|
| +
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
|
| +
|
| + def __new__(cls, name, full_name, index, number, type, cpp_type, label,
|
| + default_value, message_type, enum_type, containing_type,
|
| + is_extension, extension_scope, options=None,
|
| + has_default_value=True, containing_oneof=None):
|
| + _message.Message._CheckCalledFromGeneratedFile()
|
| + if is_extension:
|
| + return _message.default_pool.FindExtensionByName(full_name)
|
| + else:
|
| + return _message.default_pool.FindFieldByName(full_name)
|
| +
|
| def __init__(self, name, full_name, index, number, type, cpp_type, label,
|
| default_value, message_type, enum_type, containing_type,
|
| is_extension, extension_scope, options=None,
|
| - has_default_value=True):
|
| + has_default_value=True, containing_oneof=None):
|
| """The arguments are as described in the description of FieldDescriptor
|
| attributes above.
|
|
|
| @@ -439,6 +518,7 @@ class FieldDescriptor(DescriptorBase):
|
| super(FieldDescriptor, self).__init__(options, 'FieldOptions')
|
| self.name = name
|
| self.full_name = full_name
|
| + self._camelcase_name = None
|
| self.index = index
|
| self.number = number
|
| self.type = type
|
| @@ -451,20 +531,21 @@ class FieldDescriptor(DescriptorBase):
|
| self.enum_type = enum_type
|
| self.is_extension = is_extension
|
| self.extension_scope = extension_scope
|
| + self.containing_oneof = containing_oneof
|
| if api_implementation.Type() == 'cpp':
|
| if is_extension:
|
| - if api_implementation.Version() == 2:
|
| - self._cdescriptor = _message.GetExtensionDescriptor(full_name)
|
| - else:
|
| - self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
|
| + self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
|
| else:
|
| - if api_implementation.Version() == 2:
|
| - self._cdescriptor = _message.GetFieldDescriptor(full_name)
|
| - else:
|
| - self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
|
| + self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
|
| else:
|
| self._cdescriptor = None
|
|
|
| + @property
|
| + def camelcase_name(self):
|
| + if self._camelcase_name is None:
|
| + self._camelcase_name = _ToCamelCase(self.name)
|
| + return self._camelcase_name
|
| +
|
| @staticmethod
|
| def ProtoTypeToCppProtoType(proto_type):
|
| """Converts from a Python proto type to a C++ Proto Type.
|
| @@ -511,6 +592,15 @@ class EnumDescriptor(_NestedDescriptorBase):
|
| None to use default enum options.
|
| """
|
|
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
|
| +
|
| + def __new__(cls, name, full_name, filename, values,
|
| + containing_type=None, options=None, file=None,
|
| + serialized_start=None, serialized_end=None):
|
| + _message.Message._CheckCalledFromGeneratedFile()
|
| + return _message.default_pool.FindEnumTypeByName(full_name)
|
| +
|
| def __init__(self, name, full_name, filename, values,
|
| containing_type=None, options=None, file=None,
|
| serialized_start=None, serialized_end=None):
|
| @@ -522,7 +612,7 @@ class EnumDescriptor(_NestedDescriptorBase):
|
| super(EnumDescriptor, self).__init__(
|
| options, 'EnumOptions', name, full_name, file,
|
| containing_type, serialized_start=serialized_start,
|
| - serialized_end=serialized_start)
|
| + serialized_end=serialized_end)
|
|
|
| self.values = values
|
| for value in self.values:
|
| @@ -530,9 +620,6 @@ class EnumDescriptor(_NestedDescriptorBase):
|
| self.values_by_name = dict((v.name, v) for v in values)
|
| self.values_by_number = dict((v.number, v) for v in values)
|
|
|
| - self._serialized_start = serialized_start
|
| - self._serialized_end = serialized_end
|
| -
|
| def CopyToProto(self, proto):
|
| """Copies this to a descriptor_pb2.EnumDescriptorProto.
|
|
|
| @@ -558,6 +645,17 @@ class EnumValueDescriptor(DescriptorBase):
|
| None to use default enum value options options.
|
| """
|
|
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
|
| +
|
| + def __new__(cls, name, index, number, type=None, options=None):
|
| + _message.Message._CheckCalledFromGeneratedFile()
|
| + # There is no way we can build a complete EnumValueDescriptor with the
|
| + # given parameters (the name of the Enum is not known, for example).
|
| + # Fortunately generated files just pass it to the EnumDescriptor()
|
| + # constructor, which will ignore it, so returning None is good enough.
|
| + return None
|
| +
|
| def __init__(self, name, index, number, type=None, options=None):
|
| """Arguments are as described in the attribute description above."""
|
| super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
|
| @@ -567,6 +665,36 @@ class EnumValueDescriptor(DescriptorBase):
|
| self.type = type
|
|
|
|
|
| +class OneofDescriptor(object):
|
| + """Descriptor for a oneof field.
|
| +
|
| + name: (str) Name of the oneof field.
|
| + full_name: (str) Full name of the oneof field, including package name.
|
| + index: (int) 0-based index giving the order of the oneof field inside
|
| + its containing type.
|
| + containing_type: (Descriptor) Descriptor of the protocol message
|
| + type that contains this field. Set by the Descriptor constructor
|
| + if we're passed into one.
|
| + fields: (list of FieldDescriptor) The list of field descriptors this
|
| + oneof can contain.
|
| + """
|
| +
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
|
| +
|
| + def __new__(cls, name, full_name, index, containing_type, fields):
|
| + _message.Message._CheckCalledFromGeneratedFile()
|
| + return _message.default_pool.FindOneofByName(full_name)
|
| +
|
| + def __init__(self, name, full_name, index, containing_type, fields):
|
| + """Arguments are as described in the attribute description above."""
|
| + self.name = name
|
| + self.full_name = full_name
|
| + self.index = index
|
| + self.containing_type = containing_type
|
| + self.fields = fields
|
| +
|
| +
|
| class ServiceDescriptor(_NestedDescriptorBase):
|
|
|
| """Descriptor for a service.
|
| @@ -645,26 +773,59 @@ class MethodDescriptor(DescriptorBase):
|
| class FileDescriptor(DescriptorBase):
|
| """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
|
|
|
| + Note that enum_types_by_name, extensions_by_name, and dependencies
|
| + fields are only set by the message_factory module, and not by the
|
| + generated proto code.
|
| +
|
| name: name of file, relative to root of source tree.
|
| package: name of the package
|
| + syntax: string indicating syntax of the file (can be "proto2" or "proto3")
|
| serialized_pb: (str) Byte string of serialized
|
| descriptor_pb2.FileDescriptorProto.
|
| + dependencies: List of other FileDescriptors this FileDescriptor depends on.
|
| + message_types_by_name: Dict of message names of their descriptors.
|
| + enum_types_by_name: Dict of enum names and their descriptors.
|
| + extensions_by_name: Dict of extension names and their descriptors.
|
| + pool: the DescriptorPool this descriptor belongs to. When not passed to the
|
| + constructor, the global default pool is used.
|
| """
|
|
|
| - def __init__(self, name, package, options=None, serialized_pb=None):
|
| + if _USE_C_DESCRIPTORS:
|
| + _C_DESCRIPTOR_CLASS = _message.FileDescriptor
|
| +
|
| + def __new__(cls, name, package, options=None, serialized_pb=None,
|
| + dependencies=None, syntax=None, pool=None):
|
| + # FileDescriptor() is called from various places, not only from generated
|
| + # files, to register dynamic proto files and messages.
|
| + if serialized_pb:
|
| + # TODO(amauryfa): use the pool passed as argument. This will work only
|
| + # for C++-implemented DescriptorPools.
|
| + return _message.default_pool.AddSerializedFile(serialized_pb)
|
| + else:
|
| + return super(FileDescriptor, cls).__new__(cls)
|
| +
|
| + def __init__(self, name, package, options=None, serialized_pb=None,
|
| + dependencies=None, syntax=None, pool=None):
|
| """Constructor."""
|
| super(FileDescriptor, self).__init__(options, 'FileOptions')
|
|
|
| + if pool is None:
|
| + from google.protobuf import descriptor_pool
|
| + pool = descriptor_pool.Default()
|
| + self.pool = pool
|
| self.message_types_by_name = {}
|
| self.name = name
|
| self.package = package
|
| + self.syntax = syntax or "proto2"
|
| self.serialized_pb = serialized_pb
|
| +
|
| + self.enum_types_by_name = {}
|
| + self.extensions_by_name = {}
|
| + self.dependencies = (dependencies or [])
|
| +
|
| if (api_implementation.Type() == 'cpp' and
|
| self.serialized_pb is not None):
|
| - if api_implementation.Version() == 2:
|
| - _message.BuildFile(self.serialized_pb)
|
| - else:
|
| - cpp_message.BuildFile(self.serialized_pb)
|
| + _message.default_pool.AddSerializedFile(self.serialized_pb)
|
|
|
| def CopyToProto(self, proto):
|
| """Copies this to a descriptor_pb2.FileDescriptorProto.
|
| @@ -685,29 +846,121 @@ def _ParseOptions(message, string):
|
| return message
|
|
|
|
|
| -def MakeDescriptor(desc_proto, package=''):
|
| +def _ToCamelCase(name):
|
| + """Converts name to camel-case and returns it."""
|
| + capitalize_next = False
|
| + result = []
|
| +
|
| + for c in name:
|
| + if c == '_':
|
| + if result:
|
| + capitalize_next = True
|
| + elif capitalize_next:
|
| + result.append(c.upper())
|
| + capitalize_next = False
|
| + else:
|
| + result += c
|
| +
|
| + # Lower-case the first letter.
|
| + if result and result[0].isupper():
|
| + result[0] = result[0].lower()
|
| + return ''.join(result)
|
| +
|
| +
|
| +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
|
| + syntax=None):
|
| """Make a protobuf Descriptor given a DescriptorProto protobuf.
|
|
|
| + Handles nested descriptors. Note that this is limited to the scope of defining
|
| + a message inside of another message. Composite fields can currently only be
|
| + resolved if the message is defined in the same scope as the field.
|
| +
|
| Args:
|
| desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
|
| package: Optional package name for the new message Descriptor (string).
|
| -
|
| + build_file_if_cpp: Update the C++ descriptor pool if api matches.
|
| + Set to False on recursion, so no duplicates are created.
|
| + syntax: The syntax/semantics that should be used. Set to "proto3" to get
|
| + proto3 field presence semantics.
|
| Returns:
|
| A Descriptor for protobuf messages.
|
| """
|
| + if api_implementation.Type() == 'cpp' and build_file_if_cpp:
|
| + # The C++ implementation requires all descriptors to be backed by the same
|
| + # definition in the C++ descriptor pool. To do this, we build a
|
| + # FileDescriptorProto with the same definition as this descriptor and build
|
| + # it into the pool.
|
| + from google.protobuf import descriptor_pb2
|
| + file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
|
| + file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
|
| +
|
| + # Generate a random name for this proto file to prevent conflicts with any
|
| + # imported ones. We need to specify a file name so the descriptor pool
|
| + # accepts our FileDescriptorProto, but it is not important what that file
|
| + # name is actually set to.
|
| + proto_name = str(uuid.uuid4())
|
| +
|
| + if package:
|
| + file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
|
| + proto_name + '.proto')
|
| + file_descriptor_proto.package = package
|
| + else:
|
| + file_descriptor_proto.name = proto_name + '.proto'
|
| +
|
| + _message.default_pool.Add(file_descriptor_proto)
|
| + result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
|
| +
|
| + if _USE_C_DESCRIPTORS:
|
| + return result.message_types_by_name[desc_proto.name]
|
| +
|
| full_message_name = [desc_proto.name]
|
| if package: full_message_name.insert(0, package)
|
| +
|
| + # Create Descriptors for enum types
|
| + enum_types = {}
|
| + for enum_proto in desc_proto.enum_type:
|
| + full_name = '.'.join(full_message_name + [enum_proto.name])
|
| + enum_desc = EnumDescriptor(
|
| + enum_proto.name, full_name, None, [
|
| + EnumValueDescriptor(enum_val.name, ii, enum_val.number)
|
| + for ii, enum_val in enumerate(enum_proto.value)])
|
| + enum_types[full_name] = enum_desc
|
| +
|
| + # Create Descriptors for nested types
|
| + nested_types = {}
|
| + for nested_proto in desc_proto.nested_type:
|
| + full_name = '.'.join(full_message_name + [nested_proto.name])
|
| + # Nested types are just those defined inside of the message, not all types
|
| + # used by fields in the message, so no loops are possible here.
|
| + nested_desc = MakeDescriptor(nested_proto,
|
| + package='.'.join(full_message_name),
|
| + build_file_if_cpp=False,
|
| + syntax=syntax)
|
| + nested_types[full_name] = nested_desc
|
| +
|
| fields = []
|
| for field_proto in desc_proto.field:
|
| full_name = '.'.join(full_message_name + [field_proto.name])
|
| + enum_desc = None
|
| + nested_desc = None
|
| + if field_proto.HasField('type_name'):
|
| + type_name = field_proto.type_name
|
| + full_type_name = '.'.join(full_message_name +
|
| + [type_name[type_name.rfind('.')+1:]])
|
| + if full_type_name in nested_types:
|
| + nested_desc = nested_types[full_type_name]
|
| + elif full_type_name in enum_types:
|
| + enum_desc = enum_types[full_type_name]
|
| + # Else type_name references a non-local type, which isn't implemented
|
| field = FieldDescriptor(
|
| field_proto.name, full_name, field_proto.number - 1,
|
| field_proto.number, field_proto.type,
|
| FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
|
| - field_proto.label, None, None, None, None, False, None,
|
| - has_default_value=False)
|
| + field_proto.label, None, nested_desc, enum_desc, None, False, None,
|
| + options=field_proto.options, has_default_value=False)
|
| fields.append(field)
|
|
|
| desc_name = '.'.join(full_message_name)
|
| return Descriptor(desc_proto.name, desc_name, None, None, fields,
|
| - [], [], [])
|
| + list(nested_types.values()), list(enum_types.values()), [],
|
| + options=desc_proto.options)
|
|
|