Ejemplo n.º 1
0
    def testDuplicateExtensionNumber(self):
        pool = descriptor_pool.DescriptorPool()
        factory = message_factory.MessageFactory(pool=pool)

        # Add Container message.
        f = descriptor_pb2.FileDescriptorProto()
        f.name = 'google/protobuf/internal/container.proto'
        f.package = 'google.protobuf.python.internal'
        msg = f.message_type.add()
        msg.name = 'Container'
        rng = msg.extension_range.add()
        rng.start = 1
        rng.end = 10
        pool.Add(f)
        msgs = factory.GetMessages([f.name])
        self.assertIn('google.protobuf.python.internal.Container', msgs)

        # Extend container.
        f = descriptor_pb2.FileDescriptorProto()
        f.name = 'google/protobuf/internal/extension.proto'
        f.package = 'google.protobuf.python.internal'
        f.dependency.append('google/protobuf/internal/container.proto')
        msg = f.message_type.add()
        msg.name = 'Extension'
        ext = msg.extension.add()
        ext.name = 'extension_field'
        ext.number = 2
        ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
        ext.type_name = 'Extension'
        ext.extendee = 'Container'
        pool.Add(f)
        msgs = factory.GetMessages([f.name])
        self.assertIn('google.protobuf.python.internal.Extension', msgs)

        # Add Duplicate extending the same field number.
        f = descriptor_pb2.FileDescriptorProto()
        f.name = 'google/protobuf/internal/duplicate.proto'
        f.package = 'google.protobuf.python.internal'
        f.dependency.append('google/protobuf/internal/container.proto')
        msg = f.message_type.add()
        msg.name = 'Duplicate'
        ext = msg.extension.add()
        ext.name = 'extension_field'
        ext.number = 2
        ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
        ext.type_name = 'Duplicate'
        ext.extendee = 'Container'
        pool.Add(f)

        with self.assertRaises(Exception) as cm:
            factory.GetMessages([f.name])

        self.assertIn(str(cm.exception), [
            'Extensions '
            '"google.protobuf.python.internal.Duplicate.extension_field" and'
            ' "google.protobuf.python.internal.Extension.extension_field"'
            ' both try to extend message type'
            ' "google.protobuf.python.internal.Container"'
            ' with field number 2.', 'Double registration of Extensions'
        ])
Ejemplo n.º 2
0
 def testCustomDescriptorPool(self):
   # Create a new pool, and add a file descriptor.
   pool = descriptor_pool.DescriptorPool()
   file_desc = descriptor_pb2.FileDescriptorProto(
       name='some/file.proto', package='package')
   file_desc.message_type.add(name='Message')
   pool.Add(file_desc)
   self.assertEqual(pool.FindFileByName('some/file.proto').name,
                    'some/file.proto')
   self.assertEqual(pool.FindMessageTypeByName('package.Message').name,
                    'Message')
   # Test no package
   file_proto = descriptor_pb2.FileDescriptorProto(
       name='some/filename/container.proto')
   message_proto = file_proto.message_type.add(
       name='TopMessage')
   message_proto.field.add(
       name='bb',
       number=1,
       type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
       label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL)
   enum_proto = file_proto.enum_type.add(name='TopEnum')
   enum_proto.value.add(name='FOREIGN_FOO', number=4)
   file_proto.service.add(name='TopService')
   pool = descriptor_pool.DescriptorPool()
   pool.Add(file_proto)
   self.assertEqual('TopMessage',
                    pool.FindMessageTypeByName('TopMessage').name)
   self.assertEqual('TopEnum', pool.FindEnumTypeByName('TopEnum').name)
   self.assertEqual('TopService', pool.FindServiceByName('TopService').name)
Ejemplo n.º 3
0
  def testMakeDescriptorWithUnsignedIntField(self):
    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
    file_descriptor_proto.name = 'Foo'
    message_type = file_descriptor_proto.message_type.add()
    message_type.name = file_descriptor_proto.name
    enum_type = message_type.enum_type.add()
    enum_type.name = 'FOO'
    enum_type_val = enum_type.value.add()
    enum_type_val.name = 'BAR'
    enum_type_val.number = 3
    field = message_type.field.add()
    field.number = 1
    field.name = 'uint64_field'
    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
    field.type = descriptor.FieldDescriptor.TYPE_UINT64
    enum_field = message_type.field.add()
    enum_field.number = 2
    enum_field.name = 'bar_field'
    enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
    enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM
    enum_field.type_name = 'Foo.FOO'

    result = descriptor.MakeDescriptor(message_type)
    self.assertEqual(result.fields[0].cpp_type,
                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
Ejemplo n.º 4
0
  def setUp(self):
    file_proto = descriptor_pb2.FileDescriptorProto(
        name='some/filename/some.proto',
        package='protobuf_unittest')
    message_proto = file_proto.message_type.add(
        name='NestedMessage')
    message_proto.field.add(
        name='bb',
        number=1,
        type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
        label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL)
    enum_proto = message_proto.enum_type.add(
        name='ForeignEnum')
    enum_proto.value.add(name='FOREIGN_FOO', number=4)
    enum_proto.value.add(name='FOREIGN_BAR', number=5)
    enum_proto.value.add(name='FOREIGN_BAZ', number=6)

    file_proto.message_type.add(name='ResponseMessage')
    service_proto = file_proto.service.add(
        name='Service')
    method_proto = service_proto.method.add(
        name='CallMethod',
        input_type='.protobuf_unittest.NestedMessage',
        output_type='.protobuf_unittest.ResponseMessage')

    # Note: Calling DescriptorPool.Add() multiple times with the same file only
    # works if the input is canonical; in particular, all type names must be
    # fully qualified.
    self.pool = self.GetDescriptorPool()
    self.pool.Add(file_proto)
    self.my_file = self.pool.FindFileByName(file_proto.name)
    self.my_message = self.my_file.message_types_by_name[message_proto.name]
    self.my_enum = self.my_message.enum_types_by_name[enum_proto.name]
    self.my_service = self.my_file.services_by_name[service_proto.name]
    self.my_method = self.my_service.methods_by_name[method_proto.name]
Ejemplo n.º 5
0
 def testAddFileDescriptor(self):
   if isinstance(self, SecondaryDescriptorFromDescriptorDB):
     if api_implementation.Type() == 'cpp':
       # Cpp extension cannot call Add on a DescriptorPool
       # that uses a DescriptorDatabase.
       # TODO(jieluo): Fix python and cpp extension diff.
       return
   file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto')
   self.pool.Add(file_desc)
   self.pool.AddSerializedFile(file_desc.SerializeToString())
Ejemplo n.º 6
0
 def testEmptyDescriptorPool(self):
   # Check that an empty DescriptorPool() contains no messages.
   pool = descriptor_pool.DescriptorPool()
   proto_file_name = descriptor_pb2.DESCRIPTOR.name
   self.assertRaises(KeyError, pool.FindFileByName, proto_file_name)
   # Add the above file to the pool
   file_descriptor = descriptor_pb2.FileDescriptorProto()
   descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor)
   pool.Add(file_descriptor)
   # Now it exists.
   self.assertTrue(pool.FindFileByName(proto_file_name))
Ejemplo n.º 7
0
 def testFileDescriptor(self):
   self.assertEqual(self.my_file.name, 'some/filename/some.proto')
   self.assertEqual(self.my_file.package, 'protobuf_unittest')
   self.assertEqual(self.my_file.pool, self.pool)
   self.assertFalse(self.my_file.has_options)
   self.assertEqual('proto2', self.my_file.syntax)
   file_proto = descriptor_pb2.FileDescriptorProto()
   self.my_file.CopyToProto(file_proto)
   self.assertEqual(self.my_file.serialized_pb,
                    file_proto.SerializeToString())
   # Generated modules also belong to the default pool.
   self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default())
Ejemplo n.º 8
0
 def testCopyToProto_TypeError(self):
   file_proto = descriptor_pb2.FileDescriptorProto()
   self.assertRaises(TypeError,
                     unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto,
                     file_proto)
   self.assertRaises(TypeError,
                     unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto,
                     file_proto)
   self.assertRaises(TypeError,
                     unittest_pb2.TestService.DESCRIPTOR.CopyToProto,
                     file_proto)
   proto = descriptor_pb2.DescriptorProto()
   self.assertRaises(TypeError,
                     unittest_import_pb2.DESCRIPTOR.CopyToProto,
                     proto)
Ejemplo n.º 9
0
def _MakeFileDescriptorProto(proto_file_name, full_name, field_items):
    """Populate FileDescriptorProto for MessageFactory's DescriptorPool."""
    package, name = full_name.rsplit('.', 1)
    file_proto = descriptor_pb2.FileDescriptorProto()
    file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name)
    file_proto.package = package
    desc_proto = file_proto.message_type.add()
    desc_proto.name = name
    for f_number, (f_name, f_type) in enumerate(field_items, 1):
        field_proto = desc_proto.field.add()
        field_proto.name = f_name
        field_proto.number = f_number
        field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
        field_proto.type = f_type
    return file_proto
Ejemplo n.º 10
0
 def testFileDescriptorOptionsWithCustomDescriptorPool(self):
   # Create a descriptor pool, and add a new FileDescriptorProto to it.
   pool = descriptor_pool.DescriptorPool()
   file_name = 'file_descriptor_options_with_custom_descriptor_pool.proto'
   file_descriptor_proto = descriptor_pb2.FileDescriptorProto(name=file_name)
   extension_id = file_options_test_pb2.foo_options
   file_descriptor_proto.options.Extensions[extension_id].foo_name = 'foo'
   pool.Add(file_descriptor_proto)
   # The options set on the FileDescriptorProto should be available in the
   # descriptor even if they contain extensions that cannot be deserialized
   # using the pool.
   file_descriptor = pool.FindFileByName(file_name)
   options = file_descriptor.GetOptions()
   self.assertEqual('foo', options.Extensions[extension_id].foo_name)
   # The object returned by GetOptions() is cached.
   self.assertIs(options, file_descriptor.GetOptions())
Ejemplo n.º 11
0
  def testMakeDescriptorWithNestedFields(self):
    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
    file_descriptor_proto.name = 'Foo2'
    message_type = file_descriptor_proto.message_type.add()
    message_type.name = file_descriptor_proto.name
    nested_type = message_type.nested_type.add()
    nested_type.name = 'Sub'
    enum_type = nested_type.enum_type.add()
    enum_type.name = 'FOO'
    enum_type_val = enum_type.value.add()
    enum_type_val.name = 'BAR'
    enum_type_val.number = 3
    field = message_type.field.add()
    field.number = 1
    field.name = 'uint64_field'
    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
    field.type = descriptor.FieldDescriptor.TYPE_UINT64
    field = message_type.field.add()
    field.number = 2
    field.name = 'nested_message_field'
    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
    field.type = descriptor.FieldDescriptor.TYPE_MESSAGE
    field.type_name = 'Sub'
    enum_field = nested_type.field.add()
    enum_field.number = 2
    enum_field.name = 'bar_field'
    enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
    enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM
    enum_field.type_name = 'Foo2.Sub.FOO'

    result = descriptor.MakeDescriptor(message_type)
    self.assertEqual(result.fields[0].cpp_type,
                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
    self.assertEqual(result.fields[1].cpp_type,
                     descriptor.FieldDescriptor.CPPTYPE_MESSAGE)
    self.assertEqual(result.fields[1].message_type.containing_type,
                     result)
    self.assertEqual(result.nested_types[0].fields[0].full_name,
                     'Foo2.Sub.bar_field')
    self.assertEqual(result.nested_types[0].fields[0].enum_type,
                     result.nested_types[0].enum_types[0])
    self.assertFalse(result.has_options)
    self.assertFalse(result.fields[0].has_options)
    if api_implementation.Type() == 'cpp':
      with self.assertRaises(AttributeError):
        result.fields[0].has_options = False
Ejemplo n.º 12
0
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 getuipy.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 = binascii.hexlify(os.urandom(16)).decode('ascii')

    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.json_name:
      json_name = field_proto.json_name
    else:
      json_name = 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, nested_desc, enum_desc, None, False, None,
        options=_OptionsOrNone(field_proto), has_default_value=False,
        json_name=json_name)
    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=_OptionsOrNone(desc_proto))