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