1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc.  All rights reserved.
3# http://code.google.com/p/protobuf/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9#     * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15#     * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Descriptors essentially contain exactly the information found in a .proto
32file, in types that make this information accessible in Python.
33"""
34
35__author__ = 'robinson@google.com (Will Robinson)'
36
37
38from google.protobuf.internal import api_implementation
39
40
41if api_implementation.Type() == 'cpp':
42  if api_implementation.Version() == 2:
43    from google.protobuf.internal.cpp import _message
44  else:
45    from google.protobuf.internal import cpp_message
46
47
48class Error(Exception):
49  """Base error for this module."""
50
51
52class TypeTransformationError(Error):
53  """Error transforming between python proto type and corresponding C++ type."""
54
55
56class DescriptorBase(object):
57
58  """Descriptors base class.
59
60  This class is the base of all descriptor classes. It provides common options
61  related functionaility.
62
63  Attributes:
64    has_options:  True if the descriptor has non-default options.  Usually it
65        is not necessary to read this -- just call GetOptions() which will
66        happily return the default instance.  However, it's sometimes useful
67        for efficiency, and also useful inside the protobuf implementation to
68        avoid some bootstrapping issues.
69  """
70
71  def __init__(self, options, options_class_name):
72    """Initialize the descriptor given its options message and the name of the
73    class of the options message. The name of the class is required in case
74    the options message is None and has to be created.
75    """
76    self._options = options
77    self._options_class_name = options_class_name
78
79    # Does this descriptor have non-default options?
80    self.has_options = options is not None
81
82  def _SetOptions(self, options, options_class_name):
83    """Sets the descriptor's options
84
85    This function is used in generated proto2 files to update descriptor
86    options. It must not be used outside proto2.
87    """
88    self._options = options
89    self._options_class_name = options_class_name
90
91    # Does this descriptor have non-default options?
92    self.has_options = options is not None
93
94  def GetOptions(self):
95    """Retrieves descriptor options.
96
97    This method returns the options set or creates the default options for the
98    descriptor.
99    """
100    if self._options:
101      return self._options
102    from google.protobuf import descriptor_pb2
103    try:
104      options_class = getattr(descriptor_pb2, self._options_class_name)
105    except AttributeError:
106      raise RuntimeError('Unknown options class name %s!' %
107                         (self._options_class_name))
108    self._options = options_class()
109    return self._options
110
111
112class _NestedDescriptorBase(DescriptorBase):
113  """Common class for descriptors that can be nested."""
114
115  def __init__(self, options, options_class_name, name, full_name,
116               file, containing_type, serialized_start=None,
117               serialized_end=None):
118    """Constructor.
119
120    Args:
121      options: Protocol message options or None
122        to use default message options.
123      options_class_name: (str) The class name of the above options.
124
125      name: (str) Name of this protocol message type.
126      full_name: (str) Fully-qualified name of this protocol message type,
127        which will include protocol "package" name and the name of any
128        enclosing types.
129      file: (FileDescriptor) Reference to file info.
130      containing_type: if provided, this is a nested descriptor, with this
131        descriptor as parent, otherwise None.
132      serialized_start: The start index (inclusive) in block in the
133        file.serialized_pb that describes this descriptor.
134      serialized_end: The end index (exclusive) in block in the
135        file.serialized_pb that describes this descriptor.
136    """
137    super(_NestedDescriptorBase, self).__init__(
138        options, options_class_name)
139
140    self.name = name
141    # TODO(falk): Add function to calculate full_name instead of having it in
142    #             memory?
143    self.full_name = full_name
144    self.file = file
145    self.containing_type = containing_type
146
147    self._serialized_start = serialized_start
148    self._serialized_end = serialized_end
149
150  def GetTopLevelContainingType(self):
151    """Returns the root if this is a nested type, or itself if its the root."""
152    desc = self
153    while desc.containing_type is not None:
154      desc = desc.containing_type
155    return desc
156
157  def CopyToProto(self, proto):
158    """Copies this to the matching proto in descriptor_pb2.
159
160    Args:
161      proto: An empty proto instance from descriptor_pb2.
162
163    Raises:
164      Error: If self couldnt be serialized, due to to few constructor arguments.
165    """
166    if (self.file is not None and
167        self._serialized_start is not None and
168        self._serialized_end is not None):
169      proto.ParseFromString(self.file.serialized_pb[
170          self._serialized_start:self._serialized_end])
171    else:
172      raise Error('Descriptor does not contain serialization.')
173
174
175class Descriptor(_NestedDescriptorBase):
176
177  """Descriptor for a protocol message type.
178
179  A Descriptor instance has the following attributes:
180
181    name: (str) Name of this protocol message type.
182    full_name: (str) Fully-qualified name of this protocol message type,
183      which will include protocol "package" name and the name of any
184      enclosing types.
185
186    containing_type: (Descriptor) Reference to the descriptor of the
187      type containing us, or None if this is top-level.
188
189    fields: (list of FieldDescriptors) Field descriptors for all
190      fields in this type.
191    fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor
192      objects as in |fields|, but indexed by "number" attribute in each
193      FieldDescriptor.
194    fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor
195      objects as in |fields|, but indexed by "name" attribute in each
196      FieldDescriptor.
197
198    nested_types: (list of Descriptors) Descriptor references
199      for all protocol message types nested within this one.
200    nested_types_by_name: (dict str -> Descriptor) Same Descriptor
201      objects as in |nested_types|, but indexed by "name" attribute
202      in each Descriptor.
203
204    enum_types: (list of EnumDescriptors) EnumDescriptor references
205      for all enums contained within this type.
206    enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor
207      objects as in |enum_types|, but indexed by "name" attribute
208      in each EnumDescriptor.
209    enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping
210      from enum value name to EnumValueDescriptor for that value.
211
212    extensions: (list of FieldDescriptor) All extensions defined directly
213      within this message type (NOT within a nested type).
214    extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor
215      objects as |extensions|, but indexed by "name" attribute of each
216      FieldDescriptor.
217
218    is_extendable:  Does this type define any extension ranges?
219
220    options: (descriptor_pb2.MessageOptions) Protocol message options or None
221      to use default message options.
222
223    file: (FileDescriptor) Reference to file descriptor.
224  """
225
226  def __init__(self, name, full_name, filename, containing_type, fields,
227               nested_types, enum_types, extensions, options=None,
228               is_extendable=True, extension_ranges=None, file=None,
229               serialized_start=None, serialized_end=None):
230    """Arguments to __init__() are as described in the description
231    of Descriptor fields above.
232
233    Note that filename is an obsolete argument, that is not used anymore.
234    Please use file.name to access this as an attribute.
235    """
236    super(Descriptor, self).__init__(
237        options, 'MessageOptions', name, full_name, file,
238        containing_type, serialized_start=serialized_start,
239        serialized_end=serialized_start)
240
241    # We have fields in addition to fields_by_name and fields_by_number,
242    # so that:
243    #   1. Clients can index fields by "order in which they're listed."
244    #   2. Clients can easily iterate over all fields with the terse
245    #      syntax: for f in descriptor.fields: ...
246    self.fields = fields
247    for field in self.fields:
248      field.containing_type = self
249    self.fields_by_number = dict((f.number, f) for f in fields)
250    self.fields_by_name = dict((f.name, f) for f in fields)
251
252    self.nested_types = nested_types
253    self.nested_types_by_name = dict((t.name, t) for t in nested_types)
254
255    self.enum_types = enum_types
256    for enum_type in self.enum_types:
257      enum_type.containing_type = self
258    self.enum_types_by_name = dict((t.name, t) for t in enum_types)
259    self.enum_values_by_name = dict(
260        (v.name, v) for t in enum_types for v in t.values)
261
262    self.extensions = extensions
263    for extension in self.extensions:
264      extension.extension_scope = self
265    self.extensions_by_name = dict((f.name, f) for f in extensions)
266    self.is_extendable = is_extendable
267    self.extension_ranges = extension_ranges
268
269    self._serialized_start = serialized_start
270    self._serialized_end = serialized_end
271
272  def EnumValueName(self, enum, value):
273    """Returns the string name of an enum value.
274
275    This is just a small helper method to simplify a common operation.
276
277    Args:
278      enum: string name of the Enum.
279      value: int, value of the enum.
280
281    Returns:
282      string name of the enum value.
283
284    Raises:
285      KeyError if either the Enum doesn't exist or the value is not a valid
286        value for the enum.
287    """
288    return self.enum_types_by_name[enum].values_by_number[value].name
289
290  def CopyToProto(self, proto):
291    """Copies this to a descriptor_pb2.DescriptorProto.
292
293    Args:
294      proto: An empty descriptor_pb2.DescriptorProto.
295    """
296    # This function is overriden to give a better doc comment.
297    super(Descriptor, self).CopyToProto(proto)
298
299
300# TODO(robinson): We should have aggressive checking here,
301# for example:
302#   * If you specify a repeated field, you should not be allowed
303#     to specify a default value.
304#   * [Other examples here as needed].
305#
306# TODO(robinson): for this and other *Descriptor classes, we
307# might also want to lock things down aggressively (e.g.,
308# prevent clients from setting the attributes).  Having
309# stronger invariants here in general will reduce the number
310# of runtime checks we must do in reflection.py...
311class FieldDescriptor(DescriptorBase):
312
313  """Descriptor for a single field in a .proto file.
314
315  A FieldDescriptor instance has the following attributes:
316
317    name: (str) Name of this field, exactly as it appears in .proto.
318    full_name: (str) Name of this field, including containing scope.  This is
319      particularly relevant for extensions.
320    index: (int) Dense, 0-indexed index giving the order that this
321      field textually appears within its message in the .proto file.
322    number: (int) Tag number declared for this field in the .proto file.
323
324    type: (One of the TYPE_* constants below) Declared type.
325    cpp_type: (One of the CPPTYPE_* constants below) C++ type used to
326      represent this field.
327
328    label: (One of the LABEL_* constants below) Tells whether this
329      field is optional, required, or repeated.
330    has_default_value: (bool) True if this field has a default value defined,
331      otherwise false.
332    default_value: (Varies) Default value of this field.  Only
333      meaningful for non-repeated scalar fields.  Repeated fields
334      should always set this to [], and non-repeated composite
335      fields should always set this to None.
336
337    containing_type: (Descriptor) Descriptor of the protocol message
338      type that contains this field.  Set by the Descriptor constructor
339      if we're passed into one.
340      Somewhat confusingly, for extension fields, this is the
341      descriptor of the EXTENDED message, not the descriptor
342      of the message containing this field.  (See is_extension and
343      extension_scope below).
344    message_type: (Descriptor) If a composite field, a descriptor
345      of the message type contained in this field.  Otherwise, this is None.
346    enum_type: (EnumDescriptor) If this field contains an enum, a
347      descriptor of that enum.  Otherwise, this is None.
348
349    is_extension: True iff this describes an extension field.
350    extension_scope: (Descriptor) Only meaningful if is_extension is True.
351      Gives the message that immediately contains this extension field.
352      Will be None iff we're a top-level (file-level) extension field.
353
354    options: (descriptor_pb2.FieldOptions) Protocol message field options or
355      None to use default field options.
356  """
357
358  # Must be consistent with C++ FieldDescriptor::Type enum in
359  # descriptor.h.
360  #
361  # TODO(robinson): Find a way to eliminate this repetition.
362  TYPE_DOUBLE         = 1
363  TYPE_FLOAT          = 2
364  TYPE_INT64          = 3
365  TYPE_UINT64         = 4
366  TYPE_INT32          = 5
367  TYPE_FIXED64        = 6
368  TYPE_FIXED32        = 7
369  TYPE_BOOL           = 8
370  TYPE_STRING         = 9
371  TYPE_GROUP          = 10
372  TYPE_MESSAGE        = 11
373  TYPE_BYTES          = 12
374  TYPE_UINT32         = 13
375  TYPE_ENUM           = 14
376  TYPE_SFIXED32       = 15
377  TYPE_SFIXED64       = 16
378  TYPE_SINT32         = 17
379  TYPE_SINT64         = 18
380  MAX_TYPE            = 18
381
382  # Must be consistent with C++ FieldDescriptor::CppType enum in
383  # descriptor.h.
384  #
385  # TODO(robinson): Find a way to eliminate this repetition.
386  CPPTYPE_INT32       = 1
387  CPPTYPE_INT64       = 2
388  CPPTYPE_UINT32      = 3
389  CPPTYPE_UINT64      = 4
390  CPPTYPE_DOUBLE      = 5
391  CPPTYPE_FLOAT       = 6
392  CPPTYPE_BOOL        = 7
393  CPPTYPE_ENUM        = 8
394  CPPTYPE_STRING      = 9
395  CPPTYPE_MESSAGE     = 10
396  MAX_CPPTYPE         = 10
397
398  _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
399      TYPE_DOUBLE: CPPTYPE_DOUBLE,
400      TYPE_FLOAT: CPPTYPE_FLOAT,
401      TYPE_ENUM: CPPTYPE_ENUM,
402      TYPE_INT64: CPPTYPE_INT64,
403      TYPE_SINT64: CPPTYPE_INT64,
404      TYPE_SFIXED64: CPPTYPE_INT64,
405      TYPE_UINT64: CPPTYPE_UINT64,
406      TYPE_FIXED64: CPPTYPE_UINT64,
407      TYPE_INT32: CPPTYPE_INT32,
408      TYPE_SFIXED32: CPPTYPE_INT32,
409      TYPE_SINT32: CPPTYPE_INT32,
410      TYPE_UINT32: CPPTYPE_UINT32,
411      TYPE_FIXED32: CPPTYPE_UINT32,
412      TYPE_BYTES: CPPTYPE_STRING,
413      TYPE_STRING: CPPTYPE_STRING,
414      TYPE_BOOL: CPPTYPE_BOOL,
415      TYPE_MESSAGE: CPPTYPE_MESSAGE,
416      TYPE_GROUP: CPPTYPE_MESSAGE
417      }
418
419  # Must be consistent with C++ FieldDescriptor::Label enum in
420  # descriptor.h.
421  #
422  # TODO(robinson): Find a way to eliminate this repetition.
423  LABEL_OPTIONAL      = 1
424  LABEL_REQUIRED      = 2
425  LABEL_REPEATED      = 3
426  MAX_LABEL           = 3
427
428  def __init__(self, name, full_name, index, number, type, cpp_type, label,
429               default_value, message_type, enum_type, containing_type,
430               is_extension, extension_scope, options=None,
431               has_default_value=True):
432    """The arguments are as described in the description of FieldDescriptor
433    attributes above.
434
435    Note that containing_type may be None, and may be set later if necessary
436    (to deal with circular references between message types, for example).
437    Likewise for extension_scope.
438    """
439    super(FieldDescriptor, self).__init__(options, 'FieldOptions')
440    self.name = name
441    self.full_name = full_name
442    self.index = index
443    self.number = number
444    self.type = type
445    self.cpp_type = cpp_type
446    self.label = label
447    self.has_default_value = has_default_value
448    self.default_value = default_value
449    self.containing_type = containing_type
450    self.message_type = message_type
451    self.enum_type = enum_type
452    self.is_extension = is_extension
453    self.extension_scope = extension_scope
454    if api_implementation.Type() == 'cpp':
455      if is_extension:
456        if api_implementation.Version() == 2:
457          self._cdescriptor = _message.GetExtensionDescriptor(full_name)
458        else:
459          self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
460      else:
461        if api_implementation.Version() == 2:
462          self._cdescriptor = _message.GetFieldDescriptor(full_name)
463        else:
464          self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
465    else:
466      self._cdescriptor = None
467
468  @staticmethod
469  def ProtoTypeToCppProtoType(proto_type):
470    """Converts from a Python proto type to a C++ Proto Type.
471
472    The Python ProtocolBuffer classes specify both the 'Python' datatype and the
473    'C++' datatype - and they're not the same. This helper method should
474    translate from one to another.
475
476    Args:
477      proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
478    Returns:
479      descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
480    Raises:
481      TypeTransformationError: when the Python proto type isn't known.
482    """
483    try:
484      return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
485    except KeyError:
486      raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
487
488
489class EnumDescriptor(_NestedDescriptorBase):
490
491  """Descriptor for an enum defined in a .proto file.
492
493  An EnumDescriptor instance has the following attributes:
494
495    name: (str) Name of the enum type.
496    full_name: (str) Full name of the type, including package name
497      and any enclosing type(s).
498
499    values: (list of EnumValueDescriptors) List of the values
500      in this enum.
501    values_by_name: (dict str -> EnumValueDescriptor) Same as |values|,
502      but indexed by the "name" field of each EnumValueDescriptor.
503    values_by_number: (dict int -> EnumValueDescriptor) Same as |values|,
504      but indexed by the "number" field of each EnumValueDescriptor.
505    containing_type: (Descriptor) Descriptor of the immediate containing
506      type of this enum, or None if this is an enum defined at the
507      top level in a .proto file.  Set by Descriptor's constructor
508      if we're passed into one.
509    file: (FileDescriptor) Reference to file descriptor.
510    options: (descriptor_pb2.EnumOptions) Enum options message or
511      None to use default enum options.
512  """
513
514  def __init__(self, name, full_name, filename, values,
515               containing_type=None, options=None, file=None,
516               serialized_start=None, serialized_end=None):
517    """Arguments are as described in the attribute description above.
518
519    Note that filename is an obsolete argument, that is not used anymore.
520    Please use file.name to access this as an attribute.
521    """
522    super(EnumDescriptor, self).__init__(
523        options, 'EnumOptions', name, full_name, file,
524        containing_type, serialized_start=serialized_start,
525        serialized_end=serialized_start)
526
527    self.values = values
528    for value in self.values:
529      value.type = self
530    self.values_by_name = dict((v.name, v) for v in values)
531    self.values_by_number = dict((v.number, v) for v in values)
532
533    self._serialized_start = serialized_start
534    self._serialized_end = serialized_end
535
536  def CopyToProto(self, proto):
537    """Copies this to a descriptor_pb2.EnumDescriptorProto.
538
539    Args:
540      proto: An empty descriptor_pb2.EnumDescriptorProto.
541    """
542    # This function is overriden to give a better doc comment.
543    super(EnumDescriptor, self).CopyToProto(proto)
544
545
546class EnumValueDescriptor(DescriptorBase):
547
548  """Descriptor for a single value within an enum.
549
550    name: (str) Name of this value.
551    index: (int) Dense, 0-indexed index giving the order that this
552      value appears textually within its enum in the .proto file.
553    number: (int) Actual number assigned to this enum value.
554    type: (EnumDescriptor) EnumDescriptor to which this value
555      belongs.  Set by EnumDescriptor's constructor if we're
556      passed into one.
557    options: (descriptor_pb2.EnumValueOptions) Enum value options message or
558      None to use default enum value options options.
559  """
560
561  def __init__(self, name, index, number, type=None, options=None):
562    """Arguments are as described in the attribute description above."""
563    super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
564    self.name = name
565    self.index = index
566    self.number = number
567    self.type = type
568
569
570class ServiceDescriptor(_NestedDescriptorBase):
571
572  """Descriptor for a service.
573
574    name: (str) Name of the service.
575    full_name: (str) Full name of the service, including package name.
576    index: (int) 0-indexed index giving the order that this services
577      definition appears withing the .proto file.
578    methods: (list of MethodDescriptor) List of methods provided by this
579      service.
580    options: (descriptor_pb2.ServiceOptions) Service options message or
581      None to use default service options.
582    file: (FileDescriptor) Reference to file info.
583  """
584
585  def __init__(self, name, full_name, index, methods, options=None, file=None,
586               serialized_start=None, serialized_end=None):
587    super(ServiceDescriptor, self).__init__(
588        options, 'ServiceOptions', name, full_name, file,
589        None, serialized_start=serialized_start,
590        serialized_end=serialized_end)
591    self.index = index
592    self.methods = methods
593    # Set the containing service for each method in this service.
594    for method in self.methods:
595      method.containing_service = self
596
597  def FindMethodByName(self, name):
598    """Searches for the specified method, and returns its descriptor."""
599    for method in self.methods:
600      if name == method.name:
601        return method
602    return None
603
604  def CopyToProto(self, proto):
605    """Copies this to a descriptor_pb2.ServiceDescriptorProto.
606
607    Args:
608      proto: An empty descriptor_pb2.ServiceDescriptorProto.
609    """
610    # This function is overriden to give a better doc comment.
611    super(ServiceDescriptor, self).CopyToProto(proto)
612
613
614class MethodDescriptor(DescriptorBase):
615
616  """Descriptor for a method in a service.
617
618  name: (str) Name of the method within the service.
619  full_name: (str) Full name of method.
620  index: (int) 0-indexed index of the method inside the service.
621  containing_service: (ServiceDescriptor) The service that contains this
622    method.
623  input_type: The descriptor of the message that this method accepts.
624  output_type: The descriptor of the message that this method returns.
625  options: (descriptor_pb2.MethodOptions) Method options message or
626    None to use default method options.
627  """
628
629  def __init__(self, name, full_name, index, containing_service,
630               input_type, output_type, options=None):
631    """The arguments are as described in the description of MethodDescriptor
632    attributes above.
633
634    Note that containing_service may be None, and may be set later if necessary.
635    """
636    super(MethodDescriptor, self).__init__(options, 'MethodOptions')
637    self.name = name
638    self.full_name = full_name
639    self.index = index
640    self.containing_service = containing_service
641    self.input_type = input_type
642    self.output_type = output_type
643
644
645class FileDescriptor(DescriptorBase):
646  """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
647
648  name: name of file, relative to root of source tree.
649  package: name of the package
650  serialized_pb: (str) Byte string of serialized
651    descriptor_pb2.FileDescriptorProto.
652  """
653
654  def __init__(self, name, package, options=None, serialized_pb=None):
655    """Constructor."""
656    super(FileDescriptor, self).__init__(options, 'FileOptions')
657
658    self.message_types_by_name = {}
659    self.name = name
660    self.package = package
661    self.serialized_pb = serialized_pb
662    if (api_implementation.Type() == 'cpp' and
663        self.serialized_pb is not None):
664      if api_implementation.Version() == 2:
665        _message.BuildFile(self.serialized_pb)
666      else:
667        cpp_message.BuildFile(self.serialized_pb)
668
669  def CopyToProto(self, proto):
670    """Copies this to a descriptor_pb2.FileDescriptorProto.
671
672    Args:
673      proto: An empty descriptor_pb2.FileDescriptorProto.
674    """
675    proto.ParseFromString(self.serialized_pb)
676
677
678def _ParseOptions(message, string):
679  """Parses serialized options.
680
681  This helper function is used to parse serialized options in generated
682  proto2 files. It must not be used outside proto2.
683  """
684  message.ParseFromString(string)
685  return message
686
687
688def MakeDescriptor(desc_proto, package=''):
689  """Make a protobuf Descriptor given a DescriptorProto protobuf.
690
691  Args:
692    desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
693    package: Optional package name for the new message Descriptor (string).
694
695  Returns:
696    A Descriptor for protobuf messages.
697  """
698  full_message_name = [desc_proto.name]
699  if package: full_message_name.insert(0, package)
700  fields = []
701  for field_proto in desc_proto.field:
702    full_name = '.'.join(full_message_name + [field_proto.name])
703    field = FieldDescriptor(
704        field_proto.name, full_name, field_proto.number - 1,
705        field_proto.number, field_proto.type,
706        FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
707        field_proto.label, None, None, None, None, False, None,
708        has_default_value=False)
709    fields.append(field)
710
711  desc_name = '.'.join(full_message_name)
712  return Descriptor(desc_proto.name, desc_name, None, None, fields,
713                    [], [], [])
714