Skip to content

message_factory

Provides a factory class for generating dynamic messages.

The easiest way to use this class is if you have access to the FileDescriptor protos containing the messages you want to create you can just do the following:

message_classes = message_factory.GetMessages(iterable_of_file_descriptors) my_proto_instance = message_classes'some.proto.package.MessageName'

MessageFactory

Bases: object

Factory for creating Proto2 messages from descriptors in a pool.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
class MessageFactory(object):
  """Factory for creating Proto2 messages from descriptors in a pool."""

  def __init__(self, pool=None):
    """Initializes a new factory."""
    self.pool = pool or descriptor_pool.DescriptorPool()

    # local cache of all classes built from protobuf descriptors
    self._classes = {}

  def GetPrototype(self, descriptor):
    """Obtains a proto2 message class based on the passed in descriptor.

    Passing a descriptor with a fully qualified name matching a previous
    invocation will cause the same class to be returned.

    Args:
      descriptor: The descriptor to build from.

    Returns:
      A class describing the passed in descriptor.
    """
    if descriptor not in self._classes:
      result_class = self.CreatePrototype(descriptor)
      # The assignment to _classes is redundant for the base implementation, but
      # might avoid confusion in cases where CreatePrototype gets overridden and
      # does not call the base implementation.
      self._classes[descriptor] = result_class
      return result_class
    return self._classes[descriptor]

  def CreatePrototype(self, descriptor):
    """Builds a proto2 message class based on the passed in descriptor.

    Don't call this function directly, it always creates a new class. Call
    GetPrototype() instead. This method is meant to be overridden in subblasses
    to perform additional operations on the newly constructed class.

    Args:
      descriptor: The descriptor to build from.

    Returns:
      A class describing the passed in descriptor.
    """
    descriptor_name = descriptor.name
    result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
        descriptor_name,
        (message.Message,),
        {
            'DESCRIPTOR': descriptor,
            # If module not set, it wrongly points to message_factory module.
            '__module__': None,
        })
    result_class._FACTORY = self  # pylint: disable=protected-access
    # Assign in _classes before doing recursive calls to avoid infinite
    # recursion.
    self._classes[descriptor] = result_class
    for field in descriptor.fields:
      if field.message_type:
        self.GetPrototype(field.message_type)
    for extension in result_class.DESCRIPTOR.extensions:
      if extension.containing_type not in self._classes:
        self.GetPrototype(extension.containing_type)
      extended_class = self._classes[extension.containing_type]
      extended_class.RegisterExtension(extension)
    return result_class

  def GetMessages(self, files):
    """Gets all the messages from a specified file.

    This will find and resolve dependencies, failing if the descriptor
    pool cannot satisfy them.

    Args:
      files: The file names to extract messages from.

    Returns:
      A dictionary mapping proto names to the message classes. This will include
      any dependent messages as well as any messages defined in the same file as
      a specified message.
    """
    result = {}
    for file_name in files:
      file_desc = self.pool.FindFileByName(file_name)
      for desc in file_desc.message_types_by_name.values():
        result[desc.full_name] = self.GetPrototype(desc)

      # While the extension FieldDescriptors are created by the descriptor pool,
      # the python classes created in the factory need them to be registered
      # explicitly, which is done below.
      #
      # The call to RegisterExtension will specifically check if the
      # extension was already registered on the object and either
      # ignore the registration if the original was the same, or raise
      # an error if they were different.

      for extension in file_desc.extensions_by_name.values():
        if extension.containing_type not in self._classes:
          self.GetPrototype(extension.containing_type)
        extended_class = self._classes[extension.containing_type]
        extended_class.RegisterExtension(extension)
    return result

CreatePrototype(descriptor)

Builds a proto2 message class based on the passed in descriptor.

Don't call this function directly, it always creates a new class. Call GetPrototype() instead. This method is meant to be overridden in subblasses to perform additional operations on the newly constructed class.

Parameters:

Name Type Description Default
descriptor

The descriptor to build from.

required

Returns:

Type Description

A class describing the passed in descriptor.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
def CreatePrototype(self, descriptor):
  """Builds a proto2 message class based on the passed in descriptor.

  Don't call this function directly, it always creates a new class. Call
  GetPrototype() instead. This method is meant to be overridden in subblasses
  to perform additional operations on the newly constructed class.

  Args:
    descriptor: The descriptor to build from.

  Returns:
    A class describing the passed in descriptor.
  """
  descriptor_name = descriptor.name
  result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
      descriptor_name,
      (message.Message,),
      {
          'DESCRIPTOR': descriptor,
          # If module not set, it wrongly points to message_factory module.
          '__module__': None,
      })
  result_class._FACTORY = self  # pylint: disable=protected-access
  # Assign in _classes before doing recursive calls to avoid infinite
  # recursion.
  self._classes[descriptor] = result_class
  for field in descriptor.fields:
    if field.message_type:
      self.GetPrototype(field.message_type)
  for extension in result_class.DESCRIPTOR.extensions:
    if extension.containing_type not in self._classes:
      self.GetPrototype(extension.containing_type)
    extended_class = self._classes[extension.containing_type]
    extended_class.RegisterExtension(extension)
  return result_class

GetMessages(files)

Gets all the messages from a specified file.

This will find and resolve dependencies, failing if the descriptor pool cannot satisfy them.

Parameters:

Name Type Description Default
files

The file names to extract messages from.

required

Returns:

Type Description

A dictionary mapping proto names to the message classes. This will include

any dependent messages as well as any messages defined in the same file as

a specified message.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def GetMessages(self, files):
  """Gets all the messages from a specified file.

  This will find and resolve dependencies, failing if the descriptor
  pool cannot satisfy them.

  Args:
    files: The file names to extract messages from.

  Returns:
    A dictionary mapping proto names to the message classes. This will include
    any dependent messages as well as any messages defined in the same file as
    a specified message.
  """
  result = {}
  for file_name in files:
    file_desc = self.pool.FindFileByName(file_name)
    for desc in file_desc.message_types_by_name.values():
      result[desc.full_name] = self.GetPrototype(desc)

    # While the extension FieldDescriptors are created by the descriptor pool,
    # the python classes created in the factory need them to be registered
    # explicitly, which is done below.
    #
    # The call to RegisterExtension will specifically check if the
    # extension was already registered on the object and either
    # ignore the registration if the original was the same, or raise
    # an error if they were different.

    for extension in file_desc.extensions_by_name.values():
      if extension.containing_type not in self._classes:
        self.GetPrototype(extension.containing_type)
      extended_class = self._classes[extension.containing_type]
      extended_class.RegisterExtension(extension)
  return result

GetPrototype(descriptor)

Obtains a proto2 message class based on the passed in descriptor.

Passing a descriptor with a fully qualified name matching a previous invocation will cause the same class to be returned.

Parameters:

Name Type Description Default
descriptor

The descriptor to build from.

required

Returns:

Type Description

A class describing the passed in descriptor.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def GetPrototype(self, descriptor):
  """Obtains a proto2 message class based on the passed in descriptor.

  Passing a descriptor with a fully qualified name matching a previous
  invocation will cause the same class to be returned.

  Args:
    descriptor: The descriptor to build from.

  Returns:
    A class describing the passed in descriptor.
  """
  if descriptor not in self._classes:
    result_class = self.CreatePrototype(descriptor)
    # The assignment to _classes is redundant for the base implementation, but
    # might avoid confusion in cases where CreatePrototype gets overridden and
    # does not call the base implementation.
    self._classes[descriptor] = result_class
    return result_class
  return self._classes[descriptor]

__init__(pool=None)

Initializes a new factory.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
59
60
61
62
63
64
def __init__(self, pool=None):
  """Initializes a new factory."""
  self.pool = pool or descriptor_pool.DescriptorPool()

  # local cache of all classes built from protobuf descriptors
  self._classes = {}

GetMessages(file_protos)

Builds a dictionary of all the messages available in a set of files.

Parameters:

Name Type Description Default
file_protos

Iterable of FileDescriptorProto to build messages out of.

required

Returns:

Type Description

A dictionary mapping proto names to the message classes. This will include

any dependent messages as well as any messages defined in the same file as

a specified message.

Source code in client/ayon_nuke/vendor/google/protobuf/message_factory.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def GetMessages(file_protos):
  """Builds a dictionary of all the messages available in a set of files.

  Args:
    file_protos: Iterable of FileDescriptorProto to build messages out of.

  Returns:
    A dictionary mapping proto names to the message classes. This will include
    any dependent messages as well as any messages defined in the same file as
    a specified message.
  """
  # The cpp implementation of the protocol buffer library requires to add the
  # message in topological order of the dependency graph.
  file_by_name = {file_proto.name: file_proto for file_proto in file_protos}
  def _AddFile(file_proto):
    for dependency in file_proto.dependency:
      if dependency in file_by_name:
        # Remove from elements to be visited, in order to cut cycles.
        _AddFile(file_by_name.pop(dependency))
    _FACTORY.pool.Add(file_proto)
  while file_by_name:
    _AddFile(file_by_name.popitem()[1])
  return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos])