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