codekingpro/portable-devtools
114k
1# Protocol Buffers - Google's data interchange format2# Copyright 2008 Google Inc. All rights reserved.3#4# Use of this source code is governed by a BSD-style5# license that can be found in the LICENSE file or at6# https://developers.google.com/open-source/licenses/bsd7 8"""Descriptors essentially contain exactly the information found in a .proto9file, in types that make this information accessible in Python.10"""11 12__author__ = 'robinson@google.com (Will Robinson)'13 14import threading15import warnings16 17from google.protobuf.internal import api_implementation18 19_USE_C_DESCRIPTORS = False20if api_implementation.Type() != 'python':21 # Used by MakeDescriptor in cpp mode22 import binascii23 import os24 # pylint: disable=protected-access25 _message = api_implementation._c_module26 # TODO: Remove this import after fix api_implementation27 if _message is None:28 from google.protobuf.pyext import _message29 _USE_C_DESCRIPTORS = True30 31 32class Error(Exception):33 """Base error for this module."""34 35 36class TypeTransformationError(Error):37 """Error transforming between python proto type and corresponding C++ type."""38 39 40if _USE_C_DESCRIPTORS:41 # This metaclass allows to override the behavior of code like42 # isinstance(my_descriptor, FieldDescriptor)43 # and make it return True when the descriptor is an instance of the extension44 # type written in C++.45 class DescriptorMetaclass(type):46 47 def __instancecheck__(cls, obj):48 if super(DescriptorMetaclass, cls).__instancecheck__(obj):49 return True50 if isinstance(obj, cls._C_DESCRIPTOR_CLASS):51 return True52 return False53else:54 # The standard metaclass; nothing changes.55 DescriptorMetaclass = type56 57 58class _Lock(object):59 """Wrapper class of threading.Lock(), which is allowed by 'with'."""60 61 def __new__(cls):62 self = object.__new__(cls)63 self._lock = threading.Lock() # pylint: disable=protected-access64 return self65 66 def __enter__(self):67 self._lock.acquire()68 69 def __exit__(self, exc_type, exc_value, exc_tb):70 self._lock.release()71 72 73_lock = threading.Lock()74 75 76def _Deprecated(name):77 if _Deprecated.count > 0:78 _Deprecated.count -= 179 warnings.warn(80 'Call to deprecated create function %s(). Note: Create unlinked '81 'descriptors is going to go away. Please use get/find descriptors from '82 'generated code or query the descriptor_pool.'83 % name,84 category=DeprecationWarning, stacklevel=3)85 86 87# Deprecated warnings will print 100 times at most which should be enough for88# users to notice and do not cause timeout.89_Deprecated.count = 10090 91 92_internal_create_key = object()93 94 95class DescriptorBase(metaclass=DescriptorMetaclass):96 97 """Descriptors base class.98 99 This class is the base of all descriptor classes. It provides common options100 related functionality.101 102 Attributes:103 has_options: True if the descriptor has non-default options. Usually it is104 not necessary to read this -- just call GetOptions() which will happily105 return the default instance. However, it's sometimes useful for106 efficiency, and also useful inside the protobuf implementation to avoid107 some bootstrapping issues.108 file (FileDescriptor): Reference to file info.109 """110 111 if _USE_C_DESCRIPTORS:112 # The class, or tuple of classes, that are considered as "virtual113 # subclasses" of this descriptor class.114 _C_DESCRIPTOR_CLASS = ()115 116 def __init__(self, file, options, serialized_options, options_class_name):117 """Initialize the descriptor given its options message and the name of the118 class of the options message. The name of the class is required in case119 the options message is None and has to be created.120 """121 self.file = file122 self._options = options123 self._options_class_name = options_class_name124 self._serialized_options = serialized_options125 126 # Does this descriptor have non-default options?127 self.has_options = (self._options is not None) or (128 self._serialized_options is not None129 )130 131 def _SetOptions(self, options, options_class_name):132 """Sets the descriptor's options133 134 This function is used in generated proto2 files to update descriptor135 options. It must not be used outside proto2.136 """137 self._options = options138 self._options_class_name = options_class_name139 140 # Does this descriptor have non-default options?141 self.has_options = options is not None142 143 def GetOptions(self):144 """Retrieves descriptor options.145 146 This method returns the options set or creates the default options for the147 descriptor.148 """149 if self._options:150 return self._options151 152 from google.protobuf import descriptor_pb2153 try:154 options_class = getattr(descriptor_pb2,155 self._options_class_name)156 except AttributeError:157 raise RuntimeError('Unknown options class name %s!' %158 (self._options_class_name))159 160 if self._serialized_options is None:161 with _lock:162 self._options = options_class()163 else:164 options = _ParseOptions(options_class(), self._serialized_options)165 with _lock:166 self._options = options167 168 return self._options169 170 171class _NestedDescriptorBase(DescriptorBase):172 """Common class for descriptors that can be nested."""173 174 def __init__(self, options, options_class_name, name, full_name,175 file, containing_type, serialized_start=None,176 serialized_end=None, serialized_options=None):177 """Constructor.178 179 Args:180 options: Protocol message options or None to use default message options.181 options_class_name (str): The class name of the above options.182 name (str): Name of this protocol message type.183 full_name (str): Fully-qualified name of this protocol message type, which184 will include protocol "package" name and the name of any enclosing185 types.186 containing_type: if provided, this is a nested descriptor, with this187 descriptor as parent, otherwise None.188 serialized_start: The start index (inclusive) in block in the189 file.serialized_pb that describes this descriptor.190 serialized_end: The end index (exclusive) in block in the191 file.serialized_pb that describes this descriptor.192 serialized_options: Protocol message serialized options or None.193 """194 super(_NestedDescriptorBase, self).__init__(195 file, options, serialized_options, options_class_name196 )197 198 self.name = name199 # TODO: Add function to calculate full_name instead of having it in200 # memory?201 self.full_name = full_name202 self.containing_type = containing_type203 204 self._serialized_start = serialized_start205 self._serialized_end = serialized_end206 207 def CopyToProto(self, proto):208 """Copies this to the matching proto in descriptor_pb2.209 210 Args:211 proto: An empty proto instance from descriptor_pb2.212 213 Raises:214 Error: If self couldn't be serialized, due to to few constructor215 arguments.216 """217 if (self.file is not None and218 self._serialized_start is not None and219 self._serialized_end is not None):220 proto.ParseFromString(self.file.serialized_pb[221 self._serialized_start:self._serialized_end])222 else:223 raise Error('Descriptor does not contain serialization.')224 225 226class Descriptor(_NestedDescriptorBase):227 228 """Descriptor for a protocol message type.229 230 Attributes:231 name (str): Name of this protocol message type.232 full_name (str): Fully-qualified name of this protocol message type,233 which will include protocol "package" name and the name of any234 enclosing types.235 containing_type (Descriptor): Reference to the descriptor of the type236 containing us, or None if this is top-level.237 fields (list[FieldDescriptor]): Field descriptors for all fields in238 this type.239 fields_by_number (dict(int, FieldDescriptor)): Same240 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed241 by "number" attribute in each FieldDescriptor.242 fields_by_name (dict(str, FieldDescriptor)): Same243 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by244 "name" attribute in each :class:`FieldDescriptor`.245 nested_types (list[Descriptor]): Descriptor references246 for all protocol message types nested within this one.247 nested_types_by_name (dict(str, Descriptor)): Same Descriptor248 objects as in :attr:`nested_types`, but indexed by "name" attribute249 in each Descriptor.250 enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references251 for all enums contained within this type.252 enum_types_by_name (dict(str, EnumDescriptor)): Same253 :class:`EnumDescriptor` objects as in :attr:`enum_types`, but254 indexed by "name" attribute in each EnumDescriptor.255 enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping256 from enum value name to :class:`EnumValueDescriptor` for that value.257 extensions (list[FieldDescriptor]): All extensions defined directly258 within this message type (NOT within a nested type).259 extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor260 objects as :attr:`extensions`, but indexed by "name" attribute of each261 FieldDescriptor.262 is_extendable (bool): Does this type define any extension ranges?263 oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields264 in this message.265 oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in266 :attr:`oneofs`, but indexed by "name" attribute.267 file (FileDescriptor): Reference to file descriptor.268 is_map_entry: If the message type is a map entry.269 270 """271 272 if _USE_C_DESCRIPTORS:273 _C_DESCRIPTOR_CLASS = _message.Descriptor274 275 def __new__(276 cls,277 name=None,278 full_name=None,279 filename=None,280 containing_type=None,281 fields=None,282 nested_types=None,283 enum_types=None,284 extensions=None,285 options=None,286 serialized_options=None,287 is_extendable=True,288 extension_ranges=None,289 oneofs=None,290 file=None, # pylint: disable=redefined-builtin291 serialized_start=None,292 serialized_end=None,293 syntax=None,294 is_map_entry=False,295 create_key=None):296 _message.Message._CheckCalledFromGeneratedFile()297 return _message.default_pool.FindMessageTypeByName(full_name)298 299 # NOTE: The file argument redefining a builtin is nothing we can300 # fix right now since we don't know how many clients already rely on the301 # name of the argument.302 def __init__(self, name, full_name, filename, containing_type, fields,303 nested_types, enum_types, extensions, options=None,304 serialized_options=None,305 is_extendable=True, extension_ranges=None, oneofs=None,306 file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin307 syntax=None, is_map_entry=False, create_key=None):308 """Arguments to __init__() are as described in the description309 of Descriptor fields above.310 311 Note that filename is an obsolete argument, that is not used anymore.312 Please use file.name to access this as an attribute.313 """314 if create_key is not _internal_create_key:315 _Deprecated('Descriptor')316 317 super(Descriptor, self).__init__(318 options, 'MessageOptions', name, full_name, file,319 containing_type, serialized_start=serialized_start,320 serialized_end=serialized_end, serialized_options=serialized_options)321 322 # We have fields in addition to fields_by_name and fields_by_number,323 # so that:324 # 1. Clients can index fields by "order in which they're listed."325 # 2. Clients can easily iterate over all fields with the terse326 # syntax: for f in descriptor.fields: ...327 self.fields = fields328 for field in self.fields:329 field.containing_type = self330 self.fields_by_number = dict((f.number, f) for f in fields)331 self.fields_by_name = dict((f.name, f) for f in fields)332 self._fields_by_camelcase_name = None333 334 self.nested_types = nested_types335 for nested_type in nested_types:336 nested_type.containing_type = self337 self.nested_types_by_name = dict((t.name, t) for t in nested_types)338 339 self.enum_types = enum_types340 for enum_type in self.enum_types:341 enum_type.containing_type = self342 self.enum_types_by_name = dict((t.name, t) for t in enum_types)343 self.enum_values_by_name = dict(344 (v.name, v) for t in enum_types for v in t.values)345 346 self.extensions = extensions347 for extension in self.extensions:348 extension.extension_scope = self349 self.extensions_by_name = dict((f.name, f) for f in extensions)350 self.is_extendable = is_extendable351 self.extension_ranges = extension_ranges352 self.oneofs = oneofs if oneofs is not None else []353 self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)354 for oneof in self.oneofs:355 oneof.containing_type = self356 self._deprecated_syntax = syntax or "proto2"357 self._is_map_entry = is_map_entry358 359 @property360 def syntax(self):361 warnings.warn(362 'descriptor.syntax is deprecated. It will be removed'363 ' soon. Most usages are checking field descriptors. Consider to use'364 ' has_presence, is_packed on field descriptors.'365 )366 return self._deprecated_syntax367 368 @property369 def fields_by_camelcase_name(self):370 """Same FieldDescriptor objects as in :attr:`fields`, but indexed by371 :attr:`FieldDescriptor.camelcase_name`.372 """373 if self._fields_by_camelcase_name is None:374 self._fields_by_camelcase_name = dict(375 (f.camelcase_name, f) for f in self.fields)376 return self._fields_by_camelcase_name377 378 def EnumValueName(self, enum, value):379 """Returns the string name of an enum value.380 381 This is just a small helper method to simplify a common operation.382 383 Args:384 enum: string name of the Enum.385 value: int, value of the enum.386 387 Returns:388 string name of the enum value.389 390 Raises:391 KeyError if either the Enum doesn't exist or the value is not a valid392 value for the enum.393 """394 return self.enum_types_by_name[enum].values_by_number[value].name395 396 def CopyToProto(self, proto):397 """Copies this to a descriptor_pb2.DescriptorProto.398 399 Args:400 proto: An empty descriptor_pb2.DescriptorProto.401 """402 # This function is overridden to give a better doc comment.403 super(Descriptor, self).CopyToProto(proto)404 405 406# TODO: We should have aggressive checking here,407# for example:408# * If you specify a repeated field, you should not be allowed409# to specify a default value.410# * [Other examples here as needed].411#412# TODO: for this and other *Descriptor classes, we413# might also want to lock things down aggressively (e.g.,414# prevent clients from setting the attributes). Having415# stronger invariants here in general will reduce the number416# of runtime checks we must do in reflection.py...417class FieldDescriptor(DescriptorBase):418 419 """Descriptor for a single field in a .proto file.420 421 Attributes:422 name (str): Name of this field, exactly as it appears in .proto.423 full_name (str): Name of this field, including containing scope. This is424 particularly relevant for extensions.425 index (int): Dense, 0-indexed index giving the order that this426 field textually appears within its message in the .proto file.427 number (int): Tag number declared for this field in the .proto file.428 429 type (int): (One of the TYPE_* constants below) Declared type.430 cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to431 represent this field.432 433 label (int): (One of the LABEL_* constants below) Tells whether this434 field is optional, required, or repeated.435 has_default_value (bool): True if this field has a default value defined,436 otherwise false.437 default_value (Varies): Default value of this field. Only438 meaningful for non-repeated scalar fields. Repeated fields439 should always set this to [], and non-repeated composite440 fields should always set this to None.441 442 containing_type (Descriptor): Descriptor of the protocol message443 type that contains this field. Set by the Descriptor constructor444 if we're passed into one.445 Somewhat confusingly, for extension fields, this is the446 descriptor of the EXTENDED message, not the descriptor447 of the message containing this field. (See is_extension and448 extension_scope below).449 message_type (Descriptor): If a composite field, a descriptor450 of the message type contained in this field. Otherwise, this is None.451 enum_type (EnumDescriptor): If this field contains an enum, a452 descriptor of that enum. Otherwise, this is None.453 454 is_extension: True iff this describes an extension field.455 extension_scope (Descriptor): Only meaningful if is_extension is True.456 Gives the message that immediately contains this extension field.457 Will be None iff we're a top-level (file-level) extension field.458 459 options (descriptor_pb2.FieldOptions): Protocol message field options or460 None to use default field options.461 462 containing_oneof (OneofDescriptor): If the field is a member of a oneof463 union, contains its descriptor. Otherwise, None.464 465 file (FileDescriptor): Reference to file descriptor.466 """467 468 # Must be consistent with C++ FieldDescriptor::Type enum in469 # descriptor.h.470 #471 # TODO: Find a way to eliminate this repetition.472 TYPE_DOUBLE = 1473 TYPE_FLOAT = 2474 TYPE_INT64 = 3475 TYPE_UINT64 = 4476 TYPE_INT32 = 5477 TYPE_FIXED64 = 6478 TYPE_FIXED32 = 7479 TYPE_BOOL = 8480 TYPE_STRING = 9481 TYPE_GROUP = 10482 TYPE_MESSAGE = 11483 TYPE_BYTES = 12484 TYPE_UINT32 = 13485 TYPE_ENUM = 14486 TYPE_SFIXED32 = 15487 TYPE_SFIXED64 = 16488 TYPE_SINT32 = 17489 TYPE_SINT64 = 18490 MAX_TYPE = 18491 492 # Must be consistent with C++ FieldDescriptor::CppType enum in493 # descriptor.h.494 #495 # TODO: Find a way to eliminate this repetition.496 CPPTYPE_INT32 = 1497 CPPTYPE_INT64 = 2498 CPPTYPE_UINT32 = 3499 CPPTYPE_UINT64 = 4500 CPPTYPE_DOUBLE = 5501 CPPTYPE_FLOAT = 6502 CPPTYPE_BOOL = 7503 CPPTYPE_ENUM = 8504 CPPTYPE_STRING = 9505 CPPTYPE_MESSAGE = 10506 MAX_CPPTYPE = 10507 508 _PYTHON_TO_CPP_PROTO_TYPE_MAP = {509 TYPE_DOUBLE: CPPTYPE_DOUBLE,510 TYPE_FLOAT: CPPTYPE_FLOAT,511 TYPE_ENUM: CPPTYPE_ENUM,512 TYPE_INT64: CPPTYPE_INT64,513 TYPE_SINT64: CPPTYPE_INT64,514 TYPE_SFIXED64: CPPTYPE_INT64,515 TYPE_UINT64: CPPTYPE_UINT64,516 TYPE_FIXED64: CPPTYPE_UINT64,517 TYPE_INT32: CPPTYPE_INT32,518 TYPE_SFIXED32: CPPTYPE_INT32,519 TYPE_SINT32: CPPTYPE_INT32,520 TYPE_UINT32: CPPTYPE_UINT32,521 TYPE_FIXED32: CPPTYPE_UINT32,522 TYPE_BYTES: CPPTYPE_STRING,523 TYPE_STRING: CPPTYPE_STRING,524 TYPE_BOOL: CPPTYPE_BOOL,525 TYPE_MESSAGE: CPPTYPE_MESSAGE,526 TYPE_GROUP: CPPTYPE_MESSAGE527 }528 529 # Must be consistent with C++ FieldDescriptor::Label enum in530 # descriptor.h.531 #532 # TODO: Find a way to eliminate this repetition.533 LABEL_OPTIONAL = 1534 LABEL_REQUIRED = 2535 LABEL_REPEATED = 3536 MAX_LABEL = 3537 538 # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,539 # and kLastReservedNumber in descriptor.h540 MAX_FIELD_NUMBER = (1 << 29) - 1541 FIRST_RESERVED_FIELD_NUMBER = 19000542 LAST_RESERVED_FIELD_NUMBER = 19999543 544 if _USE_C_DESCRIPTORS:545 _C_DESCRIPTOR_CLASS = _message.FieldDescriptor546 547 def __new__(cls, name, full_name, index, number, type, cpp_type, label,548 default_value, message_type, enum_type, containing_type,549 is_extension, extension_scope, options=None,550 serialized_options=None,551 has_default_value=True, containing_oneof=None, json_name=None,552 file=None, create_key=None): # pylint: disable=redefined-builtin553 _message.Message._CheckCalledFromGeneratedFile()554 if is_extension:555 return _message.default_pool.FindExtensionByName(full_name)556 else:557 return _message.default_pool.FindFieldByName(full_name)558 559 def __init__(self, name, full_name, index, number, type, cpp_type, label,560 default_value, message_type, enum_type, containing_type,561 is_extension, extension_scope, options=None,562 serialized_options=None,563 has_default_value=True, containing_oneof=None, json_name=None,564 file=None, create_key=None): # pylint: disable=redefined-builtin565 """The arguments are as described in the description of FieldDescriptor566 attributes above.567 568 Note that containing_type may be None, and may be set later if necessary569 (to deal with circular references between message types, for example).570 Likewise for extension_scope.571 """572 if create_key is not _internal_create_key:573 _Deprecated('FieldDescriptor')574 575 super(FieldDescriptor, self).__init__(576 file, options, serialized_options, 'FieldOptions'577 )578 self.name = name579 self.full_name = full_name580 self._camelcase_name = None581 if json_name is None:582 self.json_name = _ToJsonName(name)583 else:584 self.json_name = json_name585 self.index = index586 self.number = number587 self.type = type588 self.cpp_type = cpp_type589 self.label = label590 self.has_default_value = has_default_value591 self.default_value = default_value592 self.containing_type = containing_type593 self.message_type = message_type594 self.enum_type = enum_type595 self.is_extension = is_extension596 self.extension_scope = extension_scope597 self.containing_oneof = containing_oneof598 if api_implementation.Type() == 'python':599 self._cdescriptor = None600 else:601 if is_extension:602 self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)603 else:604 self._cdescriptor = _message.default_pool.FindFieldByName(full_name)605 606 @property607 def camelcase_name(self):608 """Camelcase name of this field.609 610 Returns:611 str: the name in CamelCase.612 """613 if self._camelcase_name is None:614 self._camelcase_name = _ToCamelCase(self.name)615 return self._camelcase_name616 617 @property618 def has_presence(self):619 """Whether the field distinguishes between unpopulated and default values.620 621 Raises:622 RuntimeError: singular field that is not linked with message nor file.623 """624 if self.label == FieldDescriptor.LABEL_REPEATED:625 return False626 if (self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE or627 self.containing_oneof):628 return True629 # self.containing_type is used here instead of self.file for legacy630 # compatibility. FieldDescriptor.file was added in cl/153110619631 # Some old/generated code didn't link file to FieldDescriptor.632 # TODO: remove syntax usage b/240619313633 return self.containing_type._deprecated_syntax == 'proto2'634 635 @property636 def is_packed(self):637 """Returns if the field is packed."""638 if self.label != FieldDescriptor.LABEL_REPEATED:639 return False640 field_type = self.type641 if (field_type == FieldDescriptor.TYPE_STRING or642 field_type == FieldDescriptor.TYPE_GROUP or643 field_type == FieldDescriptor.TYPE_MESSAGE or644 field_type == FieldDescriptor.TYPE_BYTES):645 return False646 if self.containing_type._deprecated_syntax == 'proto2':647 return self.has_options and self.GetOptions().packed648 else:649 return (not self.has_options or650 not self.GetOptions().HasField('packed') or651 self.GetOptions().packed)652 653 @staticmethod654 def ProtoTypeToCppProtoType(proto_type):655 """Converts from a Python proto type to a C++ Proto Type.656 657 The Python ProtocolBuffer classes specify both the 'Python' datatype and the658 'C++' datatype - and they're not the same. This helper method should659 translate from one to another.660 661 Args:662 proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)663 Returns:664 int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.665 Raises:666 TypeTransformationError: when the Python proto type isn't known.667 """668 try:669 return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]670 except KeyError:671 raise TypeTransformationError('Unknown proto_type: %s' % proto_type)672 673 674class EnumDescriptor(_NestedDescriptorBase):675 676 """Descriptor for an enum defined in a .proto file.677 678 Attributes:679 name (str): Name of the enum type.680 full_name (str): Full name of the type, including package name681 and any enclosing type(s).682 683 values (list[EnumValueDescriptor]): List of the values684 in this enum.685 values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`,686 but indexed by the "name" field of each EnumValueDescriptor.687 values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`,688 but indexed by the "number" field of each EnumValueDescriptor.689 containing_type (Descriptor): Descriptor of the immediate containing690 type of this enum, or None if this is an enum defined at the691 top level in a .proto file. Set by Descriptor's constructor692 if we're passed into one.693 file (FileDescriptor): Reference to file descriptor.694 options (descriptor_pb2.EnumOptions): Enum options message or695 None to use default enum options.696 """697 698 if _USE_C_DESCRIPTORS:699 _C_DESCRIPTOR_CLASS = _message.EnumDescriptor700 701 def __new__(cls, name, full_name, filename, values,702 containing_type=None, options=None,703 serialized_options=None, file=None, # pylint: disable=redefined-builtin704 serialized_start=None, serialized_end=None, create_key=None):705 _message.Message._CheckCalledFromGeneratedFile()706 return _message.default_pool.FindEnumTypeByName(full_name)707 708 def __init__(self, name, full_name, filename, values,709 containing_type=None, options=None,710 serialized_options=None, file=None, # pylint: disable=redefined-builtin711 serialized_start=None, serialized_end=None, create_key=None):712 """Arguments are as described in the attribute description above.713 714 Note that filename is an obsolete argument, that is not used anymore.715 Please use file.name to access this as an attribute.716 """717 if create_key is not _internal_create_key:718 _Deprecated('EnumDescriptor')719 720 super(EnumDescriptor, self).__init__(721 options, 'EnumOptions', name, full_name, file,722 containing_type, serialized_start=serialized_start,723 serialized_end=serialized_end, serialized_options=serialized_options)724 725 self.values = values726 for value in self.values:727 value.file = file728 value.type = self729 self.values_by_name = dict((v.name, v) for v in values)730 # Values are reversed to ensure that the first alias is retained.731 self.values_by_number = dict((v.number, v) for v in reversed(values))732 733 @property734 def is_closed(self):735 """Returns true whether this is a "closed" enum.736 737 This means that it:738 - Has a fixed set of values, rather than being equivalent to an int32.739 - Encountering values not in this set causes them to be treated as unknown740 fields.741 - The first value (i.e., the default) may be nonzero.742 743 WARNING: Some runtimes currently have a quirk where non-closed enums are744 treated as closed when used as the type of fields defined in a745 `syntax = proto2;` file. This quirk is not present in all runtimes; as of746 writing, we know that:747 748 - C++, Java, and C++-based Python share this quirk.749 - UPB and UPB-based Python do not.750 - PHP and Ruby treat all enums as open regardless of declaration.751 752 Care should be taken when using this function to respect the target753 runtime's enum handling quirks.754 """755 return self.file._deprecated_syntax == 'proto2'756 757 def CopyToProto(self, proto):758 """Copies this to a descriptor_pb2.EnumDescriptorProto.759 760 Args:761 proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto.762 """763 # This function is overridden to give a better doc comment.764 super(EnumDescriptor, self).CopyToProto(proto)765 766 767class EnumValueDescriptor(DescriptorBase):768 769 """Descriptor for a single value within an enum.770 771 Attributes:772 name (str): Name of this value.773 index (int): Dense, 0-indexed index giving the order that this774 value appears textually within its enum in the .proto file.775 number (int): Actual number assigned to this enum value.776 type (EnumDescriptor): :class:`EnumDescriptor` to which this value777 belongs. Set by :class:`EnumDescriptor`'s constructor if we're778 passed into one.779 options (descriptor_pb2.EnumValueOptions): Enum value options message or780 None to use default enum value options options.781 """782 783 if _USE_C_DESCRIPTORS:784 _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor785 786 def __new__(cls, name, index, number,787 type=None, # pylint: disable=redefined-builtin788 options=None, serialized_options=None, create_key=None):789 _message.Message._CheckCalledFromGeneratedFile()790 # There is no way we can build a complete EnumValueDescriptor with the791 # given parameters (the name of the Enum is not known, for example).792 # Fortunately generated files just pass it to the EnumDescriptor()793 # constructor, which will ignore it, so returning None is good enough.794 return None795 796 def __init__(self, name, index, number,797 type=None, # pylint: disable=redefined-builtin798 options=None, serialized_options=None, create_key=None):799 """Arguments are as described in the attribute description above."""800 if create_key is not _internal_create_key:801 _Deprecated('EnumValueDescriptor')802 803 super(EnumValueDescriptor, self).__init__(804 type.file if type else None,805 options,806 serialized_options,807 'EnumValueOptions',808 )809 self.name = name810 self.index = index811 self.number = number812 self.type = type813 814 815class OneofDescriptor(DescriptorBase):816 """Descriptor for a oneof field.817 818 Attributes:819 name (str): Name of the oneof field.820 full_name (str): Full name of the oneof field, including package name.821 index (int): 0-based index giving the order of the oneof field inside822 its containing type.823 containing_type (Descriptor): :class:`Descriptor` of the protocol message824 type that contains this field. Set by the :class:`Descriptor` constructor825 if we're passed into one.826 fields (list[FieldDescriptor]): The list of field descriptors this827 oneof can contain.828 """829 830 if _USE_C_DESCRIPTORS:831 _C_DESCRIPTOR_CLASS = _message.OneofDescriptor832 833 def __new__(834 cls, name, full_name, index, containing_type, fields, options=None,835 serialized_options=None, create_key=None):836 _message.Message._CheckCalledFromGeneratedFile()837 return _message.default_pool.FindOneofByName(full_name)838 839 def __init__(840 self, name, full_name, index, containing_type, fields, options=None,841 serialized_options=None, create_key=None):842 """Arguments are as described in the attribute description above."""843 if create_key is not _internal_create_key:844 _Deprecated('OneofDescriptor')845 846 super(OneofDescriptor, self).__init__(847 containing_type.file if containing_type else None,848 options,849 serialized_options,850 'OneofOptions',851 )852 self.name = name853 self.full_name = full_name854 self.index = index855 self.containing_type = containing_type856 self.fields = fields857 858 859class ServiceDescriptor(_NestedDescriptorBase):860 861 """Descriptor for a service.862 863 Attributes:864 name (str): Name of the service.865 full_name (str): Full name of the service, including package name.866 index (int): 0-indexed index giving the order that this services867 definition appears within the .proto file.868 methods (list[MethodDescriptor]): List of methods provided by this869 service.870 methods_by_name (dict(str, MethodDescriptor)): Same871 :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but872 indexed by "name" attribute in each :class:`MethodDescriptor`.873 options (descriptor_pb2.ServiceOptions): Service options message or874 None to use default service options.875 file (FileDescriptor): Reference to file info.876 """877 878 if _USE_C_DESCRIPTORS:879 _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor880 881 def __new__(882 cls,883 name=None,884 full_name=None,885 index=None,886 methods=None,887 options=None,888 serialized_options=None,889 file=None, # pylint: disable=redefined-builtin890 serialized_start=None,891 serialized_end=None,892 create_key=None):893 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access894 return _message.default_pool.FindServiceByName(full_name)895 896 def __init__(self, name, full_name, index, methods, options=None,897 serialized_options=None, file=None, # pylint: disable=redefined-builtin898 serialized_start=None, serialized_end=None, create_key=None):899 if create_key is not _internal_create_key:900 _Deprecated('ServiceDescriptor')901 902 super(ServiceDescriptor, self).__init__(903 options, 'ServiceOptions', name, full_name, file,904 None, serialized_start=serialized_start,905 serialized_end=serialized_end, serialized_options=serialized_options)906 self.index = index907 self.methods = methods908 self.methods_by_name = dict((m.name, m) for m in methods)909 # Set the containing service for each method in this service.910 for method in self.methods:911 method.file = self.file912 method.containing_service = self913 914 def FindMethodByName(self, name):915 """Searches for the specified method, and returns its descriptor.916 917 Args:918 name (str): Name of the method.919 920 Returns:921 MethodDescriptor: The descriptor for the requested method.922 923 Raises:924 KeyError: if the method cannot be found in the service.925 """926 return self.methods_by_name[name]927 928 def CopyToProto(self, proto):929 """Copies this to a descriptor_pb2.ServiceDescriptorProto.930 931 Args:932 proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto.933 """934 # This function is overridden to give a better doc comment.935 super(ServiceDescriptor, self).CopyToProto(proto)936 937 938class MethodDescriptor(DescriptorBase):939 940 """Descriptor for a method in a service.941 942 Attributes:943 name (str): Name of the method within the service.944 full_name (str): Full name of method.945 index (int): 0-indexed index of the method inside the service.946 containing_service (ServiceDescriptor): The service that contains this947 method.948 input_type (Descriptor): The descriptor of the message that this method949 accepts.950 output_type (Descriptor): The descriptor of the message that this method951 returns.952 client_streaming (bool): Whether this method uses client streaming.953 server_streaming (bool): Whether this method uses server streaming.954 options (descriptor_pb2.MethodOptions or None): Method options message, or955 None to use default method options.956 """957 958 if _USE_C_DESCRIPTORS:959 _C_DESCRIPTOR_CLASS = _message.MethodDescriptor960 961 def __new__(cls,962 name,963 full_name,964 index,965 containing_service,966 input_type,967 output_type,968 client_streaming=False,969 server_streaming=False,970 options=None,971 serialized_options=None,972 create_key=None):973 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access974 return _message.default_pool.FindMethodByName(full_name)975 976 def __init__(self,977 name,978 full_name,979 index,980 containing_service,981 input_type,982 output_type,983 client_streaming=False,984 server_streaming=False,985 options=None,986 serialized_options=None,987 create_key=None):988 """The arguments are as described in the description of MethodDescriptor989 attributes above.990 991 Note that containing_service may be None, and may be set later if necessary.992 """993 if create_key is not _internal_create_key:994 _Deprecated('MethodDescriptor')995 996 super(MethodDescriptor, self).__init__(997 containing_service.file if containing_service else None,998 options,999 serialized_options,1000 'MethodOptions',1001 )1002 self.name = name1003 self.full_name = full_name1004 self.index = index1005 self.containing_service = containing_service1006 self.input_type = input_type1007 self.output_type = output_type1008 self.client_streaming = client_streaming1009 self.server_streaming = server_streaming1010 1011 def CopyToProto(self, proto):1012 """Copies this to a descriptor_pb2.MethodDescriptorProto.1013 1014 Args:1015 proto (descriptor_pb2.MethodDescriptorProto): An empty descriptor proto.1016 1017 Raises:1018 Error: If self couldn't be serialized, due to too few constructor1019 arguments.1020 """1021 if self.containing_service is not None:1022 from google.protobuf import descriptor_pb21023 service_proto = descriptor_pb2.ServiceDescriptorProto()1024 self.containing_service.CopyToProto(service_proto)1025 proto.CopyFrom(service_proto.method[self.index])1026 else:1027 raise Error('Descriptor does not contain a service.')1028 1029 1030class FileDescriptor(DescriptorBase):1031 """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.1032 1033 Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and1034 :attr:`dependencies` fields are only set by the1035 :py:mod:`google.protobuf.message_factory` module, and not by the generated1036 proto code.1037 1038 Attributes:1039 name (str): Name of file, relative to root of source tree.1040 package (str): Name of the package1041 syntax (str): string indicating syntax of the file (can be "proto2" or1042 "proto3")1043 serialized_pb (bytes): Byte string of serialized1044 :class:`descriptor_pb2.FileDescriptorProto`.1045 dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`1046 objects this :class:`FileDescriptor` depends on.1047 public_dependencies (list[FileDescriptor]): A subset of1048 :attr:`dependencies`, which were declared as "public".1049 message_types_by_name (dict(str, Descriptor)): Mapping from message names1050 to their :class:`Descriptor`.1051 enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to1052 their :class:`EnumDescriptor`.1053 extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension1054 names declared at file scope to their :class:`FieldDescriptor`.1055 services_by_name (dict(str, ServiceDescriptor)): Mapping from services'1056 names to their :class:`ServiceDescriptor`.1057 pool (DescriptorPool): The pool this descriptor belongs to. When not1058 passed to the constructor, the global default pool is used.1059 """1060 1061 if _USE_C_DESCRIPTORS:1062 _C_DESCRIPTOR_CLASS = _message.FileDescriptor1063 1064 def __new__(cls, name, package, options=None,1065 serialized_options=None, serialized_pb=None,1066 dependencies=None, public_dependencies=None,1067 syntax=None, pool=None, create_key=None):1068 # FileDescriptor() is called from various places, not only from generated1069 # files, to register dynamic proto files and messages.1070 # pylint: disable=g-explicit-bool-comparison1071 if serialized_pb:1072 return _message.default_pool.AddSerializedFile(serialized_pb)1073 else:1074 return super(FileDescriptor, cls).__new__(cls)1075 1076 def __init__(self, name, package, options=None,1077 serialized_options=None, serialized_pb=None,1078 dependencies=None, public_dependencies=None,1079 syntax=None, pool=None, create_key=None):1080 """Constructor."""1081 if create_key is not _internal_create_key:1082 _Deprecated('FileDescriptor')1083 1084 super(FileDescriptor, self).__init__(1085 None, options, serialized_options, 'FileOptions'1086 )1087 1088 if pool is None:1089 from google.protobuf import descriptor_pool1090 pool = descriptor_pool.Default()1091 self.pool = pool1092 self.message_types_by_name = {}1093 self.name = name1094 self.package = package1095 self._deprecated_syntax = syntax or "proto2"1096 self.serialized_pb = serialized_pb1097 1098 self.enum_types_by_name = {}1099 self.extensions_by_name = {}1100 self.services_by_name = {}1101 self.dependencies = (dependencies or [])1102 self.public_dependencies = (public_dependencies or [])1103 1104 @property1105 def syntax(self):1106 warnings.warn(1107 'descriptor.syntax is deprecated. It will be removed'1108 ' soon. Most usages are checking field descriptors. Consider to use'1109 ' has_presence, is_packed on field descriptors.'1110 )1111 return self._deprecated_syntax1112 1113 def CopyToProto(self, proto):1114 """Copies this to a descriptor_pb2.FileDescriptorProto.1115 1116 Args:1117 proto: An empty descriptor_pb2.FileDescriptorProto.1118 """1119 proto.ParseFromString(self.serialized_pb)1120 1121 1122def _ParseOptions(message, string):1123 """Parses serialized options.1124 1125 This helper function is used to parse serialized options in generated1126 proto2 files. It must not be used outside proto2.1127 """1128 message.ParseFromString(string)1129 return message1130 1131 1132def _ToCamelCase(name):1133 """Converts name to camel-case and returns it."""1134 capitalize_next = False1135 result = []1136 1137 for c in name:1138 if c == '_':1139 if result:1140 capitalize_next = True1141 elif capitalize_next:1142 result.append(c.upper())1143 capitalize_next = False1144 else:1145 result += c1146 1147 # Lower-case the first letter.1148 if result and result[0].isupper():1149 result[0] = result[0].lower()1150 return ''.join(result)1151 1152 1153def _OptionsOrNone(descriptor_proto):1154 """Returns the value of the field `options`, or None if it is not set."""1155 if descriptor_proto.HasField('options'):1156 return descriptor_proto.options1157 else:1158 return None1159 1160 1161def _ToJsonName(name):1162 """Converts name to Json name and returns it."""1163 capitalize_next = False1164 result = []1165 1166 for c in name:1167 if c == '_':1168 capitalize_next = True1169 elif capitalize_next:1170 result.append(c.upper())1171 capitalize_next = False1172 else:1173 result += c1174 1175 return ''.join(result)1176 1177 1178def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,1179 syntax=None):1180 """Make a protobuf Descriptor given a DescriptorProto protobuf.1181 1182 Handles nested descriptors. Note that this is limited to the scope of defining1183 a message inside of another message. Composite fields can currently only be1184 resolved if the message is defined in the same scope as the field.1185 1186 Args:1187 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.1188 package: Optional package name for the new message Descriptor (string).1189 build_file_if_cpp: Update the C++ descriptor pool if api matches.1190 Set to False on recursion, so no duplicates are created.1191 syntax: The syntax/semantics that should be used. Set to "proto3" to get1192 proto3 field presence semantics.1193 Returns:1194 A Descriptor for protobuf messages.1195 """1196 if api_implementation.Type() != 'python' and build_file_if_cpp:1197 # The C++ implementation requires all descriptors to be backed by the same1198 # definition in the C++ descriptor pool. To do this, we build a1199 # FileDescriptorProto with the same definition as this descriptor and build1200 # it into the pool.