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