aboutsummaryrefslogtreecommitdiff
path: root/generator/google/protobuf/reflection.py
diff options
context:
space:
mode:
Diffstat (limited to 'generator/google/protobuf/reflection.py')
-rw-r--r--generator/google/protobuf/reflection.py139
1 files changed, 42 insertions, 97 deletions
diff --git a/generator/google/protobuf/reflection.py b/generator/google/protobuf/reflection.py
index 9570fd5..51c8332 100644
--- a/generator/google/protobuf/reflection.py
+++ b/generator/google/protobuf/reflection.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
@@ -49,104 +49,17 @@ __author__ = 'robinson@google.com (Will Robinson)'
from google.protobuf.internal import api_implementation
-from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message
-_FieldDescriptor = descriptor_mod.FieldDescriptor
-
if api_implementation.Type() == 'cpp':
- if api_implementation.Version() == 2:
- from google.protobuf.internal.cpp import cpp_message
- _NewMessage = cpp_message.NewMessage
- _InitMessage = cpp_message.InitMessage
- else:
- from google.protobuf.internal import cpp_message
- _NewMessage = cpp_message.NewMessage
- _InitMessage = cpp_message.InitMessage
+ from google.protobuf.pyext import cpp_message as message_impl
else:
- from google.protobuf.internal import python_message
- _NewMessage = python_message.NewMessage
- _InitMessage = python_message.InitMessage
-
-
-class GeneratedProtocolMessageType(type):
+ from google.protobuf.internal import python_message as message_impl
- """Metaclass for protocol message classes created at runtime from Descriptors.
-
- We add implementations for all methods described in the Message class. We
- also create properties to allow getting/setting all fields in the protocol
- message. Finally, we create slots to prevent users from accidentally
- "setting" nonexistent fields in the protocol message, which then wouldn't get
- serialized / deserialized properly.
-
- The protocol compiler currently uses this metaclass to create protocol
- message classes at runtime. Clients can also manually create their own
- classes at runtime, as in this example:
-
- mydescriptor = Descriptor(.....)
- class MyProtoClass(Message):
- __metaclass__ = GeneratedProtocolMessageType
- DESCRIPTOR = mydescriptor
- myproto_instance = MyProtoClass()
- myproto.foo_field = 23
- ...
- """
-
- # Must be consistent with the protocol-compiler code in
- # proto2/compiler/internal/generator.*.
- _DESCRIPTOR_KEY = 'DESCRIPTOR'
-
- def __new__(cls, name, bases, dictionary):
- """Custom allocation for runtime-generated class types.
-
- We override __new__ because this is apparently the only place
- where we can meaningfully set __slots__ on the class we're creating(?).
- (The interplay between metaclasses and slots is not very well-documented).
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
-
- Returns:
- Newly-allocated class.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- bases = _NewMessage(bases, descriptor, dictionary)
- superclass = super(GeneratedProtocolMessageType, cls)
-
- new_class = superclass.__new__(cls, name, bases, dictionary)
- setattr(descriptor, '_concrete_class', new_class)
- return new_class
-
- def __init__(cls, name, bases, dictionary):
- """Here we perform the majority of our work on the class.
- We add enum getters, an __init__ method, implementations
- of all Message methods, and properties for all fields
- in the protocol type.
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- _InitMessage(descriptor, cls)
- superclass = super(GeneratedProtocolMessageType, cls)
- superclass.__init__(name, bases, dictionary)
+# The type of all Message classes.
+# Part of the public interface, but normally only used by message factories.
+GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType
def ParseMessage(descriptor, byte_str):
@@ -159,11 +72,43 @@ def ParseMessage(descriptor, byte_str):
Returns:
Newly created protobuf Message object.
"""
+ result_class = MakeClass(descriptor)
+ new_msg = result_class()
+ new_msg.ParseFromString(byte_str)
+ return new_msg
- class _ResultClass(message.Message):
+
+def MakeClass(descriptor):
+ """Construct a class object for a protobuf described by descriptor.
+
+ Composite descriptors are handled by defining the new class as a member of the
+ parent class, recursing as deep as necessary.
+ This is the dynamic equivalent to:
+
+ class Parent(message.Message):
__metaclass__ = GeneratedProtocolMessageType
DESCRIPTOR = descriptor
+ class Child(message.Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = descriptor.nested_types[0]
- new_msg = _ResultClass()
- new_msg.ParseFromString(byte_str)
- return new_msg
+ Sample usage:
+ file_descriptor = descriptor_pb2.FileDescriptorProto()
+ file_descriptor.ParseFromString(proto2_string)
+ msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0])
+ msg_class = reflection.MakeClass(msg_descriptor)
+ msg = msg_class()
+
+ Args:
+ descriptor: A descriptor.Descriptor object describing the protobuf.
+ Returns:
+ The Message class object described by the descriptor.
+ """
+ attributes = {}
+ for name, nested_type in descriptor.nested_types_by_name.items():
+ attributes[name] = MakeClass(nested_type)
+
+ attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor
+
+ return GeneratedProtocolMessageType(str(descriptor.name), (message.Message,),
+ attributes)