1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# http://code.google.com/p/protobuf/ 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 37 38from google.protobuf.internal import api_implementation 39 40 41if api_implementation.Type() == 'cpp': 42 if api_implementation.Version() == 2: 43 from google.protobuf.internal.cpp import _message 44 else: 45 from google.protobuf.internal import cpp_message 46 47 48class Error(Exception): 49 """Base error for this module.""" 50 51 52class TypeTransformationError(Error): 53 """Error transforming between python proto type and corresponding C++ type.""" 54 55 56class DescriptorBase(object): 57 58 """Descriptors base class. 59 60 This class is the base of all descriptor classes. It provides common options 61 related functionaility. 62 63 Attributes: 64 has_options: True if the descriptor has non-default options. Usually it 65 is not necessary to read this -- just call GetOptions() which will 66 happily return the default instance. However, it's sometimes useful 67 for efficiency, and also useful inside the protobuf implementation to 68 avoid some bootstrapping issues. 69 """ 70 71 def __init__(self, options, options_class_name): 72 """Initialize the descriptor given its options message and the name of the 73 class of the options message. The name of the class is required in case 74 the options message is None and has to be created. 75 """ 76 self._options = options 77 self._options_class_name = options_class_name 78 79 # Does this descriptor have non-default options? 80 self.has_options = options is not None 81 82 def _SetOptions(self, options, options_class_name): 83 """Sets the descriptor's options 84 85 This function is used in generated proto2 files to update descriptor 86 options. It must not be used outside proto2. 87 """ 88 self._options = options 89 self._options_class_name = options_class_name 90 91 # Does this descriptor have non-default options? 92 self.has_options = options is not None 93 94 def GetOptions(self): 95 """Retrieves descriptor options. 96 97 This method returns the options set or creates the default options for the 98 descriptor. 99 """ 100 if self._options: 101 return self._options 102 from google.protobuf import descriptor_pb2 103 try: 104 options_class = getattr(descriptor_pb2, self._options_class_name) 105 except AttributeError: 106 raise RuntimeError('Unknown options class name %s!' % 107 (self._options_class_name)) 108 self._options = options_class() 109 return self._options 110 111 112class _NestedDescriptorBase(DescriptorBase): 113 """Common class for descriptors that can be nested.""" 114 115 def __init__(self, options, options_class_name, name, full_name, 116 file, containing_type, serialized_start=None, 117 serialized_end=None): 118 """Constructor. 119 120 Args: 121 options: Protocol message options or None 122 to use default message options. 123 options_class_name: (str) The class name of the above options. 124 125 name: (str) Name of this protocol message type. 126 full_name: (str) Fully-qualified name of this protocol message type, 127 which will include protocol "package" name and the name of any 128 enclosing types. 129 file: (FileDescriptor) Reference to file info. 130 containing_type: if provided, this is a nested descriptor, with this 131 descriptor as parent, otherwise None. 132 serialized_start: The start index (inclusive) in block in the 133 file.serialized_pb that describes this descriptor. 134 serialized_end: The end index (exclusive) in block in the 135 file.serialized_pb that describes this descriptor. 136 """ 137 super(_NestedDescriptorBase, self).__init__( 138 options, options_class_name) 139 140 self.name = name 141 # TODO(falk): Add function to calculate full_name instead of having it in 142 # memory? 143 self.full_name = full_name 144 self.file = file 145 self.containing_type = containing_type 146 147 self._serialized_start = serialized_start 148 self._serialized_end = serialized_end 149 150 def GetTopLevelContainingType(self): 151 """Returns the root if this is a nested type, or itself if its the root.""" 152 desc = self 153 while desc.containing_type is not None: 154 desc = desc.containing_type 155 return desc 156 157 def CopyToProto(self, proto): 158 """Copies this to the matching proto in descriptor_pb2. 159 160 Args: 161 proto: An empty proto instance from descriptor_pb2. 162 163 Raises: 164 Error: If self couldnt be serialized, due to to few constructor arguments. 165 """ 166 if (self.file is not None and 167 self._serialized_start is not None and 168 self._serialized_end is not None): 169 proto.ParseFromString(self.file.serialized_pb[ 170 self._serialized_start:self._serialized_end]) 171 else: 172 raise Error('Descriptor does not contain serialization.') 173 174 175class Descriptor(_NestedDescriptorBase): 176 177 """Descriptor for a protocol message type. 178 179 A Descriptor instance has the following attributes: 180 181 name: (str) Name of this protocol message type. 182 full_name: (str) Fully-qualified name of this protocol message type, 183 which will include protocol "package" name and the name of any 184 enclosing types. 185 186 containing_type: (Descriptor) Reference to the descriptor of the 187 type containing us, or None if this is top-level. 188 189 fields: (list of FieldDescriptors) Field descriptors for all 190 fields in this type. 191 fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor 192 objects as in |fields|, but indexed by "number" attribute in each 193 FieldDescriptor. 194 fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor 195 objects as in |fields|, but indexed by "name" attribute in each 196 FieldDescriptor. 197 198 nested_types: (list of Descriptors) Descriptor references 199 for all protocol message types nested within this one. 200 nested_types_by_name: (dict str -> Descriptor) Same Descriptor 201 objects as in |nested_types|, but indexed by "name" attribute 202 in each Descriptor. 203 204 enum_types: (list of EnumDescriptors) EnumDescriptor references 205 for all enums contained within this type. 206 enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor 207 objects as in |enum_types|, but indexed by "name" attribute 208 in each EnumDescriptor. 209 enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping 210 from enum value name to EnumValueDescriptor for that value. 211 212 extensions: (list of FieldDescriptor) All extensions defined directly 213 within this message type (NOT within a nested type). 214 extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor 215 objects as |extensions|, but indexed by "name" attribute of each 216 FieldDescriptor. 217 218 is_extendable: Does this type define any extension ranges? 219 220 options: (descriptor_pb2.MessageOptions) Protocol message options or None 221 to use default message options. 222 223 file: (FileDescriptor) Reference to file descriptor. 224 """ 225 226 def __init__(self, name, full_name, filename, containing_type, fields, 227 nested_types, enum_types, extensions, options=None, 228 is_extendable=True, extension_ranges=None, file=None, 229 serialized_start=None, serialized_end=None): 230 """Arguments to __init__() are as described in the description 231 of Descriptor fields above. 232 233 Note that filename is an obsolete argument, that is not used anymore. 234 Please use file.name to access this as an attribute. 235 """ 236 super(Descriptor, self).__init__( 237 options, 'MessageOptions', name, full_name, file, 238 containing_type, serialized_start=serialized_start, 239 serialized_end=serialized_start) 240 241 # We have fields in addition to fields_by_name and fields_by_number, 242 # so that: 243 # 1. Clients can index fields by "order in which they're listed." 244 # 2. Clients can easily iterate over all fields with the terse 245 # syntax: for f in descriptor.fields: ... 246 self.fields = fields 247 for field in self.fields: 248 field.containing_type = self 249 self.fields_by_number = dict((f.number, f) for f in fields) 250 self.fields_by_name = dict((f.name, f) for f in fields) 251 252 self.nested_types = nested_types 253 self.nested_types_by_name = dict((t.name, t) for t in nested_types) 254 255 self.enum_types = enum_types 256 for enum_type in self.enum_types: 257 enum_type.containing_type = self 258 self.enum_types_by_name = dict((t.name, t) for t in enum_types) 259 self.enum_values_by_name = dict( 260 (v.name, v) for t in enum_types for v in t.values) 261 262 self.extensions = extensions 263 for extension in self.extensions: 264 extension.extension_scope = self 265 self.extensions_by_name = dict((f.name, f) for f in extensions) 266 self.is_extendable = is_extendable 267 self.extension_ranges = extension_ranges 268 269 self._serialized_start = serialized_start 270 self._serialized_end = serialized_end 271 272 def EnumValueName(self, enum, value): 273 """Returns the string name of an enum value. 274 275 This is just a small helper method to simplify a common operation. 276 277 Args: 278 enum: string name of the Enum. 279 value: int, value of the enum. 280 281 Returns: 282 string name of the enum value. 283 284 Raises: 285 KeyError if either the Enum doesn't exist or the value is not a valid 286 value for the enum. 287 """ 288 return self.enum_types_by_name[enum].values_by_number[value].name 289 290 def CopyToProto(self, proto): 291 """Copies this to a descriptor_pb2.DescriptorProto. 292 293 Args: 294 proto: An empty descriptor_pb2.DescriptorProto. 295 """ 296 # This function is overriden to give a better doc comment. 297 super(Descriptor, self).CopyToProto(proto) 298 299 300# TODO(robinson): We should have aggressive checking here, 301# for example: 302# * If you specify a repeated field, you should not be allowed 303# to specify a default value. 304# * [Other examples here as needed]. 305# 306# TODO(robinson): for this and other *Descriptor classes, we 307# might also want to lock things down aggressively (e.g., 308# prevent clients from setting the attributes). Having 309# stronger invariants here in general will reduce the number 310# of runtime checks we must do in reflection.py... 311class FieldDescriptor(DescriptorBase): 312 313 """Descriptor for a single field in a .proto file. 314 315 A FieldDescriptor instance has the following attributes: 316 317 name: (str) Name of this field, exactly as it appears in .proto. 318 full_name: (str) Name of this field, including containing scope. This is 319 particularly relevant for extensions. 320 index: (int) Dense, 0-indexed index giving the order that this 321 field textually appears within its message in the .proto file. 322 number: (int) Tag number declared for this field in the .proto file. 323 324 type: (One of the TYPE_* constants below) Declared type. 325 cpp_type: (One of the CPPTYPE_* constants below) C++ type used to 326 represent this field. 327 328 label: (One of the LABEL_* constants below) Tells whether this 329 field is optional, required, or repeated. 330 has_default_value: (bool) True if this field has a default value defined, 331 otherwise false. 332 default_value: (Varies) Default value of this field. Only 333 meaningful for non-repeated scalar fields. Repeated fields 334 should always set this to [], and non-repeated composite 335 fields should always set this to None. 336 337 containing_type: (Descriptor) Descriptor of the protocol message 338 type that contains this field. Set by the Descriptor constructor 339 if we're passed into one. 340 Somewhat confusingly, for extension fields, this is the 341 descriptor of the EXTENDED message, not the descriptor 342 of the message containing this field. (See is_extension and 343 extension_scope below). 344 message_type: (Descriptor) If a composite field, a descriptor 345 of the message type contained in this field. Otherwise, this is None. 346 enum_type: (EnumDescriptor) If this field contains an enum, a 347 descriptor of that enum. Otherwise, this is None. 348 349 is_extension: True iff this describes an extension field. 350 extension_scope: (Descriptor) Only meaningful if is_extension is True. 351 Gives the message that immediately contains this extension field. 352 Will be None iff we're a top-level (file-level) extension field. 353 354 options: (descriptor_pb2.FieldOptions) Protocol message field options or 355 None to use default field options. 356 """ 357 358 # Must be consistent with C++ FieldDescriptor::Type enum in 359 # descriptor.h. 360 # 361 # TODO(robinson): Find a way to eliminate this repetition. 362 TYPE_DOUBLE = 1 363 TYPE_FLOAT = 2 364 TYPE_INT64 = 3 365 TYPE_UINT64 = 4 366 TYPE_INT32 = 5 367 TYPE_FIXED64 = 6 368 TYPE_FIXED32 = 7 369 TYPE_BOOL = 8 370 TYPE_STRING = 9 371 TYPE_GROUP = 10 372 TYPE_MESSAGE = 11 373 TYPE_BYTES = 12 374 TYPE_UINT32 = 13 375 TYPE_ENUM = 14 376 TYPE_SFIXED32 = 15 377 TYPE_SFIXED64 = 16 378 TYPE_SINT32 = 17 379 TYPE_SINT64 = 18 380 MAX_TYPE = 18 381 382 # Must be consistent with C++ FieldDescriptor::CppType enum in 383 # descriptor.h. 384 # 385 # TODO(robinson): Find a way to eliminate this repetition. 386 CPPTYPE_INT32 = 1 387 CPPTYPE_INT64 = 2 388 CPPTYPE_UINT32 = 3 389 CPPTYPE_UINT64 = 4 390 CPPTYPE_DOUBLE = 5 391 CPPTYPE_FLOAT = 6 392 CPPTYPE_BOOL = 7 393 CPPTYPE_ENUM = 8 394 CPPTYPE_STRING = 9 395 CPPTYPE_MESSAGE = 10 396 MAX_CPPTYPE = 10 397 398 _PYTHON_TO_CPP_PROTO_TYPE_MAP = { 399 TYPE_DOUBLE: CPPTYPE_DOUBLE, 400 TYPE_FLOAT: CPPTYPE_FLOAT, 401 TYPE_ENUM: CPPTYPE_ENUM, 402 TYPE_INT64: CPPTYPE_INT64, 403 TYPE_SINT64: CPPTYPE_INT64, 404 TYPE_SFIXED64: CPPTYPE_INT64, 405 TYPE_UINT64: CPPTYPE_UINT64, 406 TYPE_FIXED64: CPPTYPE_UINT64, 407 TYPE_INT32: CPPTYPE_INT32, 408 TYPE_SFIXED32: CPPTYPE_INT32, 409 TYPE_SINT32: CPPTYPE_INT32, 410 TYPE_UINT32: CPPTYPE_UINT32, 411 TYPE_FIXED32: CPPTYPE_UINT32, 412 TYPE_BYTES: CPPTYPE_STRING, 413 TYPE_STRING: CPPTYPE_STRING, 414 TYPE_BOOL: CPPTYPE_BOOL, 415 TYPE_MESSAGE: CPPTYPE_MESSAGE, 416 TYPE_GROUP: CPPTYPE_MESSAGE 417 } 418 419 # Must be consistent with C++ FieldDescriptor::Label enum in 420 # descriptor.h. 421 # 422 # TODO(robinson): Find a way to eliminate this repetition. 423 LABEL_OPTIONAL = 1 424 LABEL_REQUIRED = 2 425 LABEL_REPEATED = 3 426 MAX_LABEL = 3 427 428 def __init__(self, name, full_name, index, number, type, cpp_type, label, 429 default_value, message_type, enum_type, containing_type, 430 is_extension, extension_scope, options=None, 431 has_default_value=True): 432 """The arguments are as described in the description of FieldDescriptor 433 attributes above. 434 435 Note that containing_type may be None, and may be set later if necessary 436 (to deal with circular references between message types, for example). 437 Likewise for extension_scope. 438 """ 439 super(FieldDescriptor, self).__init__(options, 'FieldOptions') 440 self.name = name 441 self.full_name = full_name 442 self.index = index 443 self.number = number 444 self.type = type 445 self.cpp_type = cpp_type 446 self.label = label 447 self.has_default_value = has_default_value 448 self.default_value = default_value 449 self.containing_type = containing_type 450 self.message_type = message_type 451 self.enum_type = enum_type 452 self.is_extension = is_extension 453 self.extension_scope = extension_scope 454 if api_implementation.Type() == 'cpp': 455 if is_extension: 456 if api_implementation.Version() == 2: 457 self._cdescriptor = _message.GetExtensionDescriptor(full_name) 458 else: 459 self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name) 460 else: 461 if api_implementation.Version() == 2: 462 self._cdescriptor = _message.GetFieldDescriptor(full_name) 463 else: 464 self._cdescriptor = cpp_message.GetFieldDescriptor(full_name) 465 else: 466 self._cdescriptor = None 467 468 @staticmethod 469 def ProtoTypeToCppProtoType(proto_type): 470 """Converts from a Python proto type to a C++ Proto Type. 471 472 The Python ProtocolBuffer classes specify both the 'Python' datatype and the 473 'C++' datatype - and they're not the same. This helper method should 474 translate from one to another. 475 476 Args: 477 proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) 478 Returns: 479 descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. 480 Raises: 481 TypeTransformationError: when the Python proto type isn't known. 482 """ 483 try: 484 return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type] 485 except KeyError: 486 raise TypeTransformationError('Unknown proto_type: %s' % proto_type) 487 488 489class EnumDescriptor(_NestedDescriptorBase): 490 491 """Descriptor for an enum defined in a .proto file. 492 493 An EnumDescriptor instance has the following attributes: 494 495 name: (str) Name of the enum type. 496 full_name: (str) Full name of the type, including package name 497 and any enclosing type(s). 498 499 values: (list of EnumValueDescriptors) List of the values 500 in this enum. 501 values_by_name: (dict str -> EnumValueDescriptor) Same as |values|, 502 but indexed by the "name" field of each EnumValueDescriptor. 503 values_by_number: (dict int -> EnumValueDescriptor) Same as |values|, 504 but indexed by the "number" field of each EnumValueDescriptor. 505 containing_type: (Descriptor) Descriptor of the immediate containing 506 type of this enum, or None if this is an enum defined at the 507 top level in a .proto file. Set by Descriptor's constructor 508 if we're passed into one. 509 file: (FileDescriptor) Reference to file descriptor. 510 options: (descriptor_pb2.EnumOptions) Enum options message or 511 None to use default enum options. 512 """ 513 514 def __init__(self, name, full_name, filename, values, 515 containing_type=None, options=None, file=None, 516 serialized_start=None, serialized_end=None): 517 """Arguments are as described in the attribute description above. 518 519 Note that filename is an obsolete argument, that is not used anymore. 520 Please use file.name to access this as an attribute. 521 """ 522 super(EnumDescriptor, self).__init__( 523 options, 'EnumOptions', name, full_name, file, 524 containing_type, serialized_start=serialized_start, 525 serialized_end=serialized_start) 526 527 self.values = values 528 for value in self.values: 529 value.type = self 530 self.values_by_name = dict((v.name, v) for v in values) 531 self.values_by_number = dict((v.number, v) for v in values) 532 533 self._serialized_start = serialized_start 534 self._serialized_end = serialized_end 535 536 def CopyToProto(self, proto): 537 """Copies this to a descriptor_pb2.EnumDescriptorProto. 538 539 Args: 540 proto: An empty descriptor_pb2.EnumDescriptorProto. 541 """ 542 # This function is overriden to give a better doc comment. 543 super(EnumDescriptor, self).CopyToProto(proto) 544 545 546class EnumValueDescriptor(DescriptorBase): 547 548 """Descriptor for a single value within an enum. 549 550 name: (str) Name of this value. 551 index: (int) Dense, 0-indexed index giving the order that this 552 value appears textually within its enum in the .proto file. 553 number: (int) Actual number assigned to this enum value. 554 type: (EnumDescriptor) EnumDescriptor to which this value 555 belongs. Set by EnumDescriptor's constructor if we're 556 passed into one. 557 options: (descriptor_pb2.EnumValueOptions) Enum value options message or 558 None to use default enum value options options. 559 """ 560 561 def __init__(self, name, index, number, type=None, options=None): 562 """Arguments are as described in the attribute description above.""" 563 super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions') 564 self.name = name 565 self.index = index 566 self.number = number 567 self.type = type 568 569 570class ServiceDescriptor(_NestedDescriptorBase): 571 572 """Descriptor for a service. 573 574 name: (str) Name of the service. 575 full_name: (str) Full name of the service, including package name. 576 index: (int) 0-indexed index giving the order that this services 577 definition appears withing the .proto file. 578 methods: (list of MethodDescriptor) List of methods provided by this 579 service. 580 options: (descriptor_pb2.ServiceOptions) Service options message or 581 None to use default service options. 582 file: (FileDescriptor) Reference to file info. 583 """ 584 585 def __init__(self, name, full_name, index, methods, options=None, file=None, 586 serialized_start=None, serialized_end=None): 587 super(ServiceDescriptor, self).__init__( 588 options, 'ServiceOptions', name, full_name, file, 589 None, serialized_start=serialized_start, 590 serialized_end=serialized_end) 591 self.index = index 592 self.methods = methods 593 # Set the containing service for each method in this service. 594 for method in self.methods: 595 method.containing_service = self 596 597 def FindMethodByName(self, name): 598 """Searches for the specified method, and returns its descriptor.""" 599 for method in self.methods: 600 if name == method.name: 601 return method 602 return None 603 604 def CopyToProto(self, proto): 605 """Copies this to a descriptor_pb2.ServiceDescriptorProto. 606 607 Args: 608 proto: An empty descriptor_pb2.ServiceDescriptorProto. 609 """ 610 # This function is overriden to give a better doc comment. 611 super(ServiceDescriptor, self).CopyToProto(proto) 612 613 614class MethodDescriptor(DescriptorBase): 615 616 """Descriptor for a method in a service. 617 618 name: (str) Name of the method within the service. 619 full_name: (str) Full name of method. 620 index: (int) 0-indexed index of the method inside the service. 621 containing_service: (ServiceDescriptor) The service that contains this 622 method. 623 input_type: The descriptor of the message that this method accepts. 624 output_type: The descriptor of the message that this method returns. 625 options: (descriptor_pb2.MethodOptions) Method options message or 626 None to use default method options. 627 """ 628 629 def __init__(self, name, full_name, index, containing_service, 630 input_type, output_type, options=None): 631 """The arguments are as described in the description of MethodDescriptor 632 attributes above. 633 634 Note that containing_service may be None, and may be set later if necessary. 635 """ 636 super(MethodDescriptor, self).__init__(options, 'MethodOptions') 637 self.name = name 638 self.full_name = full_name 639 self.index = index 640 self.containing_service = containing_service 641 self.input_type = input_type 642 self.output_type = output_type 643 644 645class FileDescriptor(DescriptorBase): 646 """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. 647 648 name: name of file, relative to root of source tree. 649 package: name of the package 650 serialized_pb: (str) Byte string of serialized 651 descriptor_pb2.FileDescriptorProto. 652 """ 653 654 def __init__(self, name, package, options=None, serialized_pb=None): 655 """Constructor.""" 656 super(FileDescriptor, self).__init__(options, 'FileOptions') 657 658 self.message_types_by_name = {} 659 self.name = name 660 self.package = package 661 self.serialized_pb = serialized_pb 662 if (api_implementation.Type() == 'cpp' and 663 self.serialized_pb is not None): 664 if api_implementation.Version() == 2: 665 _message.BuildFile(self.serialized_pb) 666 else: 667 cpp_message.BuildFile(self.serialized_pb) 668 669 def CopyToProto(self, proto): 670 """Copies this to a descriptor_pb2.FileDescriptorProto. 671 672 Args: 673 proto: An empty descriptor_pb2.FileDescriptorProto. 674 """ 675 proto.ParseFromString(self.serialized_pb) 676 677 678def _ParseOptions(message, string): 679 """Parses serialized options. 680 681 This helper function is used to parse serialized options in generated 682 proto2 files. It must not be used outside proto2. 683 """ 684 message.ParseFromString(string) 685 return message 686 687 688def MakeDescriptor(desc_proto, package=''): 689 """Make a protobuf Descriptor given a DescriptorProto protobuf. 690 691 Args: 692 desc_proto: The descriptor_pb2.DescriptorProto protobuf message. 693 package: Optional package name for the new message Descriptor (string). 694 695 Returns: 696 A Descriptor for protobuf messages. 697 """ 698 full_message_name = [desc_proto.name] 699 if package: full_message_name.insert(0, package) 700 fields = [] 701 for field_proto in desc_proto.field: 702 full_name = '.'.join(full_message_name + [field_proto.name]) 703 field = FieldDescriptor( 704 field_proto.name, full_name, field_proto.number - 1, 705 field_proto.number, field_proto.type, 706 FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), 707 field_proto.label, None, None, None, None, False, None, 708 has_default_value=False) 709 fields.append(field) 710 711 desc_name = '.'.join(full_message_name) 712 return Descriptor(desc_proto.name, desc_name, None, None, fields, 713 [], [], []) 714