Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/protobuf/descriptor.py: 28%
529 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-01-31 06:32 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-01-31 06:32 +0000
1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc. All rights reserved.
3#
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file or at
6# https://developers.google.com/open-source/licenses/bsd
8"""Descriptors essentially contain exactly the information found in a .proto
9file, in types that make this information accessible in Python.
10"""
12__author__ = 'robinson@google.com (Will Robinson)'
14import abc
15import binascii
16import os
17import threading
18import warnings
20from google.protobuf.internal import api_implementation
22_USE_C_DESCRIPTORS = False
23if api_implementation.Type() != 'python':
24 # pylint: disable=protected-access
25 _message = api_implementation._c_module
26 # TODO: Remove this import after fix api_implementation
27 if _message is None:
28 from google.protobuf.pyext import _message
29 _USE_C_DESCRIPTORS = True
32class Error(Exception):
33 """Base error for this module."""
36class TypeTransformationError(Error):
37 """Error transforming between python proto type and corresponding C++ type."""
40if _USE_C_DESCRIPTORS:
41 # This metaclass allows to override the behavior of code like
42 # isinstance(my_descriptor, FieldDescriptor)
43 # and make it return True when the descriptor is an instance of the extension
44 # type written in C++.
45 class DescriptorMetaclass(type):
47 def __instancecheck__(cls, obj):
48 if super(DescriptorMetaclass, cls).__instancecheck__(obj):
49 return True
50 if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
51 return True
52 return False
53else:
54 # The standard metaclass; nothing changes.
55 DescriptorMetaclass = abc.ABCMeta
58class _Lock(object):
59 """Wrapper class of threading.Lock(), which is allowed by 'with'."""
61 def __new__(cls):
62 self = object.__new__(cls)
63 self._lock = threading.Lock() # pylint: disable=protected-access
64 return self
66 def __enter__(self):
67 self._lock.acquire()
69 def __exit__(self, exc_type, exc_value, exc_tb):
70 self._lock.release()
73_lock = threading.Lock()
76def _Deprecated(name):
77 if _Deprecated.count > 0:
78 _Deprecated.count -= 1
79 warnings.warn(
80 'Call to deprecated create function %s(). Note: Create unlinked '
81 'descriptors is going to go away. Please use get/find descriptors from '
82 'generated code or query the descriptor_pool.'
83 % name,
84 category=DeprecationWarning, stacklevel=3)
86# These must match the values in descriptor.proto, but we can't use them
87# directly because we sometimes need to reference them in feature helpers
88# below *during* the build of descriptor.proto.
89_FEATURESET_MESSAGE_ENCODING_DELIMITED = 2
90_FEATURESET_FIELD_PRESENCE_IMPLICIT = 2
91_FEATURESET_FIELD_PRESENCE_LEGACY_REQUIRED = 3
92_FEATURESET_REPEATED_FIELD_ENCODING_PACKED = 1
93_FEATURESET_ENUM_TYPE_CLOSED = 2
95# Deprecated warnings will print 100 times at most which should be enough for
96# users to notice and do not cause timeout.
97_Deprecated.count = 100
100_internal_create_key = object()
103class DescriptorBase(metaclass=DescriptorMetaclass):
105 """Descriptors base class.
107 This class is the base of all descriptor classes. It provides common options
108 related functionality.
110 Attributes:
111 has_options: True if the descriptor has non-default options. Usually it is
112 not necessary to read this -- just call GetOptions() which will happily
113 return the default instance. However, it's sometimes useful for
114 efficiency, and also useful inside the protobuf implementation to avoid
115 some bootstrapping issues.
116 file (FileDescriptor): Reference to file info.
117 """
119 if _USE_C_DESCRIPTORS:
120 # The class, or tuple of classes, that are considered as "virtual
121 # subclasses" of this descriptor class.
122 _C_DESCRIPTOR_CLASS = ()
124 def __init__(self, file, options, serialized_options, options_class_name):
125 """Initialize the descriptor given its options message and the name of the
126 class of the options message. The name of the class is required in case
127 the options message is None and has to be created.
128 """
129 self._features = None
130 self.file = file
131 self._options = options
132 self._loaded_options = None
133 self._options_class_name = options_class_name
134 self._serialized_options = serialized_options
136 # Does this descriptor have non-default options?
137 self.has_options = (self._options is not None) or (
138 self._serialized_options is not None
139 )
141 @property
142 @abc.abstractmethod
143 def _parent(self):
144 pass
146 def _InferLegacyFeatures(self, edition, options, features):
147 """Infers features from proto2/proto3 syntax so that editions logic can be used everywhere.
149 Args:
150 edition: The edition to infer features for.
151 options: The options for this descriptor that are being processed.
152 features: The feature set object to modify with inferred features.
153 """
154 pass
156 def _GetFeatures(self):
157 if not self._features:
158 self._LazyLoadOptions()
159 return self._features
161 def _ResolveFeatures(self, edition, raw_options):
162 """Resolves features from the raw options of this descriptor.
164 Args:
165 edition: The edition to use for feature defaults.
166 raw_options: The options for this descriptor that are being processed.
168 Returns:
169 A fully resolved feature set for making runtime decisions.
170 """
171 # pylint: disable=g-import-not-at-top
172 from google.protobuf import descriptor_pb2
174 if self._parent:
175 features = descriptor_pb2.FeatureSet()
176 features.CopyFrom(self._parent._GetFeatures())
177 else:
178 features = self.file.pool._CreateDefaultFeatures(edition)
179 unresolved = descriptor_pb2.FeatureSet()
180 unresolved.CopyFrom(raw_options.features)
181 self._InferLegacyFeatures(edition, raw_options, unresolved)
182 features.MergeFrom(unresolved)
184 # Use the feature cache to reduce memory bloat.
185 return self.file.pool._InternFeatures(features)
187 def _LazyLoadOptions(self):
188 """Lazily initializes descriptor options towards the end of the build."""
189 if self._loaded_options:
190 return
192 # pylint: disable=g-import-not-at-top
193 from google.protobuf import descriptor_pb2
195 if not hasattr(descriptor_pb2, self._options_class_name):
196 raise RuntimeError(
197 'Unknown options class name %s!' % self._options_class_name
198 )
199 options_class = getattr(descriptor_pb2, self._options_class_name)
200 features = None
201 edition = self.file._edition
203 if not self.has_options:
204 if not self._features:
205 features = self._ResolveFeatures(
206 descriptor_pb2.Edition.Value(edition), options_class()
207 )
208 with _lock:
209 self._loaded_options = options_class()
210 if not self._features:
211 self._features = features
212 else:
213 if not self._serialized_options:
214 options = self._options
215 else:
216 options = _ParseOptions(options_class(), self._serialized_options)
218 if not self._features:
219 features = self._ResolveFeatures(
220 descriptor_pb2.Edition.Value(edition), options
221 )
222 with _lock:
223 self._loaded_options = options
224 if not self._features:
225 self._features = features
226 if options.HasField('features'):
227 options.ClearField('features')
228 if not options.SerializeToString():
229 self._loaded_options = options_class()
230 self.has_options = False
232 def GetOptions(self):
233 """Retrieves descriptor options.
235 Returns:
236 The options set on this descriptor.
237 """
238 if not self._loaded_options:
239 self._LazyLoadOptions()
240 return self._loaded_options
243class _NestedDescriptorBase(DescriptorBase):
244 """Common class for descriptors that can be nested."""
246 def __init__(self, options, options_class_name, name, full_name,
247 file, containing_type, serialized_start=None,
248 serialized_end=None, serialized_options=None):
249 """Constructor.
251 Args:
252 options: Protocol message options or None to use default message options.
253 options_class_name (str): The class name of the above options.
254 name (str): Name of this protocol message type.
255 full_name (str): Fully-qualified name of this protocol message type, which
256 will include protocol "package" name and the name of any enclosing
257 types.
258 containing_type: if provided, this is a nested descriptor, with this
259 descriptor as parent, otherwise None.
260 serialized_start: The start index (inclusive) in block in the
261 file.serialized_pb that describes this descriptor.
262 serialized_end: The end index (exclusive) in block in the
263 file.serialized_pb that describes this descriptor.
264 serialized_options: Protocol message serialized options or None.
265 """
266 super(_NestedDescriptorBase, self).__init__(
267 file, options, serialized_options, options_class_name
268 )
270 self.name = name
271 # TODO: Add function to calculate full_name instead of having it in
272 # memory?
273 self.full_name = full_name
274 self.containing_type = containing_type
276 self._serialized_start = serialized_start
277 self._serialized_end = serialized_end
279 def CopyToProto(self, proto):
280 """Copies this to the matching proto in descriptor_pb2.
282 Args:
283 proto: An empty proto instance from descriptor_pb2.
285 Raises:
286 Error: If self couldn't be serialized, due to to few constructor
287 arguments.
288 """
289 if (self.file is not None and
290 self._serialized_start is not None and
291 self._serialized_end is not None):
292 proto.ParseFromString(self.file.serialized_pb[
293 self._serialized_start:self._serialized_end])
294 else:
295 raise Error('Descriptor does not contain serialization.')
298class Descriptor(_NestedDescriptorBase):
300 """Descriptor for a protocol message type.
302 Attributes:
303 name (str): Name of this protocol message type.
304 full_name (str): Fully-qualified name of this protocol message type,
305 which will include protocol "package" name and the name of any
306 enclosing types.
307 containing_type (Descriptor): Reference to the descriptor of the type
308 containing us, or None if this is top-level.
309 fields (list[FieldDescriptor]): Field descriptors for all fields in
310 this type.
311 fields_by_number (dict(int, FieldDescriptor)): Same
312 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed
313 by "number" attribute in each FieldDescriptor.
314 fields_by_name (dict(str, FieldDescriptor)): Same
315 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by
316 "name" attribute in each :class:`FieldDescriptor`.
317 nested_types (list[Descriptor]): Descriptor references
318 for all protocol message types nested within this one.
319 nested_types_by_name (dict(str, Descriptor)): Same Descriptor
320 objects as in :attr:`nested_types`, but indexed by "name" attribute
321 in each Descriptor.
322 enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references
323 for all enums contained within this type.
324 enum_types_by_name (dict(str, EnumDescriptor)): Same
325 :class:`EnumDescriptor` objects as in :attr:`enum_types`, but
326 indexed by "name" attribute in each EnumDescriptor.
327 enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping
328 from enum value name to :class:`EnumValueDescriptor` for that value.
329 extensions (list[FieldDescriptor]): All extensions defined directly
330 within this message type (NOT within a nested type).
331 extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor
332 objects as :attr:`extensions`, but indexed by "name" attribute of each
333 FieldDescriptor.
334 is_extendable (bool): Does this type define any extension ranges?
335 oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields
336 in this message.
337 oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in
338 :attr:`oneofs`, but indexed by "name" attribute.
339 file (FileDescriptor): Reference to file descriptor.
340 is_map_entry: If the message type is a map entry.
342 """
344 if _USE_C_DESCRIPTORS:
345 _C_DESCRIPTOR_CLASS = _message.Descriptor
347 def __new__(
348 cls,
349 name=None,
350 full_name=None,
351 filename=None,
352 containing_type=None,
353 fields=None,
354 nested_types=None,
355 enum_types=None,
356 extensions=None,
357 options=None,
358 serialized_options=None,
359 is_extendable=True,
360 extension_ranges=None,
361 oneofs=None,
362 file=None, # pylint: disable=redefined-builtin
363 serialized_start=None,
364 serialized_end=None,
365 syntax=None,
366 is_map_entry=False,
367 create_key=None):
368 _message.Message._CheckCalledFromGeneratedFile()
369 return _message.default_pool.FindMessageTypeByName(full_name)
371 # NOTE: The file argument redefining a builtin is nothing we can
372 # fix right now since we don't know how many clients already rely on the
373 # name of the argument.
374 def __init__(self, name, full_name, filename, containing_type, fields,
375 nested_types, enum_types, extensions, options=None,
376 serialized_options=None,
377 is_extendable=True, extension_ranges=None, oneofs=None,
378 file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin
379 syntax=None, is_map_entry=False, create_key=None):
380 """Arguments to __init__() are as described in the description
381 of Descriptor fields above.
383 Note that filename is an obsolete argument, that is not used anymore.
384 Please use file.name to access this as an attribute.
385 """
386 if create_key is not _internal_create_key:
387 _Deprecated('Descriptor')
389 super(Descriptor, self).__init__(
390 options, 'MessageOptions', name, full_name, file,
391 containing_type, serialized_start=serialized_start,
392 serialized_end=serialized_end, serialized_options=serialized_options)
394 # We have fields in addition to fields_by_name and fields_by_number,
395 # so that:
396 # 1. Clients can index fields by "order in which they're listed."
397 # 2. Clients can easily iterate over all fields with the terse
398 # syntax: for f in descriptor.fields: ...
399 self.fields = fields
400 for field in self.fields:
401 field.containing_type = self
402 field.file = file
403 self.fields_by_number = dict((f.number, f) for f in fields)
404 self.fields_by_name = dict((f.name, f) for f in fields)
405 self._fields_by_camelcase_name = None
407 self.nested_types = nested_types
408 for nested_type in nested_types:
409 nested_type.containing_type = self
410 self.nested_types_by_name = dict((t.name, t) for t in nested_types)
412 self.enum_types = enum_types
413 for enum_type in self.enum_types:
414 enum_type.containing_type = self
415 self.enum_types_by_name = dict((t.name, t) for t in enum_types)
416 self.enum_values_by_name = dict(
417 (v.name, v) for t in enum_types for v in t.values)
419 self.extensions = extensions
420 for extension in self.extensions:
421 extension.extension_scope = self
422 self.extensions_by_name = dict((f.name, f) for f in extensions)
423 self.is_extendable = is_extendable
424 self.extension_ranges = extension_ranges
425 self.oneofs = oneofs if oneofs is not None else []
426 self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
427 for oneof in self.oneofs:
428 oneof.containing_type = self
429 oneof.file = file
430 self._is_map_entry = is_map_entry
432 @property
433 def _parent(self):
434 return self.containing_type or self.file
436 @property
437 def fields_by_camelcase_name(self):
438 """Same FieldDescriptor objects as in :attr:`fields`, but indexed by
439 :attr:`FieldDescriptor.camelcase_name`.
440 """
441 if self._fields_by_camelcase_name is None:
442 self._fields_by_camelcase_name = dict(
443 (f.camelcase_name, f) for f in self.fields)
444 return self._fields_by_camelcase_name
446 def EnumValueName(self, enum, value):
447 """Returns the string name of an enum value.
449 This is just a small helper method to simplify a common operation.
451 Args:
452 enum: string name of the Enum.
453 value: int, value of the enum.
455 Returns:
456 string name of the enum value.
458 Raises:
459 KeyError if either the Enum doesn't exist or the value is not a valid
460 value for the enum.
461 """
462 return self.enum_types_by_name[enum].values_by_number[value].name
464 def CopyToProto(self, proto):
465 """Copies this to a descriptor_pb2.DescriptorProto.
467 Args:
468 proto: An empty descriptor_pb2.DescriptorProto.
469 """
470 # This function is overridden to give a better doc comment.
471 super(Descriptor, self).CopyToProto(proto)
474# TODO: We should have aggressive checking here,
475# for example:
476# * If you specify a repeated field, you should not be allowed
477# to specify a default value.
478# * [Other examples here as needed].
479#
480# TODO: for this and other *Descriptor classes, we
481# might also want to lock things down aggressively (e.g.,
482# prevent clients from setting the attributes). Having
483# stronger invariants here in general will reduce the number
484# of runtime checks we must do in reflection.py...
485class FieldDescriptor(DescriptorBase):
487 """Descriptor for a single field in a .proto file.
489 Attributes:
490 name (str): Name of this field, exactly as it appears in .proto.
491 full_name (str): Name of this field, including containing scope. This is
492 particularly relevant for extensions.
493 index (int): Dense, 0-indexed index giving the order that this
494 field textually appears within its message in the .proto file.
495 number (int): Tag number declared for this field in the .proto file.
497 type (int): (One of the TYPE_* constants below) Declared type.
498 cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to
499 represent this field.
501 label (int): (One of the LABEL_* constants below) Tells whether this
502 field is optional, required, or repeated.
503 has_default_value (bool): True if this field has a default value defined,
504 otherwise false.
505 default_value (Varies): Default value of this field. Only
506 meaningful for non-repeated scalar fields. Repeated fields
507 should always set this to [], and non-repeated composite
508 fields should always set this to None.
510 containing_type (Descriptor): Descriptor of the protocol message
511 type that contains this field. Set by the Descriptor constructor
512 if we're passed into one.
513 Somewhat confusingly, for extension fields, this is the
514 descriptor of the EXTENDED message, not the descriptor
515 of the message containing this field. (See is_extension and
516 extension_scope below).
517 message_type (Descriptor): If a composite field, a descriptor
518 of the message type contained in this field. Otherwise, this is None.
519 enum_type (EnumDescriptor): If this field contains an enum, a
520 descriptor of that enum. Otherwise, this is None.
522 is_extension: True iff this describes an extension field.
523 extension_scope (Descriptor): Only meaningful if is_extension is True.
524 Gives the message that immediately contains this extension field.
525 Will be None iff we're a top-level (file-level) extension field.
527 options (descriptor_pb2.FieldOptions): Protocol message field options or
528 None to use default field options.
530 containing_oneof (OneofDescriptor): If the field is a member of a oneof
531 union, contains its descriptor. Otherwise, None.
533 file (FileDescriptor): Reference to file descriptor.
534 """
536 # Must be consistent with C++ FieldDescriptor::Type enum in
537 # descriptor.h.
538 #
539 # TODO: Find a way to eliminate this repetition.
540 TYPE_DOUBLE = 1
541 TYPE_FLOAT = 2
542 TYPE_INT64 = 3
543 TYPE_UINT64 = 4
544 TYPE_INT32 = 5
545 TYPE_FIXED64 = 6
546 TYPE_FIXED32 = 7
547 TYPE_BOOL = 8
548 TYPE_STRING = 9
549 TYPE_GROUP = 10
550 TYPE_MESSAGE = 11
551 TYPE_BYTES = 12
552 TYPE_UINT32 = 13
553 TYPE_ENUM = 14
554 TYPE_SFIXED32 = 15
555 TYPE_SFIXED64 = 16
556 TYPE_SINT32 = 17
557 TYPE_SINT64 = 18
558 MAX_TYPE = 18
560 # Must be consistent with C++ FieldDescriptor::CppType enum in
561 # descriptor.h.
562 #
563 # TODO: Find a way to eliminate this repetition.
564 CPPTYPE_INT32 = 1
565 CPPTYPE_INT64 = 2
566 CPPTYPE_UINT32 = 3
567 CPPTYPE_UINT64 = 4
568 CPPTYPE_DOUBLE = 5
569 CPPTYPE_FLOAT = 6
570 CPPTYPE_BOOL = 7
571 CPPTYPE_ENUM = 8
572 CPPTYPE_STRING = 9
573 CPPTYPE_MESSAGE = 10
574 MAX_CPPTYPE = 10
576 _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
577 TYPE_DOUBLE: CPPTYPE_DOUBLE,
578 TYPE_FLOAT: CPPTYPE_FLOAT,
579 TYPE_ENUM: CPPTYPE_ENUM,
580 TYPE_INT64: CPPTYPE_INT64,
581 TYPE_SINT64: CPPTYPE_INT64,
582 TYPE_SFIXED64: CPPTYPE_INT64,
583 TYPE_UINT64: CPPTYPE_UINT64,
584 TYPE_FIXED64: CPPTYPE_UINT64,
585 TYPE_INT32: CPPTYPE_INT32,
586 TYPE_SFIXED32: CPPTYPE_INT32,
587 TYPE_SINT32: CPPTYPE_INT32,
588 TYPE_UINT32: CPPTYPE_UINT32,
589 TYPE_FIXED32: CPPTYPE_UINT32,
590 TYPE_BYTES: CPPTYPE_STRING,
591 TYPE_STRING: CPPTYPE_STRING,
592 TYPE_BOOL: CPPTYPE_BOOL,
593 TYPE_MESSAGE: CPPTYPE_MESSAGE,
594 TYPE_GROUP: CPPTYPE_MESSAGE
595 }
597 # Must be consistent with C++ FieldDescriptor::Label enum in
598 # descriptor.h.
599 #
600 # TODO: Find a way to eliminate this repetition.
601 LABEL_OPTIONAL = 1
602 LABEL_REQUIRED = 2
603 LABEL_REPEATED = 3
604 MAX_LABEL = 3
606 # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
607 # and kLastReservedNumber in descriptor.h
608 MAX_FIELD_NUMBER = (1 << 29) - 1
609 FIRST_RESERVED_FIELD_NUMBER = 19000
610 LAST_RESERVED_FIELD_NUMBER = 19999
612 if _USE_C_DESCRIPTORS:
613 _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
615 def __new__(cls, name, full_name, index, number, type, cpp_type, label,
616 default_value, message_type, enum_type, containing_type,
617 is_extension, extension_scope, options=None,
618 serialized_options=None,
619 has_default_value=True, containing_oneof=None, json_name=None,
620 file=None, create_key=None): # pylint: disable=redefined-builtin
621 _message.Message._CheckCalledFromGeneratedFile()
622 if is_extension:
623 return _message.default_pool.FindExtensionByName(full_name)
624 else:
625 return _message.default_pool.FindFieldByName(full_name)
627 def __init__(self, name, full_name, index, number, type, cpp_type, label,
628 default_value, message_type, enum_type, containing_type,
629 is_extension, extension_scope, options=None,
630 serialized_options=None,
631 has_default_value=True, containing_oneof=None, json_name=None,
632 file=None, create_key=None): # pylint: disable=redefined-builtin
633 """The arguments are as described in the description of FieldDescriptor
634 attributes above.
636 Note that containing_type may be None, and may be set later if necessary
637 (to deal with circular references between message types, for example).
638 Likewise for extension_scope.
639 """
640 if create_key is not _internal_create_key:
641 _Deprecated('FieldDescriptor')
643 super(FieldDescriptor, self).__init__(
644 file, options, serialized_options, 'FieldOptions'
645 )
646 self.name = name
647 self.full_name = full_name
648 self._camelcase_name = None
649 if json_name is None:
650 self.json_name = _ToJsonName(name)
651 else:
652 self.json_name = json_name
653 self.index = index
654 self.number = number
655 self._type = type
656 self.cpp_type = cpp_type
657 self._label = label
658 self.has_default_value = has_default_value
659 self.default_value = default_value
660 self.containing_type = containing_type
661 self.message_type = message_type
662 self.enum_type = enum_type
663 self.is_extension = is_extension
664 self.extension_scope = extension_scope
665 self.containing_oneof = containing_oneof
666 if api_implementation.Type() == 'python':
667 self._cdescriptor = None
668 else:
669 if is_extension:
670 self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
671 else:
672 self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
674 @property
675 def _parent(self):
676 if self.containing_oneof:
677 return self.containing_oneof
678 if self.is_extension:
679 return self.extension_scope or self.file
680 return self.containing_type
682 def _InferLegacyFeatures(self, edition, options, features):
683 # pylint: disable=g-import-not-at-top
684 from google.protobuf import descriptor_pb2
686 if edition >= descriptor_pb2.Edition.EDITION_2023:
687 return
689 if self._label == FieldDescriptor.LABEL_REQUIRED:
690 features.field_presence = (
691 descriptor_pb2.FeatureSet.FieldPresence.LEGACY_REQUIRED
692 )
694 if self._type == FieldDescriptor.TYPE_GROUP:
695 features.message_encoding = (
696 descriptor_pb2.FeatureSet.MessageEncoding.DELIMITED
697 )
699 if options.HasField('packed'):
700 features.repeated_field_encoding = (
701 descriptor_pb2.FeatureSet.RepeatedFieldEncoding.PACKED
702 if options.packed
703 else descriptor_pb2.FeatureSet.RepeatedFieldEncoding.EXPANDED
704 )
706 @property
707 def type(self):
708 if (
709 self._GetFeatures().message_encoding
710 == _FEATURESET_MESSAGE_ENCODING_DELIMITED
711 ):
712 return FieldDescriptor.TYPE_GROUP
713 return self._type
715 @type.setter
716 def type(self, val):
717 self._type = val
719 @property
720 def label(self):
721 if (
722 self._GetFeatures().field_presence
723 == _FEATURESET_FIELD_PRESENCE_LEGACY_REQUIRED
724 ):
725 return FieldDescriptor.LABEL_REQUIRED
726 return self._label
728 @property
729 def camelcase_name(self):
730 """Camelcase name of this field.
732 Returns:
733 str: the name in CamelCase.
734 """
735 if self._camelcase_name is None:
736 self._camelcase_name = _ToCamelCase(self.name)
737 return self._camelcase_name
739 @property
740 def has_presence(self):
741 """Whether the field distinguishes between unpopulated and default values.
743 Raises:
744 RuntimeError: singular field that is not linked with message nor file.
745 """
746 if self.label == FieldDescriptor.LABEL_REPEATED:
747 return False
748 if (self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE or
749 self.containing_oneof):
750 return True
752 return (
753 self._GetFeatures().field_presence
754 != _FEATURESET_FIELD_PRESENCE_IMPLICIT
755 )
757 @property
758 def is_packed(self):
759 """Returns if the field is packed."""
760 if self.label != FieldDescriptor.LABEL_REPEATED:
761 return False
762 field_type = self.type
763 if (field_type == FieldDescriptor.TYPE_STRING or
764 field_type == FieldDescriptor.TYPE_GROUP or
765 field_type == FieldDescriptor.TYPE_MESSAGE or
766 field_type == FieldDescriptor.TYPE_BYTES):
767 return False
769 return (
770 self._GetFeatures().repeated_field_encoding
771 == _FEATURESET_REPEATED_FIELD_ENCODING_PACKED
772 )
774 @staticmethod
775 def ProtoTypeToCppProtoType(proto_type):
776 """Converts from a Python proto type to a C++ Proto Type.
778 The Python ProtocolBuffer classes specify both the 'Python' datatype and the
779 'C++' datatype - and they're not the same. This helper method should
780 translate from one to another.
782 Args:
783 proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
784 Returns:
785 int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
786 Raises:
787 TypeTransformationError: when the Python proto type isn't known.
788 """
789 try:
790 return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
791 except KeyError:
792 raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
795class EnumDescriptor(_NestedDescriptorBase):
797 """Descriptor for an enum defined in a .proto file.
799 Attributes:
800 name (str): Name of the enum type.
801 full_name (str): Full name of the type, including package name
802 and any enclosing type(s).
804 values (list[EnumValueDescriptor]): List of the values
805 in this enum.
806 values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`,
807 but indexed by the "name" field of each EnumValueDescriptor.
808 values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`,
809 but indexed by the "number" field of each EnumValueDescriptor.
810 containing_type (Descriptor): Descriptor of the immediate containing
811 type of this enum, or None if this is an enum defined at the
812 top level in a .proto file. Set by Descriptor's constructor
813 if we're passed into one.
814 file (FileDescriptor): Reference to file descriptor.
815 options (descriptor_pb2.EnumOptions): Enum options message or
816 None to use default enum options.
817 """
819 if _USE_C_DESCRIPTORS:
820 _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
822 def __new__(cls, name, full_name, filename, values,
823 containing_type=None, options=None,
824 serialized_options=None, file=None, # pylint: disable=redefined-builtin
825 serialized_start=None, serialized_end=None, create_key=None):
826 _message.Message._CheckCalledFromGeneratedFile()
827 return _message.default_pool.FindEnumTypeByName(full_name)
829 def __init__(self, name, full_name, filename, values,
830 containing_type=None, options=None,
831 serialized_options=None, file=None, # pylint: disable=redefined-builtin
832 serialized_start=None, serialized_end=None, create_key=None):
833 """Arguments are as described in the attribute description above.
835 Note that filename is an obsolete argument, that is not used anymore.
836 Please use file.name to access this as an attribute.
837 """
838 if create_key is not _internal_create_key:
839 _Deprecated('EnumDescriptor')
841 super(EnumDescriptor, self).__init__(
842 options, 'EnumOptions', name, full_name, file,
843 containing_type, serialized_start=serialized_start,
844 serialized_end=serialized_end, serialized_options=serialized_options)
846 self.values = values
847 for value in self.values:
848 value.file = file
849 value.type = self
850 self.values_by_name = dict((v.name, v) for v in values)
851 # Values are reversed to ensure that the first alias is retained.
852 self.values_by_number = dict((v.number, v) for v in reversed(values))
854 @property
855 def _parent(self):
856 return self.containing_type or self.file
858 @property
859 def is_closed(self):
860 """Returns true whether this is a "closed" enum.
862 This means that it:
863 - Has a fixed set of values, rather than being equivalent to an int32.
864 - Encountering values not in this set causes them to be treated as unknown
865 fields.
866 - The first value (i.e., the default) may be nonzero.
868 WARNING: Some runtimes currently have a quirk where non-closed enums are
869 treated as closed when used as the type of fields defined in a
870 `syntax = proto2;` file. This quirk is not present in all runtimes; as of
871 writing, we know that:
873 - C++, Java, and C++-based Python share this quirk.
874 - UPB and UPB-based Python do not.
875 - PHP and Ruby treat all enums as open regardless of declaration.
877 Care should be taken when using this function to respect the target
878 runtime's enum handling quirks.
879 """
880 return self._GetFeatures().enum_type == _FEATURESET_ENUM_TYPE_CLOSED
882 def CopyToProto(self, proto):
883 """Copies this to a descriptor_pb2.EnumDescriptorProto.
885 Args:
886 proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto.
887 """
888 # This function is overridden to give a better doc comment.
889 super(EnumDescriptor, self).CopyToProto(proto)
892class EnumValueDescriptor(DescriptorBase):
894 """Descriptor for a single value within an enum.
896 Attributes:
897 name (str): Name of this value.
898 index (int): Dense, 0-indexed index giving the order that this
899 value appears textually within its enum in the .proto file.
900 number (int): Actual number assigned to this enum value.
901 type (EnumDescriptor): :class:`EnumDescriptor` to which this value
902 belongs. Set by :class:`EnumDescriptor`'s constructor if we're
903 passed into one.
904 options (descriptor_pb2.EnumValueOptions): Enum value options message or
905 None to use default enum value options options.
906 """
908 if _USE_C_DESCRIPTORS:
909 _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
911 def __new__(cls, name, index, number,
912 type=None, # pylint: disable=redefined-builtin
913 options=None, serialized_options=None, create_key=None):
914 _message.Message._CheckCalledFromGeneratedFile()
915 # There is no way we can build a complete EnumValueDescriptor with the
916 # given parameters (the name of the Enum is not known, for example).
917 # Fortunately generated files just pass it to the EnumDescriptor()
918 # constructor, which will ignore it, so returning None is good enough.
919 return None
921 def __init__(self, name, index, number,
922 type=None, # pylint: disable=redefined-builtin
923 options=None, serialized_options=None, create_key=None):
924 """Arguments are as described in the attribute description above."""
925 if create_key is not _internal_create_key:
926 _Deprecated('EnumValueDescriptor')
928 super(EnumValueDescriptor, self).__init__(
929 type.file if type else None,
930 options,
931 serialized_options,
932 'EnumValueOptions',
933 )
934 self.name = name
935 self.index = index
936 self.number = number
937 self.type = type
939 @property
940 def _parent(self):
941 return self.type
944class OneofDescriptor(DescriptorBase):
945 """Descriptor for a oneof field.
947 Attributes:
948 name (str): Name of the oneof field.
949 full_name (str): Full name of the oneof field, including package name.
950 index (int): 0-based index giving the order of the oneof field inside
951 its containing type.
952 containing_type (Descriptor): :class:`Descriptor` of the protocol message
953 type that contains this field. Set by the :class:`Descriptor` constructor
954 if we're passed into one.
955 fields (list[FieldDescriptor]): The list of field descriptors this
956 oneof can contain.
957 """
959 if _USE_C_DESCRIPTORS:
960 _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
962 def __new__(
963 cls, name, full_name, index, containing_type, fields, options=None,
964 serialized_options=None, create_key=None):
965 _message.Message._CheckCalledFromGeneratedFile()
966 return _message.default_pool.FindOneofByName(full_name)
968 def __init__(
969 self, name, full_name, index, containing_type, fields, options=None,
970 serialized_options=None, create_key=None):
971 """Arguments are as described in the attribute description above."""
972 if create_key is not _internal_create_key:
973 _Deprecated('OneofDescriptor')
975 super(OneofDescriptor, self).__init__(
976 containing_type.file if containing_type else None,
977 options,
978 serialized_options,
979 'OneofOptions',
980 )
981 self.name = name
982 self.full_name = full_name
983 self.index = index
984 self.containing_type = containing_type
985 self.fields = fields
987 @property
988 def _parent(self):
989 return self.containing_type
992class ServiceDescriptor(_NestedDescriptorBase):
994 """Descriptor for a service.
996 Attributes:
997 name (str): Name of the service.
998 full_name (str): Full name of the service, including package name.
999 index (int): 0-indexed index giving the order that this services
1000 definition appears within the .proto file.
1001 methods (list[MethodDescriptor]): List of methods provided by this
1002 service.
1003 methods_by_name (dict(str, MethodDescriptor)): Same
1004 :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but
1005 indexed by "name" attribute in each :class:`MethodDescriptor`.
1006 options (descriptor_pb2.ServiceOptions): Service options message or
1007 None to use default service options.
1008 file (FileDescriptor): Reference to file info.
1009 """
1011 if _USE_C_DESCRIPTORS:
1012 _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
1014 def __new__(
1015 cls,
1016 name=None,
1017 full_name=None,
1018 index=None,
1019 methods=None,
1020 options=None,
1021 serialized_options=None,
1022 file=None, # pylint: disable=redefined-builtin
1023 serialized_start=None,
1024 serialized_end=None,
1025 create_key=None):
1026 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
1027 return _message.default_pool.FindServiceByName(full_name)
1029 def __init__(self, name, full_name, index, methods, options=None,
1030 serialized_options=None, file=None, # pylint: disable=redefined-builtin
1031 serialized_start=None, serialized_end=None, create_key=None):
1032 if create_key is not _internal_create_key:
1033 _Deprecated('ServiceDescriptor')
1035 super(ServiceDescriptor, self).__init__(
1036 options, 'ServiceOptions', name, full_name, file,
1037 None, serialized_start=serialized_start,
1038 serialized_end=serialized_end, serialized_options=serialized_options)
1039 self.index = index
1040 self.methods = methods
1041 self.methods_by_name = dict((m.name, m) for m in methods)
1042 # Set the containing service for each method in this service.
1043 for method in self.methods:
1044 method.file = self.file
1045 method.containing_service = self
1047 @property
1048 def _parent(self):
1049 return self.file
1051 def FindMethodByName(self, name):
1052 """Searches for the specified method, and returns its descriptor.
1054 Args:
1055 name (str): Name of the method.
1057 Returns:
1058 MethodDescriptor: The descriptor for the requested method.
1060 Raises:
1061 KeyError: if the method cannot be found in the service.
1062 """
1063 return self.methods_by_name[name]
1065 def CopyToProto(self, proto):
1066 """Copies this to a descriptor_pb2.ServiceDescriptorProto.
1068 Args:
1069 proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto.
1070 """
1071 # This function is overridden to give a better doc comment.
1072 super(ServiceDescriptor, self).CopyToProto(proto)
1075class MethodDescriptor(DescriptorBase):
1077 """Descriptor for a method in a service.
1079 Attributes:
1080 name (str): Name of the method within the service.
1081 full_name (str): Full name of method.
1082 index (int): 0-indexed index of the method inside the service.
1083 containing_service (ServiceDescriptor): The service that contains this
1084 method.
1085 input_type (Descriptor): The descriptor of the message that this method
1086 accepts.
1087 output_type (Descriptor): The descriptor of the message that this method
1088 returns.
1089 client_streaming (bool): Whether this method uses client streaming.
1090 server_streaming (bool): Whether this method uses server streaming.
1091 options (descriptor_pb2.MethodOptions or None): Method options message, or
1092 None to use default method options.
1093 """
1095 if _USE_C_DESCRIPTORS:
1096 _C_DESCRIPTOR_CLASS = _message.MethodDescriptor
1098 def __new__(cls,
1099 name,
1100 full_name,
1101 index,
1102 containing_service,
1103 input_type,
1104 output_type,
1105 client_streaming=False,
1106 server_streaming=False,
1107 options=None,
1108 serialized_options=None,
1109 create_key=None):
1110 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
1111 return _message.default_pool.FindMethodByName(full_name)
1113 def __init__(self,
1114 name,
1115 full_name,
1116 index,
1117 containing_service,
1118 input_type,
1119 output_type,
1120 client_streaming=False,
1121 server_streaming=False,
1122 options=None,
1123 serialized_options=None,
1124 create_key=None):
1125 """The arguments are as described in the description of MethodDescriptor
1126 attributes above.
1128 Note that containing_service may be None, and may be set later if necessary.
1129 """
1130 if create_key is not _internal_create_key:
1131 _Deprecated('MethodDescriptor')
1133 super(MethodDescriptor, self).__init__(
1134 containing_service.file if containing_service else None,
1135 options,
1136 serialized_options,
1137 'MethodOptions',
1138 )
1139 self.name = name
1140 self.full_name = full_name
1141 self.index = index
1142 self.containing_service = containing_service
1143 self.input_type = input_type
1144 self.output_type = output_type
1145 self.client_streaming = client_streaming
1146 self.server_streaming = server_streaming
1148 @property
1149 def _parent(self):
1150 return self.containing_service
1152 def CopyToProto(self, proto):
1153 """Copies this to a descriptor_pb2.MethodDescriptorProto.
1155 Args:
1156 proto (descriptor_pb2.MethodDescriptorProto): An empty descriptor proto.
1158 Raises:
1159 Error: If self couldn't be serialized, due to too few constructor
1160 arguments.
1161 """
1162 if self.containing_service is not None:
1163 from google.protobuf import descriptor_pb2
1164 service_proto = descriptor_pb2.ServiceDescriptorProto()
1165 self.containing_service.CopyToProto(service_proto)
1166 proto.CopyFrom(service_proto.method[self.index])
1167 else:
1168 raise Error('Descriptor does not contain a service.')
1171class FileDescriptor(DescriptorBase):
1172 """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
1174 Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and
1175 :attr:`dependencies` fields are only set by the
1176 :py:mod:`google.protobuf.message_factory` module, and not by the generated
1177 proto code.
1179 Attributes:
1180 name (str): Name of file, relative to root of source tree.
1181 package (str): Name of the package
1182 edition (Edition): Enum value indicating edition of the file
1183 serialized_pb (bytes): Byte string of serialized
1184 :class:`descriptor_pb2.FileDescriptorProto`.
1185 dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`
1186 objects this :class:`FileDescriptor` depends on.
1187 public_dependencies (list[FileDescriptor]): A subset of
1188 :attr:`dependencies`, which were declared as "public".
1189 message_types_by_name (dict(str, Descriptor)): Mapping from message names to
1190 their :class:`Descriptor`.
1191 enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to
1192 their :class:`EnumDescriptor`.
1193 extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension
1194 names declared at file scope to their :class:`FieldDescriptor`.
1195 services_by_name (dict(str, ServiceDescriptor)): Mapping from services'
1196 names to their :class:`ServiceDescriptor`.
1197 pool (DescriptorPool): The pool this descriptor belongs to. When not passed
1198 to the constructor, the global default pool is used.
1199 """
1201 if _USE_C_DESCRIPTORS:
1202 _C_DESCRIPTOR_CLASS = _message.FileDescriptor
1204 def __new__(
1205 cls,
1206 name,
1207 package,
1208 options=None,
1209 serialized_options=None,
1210 serialized_pb=None,
1211 dependencies=None,
1212 public_dependencies=None,
1213 syntax=None,
1214 edition=None,
1215 pool=None,
1216 create_key=None,
1217 ):
1218 # FileDescriptor() is called from various places, not only from generated
1219 # files, to register dynamic proto files and messages.
1220 # pylint: disable=g-explicit-bool-comparison
1221 if serialized_pb:
1222 return _message.default_pool.AddSerializedFile(serialized_pb)
1223 else:
1224 return super(FileDescriptor, cls).__new__(cls)
1226 def __init__(
1227 self,
1228 name,
1229 package,
1230 options=None,
1231 serialized_options=None,
1232 serialized_pb=None,
1233 dependencies=None,
1234 public_dependencies=None,
1235 syntax=None,
1236 edition=None,
1237 pool=None,
1238 create_key=None,
1239 ):
1240 """Constructor."""
1241 if create_key is not _internal_create_key:
1242 _Deprecated('FileDescriptor')
1244 super(FileDescriptor, self).__init__(
1245 self, options, serialized_options, 'FileOptions'
1246 )
1248 if edition and edition != 'EDITION_UNKNOWN':
1249 self._edition = edition
1250 elif syntax == 'proto3':
1251 self._edition = 'EDITION_PROTO3'
1252 else:
1253 self._edition = 'EDITION_PROTO2'
1255 if pool is None:
1256 from google.protobuf import descriptor_pool
1257 pool = descriptor_pool.Default()
1258 self.pool = pool
1259 self.message_types_by_name = {}
1260 self.name = name
1261 self.package = package
1262 self.serialized_pb = serialized_pb
1264 self.enum_types_by_name = {}
1265 self.extensions_by_name = {}
1266 self.services_by_name = {}
1267 self.dependencies = (dependencies or [])
1268 self.public_dependencies = (public_dependencies or [])
1270 def CopyToProto(self, proto):
1271 """Copies this to a descriptor_pb2.FileDescriptorProto.
1273 Args:
1274 proto: An empty descriptor_pb2.FileDescriptorProto.
1275 """
1276 proto.ParseFromString(self.serialized_pb)
1278 @property
1279 def _parent(self):
1280 return None
1283def _ParseOptions(message, string):
1284 """Parses serialized options.
1286 This helper function is used to parse serialized options in generated
1287 proto2 files. It must not be used outside proto2.
1288 """
1289 message.ParseFromString(string)
1290 return message
1293def _ToCamelCase(name):
1294 """Converts name to camel-case and returns it."""
1295 capitalize_next = False
1296 result = []
1298 for c in name:
1299 if c == '_':
1300 if result:
1301 capitalize_next = True
1302 elif capitalize_next:
1303 result.append(c.upper())
1304 capitalize_next = False
1305 else:
1306 result += c
1308 # Lower-case the first letter.
1309 if result and result[0].isupper():
1310 result[0] = result[0].lower()
1311 return ''.join(result)
1314def _OptionsOrNone(descriptor_proto):
1315 """Returns the value of the field `options`, or None if it is not set."""
1316 if descriptor_proto.HasField('options'):
1317 return descriptor_proto.options
1318 else:
1319 return None
1322def _ToJsonName(name):
1323 """Converts name to Json name and returns it."""
1324 capitalize_next = False
1325 result = []
1327 for c in name:
1328 if c == '_':
1329 capitalize_next = True
1330 elif capitalize_next:
1331 result.append(c.upper())
1332 capitalize_next = False
1333 else:
1334 result += c
1336 return ''.join(result)
1339def MakeDescriptor(
1340 desc_proto,
1341 package='',
1342 build_file_if_cpp=True,
1343 syntax=None,
1344 edition=None,
1345 file_desc=None,
1346):
1347 """Make a protobuf Descriptor given a DescriptorProto protobuf.
1349 Handles nested descriptors. Note that this is limited to the scope of defining
1350 a message inside of another message. Composite fields can currently only be
1351 resolved if the message is defined in the same scope as the field.
1353 Args:
1354 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
1355 package: Optional package name for the new message Descriptor (string).
1356 build_file_if_cpp: Update the C++ descriptor pool if api matches. Set to
1357 False on recursion, so no duplicates are created.
1358 syntax: The syntax/semantics that should be used. Set to "proto3" to get
1359 proto3 field presence semantics.
1360 edition: The edition that should be used if syntax is "edition".
1361 file_desc: A FileDescriptor to place this descriptor into.
1363 Returns:
1364 A Descriptor for protobuf messages.
1365 """
1366 # pylint: disable=g-import-not-at-top
1367 from google.protobuf import descriptor_pb2
1369 # Generate a random name for this proto file to prevent conflicts with any
1370 # imported ones. We need to specify a file name so the descriptor pool
1371 # accepts our FileDescriptorProto, but it is not important what that file
1372 # name is actually set to.
1373 proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
1375 if package:
1376 file_name = os.path.join(package.replace('.', '/'), proto_name + '.proto')
1377 else:
1378 file_name = proto_name + '.proto'
1380 if api_implementation.Type() != 'python' and build_file_if_cpp:
1381 # The C++ implementation requires all descriptors to be backed by the same
1382 # definition in the C++ descriptor pool. To do this, we build a
1383 # FileDescriptorProto with the same definition as this descriptor and build
1384 # it into the pool.
1385 file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
1386 file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
1388 if package:
1389 file_descriptor_proto.package = package
1390 file_descriptor_proto.name = file_name
1392 _message.default_pool.Add(file_descriptor_proto)
1393 result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
1395 if _USE_C_DESCRIPTORS:
1396 return result.message_types_by_name[desc_proto.name]
1398 if file_desc is None:
1399 file_desc = FileDescriptor(
1400 pool=None,
1401 name=file_name,
1402 package=package,
1403 syntax=syntax,
1404 edition=edition,
1405 options=None,
1406 serialized_pb='',
1407 dependencies=[],
1408 public_dependencies=[],
1409 create_key=_internal_create_key,
1410 )
1411 full_message_name = [desc_proto.name]
1412 if package: full_message_name.insert(0, package)
1414 # Create Descriptors for enum types
1415 enum_types = {}
1416 for enum_proto in desc_proto.enum_type:
1417 full_name = '.'.join(full_message_name + [enum_proto.name])
1418 enum_desc = EnumDescriptor(
1419 enum_proto.name,
1420 full_name,
1421 None,
1422 [
1423 EnumValueDescriptor(
1424 enum_val.name,
1425 ii,
1426 enum_val.number,
1427 create_key=_internal_create_key,
1428 )
1429 for ii, enum_val in enumerate(enum_proto.value)
1430 ],
1431 file=file_desc,
1432 create_key=_internal_create_key,
1433 )
1434 enum_types[full_name] = enum_desc
1436 # Create Descriptors for nested types
1437 nested_types = {}
1438 for nested_proto in desc_proto.nested_type:
1439 full_name = '.'.join(full_message_name + [nested_proto.name])
1440 # Nested types are just those defined inside of the message, not all types
1441 # used by fields in the message, so no loops are possible here.
1442 nested_desc = MakeDescriptor(
1443 nested_proto,
1444 package='.'.join(full_message_name),
1445 build_file_if_cpp=False,
1446 syntax=syntax,
1447 edition=edition,
1448 file_desc=file_desc,
1449 )
1450 nested_types[full_name] = nested_desc
1452 fields = []
1453 for field_proto in desc_proto.field:
1454 full_name = '.'.join(full_message_name + [field_proto.name])
1455 enum_desc = None
1456 nested_desc = None
1457 if field_proto.json_name:
1458 json_name = field_proto.json_name
1459 else:
1460 json_name = None
1461 if field_proto.HasField('type_name'):
1462 type_name = field_proto.type_name
1463 full_type_name = '.'.join(full_message_name +
1464 [type_name[type_name.rfind('.')+1:]])
1465 if full_type_name in nested_types:
1466 nested_desc = nested_types[full_type_name]
1467 elif full_type_name in enum_types:
1468 enum_desc = enum_types[full_type_name]
1469 # Else type_name references a non-local type, which isn't implemented
1470 field = FieldDescriptor(
1471 field_proto.name,
1472 full_name,
1473 field_proto.number - 1,
1474 field_proto.number,
1475 field_proto.type,
1476 FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
1477 field_proto.label,
1478 None,
1479 nested_desc,
1480 enum_desc,
1481 None,
1482 False,
1483 None,
1484 options=_OptionsOrNone(field_proto),
1485 has_default_value=False,
1486 json_name=json_name,
1487 file=file_desc,
1488 create_key=_internal_create_key,
1489 )
1490 fields.append(field)
1492 desc_name = '.'.join(full_message_name)
1493 return Descriptor(
1494 desc_proto.name,
1495 desc_name,
1496 None,
1497 None,
1498 fields,
1499 list(nested_types.values()),
1500 list(enum_types.values()),
1501 [],
1502 options=_OptionsOrNone(desc_proto),
1503 file=file_desc,
1504 create_key=_internal_create_key,
1505 )