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