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"""Provides DescriptorPool to use as a container for proto2 descriptors. 32 33The DescriptorPool is used in conjection with a DescriptorDatabase to maintain 34a collection of protocol buffer descriptors for use when dynamically creating 35message types at runtime. 36 37For most applications protocol buffers should be used via modules generated by 38the protocol buffer compiler tool. This should only be used when the type of 39protocol buffers used in an application or library cannot be predetermined. 40 41Below is a straightforward example on how to use this class: 42 43 pool = DescriptorPool() 44 file_descriptor_protos = [ ... ] 45 for file_descriptor_proto in file_descriptor_protos: 46 pool.Add(file_descriptor_proto) 47 my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType') 48 49The message descriptor can be used in conjunction with the message_factory 50module in order to create a protocol buffer class that can be encoded and 51decoded. 52 53If you want to get a Python class for the specified proto, use the 54helper functions inside google.protobuf.message_factory 55directly instead of this class. 56""" 57 58__author__ = 'matthewtoia@google.com (Matt Toia)' 59 60from google.protobuf import descriptor 61from google.protobuf import descriptor_database 62from google.protobuf import text_encoding 63 64 65_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS 66 67 68def _NormalizeFullyQualifiedName(name): 69 """Remove leading period from fully-qualified type name. 70 71 Due to b/13860351 in descriptor_database.py, types in the root namespace are 72 generated with a leading period. This function removes that prefix. 73 74 Args: 75 name: A str, the fully-qualified symbol name. 76 77 Returns: 78 A str, the normalized fully-qualified symbol name. 79 """ 80 return name.lstrip('.') 81 82 83class DescriptorPool(object): 84 """A collection of protobufs dynamically constructed by descriptor protos.""" 85 86 if _USE_C_DESCRIPTORS: 87 88 def __new__(cls, descriptor_db=None): 89 # pylint: disable=protected-access 90 return descriptor._message.DescriptorPool(descriptor_db) 91 92 def __init__(self, descriptor_db=None): 93 """Initializes a Pool of proto buffs. 94 95 The descriptor_db argument to the constructor is provided to allow 96 specialized file descriptor proto lookup code to be triggered on demand. An 97 example would be an implementation which will read and compile a file 98 specified in a call to FindFileByName() and not require the call to Add() 99 at all. Results from this database will be cached internally here as well. 100 101 Args: 102 descriptor_db: A secondary source of file descriptors. 103 """ 104 105 self._internal_db = descriptor_database.DescriptorDatabase() 106 self._descriptor_db = descriptor_db 107 self._descriptors = {} 108 self._enum_descriptors = {} 109 self._file_descriptors = {} 110 111 def Add(self, file_desc_proto): 112 """Adds the FileDescriptorProto and its types to this pool. 113 114 Args: 115 file_desc_proto: The FileDescriptorProto to add. 116 """ 117 118 self._internal_db.Add(file_desc_proto) 119 120 def AddSerializedFile(self, serialized_file_desc_proto): 121 """Adds the FileDescriptorProto and its types to this pool. 122 123 Args: 124 serialized_file_desc_proto: A bytes string, serialization of the 125 FileDescriptorProto to add. 126 """ 127 128 # pylint: disable=g-import-not-at-top 129 from google.protobuf import descriptor_pb2 130 file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( 131 serialized_file_desc_proto) 132 self.Add(file_desc_proto) 133 134 def AddDescriptor(self, desc): 135 """Adds a Descriptor to the pool, non-recursively. 136 137 If the Descriptor contains nested messages or enums, the caller must 138 explicitly register them. This method also registers the FileDescriptor 139 associated with the message. 140 141 Args: 142 desc: A Descriptor. 143 """ 144 if not isinstance(desc, descriptor.Descriptor): 145 raise TypeError('Expected instance of descriptor.Descriptor.') 146 147 self._descriptors[desc.full_name] = desc 148 self.AddFileDescriptor(desc.file) 149 150 def AddEnumDescriptor(self, enum_desc): 151 """Adds an EnumDescriptor to the pool. 152 153 This method also registers the FileDescriptor associated with the message. 154 155 Args: 156 enum_desc: An EnumDescriptor. 157 """ 158 159 if not isinstance(enum_desc, descriptor.EnumDescriptor): 160 raise TypeError('Expected instance of descriptor.EnumDescriptor.') 161 162 self._enum_descriptors[enum_desc.full_name] = enum_desc 163 self.AddFileDescriptor(enum_desc.file) 164 165 def AddFileDescriptor(self, file_desc): 166 """Adds a FileDescriptor to the pool, non-recursively. 167 168 If the FileDescriptor contains messages or enums, the caller must explicitly 169 register them. 170 171 Args: 172 file_desc: A FileDescriptor. 173 """ 174 175 if not isinstance(file_desc, descriptor.FileDescriptor): 176 raise TypeError('Expected instance of descriptor.FileDescriptor.') 177 self._file_descriptors[file_desc.name] = file_desc 178 179 def FindFileByName(self, file_name): 180 """Gets a FileDescriptor by file name. 181 182 Args: 183 file_name: The path to the file to get a descriptor for. 184 185 Returns: 186 A FileDescriptor for the named file. 187 188 Raises: 189 KeyError: if the file can not be found in the pool. 190 """ 191 192 try: 193 return self._file_descriptors[file_name] 194 except KeyError: 195 pass 196 197 try: 198 file_proto = self._internal_db.FindFileByName(file_name) 199 except KeyError as error: 200 if self._descriptor_db: 201 file_proto = self._descriptor_db.FindFileByName(file_name) 202 else: 203 raise error 204 if not file_proto: 205 raise KeyError('Cannot find a file named %s' % file_name) 206 return self._ConvertFileProtoToFileDescriptor(file_proto) 207 208 def FindFileContainingSymbol(self, symbol): 209 """Gets the FileDescriptor for the file containing the specified symbol. 210 211 Args: 212 symbol: The name of the symbol to search for. 213 214 Returns: 215 A FileDescriptor that contains the specified symbol. 216 217 Raises: 218 KeyError: if the file can not be found in the pool. 219 """ 220 221 symbol = _NormalizeFullyQualifiedName(symbol) 222 try: 223 return self._descriptors[symbol].file 224 except KeyError: 225 pass 226 227 try: 228 return self._enum_descriptors[symbol].file 229 except KeyError: 230 pass 231 232 try: 233 file_proto = self._internal_db.FindFileContainingSymbol(symbol) 234 except KeyError as error: 235 if self._descriptor_db: 236 file_proto = self._descriptor_db.FindFileContainingSymbol(symbol) 237 else: 238 raise error 239 if not file_proto: 240 raise KeyError('Cannot find a file containing %s' % symbol) 241 return self._ConvertFileProtoToFileDescriptor(file_proto) 242 243 def FindMessageTypeByName(self, full_name): 244 """Loads the named descriptor from the pool. 245 246 Args: 247 full_name: The full name of the descriptor to load. 248 249 Returns: 250 The descriptor for the named type. 251 """ 252 253 full_name = _NormalizeFullyQualifiedName(full_name) 254 if full_name not in self._descriptors: 255 self.FindFileContainingSymbol(full_name) 256 return self._descriptors[full_name] 257 258 def FindEnumTypeByName(self, full_name): 259 """Loads the named enum descriptor from the pool. 260 261 Args: 262 full_name: The full name of the enum descriptor to load. 263 264 Returns: 265 The enum descriptor for the named type. 266 """ 267 268 full_name = _NormalizeFullyQualifiedName(full_name) 269 if full_name not in self._enum_descriptors: 270 self.FindFileContainingSymbol(full_name) 271 return self._enum_descriptors[full_name] 272 273 def FindFieldByName(self, full_name): 274 """Loads the named field descriptor from the pool. 275 276 Args: 277 full_name: The full name of the field descriptor to load. 278 279 Returns: 280 The field descriptor for the named field. 281 """ 282 full_name = _NormalizeFullyQualifiedName(full_name) 283 message_name, _, field_name = full_name.rpartition('.') 284 message_descriptor = self.FindMessageTypeByName(message_name) 285 return message_descriptor.fields_by_name[field_name] 286 287 def FindExtensionByName(self, full_name): 288 """Loads the named extension descriptor from the pool. 289 290 Args: 291 full_name: The full name of the extension descriptor to load. 292 293 Returns: 294 A FieldDescriptor, describing the named extension. 295 """ 296 full_name = _NormalizeFullyQualifiedName(full_name) 297 message_name, _, extension_name = full_name.rpartition('.') 298 try: 299 # Most extensions are nested inside a message. 300 scope = self.FindMessageTypeByName(message_name) 301 except KeyError: 302 # Some extensions are defined at file scope. 303 scope = self.FindFileContainingSymbol(full_name) 304 return scope.extensions_by_name[extension_name] 305 306 def _ConvertFileProtoToFileDescriptor(self, file_proto): 307 """Creates a FileDescriptor from a proto or returns a cached copy. 308 309 This method also has the side effect of loading all the symbols found in 310 the file into the appropriate dictionaries in the pool. 311 312 Args: 313 file_proto: The proto to convert. 314 315 Returns: 316 A FileDescriptor matching the passed in proto. 317 """ 318 319 if file_proto.name not in self._file_descriptors: 320 built_deps = list(self._GetDeps(file_proto.dependency)) 321 direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] 322 public_deps = [direct_deps[i] for i in file_proto.public_dependency] 323 324 file_descriptor = descriptor.FileDescriptor( 325 pool=self, 326 name=file_proto.name, 327 package=file_proto.package, 328 syntax=file_proto.syntax, 329 options=file_proto.options, 330 serialized_pb=file_proto.SerializeToString(), 331 dependencies=direct_deps, 332 public_dependencies=public_deps) 333 if _USE_C_DESCRIPTORS: 334 # When using C++ descriptors, all objects defined in the file were added 335 # to the C++ database when the FileDescriptor was built above. 336 # Just add them to this descriptor pool. 337 def _AddMessageDescriptor(message_desc): 338 self._descriptors[message_desc.full_name] = message_desc 339 for nested in message_desc.nested_types: 340 _AddMessageDescriptor(nested) 341 for enum_type in message_desc.enum_types: 342 _AddEnumDescriptor(enum_type) 343 def _AddEnumDescriptor(enum_desc): 344 self._enum_descriptors[enum_desc.full_name] = enum_desc 345 for message_type in file_descriptor.message_types_by_name.values(): 346 _AddMessageDescriptor(message_type) 347 for enum_type in file_descriptor.enum_types_by_name.values(): 348 _AddEnumDescriptor(enum_type) 349 else: 350 scope = {} 351 352 # This loop extracts all the message and enum types from all the 353 # dependencies of the file_proto. This is necessary to create the 354 # scope of available message types when defining the passed in 355 # file proto. 356 for dependency in built_deps: 357 scope.update(self._ExtractSymbols( 358 dependency.message_types_by_name.values())) 359 scope.update((_PrefixWithDot(enum.full_name), enum) 360 for enum in dependency.enum_types_by_name.values()) 361 362 for message_type in file_proto.message_type: 363 message_desc = self._ConvertMessageDescriptor( 364 message_type, file_proto.package, file_descriptor, scope, 365 file_proto.syntax) 366 file_descriptor.message_types_by_name[message_desc.name] = ( 367 message_desc) 368 369 for enum_type in file_proto.enum_type: 370 file_descriptor.enum_types_by_name[enum_type.name] = ( 371 self._ConvertEnumDescriptor(enum_type, file_proto.package, 372 file_descriptor, None, scope)) 373 374 for index, extension_proto in enumerate(file_proto.extension): 375 extension_desc = self._MakeFieldDescriptor( 376 extension_proto, file_proto.package, index, is_extension=True) 377 extension_desc.containing_type = self._GetTypeFromScope( 378 file_descriptor.package, extension_proto.extendee, scope) 379 self._SetFieldType(extension_proto, extension_desc, 380 file_descriptor.package, scope) 381 file_descriptor.extensions_by_name[extension_desc.name] = ( 382 extension_desc) 383 384 for desc_proto in file_proto.message_type: 385 self._SetAllFieldTypes(file_proto.package, desc_proto, scope) 386 387 if file_proto.package: 388 desc_proto_prefix = _PrefixWithDot(file_proto.package) 389 else: 390 desc_proto_prefix = '' 391 392 for desc_proto in file_proto.message_type: 393 desc = self._GetTypeFromScope( 394 desc_proto_prefix, desc_proto.name, scope) 395 file_descriptor.message_types_by_name[desc_proto.name] = desc 396 397 self.Add(file_proto) 398 self._file_descriptors[file_proto.name] = file_descriptor 399 400 return self._file_descriptors[file_proto.name] 401 402 def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, 403 scope=None, syntax=None): 404 """Adds the proto to the pool in the specified package. 405 406 Args: 407 desc_proto: The descriptor_pb2.DescriptorProto protobuf message. 408 package: The package the proto should be located in. 409 file_desc: The file containing this message. 410 scope: Dict mapping short and full symbols to message and enum types. 411 412 Returns: 413 The added descriptor. 414 """ 415 416 if package: 417 desc_name = '.'.join((package, desc_proto.name)) 418 else: 419 desc_name = desc_proto.name 420 421 if file_desc is None: 422 file_name = None 423 else: 424 file_name = file_desc.name 425 426 if scope is None: 427 scope = {} 428 429 nested = [ 430 self._ConvertMessageDescriptor( 431 nested, desc_name, file_desc, scope, syntax) 432 for nested in desc_proto.nested_type] 433 enums = [ 434 self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) 435 for enum in desc_proto.enum_type] 436 fields = [self._MakeFieldDescriptor(field, desc_name, index) 437 for index, field in enumerate(desc_proto.field)] 438 extensions = [ 439 self._MakeFieldDescriptor(extension, desc_name, index, 440 is_extension=True) 441 for index, extension in enumerate(desc_proto.extension)] 442 oneofs = [ 443 descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), 444 index, None, []) 445 for index, desc in enumerate(desc_proto.oneof_decl)] 446 extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] 447 if extension_ranges: 448 is_extendable = True 449 else: 450 is_extendable = False 451 desc = descriptor.Descriptor( 452 name=desc_proto.name, 453 full_name=desc_name, 454 filename=file_name, 455 containing_type=None, 456 fields=fields, 457 oneofs=oneofs, 458 nested_types=nested, 459 enum_types=enums, 460 extensions=extensions, 461 options=desc_proto.options, 462 is_extendable=is_extendable, 463 extension_ranges=extension_ranges, 464 file=file_desc, 465 serialized_start=None, 466 serialized_end=None, 467 syntax=syntax) 468 for nested in desc.nested_types: 469 nested.containing_type = desc 470 for enum in desc.enum_types: 471 enum.containing_type = desc 472 for field_index, field_desc in enumerate(desc_proto.field): 473 if field_desc.HasField('oneof_index'): 474 oneof_index = field_desc.oneof_index 475 oneofs[oneof_index].fields.append(fields[field_index]) 476 fields[field_index].containing_oneof = oneofs[oneof_index] 477 478 scope[_PrefixWithDot(desc_name)] = desc 479 self._descriptors[desc_name] = desc 480 return desc 481 482 def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, 483 containing_type=None, scope=None): 484 """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. 485 486 Args: 487 enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message. 488 package: Optional package name for the new message EnumDescriptor. 489 file_desc: The file containing the enum descriptor. 490 containing_type: The type containing this enum. 491 scope: Scope containing available types. 492 493 Returns: 494 The added descriptor 495 """ 496 497 if package: 498 enum_name = '.'.join((package, enum_proto.name)) 499 else: 500 enum_name = enum_proto.name 501 502 if file_desc is None: 503 file_name = None 504 else: 505 file_name = file_desc.name 506 507 values = [self._MakeEnumValueDescriptor(value, index) 508 for index, value in enumerate(enum_proto.value)] 509 desc = descriptor.EnumDescriptor(name=enum_proto.name, 510 full_name=enum_name, 511 filename=file_name, 512 file=file_desc, 513 values=values, 514 containing_type=containing_type, 515 options=enum_proto.options) 516 scope['.%s' % enum_name] = desc 517 self._enum_descriptors[enum_name] = desc 518 return desc 519 520 def _MakeFieldDescriptor(self, field_proto, message_name, index, 521 is_extension=False): 522 """Creates a field descriptor from a FieldDescriptorProto. 523 524 For message and enum type fields, this method will do a look up 525 in the pool for the appropriate descriptor for that type. If it 526 is unavailable, it will fall back to the _source function to 527 create it. If this type is still unavailable, construction will 528 fail. 529 530 Args: 531 field_proto: The proto describing the field. 532 message_name: The name of the containing message. 533 index: Index of the field 534 is_extension: Indication that this field is for an extension. 535 536 Returns: 537 An initialized FieldDescriptor object 538 """ 539 540 if message_name: 541 full_name = '.'.join((message_name, field_proto.name)) 542 else: 543 full_name = field_proto.name 544 545 return descriptor.FieldDescriptor( 546 name=field_proto.name, 547 full_name=full_name, 548 index=index, 549 number=field_proto.number, 550 type=field_proto.type, 551 cpp_type=None, 552 message_type=None, 553 enum_type=None, 554 containing_type=None, 555 label=field_proto.label, 556 has_default_value=False, 557 default_value=None, 558 is_extension=is_extension, 559 extension_scope=None, 560 options=field_proto.options) 561 562 def _SetAllFieldTypes(self, package, desc_proto, scope): 563 """Sets all the descriptor's fields's types. 564 565 This method also sets the containing types on any extensions. 566 567 Args: 568 package: The current package of desc_proto. 569 desc_proto: The message descriptor to update. 570 scope: Enclosing scope of available types. 571 """ 572 573 package = _PrefixWithDot(package) 574 575 main_desc = self._GetTypeFromScope(package, desc_proto.name, scope) 576 577 if package == '.': 578 nested_package = _PrefixWithDot(desc_proto.name) 579 else: 580 nested_package = '.'.join([package, desc_proto.name]) 581 582 for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): 583 self._SetFieldType(field_proto, field_desc, nested_package, scope) 584 585 for extension_proto, extension_desc in ( 586 zip(desc_proto.extension, main_desc.extensions)): 587 extension_desc.containing_type = self._GetTypeFromScope( 588 nested_package, extension_proto.extendee, scope) 589 self._SetFieldType(extension_proto, extension_desc, nested_package, scope) 590 591 for nested_type in desc_proto.nested_type: 592 self._SetAllFieldTypes(nested_package, nested_type, scope) 593 594 def _SetFieldType(self, field_proto, field_desc, package, scope): 595 """Sets the field's type, cpp_type, message_type and enum_type. 596 597 Args: 598 field_proto: Data about the field in proto format. 599 field_desc: The descriptor to modiy. 600 package: The package the field's container is in. 601 scope: Enclosing scope of available types. 602 """ 603 if field_proto.type_name: 604 desc = self._GetTypeFromScope(package, field_proto.type_name, scope) 605 else: 606 desc = None 607 608 if not field_proto.HasField('type'): 609 if isinstance(desc, descriptor.Descriptor): 610 field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE 611 else: 612 field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM 613 614 field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType( 615 field_proto.type) 616 617 if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE 618 or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP): 619 field_desc.message_type = desc 620 621 if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: 622 field_desc.enum_type = desc 623 624 if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED: 625 field_desc.has_default_value = False 626 field_desc.default_value = [] 627 elif field_proto.HasField('default_value'): 628 field_desc.has_default_value = True 629 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or 630 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): 631 field_desc.default_value = float(field_proto.default_value) 632 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: 633 field_desc.default_value = field_proto.default_value 634 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: 635 field_desc.default_value = field_proto.default_value.lower() == 'true' 636 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: 637 field_desc.default_value = field_desc.enum_type.values_by_name[ 638 field_proto.default_value].number 639 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: 640 field_desc.default_value = text_encoding.CUnescape( 641 field_proto.default_value) 642 else: 643 # All other types are of the "int" type. 644 field_desc.default_value = int(field_proto.default_value) 645 else: 646 field_desc.has_default_value = False 647 if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or 648 field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): 649 field_desc.default_value = 0.0 650 elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: 651 field_desc.default_value = u'' 652 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: 653 field_desc.default_value = False 654 elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: 655 field_desc.default_value = field_desc.enum_type.values[0].number 656 elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: 657 field_desc.default_value = b'' 658 else: 659 # All other types are of the "int" type. 660 field_desc.default_value = 0 661 662 field_desc.type = field_proto.type 663 664 def _MakeEnumValueDescriptor(self, value_proto, index): 665 """Creates a enum value descriptor object from a enum value proto. 666 667 Args: 668 value_proto: The proto describing the enum value. 669 index: The index of the enum value. 670 671 Returns: 672 An initialized EnumValueDescriptor object. 673 """ 674 675 return descriptor.EnumValueDescriptor( 676 name=value_proto.name, 677 index=index, 678 number=value_proto.number, 679 options=value_proto.options, 680 type=None) 681 682 def _ExtractSymbols(self, descriptors): 683 """Pulls out all the symbols from descriptor protos. 684 685 Args: 686 descriptors: The messages to extract descriptors from. 687 Yields: 688 A two element tuple of the type name and descriptor object. 689 """ 690 691 for desc in descriptors: 692 yield (_PrefixWithDot(desc.full_name), desc) 693 for symbol in self._ExtractSymbols(desc.nested_types): 694 yield symbol 695 for enum in desc.enum_types: 696 yield (_PrefixWithDot(enum.full_name), enum) 697 698 def _GetDeps(self, dependencies): 699 """Recursively finds dependencies for file protos. 700 701 Args: 702 dependencies: The names of the files being depended on. 703 704 Yields: 705 Each direct and indirect dependency. 706 """ 707 708 for dependency in dependencies: 709 dep_desc = self.FindFileByName(dependency) 710 yield dep_desc 711 for parent_dep in dep_desc.dependencies: 712 yield parent_dep 713 714 def _GetTypeFromScope(self, package, type_name, scope): 715 """Finds a given type name in the current scope. 716 717 Args: 718 package: The package the proto should be located in. 719 type_name: The name of the type to be found in the scope. 720 scope: Dict mapping short and full symbols to message and enum types. 721 722 Returns: 723 The descriptor for the requested type. 724 """ 725 if type_name not in scope: 726 components = _PrefixWithDot(package).split('.') 727 while components: 728 possible_match = '.'.join(components + [type_name]) 729 if possible_match in scope: 730 type_name = possible_match 731 break 732 else: 733 components.pop(-1) 734 return scope[type_name] 735 736 737def _PrefixWithDot(name): 738 return name if name.startswith('.') else '.%s' % name 739 740 741if _USE_C_DESCRIPTORS: 742 # TODO(amauryfa): This pool could be constructed from Python code, when we 743 # support a flag like 'use_cpp_generated_pool=True'. 744 # pylint: disable=protected-access 745 _DEFAULT = descriptor._message.default_pool 746else: 747 _DEFAULT = DescriptorPool() 748 749 750def Default(): 751 return _DEFAULT 752