90
111
self._internal_db.Add(file_desc_proto)
113
def AddDescriptor(self, desc):
114
"""Adds a Descriptor to the pool, non-recursively.
116
If the Descriptor contains nested messages or enums, the caller must
117
explicitly register them. This method also registers the FileDescriptor
118
associated with the message.
123
if not isinstance(desc, descriptor.Descriptor):
124
raise TypeError('Expected instance of descriptor.Descriptor.')
126
self._descriptors[desc.full_name] = desc
127
self.AddFileDescriptor(desc.file)
129
def AddEnumDescriptor(self, enum_desc):
130
"""Adds an EnumDescriptor to the pool.
132
This method also registers the FileDescriptor associated with the message.
135
enum_desc: An EnumDescriptor.
138
if not isinstance(enum_desc, descriptor.EnumDescriptor):
139
raise TypeError('Expected instance of descriptor.EnumDescriptor.')
141
self._enum_descriptors[enum_desc.full_name] = enum_desc
142
self.AddFileDescriptor(enum_desc.file)
144
def AddFileDescriptor(self, file_desc):
145
"""Adds a FileDescriptor to the pool, non-recursively.
147
If the FileDescriptor contains messages or enums, the caller must explicitly
151
file_desc: A FileDescriptor.
154
if not isinstance(file_desc, descriptor.FileDescriptor):
155
raise TypeError('Expected instance of descriptor.FileDescriptor.')
156
self._file_descriptors[file_desc.name] = file_desc
92
158
def FindFileByName(self, file_name):
93
159
"""Gets a FileDescriptor by file name.
183
267
if file_proto.name not in self._file_descriptors:
268
built_deps = list(self._GetDeps(file_proto.dependency))
269
direct_deps = [self.FindFileByName(n) for n in file_proto.dependency]
184
271
file_descriptor = descriptor.FileDescriptor(
185
272
name=file_proto.name,
186
273
package=file_proto.package,
187
274
options=file_proto.options,
188
serialized_pb=file_proto.SerializeToString())
275
serialized_pb=file_proto.SerializeToString(),
276
dependencies=direct_deps)
190
dependencies = list(self._GetDeps(file_proto))
192
for dependency in dependencies:
193
dep_desc = self.FindFileByName(dependency.name)
194
dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
195
dep_desc.serialized_pb)
196
package = '.' + dep_proto.package
197
package_prefix = package + '.'
199
def _strip_package(symbol):
200
if symbol.startswith(package_prefix):
201
return symbol[len(package_prefix):]
204
symbols = list(self._ExtractSymbols(dep_proto.message_type, package))
205
scope.update(symbols)
206
scope.update((_strip_package(k), v) for k, v in symbols)
208
symbols = list(self._ExtractEnums(dep_proto.enum_type, package))
209
scope.update(symbols)
210
scope.update((_strip_package(k), v) for k, v in symbols)
279
# This loop extracts all the message and enum types from all the
280
# dependencoes of the file_proto. This is necessary to create the
281
# scope of available message types when defining the passed in
283
for dependency in built_deps:
284
scope.update(self._ExtractSymbols(
285
dependency.message_types_by_name.values()))
286
scope.update((_PrefixWithDot(enum.full_name), enum)
287
for enum in dependency.enum_types_by_name.values())
212
289
for message_type in file_proto.message_type:
213
290
message_desc = self._ConvertMessageDescriptor(
214
291
message_type, file_proto.package, file_descriptor, scope)
215
292
file_descriptor.message_types_by_name[message_desc.name] = message_desc
216
294
for enum_type in file_proto.enum_type:
217
self._ConvertEnumDescriptor(enum_type, file_proto.package,
218
file_descriptor, None, scope)
219
for desc_proto in self._ExtractMessages(file_proto.message_type):
220
self._SetFieldTypes(desc_proto, scope)
222
for desc_proto in file_proto.message_type:
223
desc = scope[desc_proto.name]
295
file_descriptor.enum_types_by_name[enum_type.name] = (
296
self._ConvertEnumDescriptor(enum_type, file_proto.package,
297
file_descriptor, None, scope))
299
for index, extension_proto in enumerate(file_proto.extension):
300
extension_desc = self.MakeFieldDescriptor(
301
extension_proto, file_proto.package, index, is_extension=True)
302
extension_desc.containing_type = self._GetTypeFromScope(
303
file_descriptor.package, extension_proto.extendee, scope)
304
self.SetFieldType(extension_proto, extension_desc,
305
file_descriptor.package, scope)
306
file_descriptor.extensions_by_name[extension_desc.name] = extension_desc
308
for desc_proto in file_proto.message_type:
309
self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
311
if file_proto.package:
312
desc_proto_prefix = _PrefixWithDot(file_proto.package)
314
desc_proto_prefix = ''
316
for desc_proto in file_proto.message_type:
317
desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope)
224
318
file_descriptor.message_types_by_name[desc_proto.name] = desc
225
319
self.Add(file_proto)
226
320
self._file_descriptors[file_proto.name] = file_descriptor
261
355
self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
262
356
for enum in desc_proto.enum_type]
263
fields = [self._MakeFieldDescriptor(field, desc_name, index)
357
fields = [self.MakeFieldDescriptor(field, desc_name, index)
264
358
for index, field in enumerate(desc_proto.field)]
265
extensions = [self._MakeFieldDescriptor(extension, desc_name, True)
266
for index, extension in enumerate(desc_proto.extension)]
360
self.MakeFieldDescriptor(extension, desc_name, index, is_extension=True)
361
for index, extension in enumerate(desc_proto.extension)]
363
descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)),
365
for index, desc in enumerate(desc_proto.oneof_decl)]
267
366
extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
268
367
if extension_ranges:
269
368
is_extendable = True
374
478
extension_scope=None,
375
479
options=field_proto.options)
377
def _SetFieldTypes(self, desc_proto, scope):
378
"""Sets the field's type, cpp_type, message_type and enum_type.
481
def SetAllFieldTypes(self, package, desc_proto, scope):
482
"""Sets all the descriptor's fields's types.
484
This method also sets the containing types on any extensions.
487
package: The current package of desc_proto.
381
488
desc_proto: The message descriptor to update.
382
489
scope: Enclosing scope of available types.
385
desc = scope[desc_proto.name]
386
for field_proto, field_desc in zip(desc_proto.field, desc.fields):
387
if field_proto.type_name:
388
type_name = field_proto.type_name
389
if type_name not in scope:
390
type_name = '.' + type_name
391
desc = scope[type_name]
395
if not field_proto.HasField('type'):
396
if isinstance(desc, descriptor.Descriptor):
397
field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
399
field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
401
field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
404
if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
405
or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
406
field_desc.message_type = desc
408
if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
409
field_desc.enum_type = desc
411
if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
412
field_desc.has_default = False
413
field_desc.default_value = []
414
elif field_proto.HasField('default_value'):
415
field_desc.has_default = True
416
if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
417
field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
418
field_desc.default_value = float(field_proto.default_value)
419
elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
420
field_desc.default_value = field_proto.default_value
421
elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
422
field_desc.default_value = field_proto.default_value.lower() == 'true'
423
elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
424
field_desc.default_value = field_desc.enum_type.values_by_name[
425
field_proto.default_value].index
427
field_desc.default_value = int(field_proto.default_value)
429
field_desc.has_default = False
430
field_desc.default_value = None
432
field_desc.type = field_proto.type
492
package = _PrefixWithDot(package)
494
main_desc = self._GetTypeFromScope(package, desc_proto.name, scope)
497
nested_package = _PrefixWithDot(desc_proto.name)
499
nested_package = '.'.join([package, desc_proto.name])
501
for field_proto, field_desc in zip(desc_proto.field, main_desc.fields):
502
self.SetFieldType(field_proto, field_desc, nested_package, scope)
504
for extension_proto, extension_desc in (
505
zip(desc_proto.extension, main_desc.extensions)):
506
extension_desc.containing_type = self._GetTypeFromScope(
507
nested_package, extension_proto.extendee, scope)
508
self.SetFieldType(extension_proto, extension_desc, nested_package, scope)
434
510
for nested_type in desc_proto.nested_type:
435
self._SetFieldTypes(nested_type, scope)
511
self.SetAllFieldTypes(nested_package, nested_type, scope)
513
def SetFieldType(self, field_proto, field_desc, package, scope):
514
"""Sets the field's type, cpp_type, message_type and enum_type.
517
field_proto: Data about the field in proto format.
518
field_desc: The descriptor to modiy.
519
package: The package the field's container is in.
520
scope: Enclosing scope of available types.
522
if field_proto.type_name:
523
desc = self._GetTypeFromScope(package, field_proto.type_name, scope)
527
if not field_proto.HasField('type'):
528
if isinstance(desc, descriptor.Descriptor):
529
field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
531
field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
533
field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
536
if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
537
or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
538
field_desc.message_type = desc
540
if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
541
field_desc.enum_type = desc
543
if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
544
field_desc.has_default_value = False
545
field_desc.default_value = []
546
elif field_proto.HasField('default_value'):
547
field_desc.has_default_value = True
548
if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
549
field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
550
field_desc.default_value = float(field_proto.default_value)
551
elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
552
field_desc.default_value = field_proto.default_value
553
elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
554
field_desc.default_value = field_proto.default_value.lower() == 'true'
555
elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
556
field_desc.default_value = field_desc.enum_type.values_by_name[
557
field_proto.default_value].index
558
elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
559
field_desc.default_value = text_encoding.CUnescape(
560
field_proto.default_value)
562
field_desc.default_value = int(field_proto.default_value)
564
field_desc.has_default_value = False
565
field_desc.default_value = None
567
field_desc.type = field_proto.type
437
569
def _MakeEnumValueDescriptor(self, value_proto, index):
438
570
"""Creates a enum value descriptor object from a enum value proto.
452
584
options=value_proto.options,
455
def _ExtractSymbols(self, desc_protos, package):
587
def _ExtractSymbols(self, descriptors):
456
588
"""Pulls out all the symbols from descriptor protos.
459
desc_protos: The protos to extract symbols from.
460
package: The package containing the descriptor type.
591
descriptors: The messages to extract descriptors from.
462
593
A two element tuple of the type name and descriptor object.
465
for desc_proto in desc_protos:
467
message_name = '.'.join((package, desc_proto.name))
469
message_name = desc_proto.name
470
message_desc = self.FindMessageTypeByName(message_name)
471
yield (message_name, message_desc)
472
for symbol in self._ExtractSymbols(desc_proto.nested_type, message_name):
474
for symbol in self._ExtractEnums(desc_proto.enum_type, message_name):
477
def _ExtractEnums(self, enum_protos, package):
478
"""Pulls out all the symbols from enum protos.
481
enum_protos: The protos to extract symbols from.
482
package: The package containing the enum type.
485
A two element tuple of the type name and enum descriptor object.
488
for enum_proto in enum_protos:
490
enum_name = '.'.join((package, enum_proto.name))
492
enum_name = enum_proto.name
493
enum_desc = self.FindEnumTypeByName(enum_name)
494
yield (enum_name, enum_desc)
496
def _ExtractMessages(self, desc_protos):
497
"""Pulls out all the message protos from descriptos.
500
desc_protos: The protos to extract symbols from.
506
for desc_proto in desc_protos:
508
for message in self._ExtractMessages(desc_proto.nested_type):
511
def _GetDeps(self, file_proto):
596
for desc in descriptors:
597
yield (_PrefixWithDot(desc.full_name), desc)
598
for symbol in self._ExtractSymbols(desc.nested_types):
600
for enum in desc.enum_types:
601
yield (_PrefixWithDot(enum.full_name), enum)
603
def _GetDeps(self, dependencies):
512
604
"""Recursively finds dependencies for file protos.
515
file_proto: The proto to get dependencies from.
607
dependencies: The names of the files being depended on.
518
610
Each direct and indirect dependency.
521
for dependency in file_proto.dependency:
613
for dependency in dependencies:
522
614
dep_desc = self.FindFileByName(dependency)
523
dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
524
dep_desc.serialized_pb)
526
for parent_dep in self._GetDeps(dep_proto):
616
for parent_dep in dep_desc.dependencies:
619
def _GetTypeFromScope(self, package, type_name, scope):
620
"""Finds a given type name in the current scope.
623
package: The package the proto should be located in.
624
type_name: The name of the type to be found in the scope.
625
scope: Dict mapping short and full symbols to message and enum types.
628
The descriptor for the requested type.
630
if type_name not in scope:
631
components = _PrefixWithDot(package).split('.')
633
possible_match = '.'.join(components + [type_name])
634
if possible_match in scope:
635
type_name = possible_match
639
return scope[type_name]
642
def _PrefixWithDot(name):
643
return name if name.startswith('.') else '.%s' % name