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