1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc.  All rights reserved.
3# https://developers.google.com/protocol-buffers/
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
37import threading
38import warnings
39import six
40
41from google.protobuf.internal import api_implementation
42
43_USE_C_DESCRIPTORS = False
44if api_implementation.Type() == 'cpp':
45  # Used by MakeDescriptor in cpp mode
46  import binascii
47  import os
48  from google.protobuf.pyext import _message
49  _USE_C_DESCRIPTORS = True
50
51
52class Error(Exception):
53  """Base error for this module."""
54
55
56class TypeTransformationError(Error):
57  """Error transforming between python proto type and corresponding C++ type."""
58
59
60if _USE_C_DESCRIPTORS:
61  # This metaclass allows to override the behavior of code like
62  #     isinstance(my_descriptor, FieldDescriptor)
63  # and make it return True when the descriptor is an instance of the extension
64  # type written in C++.
65  class DescriptorMetaclass(type):
66    def __instancecheck__(cls, obj):
67      if super(DescriptorMetaclass, cls).__instancecheck__(obj):
68        return True
69      if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
70        return True
71      return False
72else:
73  # The standard metaclass; nothing changes.
74  DescriptorMetaclass = type
75
76
77class _Lock(object):
78  """Wrapper class of threading.Lock(), which is allowed by 'with'."""
79
80  def __new__(cls):
81    self = object.__new__(cls)
82    self._lock = threading.Lock()  # pylint: disable=protected-access
83    return self
84
85  def __enter__(self):
86    self._lock.acquire()
87
88  def __exit__(self, exc_type, exc_value, exc_tb):
89    self._lock.release()
90
91
92_lock = threading.Lock()
93
94
95def _Deprecated(name):
96  if _Deprecated.count > 0:
97    _Deprecated.count -= 1
98    warnings.warn(
99        'Call to deprecated create function %s(). Note: Create unlinked '
100        'descriptors is going to go away. Please use get/find descriptors from '
101        'generated code or query the descriptor_pool.'
102        % name,
103        category=DeprecationWarning, stacklevel=3)
104
105
106# Deprecated warnings will print 100 times at most which should be enough for
107# users to notice and do not cause timeout.
108_Deprecated.count = 100
109
110
111_internal_create_key = object()
112
113
114class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
115
116  """Descriptors base class.
117
118  This class is the base of all descriptor classes. It provides common options
119  related functionality.
120
121  Attributes:
122    has_options:  True if the descriptor has non-default options.  Usually it
123        is not necessary to read this -- just call GetOptions() which will
124        happily return the default instance.  However, it's sometimes useful
125        for efficiency, and also useful inside the protobuf implementation to
126        avoid some bootstrapping issues.
127  """
128
129  if _USE_C_DESCRIPTORS:
130    # The class, or tuple of classes, that are considered as "virtual
131    # subclasses" of this descriptor class.
132    _C_DESCRIPTOR_CLASS = ()
133
134  def __init__(self, options, serialized_options, options_class_name):
135    """Initialize the descriptor given its options message and the name of the
136    class of the options message. The name of the class is required in case
137    the options message is None and has to be created.
138    """
139    self._options = options
140    self._options_class_name = options_class_name
141    self._serialized_options = serialized_options
142
143    # Does this descriptor have non-default options?
144    self.has_options = (options is not None) or (serialized_options is not None)
145
146  def _SetOptions(self, options, options_class_name):
147    """Sets the descriptor's options
148
149    This function is used in generated proto2 files to update descriptor
150    options. It must not be used outside proto2.
151    """
152    self._options = options
153    self._options_class_name = options_class_name
154
155    # Does this descriptor have non-default options?
156    self.has_options = options is not None
157
158  def GetOptions(self):
159    """Retrieves descriptor options.
160
161    This method returns the options set or creates the default options for the
162    descriptor.
163    """
164    if self._options:
165      return self._options
166
167    from google.protobuf import descriptor_pb2
168    try:
169      options_class = getattr(descriptor_pb2,
170                              self._options_class_name)
171    except AttributeError:
172      raise RuntimeError('Unknown options class name %s!' %
173                         (self._options_class_name))
174
175    with _lock:
176      if self._serialized_options is None:
177        self._options = options_class()
178      else:
179        self._options = _ParseOptions(options_class(),
180                                      self._serialized_options)
181
182      return self._options
183
184
185class _NestedDescriptorBase(DescriptorBase):
186  """Common class for descriptors that can be nested."""
187
188  def __init__(self, options, options_class_name, name, full_name,
189               file, containing_type, serialized_start=None,
190               serialized_end=None, serialized_options=None):
191    """Constructor.
192
193    Args:
194      options: Protocol message options or None
195        to use default message options.
196      options_class_name (str): The class name of the above options.
197      name (str): Name of this protocol message type.
198      full_name (str): Fully-qualified name of this protocol message type,
199        which will include protocol "package" name and the name of any
200        enclosing types.
201      file (FileDescriptor): Reference to file info.
202      containing_type: if provided, this is a nested descriptor, with this
203        descriptor as parent, otherwise None.
204      serialized_start: The start index (inclusive) in block in the
205        file.serialized_pb that describes this descriptor.
206      serialized_end: The end index (exclusive) in block in the
207        file.serialized_pb that describes this descriptor.
208      serialized_options: Protocol message serialized options or None.
209    """
210    super(_NestedDescriptorBase, self).__init__(
211        options, serialized_options, options_class_name)
212
213    self.name = name
214    # TODO(falk): Add function to calculate full_name instead of having it in
215    #             memory?
216    self.full_name = full_name
217    self.file = file
218    self.containing_type = containing_type
219
220    self._serialized_start = serialized_start
221    self._serialized_end = serialized_end
222
223  def CopyToProto(self, proto):
224    """Copies this to the matching proto in descriptor_pb2.
225
226    Args:
227      proto: An empty proto instance from descriptor_pb2.
228
229    Raises:
230      Error: If self couldnt be serialized, due to to few constructor arguments.
231    """
232    if (self.file is not None and
233        self._serialized_start is not None and
234        self._serialized_end is not None):
235      proto.ParseFromString(self.file.serialized_pb[
236          self._serialized_start:self._serialized_end])
237    else:
238      raise Error('Descriptor does not contain serialization.')
239
240
241class Descriptor(_NestedDescriptorBase):
242
243  """Descriptor for a protocol message type.
244
245  Attributes:
246      name (str): Name of this protocol message type.
247      full_name (str): Fully-qualified name of this protocol message type,
248          which will include protocol "package" name and the name of any
249          enclosing types.
250      containing_type (Descriptor): Reference to the descriptor of the type
251          containing us, or None if this is top-level.
252      fields (list[FieldDescriptor]): Field descriptors for all fields in
253          this type.
254      fields_by_number (dict(int, FieldDescriptor)): Same
255          :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed
256          by "number" attribute in each FieldDescriptor.
257      fields_by_name (dict(str, FieldDescriptor)): Same
258          :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by
259          "name" attribute in each :class:`FieldDescriptor`.
260      nested_types (list[Descriptor]): Descriptor references
261          for all protocol message types nested within this one.
262      nested_types_by_name (dict(str, Descriptor)): Same Descriptor
263          objects as in :attr:`nested_types`, but indexed by "name" attribute
264          in each Descriptor.
265      enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references
266          for all enums contained within this type.
267      enum_types_by_name (dict(str, EnumDescriptor)): Same
268          :class:`EnumDescriptor` objects as in :attr:`enum_types`, but
269          indexed by "name" attribute in each EnumDescriptor.
270      enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping
271          from enum value name to :class:`EnumValueDescriptor` for that value.
272      extensions (list[FieldDescriptor]): All extensions defined directly
273          within this message type (NOT within a nested type).
274      extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor
275          objects as :attr:`extensions`, but indexed by "name" attribute of each
276          FieldDescriptor.
277      is_extendable (bool):  Does this type define any extension ranges?
278      oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields
279          in this message.
280      oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in
281          :attr:`oneofs`, but indexed by "name" attribute.
282      file (FileDescriptor): Reference to file descriptor.
283
284  """
285
286  if _USE_C_DESCRIPTORS:
287    _C_DESCRIPTOR_CLASS = _message.Descriptor
288
289    def __new__(cls, name, full_name, filename, containing_type, fields,
290                nested_types, enum_types, extensions, options=None,
291                serialized_options=None,
292                is_extendable=True, extension_ranges=None, oneofs=None,
293                file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
294                syntax=None, create_key=None):
295      _message.Message._CheckCalledFromGeneratedFile()
296      return _message.default_pool.FindMessageTypeByName(full_name)
297
298  # NOTE(tmarek): The file argument redefining a builtin is nothing we can
299  # fix right now since we don't know how many clients already rely on the
300  # name of the argument.
301  def __init__(self, name, full_name, filename, containing_type, fields,
302               nested_types, enum_types, extensions, options=None,
303               serialized_options=None,
304               is_extendable=True, extension_ranges=None, oneofs=None,
305               file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
306               syntax=None, create_key=None):
307    """Arguments to __init__() are as described in the description
308    of Descriptor fields above.
309
310    Note that filename is an obsolete argument, that is not used anymore.
311    Please use file.name to access this as an attribute.
312    """
313    if create_key is not _internal_create_key:
314      _Deprecated('Descriptor')
315
316    super(Descriptor, self).__init__(
317        options, 'MessageOptions', name, full_name, file,
318        containing_type, serialized_start=serialized_start,
319        serialized_end=serialized_end, serialized_options=serialized_options)
320
321    # We have fields in addition to fields_by_name and fields_by_number,
322    # so that:
323    #   1. Clients can index fields by "order in which they're listed."
324    #   2. Clients can easily iterate over all fields with the terse
325    #      syntax: for f in descriptor.fields: ...
326    self.fields = fields
327    for field in self.fields:
328      field.containing_type = self
329    self.fields_by_number = dict((f.number, f) for f in fields)
330    self.fields_by_name = dict((f.name, f) for f in fields)
331    self._fields_by_camelcase_name = None
332
333    self.nested_types = nested_types
334    for nested_type in nested_types:
335      nested_type.containing_type = self
336    self.nested_types_by_name = dict((t.name, t) for t in nested_types)
337
338    self.enum_types = enum_types
339    for enum_type in self.enum_types:
340      enum_type.containing_type = self
341    self.enum_types_by_name = dict((t.name, t) for t in enum_types)
342    self.enum_values_by_name = dict(
343        (v.name, v) for t in enum_types for v in t.values)
344
345    self.extensions = extensions
346    for extension in self.extensions:
347      extension.extension_scope = self
348    self.extensions_by_name = dict((f.name, f) for f in extensions)
349    self.is_extendable = is_extendable
350    self.extension_ranges = extension_ranges
351    self.oneofs = oneofs if oneofs is not None else []
352    self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
353    for oneof in self.oneofs:
354      oneof.containing_type = self
355    self.syntax = syntax or "proto2"
356
357  @property
358  def fields_by_camelcase_name(self):
359    """Same FieldDescriptor objects as in :attr:`fields`, but indexed by
360    :attr:`FieldDescriptor.camelcase_name`.
361    """
362    if self._fields_by_camelcase_name is None:
363      self._fields_by_camelcase_name = dict(
364          (f.camelcase_name, f) for f in self.fields)
365    return self._fields_by_camelcase_name
366
367  def EnumValueName(self, enum, value):
368    """Returns the string name of an enum value.
369
370    This is just a small helper method to simplify a common operation.
371
372    Args:
373      enum: string name of the Enum.
374      value: int, value of the enum.
375
376    Returns:
377      string name of the enum value.
378
379    Raises:
380      KeyError if either the Enum doesn't exist or the value is not a valid
381        value for the enum.
382    """
383    return self.enum_types_by_name[enum].values_by_number[value].name
384
385  def CopyToProto(self, proto):
386    """Copies this to a descriptor_pb2.DescriptorProto.
387
388    Args:
389      proto: An empty descriptor_pb2.DescriptorProto.
390    """
391    # This function is overridden to give a better doc comment.
392    super(Descriptor, self).CopyToProto(proto)
393
394
395# TODO(robinson): We should have aggressive checking here,
396# for example:
397#   * If you specify a repeated field, you should not be allowed
398#     to specify a default value.
399#   * [Other examples here as needed].
400#
401# TODO(robinson): for this and other *Descriptor classes, we
402# might also want to lock things down aggressively (e.g.,
403# prevent clients from setting the attributes).  Having
404# stronger invariants here in general will reduce the number
405# of runtime checks we must do in reflection.py...
406class FieldDescriptor(DescriptorBase):
407
408  """Descriptor for a single field in a .proto file.
409
410  Attributes:
411    name (str): Name of this field, exactly as it appears in .proto.
412    full_name (str): Name of this field, including containing scope.  This is
413      particularly relevant for extensions.
414    index (int): Dense, 0-indexed index giving the order that this
415      field textually appears within its message in the .proto file.
416    number (int): Tag number declared for this field in the .proto file.
417
418    type (int): (One of the TYPE_* constants below) Declared type.
419    cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to
420      represent this field.
421
422    label (int): (One of the LABEL_* constants below) Tells whether this
423      field is optional, required, or repeated.
424    has_default_value (bool): True if this field has a default value defined,
425      otherwise false.
426    default_value (Varies): Default value of this field.  Only
427      meaningful for non-repeated scalar fields.  Repeated fields
428      should always set this to [], and non-repeated composite
429      fields should always set this to None.
430
431    containing_type (Descriptor): Descriptor of the protocol message
432      type that contains this field.  Set by the Descriptor constructor
433      if we're passed into one.
434      Somewhat confusingly, for extension fields, this is the
435      descriptor of the EXTENDED message, not the descriptor
436      of the message containing this field.  (See is_extension and
437      extension_scope below).
438    message_type (Descriptor): If a composite field, a descriptor
439      of the message type contained in this field.  Otherwise, this is None.
440    enum_type (EnumDescriptor): If this field contains an enum, a
441      descriptor of that enum.  Otherwise, this is None.
442
443    is_extension: True iff this describes an extension field.
444    extension_scope (Descriptor): Only meaningful if is_extension is True.
445      Gives the message that immediately contains this extension field.
446      Will be None iff we're a top-level (file-level) extension field.
447
448    options (descriptor_pb2.FieldOptions): Protocol message field options or
449      None to use default field options.
450
451    containing_oneof (OneofDescriptor): If the field is a member of a oneof
452      union, contains its descriptor. Otherwise, None.
453
454    file (FileDescriptor): Reference to file descriptor.
455  """
456
457  # Must be consistent with C++ FieldDescriptor::Type enum in
458  # descriptor.h.
459  #
460  # TODO(robinson): Find a way to eliminate this repetition.
461  TYPE_DOUBLE         = 1
462  TYPE_FLOAT          = 2
463  TYPE_INT64          = 3
464  TYPE_UINT64         = 4
465  TYPE_INT32          = 5
466  TYPE_FIXED64        = 6
467  TYPE_FIXED32        = 7
468  TYPE_BOOL           = 8
469  TYPE_STRING         = 9
470  TYPE_GROUP          = 10
471  TYPE_MESSAGE        = 11
472  TYPE_BYTES          = 12
473  TYPE_UINT32         = 13
474  TYPE_ENUM           = 14
475  TYPE_SFIXED32       = 15
476  TYPE_SFIXED64       = 16
477  TYPE_SINT32         = 17
478  TYPE_SINT64         = 18
479  MAX_TYPE            = 18
480
481  # Must be consistent with C++ FieldDescriptor::CppType enum in
482  # descriptor.h.
483  #
484  # TODO(robinson): Find a way to eliminate this repetition.
485  CPPTYPE_INT32       = 1
486  CPPTYPE_INT64       = 2
487  CPPTYPE_UINT32      = 3
488  CPPTYPE_UINT64      = 4
489  CPPTYPE_DOUBLE      = 5
490  CPPTYPE_FLOAT       = 6
491  CPPTYPE_BOOL        = 7
492  CPPTYPE_ENUM        = 8
493  CPPTYPE_STRING      = 9
494  CPPTYPE_MESSAGE     = 10
495  MAX_CPPTYPE         = 10
496
497  _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
498      TYPE_DOUBLE: CPPTYPE_DOUBLE,
499      TYPE_FLOAT: CPPTYPE_FLOAT,
500      TYPE_ENUM: CPPTYPE_ENUM,
501      TYPE_INT64: CPPTYPE_INT64,
502      TYPE_SINT64: CPPTYPE_INT64,
503      TYPE_SFIXED64: CPPTYPE_INT64,
504      TYPE_UINT64: CPPTYPE_UINT64,
505      TYPE_FIXED64: CPPTYPE_UINT64,
506      TYPE_INT32: CPPTYPE_INT32,
507      TYPE_SFIXED32: CPPTYPE_INT32,
508      TYPE_SINT32: CPPTYPE_INT32,
509      TYPE_UINT32: CPPTYPE_UINT32,
510      TYPE_FIXED32: CPPTYPE_UINT32,
511      TYPE_BYTES: CPPTYPE_STRING,
512      TYPE_STRING: CPPTYPE_STRING,
513      TYPE_BOOL: CPPTYPE_BOOL,
514      TYPE_MESSAGE: CPPTYPE_MESSAGE,
515      TYPE_GROUP: CPPTYPE_MESSAGE
516      }
517
518  # Must be consistent with C++ FieldDescriptor::Label enum in
519  # descriptor.h.
520  #
521  # TODO(robinson): Find a way to eliminate this repetition.
522  LABEL_OPTIONAL      = 1
523  LABEL_REQUIRED      = 2
524  LABEL_REPEATED      = 3
525  MAX_LABEL           = 3
526
527  # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
528  # and kLastReservedNumber in descriptor.h
529  MAX_FIELD_NUMBER = (1 << 29) - 1
530  FIRST_RESERVED_FIELD_NUMBER = 19000
531  LAST_RESERVED_FIELD_NUMBER = 19999
532
533  if _USE_C_DESCRIPTORS:
534    _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
535
536    def __new__(cls, name, full_name, index, number, type, cpp_type, label,
537                default_value, message_type, enum_type, containing_type,
538                is_extension, extension_scope, options=None,
539                serialized_options=None,
540                has_default_value=True, containing_oneof=None, json_name=None,
541                file=None, create_key=None):  # pylint: disable=redefined-builtin
542      _message.Message._CheckCalledFromGeneratedFile()
543      if is_extension:
544        return _message.default_pool.FindExtensionByName(full_name)
545      else:
546        return _message.default_pool.FindFieldByName(full_name)
547
548  def __init__(self, name, full_name, index, number, type, cpp_type, label,
549               default_value, message_type, enum_type, containing_type,
550               is_extension, extension_scope, options=None,
551               serialized_options=None,
552               has_default_value=True, containing_oneof=None, json_name=None,
553               file=None, create_key=None):  # pylint: disable=redefined-builtin
554    """The arguments are as described in the description of FieldDescriptor
555    attributes above.
556
557    Note that containing_type may be None, and may be set later if necessary
558    (to deal with circular references between message types, for example).
559    Likewise for extension_scope.
560    """
561    if create_key is not _internal_create_key:
562      _Deprecated('FieldDescriptor')
563
564    super(FieldDescriptor, self).__init__(
565        options, serialized_options, 'FieldOptions')
566    self.name = name
567    self.full_name = full_name
568    self.file = file
569    self._camelcase_name = None
570    if json_name is None:
571      self.json_name = _ToJsonName(name)
572    else:
573      self.json_name = json_name
574    self.index = index
575    self.number = number
576    self.type = type
577    self.cpp_type = cpp_type
578    self.label = label
579    self.has_default_value = has_default_value
580    self.default_value = default_value
581    self.containing_type = containing_type
582    self.message_type = message_type
583    self.enum_type = enum_type
584    self.is_extension = is_extension
585    self.extension_scope = extension_scope
586    self.containing_oneof = containing_oneof
587    if api_implementation.Type() == 'cpp':
588      if is_extension:
589        self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
590      else:
591        self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
592    else:
593      self._cdescriptor = None
594
595  @property
596  def camelcase_name(self):
597    """Camelcase name of this field.
598
599    Returns:
600      str: the name in CamelCase.
601    """
602    if self._camelcase_name is None:
603      self._camelcase_name = _ToCamelCase(self.name)
604    return self._camelcase_name
605
606  @staticmethod
607  def ProtoTypeToCppProtoType(proto_type):
608    """Converts from a Python proto type to a C++ Proto Type.
609
610    The Python ProtocolBuffer classes specify both the 'Python' datatype and the
611    'C++' datatype - and they're not the same. This helper method should
612    translate from one to another.
613
614    Args:
615      proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
616    Returns:
617      int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
618    Raises:
619      TypeTransformationError: when the Python proto type isn't known.
620    """
621    try:
622      return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
623    except KeyError:
624      raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
625
626
627class EnumDescriptor(_NestedDescriptorBase):
628
629  """Descriptor for an enum defined in a .proto file.
630
631  Attributes:
632    name (str): Name of the enum type.
633    full_name (str): Full name of the type, including package name
634      and any enclosing type(s).
635
636    values (list[EnumValueDescriptors]): List of the values
637      in this enum.
638    values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`,
639      but indexed by the "name" field of each EnumValueDescriptor.
640    values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`,
641      but indexed by the "number" field of each EnumValueDescriptor.
642    containing_type (Descriptor): Descriptor of the immediate containing
643      type of this enum, or None if this is an enum defined at the
644      top level in a .proto file.  Set by Descriptor's constructor
645      if we're passed into one.
646    file (FileDescriptor): Reference to file descriptor.
647    options (descriptor_pb2.EnumOptions): Enum options message or
648      None to use default enum options.
649  """
650
651  if _USE_C_DESCRIPTORS:
652    _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
653
654    def __new__(cls, name, full_name, filename, values,
655                containing_type=None, options=None,
656                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
657                serialized_start=None, serialized_end=None, create_key=None):
658      _message.Message._CheckCalledFromGeneratedFile()
659      return _message.default_pool.FindEnumTypeByName(full_name)
660
661  def __init__(self, name, full_name, filename, values,
662               containing_type=None, options=None,
663               serialized_options=None, file=None,  # pylint: disable=redefined-builtin
664               serialized_start=None, serialized_end=None, create_key=None):
665    """Arguments are as described in the attribute description above.
666
667    Note that filename is an obsolete argument, that is not used anymore.
668    Please use file.name to access this as an attribute.
669    """
670    if create_key is not _internal_create_key:
671      _Deprecated('EnumDescriptor')
672
673    super(EnumDescriptor, self).__init__(
674        options, 'EnumOptions', name, full_name, file,
675        containing_type, serialized_start=serialized_start,
676        serialized_end=serialized_end, serialized_options=serialized_options)
677
678    self.values = values
679    for value in self.values:
680      value.type = self
681    self.values_by_name = dict((v.name, v) for v in values)
682    # Values are reversed to ensure that the first alias is retained.
683    self.values_by_number = dict((v.number, v) for v in reversed(values))
684
685  def CopyToProto(self, proto):
686    """Copies this to a descriptor_pb2.EnumDescriptorProto.
687
688    Args:
689      proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto.
690    """
691    # This function is overridden to give a better doc comment.
692    super(EnumDescriptor, self).CopyToProto(proto)
693
694
695class EnumValueDescriptor(DescriptorBase):
696
697  """Descriptor for a single value within an enum.
698
699  Attributes:
700    name (str): Name of this value.
701    index (int): Dense, 0-indexed index giving the order that this
702      value appears textually within its enum in the .proto file.
703    number (int): Actual number assigned to this enum value.
704    type (EnumDescriptor): :class:`EnumDescriptor` to which this value
705      belongs.  Set by :class:`EnumDescriptor`'s constructor if we're
706      passed into one.
707    options (descriptor_pb2.EnumValueOptions): Enum value options message or
708      None to use default enum value options options.
709  """
710
711  if _USE_C_DESCRIPTORS:
712    _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
713
714    def __new__(cls, name, index, number,
715                type=None,  # pylint: disable=redefined-builtin
716                options=None, serialized_options=None, create_key=None):
717      _message.Message._CheckCalledFromGeneratedFile()
718      # There is no way we can build a complete EnumValueDescriptor with the
719      # given parameters (the name of the Enum is not known, for example).
720      # Fortunately generated files just pass it to the EnumDescriptor()
721      # constructor, which will ignore it, so returning None is good enough.
722      return None
723
724  def __init__(self, name, index, number,
725               type=None,  # pylint: disable=redefined-builtin
726               options=None, serialized_options=None, create_key=None):
727    """Arguments are as described in the attribute description above."""
728    if create_key is not _internal_create_key:
729      _Deprecated('EnumValueDescriptor')
730
731    super(EnumValueDescriptor, self).__init__(
732        options, serialized_options, 'EnumValueOptions')
733    self.name = name
734    self.index = index
735    self.number = number
736    self.type = type
737
738
739class OneofDescriptor(DescriptorBase):
740  """Descriptor for a oneof field.
741
742  Attributes:
743    name (str): Name of the oneof field.
744    full_name (str): Full name of the oneof field, including package name.
745    index (int): 0-based index giving the order of the oneof field inside
746      its containing type.
747    containing_type (Descriptor): :class:`Descriptor` of the protocol message
748      type that contains this field.  Set by the :class:`Descriptor` constructor
749      if we're passed into one.
750    fields (list[FieldDescriptor]): The list of field descriptors this
751      oneof can contain.
752  """
753
754  if _USE_C_DESCRIPTORS:
755    _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
756
757    def __new__(
758        cls, name, full_name, index, containing_type, fields, options=None,
759        serialized_options=None, create_key=None):
760      _message.Message._CheckCalledFromGeneratedFile()
761      return _message.default_pool.FindOneofByName(full_name)
762
763  def __init__(
764      self, name, full_name, index, containing_type, fields, options=None,
765      serialized_options=None, create_key=None):
766    """Arguments are as described in the attribute description above."""
767    if create_key is not _internal_create_key:
768      _Deprecated('OneofDescriptor')
769
770    super(OneofDescriptor, self).__init__(
771        options, serialized_options, 'OneofOptions')
772    self.name = name
773    self.full_name = full_name
774    self.index = index
775    self.containing_type = containing_type
776    self.fields = fields
777
778
779class ServiceDescriptor(_NestedDescriptorBase):
780
781  """Descriptor for a service.
782
783  Attributes:
784    name (str): Name of the service.
785    full_name (str): Full name of the service, including package name.
786    index (int): 0-indexed index giving the order that this services
787      definition appears within the .proto file.
788    methods (list[MethodDescriptor]): List of methods provided by this
789      service.
790    methods_by_name (dict(str, MethodDescriptor)): Same
791      :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but
792      indexed by "name" attribute in each :class:`MethodDescriptor`.
793    options (descriptor_pb2.ServiceOptions): Service options message or
794      None to use default service options.
795    file (FileDescriptor): Reference to file info.
796  """
797
798  if _USE_C_DESCRIPTORS:
799    _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
800
801    def __new__(cls, name, full_name, index, methods, options=None,
802                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
803                serialized_start=None, serialized_end=None, create_key=None):
804      _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
805      return _message.default_pool.FindServiceByName(full_name)
806
807  def __init__(self, name, full_name, index, methods, options=None,
808               serialized_options=None, file=None,  # pylint: disable=redefined-builtin
809               serialized_start=None, serialized_end=None, create_key=None):
810    if create_key is not _internal_create_key:
811      _Deprecated('ServiceDescriptor')
812
813    super(ServiceDescriptor, self).__init__(
814        options, 'ServiceOptions', name, full_name, file,
815        None, serialized_start=serialized_start,
816        serialized_end=serialized_end, serialized_options=serialized_options)
817    self.index = index
818    self.methods = methods
819    self.methods_by_name = dict((m.name, m) for m in methods)
820    # Set the containing service for each method in this service.
821    for method in self.methods:
822      method.containing_service = self
823
824  def FindMethodByName(self, name):
825    """Searches for the specified method, and returns its descriptor.
826
827    Args:
828      name (str): Name of the method.
829    Returns:
830      MethodDescriptor or None: the desctiptor for the requested method, if
831      found.
832    """
833    return self.methods_by_name.get(name, None)
834
835  def CopyToProto(self, proto):
836    """Copies this to a descriptor_pb2.ServiceDescriptorProto.
837
838    Args:
839      proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto.
840    """
841    # This function is overridden to give a better doc comment.
842    super(ServiceDescriptor, self).CopyToProto(proto)
843
844
845class MethodDescriptor(DescriptorBase):
846
847  """Descriptor for a method in a service.
848
849  Attributes:
850    name (str): Name of the method within the service.
851    full_name (str): Full name of method.
852    index (int): 0-indexed index of the method inside the service.
853    containing_service (ServiceDescriptor): The service that contains this
854      method.
855    input_type (Descriptor): The descriptor of the message that this method
856      accepts.
857    output_type (Descriptor): The descriptor of the message that this method
858      returns.
859    options (descriptor_pb2.MethodOptions or None): Method options message, or
860      None to use default method options.
861  """
862
863  if _USE_C_DESCRIPTORS:
864    _C_DESCRIPTOR_CLASS = _message.MethodDescriptor
865
866    def __new__(cls, name, full_name, index, containing_service,
867                input_type, output_type, options=None, serialized_options=None,
868                create_key=None):
869      _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
870      return _message.default_pool.FindMethodByName(full_name)
871
872  def __init__(self, name, full_name, index, containing_service,
873               input_type, output_type, options=None, serialized_options=None,
874               create_key=None):
875    """The arguments are as described in the description of MethodDescriptor
876    attributes above.
877
878    Note that containing_service may be None, and may be set later if necessary.
879    """
880    if create_key is not _internal_create_key:
881      _Deprecated('MethodDescriptor')
882
883    super(MethodDescriptor, self).__init__(
884        options, serialized_options, 'MethodOptions')
885    self.name = name
886    self.full_name = full_name
887    self.index = index
888    self.containing_service = containing_service
889    self.input_type = input_type
890    self.output_type = output_type
891
892
893class FileDescriptor(DescriptorBase):
894  """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
895
896  Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and
897  :attr:`dependencies` fields are only set by the
898  :py:mod:`google.protobuf.message_factory` module, and not by the generated
899  proto code.
900
901  Attributes:
902    name (str): Name of file, relative to root of source tree.
903    package (str): Name of the package
904    syntax (str): string indicating syntax of the file (can be "proto2" or
905      "proto3")
906    serialized_pb (bytes): Byte string of serialized
907      :class:`descriptor_pb2.FileDescriptorProto`.
908    dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`
909      objects this :class:`FileDescriptor` depends on.
910    public_dependencies (list[FileDescriptor]): A subset of
911      :attr:`dependencies`, which were declared as "public".
912    message_types_by_name (dict(str, Descriptor)): Mapping from message names
913      to their :class:`Desctiptor`.
914    enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to
915      their :class:`EnumDescriptor`.
916    extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension
917      names declared at file scope to their :class:`FieldDescriptor`.
918    services_by_name (dict(str, ServiceDescriptor)): Mapping from services'
919      names to their :class:`ServiceDescriptor`.
920    pool (DescriptorPool): The pool this descriptor belongs to.  When not
921      passed to the constructor, the global default pool is used.
922  """
923
924  if _USE_C_DESCRIPTORS:
925    _C_DESCRIPTOR_CLASS = _message.FileDescriptor
926
927    def __new__(cls, name, package, options=None,
928                serialized_options=None, serialized_pb=None,
929                dependencies=None, public_dependencies=None,
930                syntax=None, pool=None, create_key=None):
931      # FileDescriptor() is called from various places, not only from generated
932      # files, to register dynamic proto files and messages.
933      # pylint: disable=g-explicit-bool-comparison
934      if serialized_pb == b'':
935        # Cpp generated code must be linked in if serialized_pb is ''
936        try:
937          return _message.default_pool.FindFileByName(name)
938        except KeyError:
939          raise RuntimeError('Please link in cpp generated lib for %s' % (name))
940      elif serialized_pb:
941        return _message.default_pool.AddSerializedFile(serialized_pb)
942      else:
943        return super(FileDescriptor, cls).__new__(cls)
944
945  def __init__(self, name, package, options=None,
946               serialized_options=None, serialized_pb=None,
947               dependencies=None, public_dependencies=None,
948               syntax=None, pool=None, create_key=None):
949    """Constructor."""
950    if create_key is not _internal_create_key:
951      _Deprecated('FileDescriptor')
952
953    super(FileDescriptor, self).__init__(
954        options, serialized_options, 'FileOptions')
955
956    if pool is None:
957      from google.protobuf import descriptor_pool
958      pool = descriptor_pool.Default()
959    self.pool = pool
960    self.message_types_by_name = {}
961    self.name = name
962    self.package = package
963    self.syntax = syntax or "proto2"
964    self.serialized_pb = serialized_pb
965
966    self.enum_types_by_name = {}
967    self.extensions_by_name = {}
968    self.services_by_name = {}
969    self.dependencies = (dependencies or [])
970    self.public_dependencies = (public_dependencies or [])
971
972  def CopyToProto(self, proto):
973    """Copies this to a descriptor_pb2.FileDescriptorProto.
974
975    Args:
976      proto: An empty descriptor_pb2.FileDescriptorProto.
977    """
978    proto.ParseFromString(self.serialized_pb)
979
980
981def _ParseOptions(message, string):
982  """Parses serialized options.
983
984  This helper function is used to parse serialized options in generated
985  proto2 files. It must not be used outside proto2.
986  """
987  message.ParseFromString(string)
988  return message
989
990
991def _ToCamelCase(name):
992  """Converts name to camel-case and returns it."""
993  capitalize_next = False
994  result = []
995
996  for c in name:
997    if c == '_':
998      if result:
999        capitalize_next = True
1000    elif capitalize_next:
1001      result.append(c.upper())
1002      capitalize_next = False
1003    else:
1004      result += c
1005
1006  # Lower-case the first letter.
1007  if result and result[0].isupper():
1008    result[0] = result[0].lower()
1009  return ''.join(result)
1010
1011
1012def _OptionsOrNone(descriptor_proto):
1013  """Returns the value of the field `options`, or None if it is not set."""
1014  if descriptor_proto.HasField('options'):
1015    return descriptor_proto.options
1016  else:
1017    return None
1018
1019
1020def _ToJsonName(name):
1021  """Converts name to Json name and returns it."""
1022  capitalize_next = False
1023  result = []
1024
1025  for c in name:
1026    if c == '_':
1027      capitalize_next = True
1028    elif capitalize_next:
1029      result.append(c.upper())
1030      capitalize_next = False
1031    else:
1032      result += c
1033
1034  return ''.join(result)
1035
1036
1037def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
1038                   syntax=None):
1039  """Make a protobuf Descriptor given a DescriptorProto protobuf.
1040
1041  Handles nested descriptors. Note that this is limited to the scope of defining
1042  a message inside of another message. Composite fields can currently only be
1043  resolved if the message is defined in the same scope as the field.
1044
1045  Args:
1046    desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
1047    package: Optional package name for the new message Descriptor (string).
1048    build_file_if_cpp: Update the C++ descriptor pool if api matches.
1049                       Set to False on recursion, so no duplicates are created.
1050    syntax: The syntax/semantics that should be used.  Set to "proto3" to get
1051            proto3 field presence semantics.
1052  Returns:
1053    A Descriptor for protobuf messages.
1054  """
1055  if api_implementation.Type() == 'cpp' and build_file_if_cpp:
1056    # The C++ implementation requires all descriptors to be backed by the same
1057    # definition in the C++ descriptor pool. To do this, we build a
1058    # FileDescriptorProto with the same definition as this descriptor and build
1059    # it into the pool.
1060    from google.protobuf import descriptor_pb2
1061    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
1062    file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
1063
1064    # Generate a random name for this proto file to prevent conflicts with any
1065    # imported ones. We need to specify a file name so the descriptor pool
1066    # accepts our FileDescriptorProto, but it is not important what that file
1067    # name is actually set to.
1068    proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
1069
1070    if package:
1071      file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
1072                                                proto_name + '.proto')
1073      file_descriptor_proto.package = package
1074    else:
1075      file_descriptor_proto.name = proto_name + '.proto'
1076
1077    _message.default_pool.Add(file_descriptor_proto)
1078    result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
1079
1080    if _USE_C_DESCRIPTORS:
1081      return result.message_types_by_name[desc_proto.name]
1082
1083  full_message_name = [desc_proto.name]
1084  if package: full_message_name.insert(0, package)
1085
1086  # Create Descriptors for enum types
1087  enum_types = {}
1088  for enum_proto in desc_proto.enum_type:
1089    full_name = '.'.join(full_message_name + [enum_proto.name])
1090    enum_desc = EnumDescriptor(
1091        enum_proto.name, full_name, None, [
1092            EnumValueDescriptor(enum_val.name, ii, enum_val.number,
1093                                create_key=_internal_create_key)
1094            for ii, enum_val in enumerate(enum_proto.value)],
1095        create_key=_internal_create_key)
1096    enum_types[full_name] = enum_desc
1097
1098  # Create Descriptors for nested types
1099  nested_types = {}
1100  for nested_proto in desc_proto.nested_type:
1101    full_name = '.'.join(full_message_name + [nested_proto.name])
1102    # Nested types are just those defined inside of the message, not all types
1103    # used by fields in the message, so no loops are possible here.
1104    nested_desc = MakeDescriptor(nested_proto,
1105                                 package='.'.join(full_message_name),
1106                                 build_file_if_cpp=False,
1107                                 syntax=syntax)
1108    nested_types[full_name] = nested_desc
1109
1110  fields = []
1111  for field_proto in desc_proto.field:
1112    full_name = '.'.join(full_message_name + [field_proto.name])
1113    enum_desc = None
1114    nested_desc = None
1115    if field_proto.json_name:
1116      json_name = field_proto.json_name
1117    else:
1118      json_name = None
1119    if field_proto.HasField('type_name'):
1120      type_name = field_proto.type_name
1121      full_type_name = '.'.join(full_message_name +
1122                                [type_name[type_name.rfind('.')+1:]])
1123      if full_type_name in nested_types:
1124        nested_desc = nested_types[full_type_name]
1125      elif full_type_name in enum_types:
1126        enum_desc = enum_types[full_type_name]
1127      # Else type_name references a non-local type, which isn't implemented
1128    field = FieldDescriptor(
1129        field_proto.name, full_name, field_proto.number - 1,
1130        field_proto.number, field_proto.type,
1131        FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
1132        field_proto.label, None, nested_desc, enum_desc, None, False, None,
1133        options=_OptionsOrNone(field_proto), has_default_value=False,
1134        json_name=json_name, create_key=_internal_create_key)
1135    fields.append(field)
1136
1137  desc_name = '.'.join(full_message_name)
1138  return Descriptor(desc_proto.name, desc_name, None, None, fields,
1139                    list(nested_types.values()), list(enum_types.values()), [],
1140                    options=_OptionsOrNone(desc_proto),
1141                    create_key=_internal_create_key)
1142