Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/protobuf/descriptor.py: 53%
427 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:32 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 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 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.syntax = syntax or "proto2"
357 self._is_map_entry = is_map_entry
359 @property
360 def fields_by_camelcase_name(self):
361 """Same FieldDescriptor objects as in :attr:`fields`, but indexed by
362 :attr:`FieldDescriptor.camelcase_name`.
363 """
364 if self._fields_by_camelcase_name is None:
365 self._fields_by_camelcase_name = dict(
366 (f.camelcase_name, f) for f in self.fields)
367 return self._fields_by_camelcase_name
369 def EnumValueName(self, enum, value):
370 """Returns the string name of an enum value.
372 This is just a small helper method to simplify a common operation.
374 Args:
375 enum: string name of the Enum.
376 value: int, value of the enum.
378 Returns:
379 string name of the enum value.
381 Raises:
382 KeyError if either the Enum doesn't exist or the value is not a valid
383 value for the enum.
384 """
385 return self.enum_types_by_name[enum].values_by_number[value].name
387 def CopyToProto(self, proto):
388 """Copies this to a descriptor_pb2.DescriptorProto.
390 Args:
391 proto: An empty descriptor_pb2.DescriptorProto.
392 """
393 # This function is overridden to give a better doc comment.
394 super(Descriptor, self).CopyToProto(proto)
397# TODO: We should have aggressive checking here,
398# for example:
399# * If you specify a repeated field, you should not be allowed
400# to specify a default value.
401# * [Other examples here as needed].
402#
403# TODO: for this and other *Descriptor classes, we
404# might also want to lock things down aggressively (e.g.,
405# prevent clients from setting the attributes). Having
406# stronger invariants here in general will reduce the number
407# of runtime checks we must do in reflection.py...
408class FieldDescriptor(DescriptorBase):
410 """Descriptor for a single field in a .proto file.
412 Attributes:
413 name (str): Name of this field, exactly as it appears in .proto.
414 full_name (str): Name of this field, including containing scope. This is
415 particularly relevant for extensions.
416 index (int): Dense, 0-indexed index giving the order that this
417 field textually appears within its message in the .proto file.
418 number (int): Tag number declared for this field in the .proto file.
420 type (int): (One of the TYPE_* constants below) Declared type.
421 cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to
422 represent this field.
424 label (int): (One of the LABEL_* constants below) Tells whether this
425 field is optional, required, or repeated.
426 has_default_value (bool): True if this field has a default value defined,
427 otherwise false.
428 default_value (Varies): Default value of this field. Only
429 meaningful for non-repeated scalar fields. Repeated fields
430 should always set this to [], and non-repeated composite
431 fields should always set this to None.
433 containing_type (Descriptor): Descriptor of the protocol message
434 type that contains this field. Set by the Descriptor constructor
435 if we're passed into one.
436 Somewhat confusingly, for extension fields, this is the
437 descriptor of the EXTENDED message, not the descriptor
438 of the message containing this field. (See is_extension and
439 extension_scope below).
440 message_type (Descriptor): If a composite field, a descriptor
441 of the message type contained in this field. Otherwise, this is None.
442 enum_type (EnumDescriptor): If this field contains an enum, a
443 descriptor of that enum. Otherwise, this is None.
445 is_extension: True iff this describes an extension field.
446 extension_scope (Descriptor): Only meaningful if is_extension is True.
447 Gives the message that immediately contains this extension field.
448 Will be None iff we're a top-level (file-level) extension field.
450 options (descriptor_pb2.FieldOptions): Protocol message field options or
451 None to use default field options.
453 containing_oneof (OneofDescriptor): If the field is a member of a oneof
454 union, contains its descriptor. Otherwise, None.
456 file (FileDescriptor): Reference to file descriptor.
457 """
459 # Must be consistent with C++ FieldDescriptor::Type enum in
460 # descriptor.h.
461 #
462 # TODO: Find a way to eliminate this repetition.
463 TYPE_DOUBLE = 1
464 TYPE_FLOAT = 2
465 TYPE_INT64 = 3
466 TYPE_UINT64 = 4
467 TYPE_INT32 = 5
468 TYPE_FIXED64 = 6
469 TYPE_FIXED32 = 7
470 TYPE_BOOL = 8
471 TYPE_STRING = 9
472 TYPE_GROUP = 10
473 TYPE_MESSAGE = 11
474 TYPE_BYTES = 12
475 TYPE_UINT32 = 13
476 TYPE_ENUM = 14
477 TYPE_SFIXED32 = 15
478 TYPE_SFIXED64 = 16
479 TYPE_SINT32 = 17
480 TYPE_SINT64 = 18
481 MAX_TYPE = 18
483 # Must be consistent with C++ FieldDescriptor::CppType enum in
484 # descriptor.h.
485 #
486 # TODO: Find a way to eliminate this repetition.
487 CPPTYPE_INT32 = 1
488 CPPTYPE_INT64 = 2
489 CPPTYPE_UINT32 = 3
490 CPPTYPE_UINT64 = 4
491 CPPTYPE_DOUBLE = 5
492 CPPTYPE_FLOAT = 6
493 CPPTYPE_BOOL = 7
494 CPPTYPE_ENUM = 8
495 CPPTYPE_STRING = 9
496 CPPTYPE_MESSAGE = 10
497 MAX_CPPTYPE = 10
499 _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
500 TYPE_DOUBLE: CPPTYPE_DOUBLE,
501 TYPE_FLOAT: CPPTYPE_FLOAT,
502 TYPE_ENUM: CPPTYPE_ENUM,
503 TYPE_INT64: CPPTYPE_INT64,
504 TYPE_SINT64: CPPTYPE_INT64,
505 TYPE_SFIXED64: CPPTYPE_INT64,
506 TYPE_UINT64: CPPTYPE_UINT64,
507 TYPE_FIXED64: CPPTYPE_UINT64,
508 TYPE_INT32: CPPTYPE_INT32,
509 TYPE_SFIXED32: CPPTYPE_INT32,
510 TYPE_SINT32: CPPTYPE_INT32,
511 TYPE_UINT32: CPPTYPE_UINT32,
512 TYPE_FIXED32: CPPTYPE_UINT32,
513 TYPE_BYTES: CPPTYPE_STRING,
514 TYPE_STRING: CPPTYPE_STRING,
515 TYPE_BOOL: CPPTYPE_BOOL,
516 TYPE_MESSAGE: CPPTYPE_MESSAGE,
517 TYPE_GROUP: CPPTYPE_MESSAGE
518 }
520 # Must be consistent with C++ FieldDescriptor::Label enum in
521 # descriptor.h.
522 #
523 # TODO: Find a way to eliminate this repetition.
524 LABEL_OPTIONAL = 1
525 LABEL_REQUIRED = 2
526 LABEL_REPEATED = 3
527 MAX_LABEL = 3
529 # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
530 # and kLastReservedNumber in descriptor.h
531 MAX_FIELD_NUMBER = (1 << 29) - 1
532 FIRST_RESERVED_FIELD_NUMBER = 19000
533 LAST_RESERVED_FIELD_NUMBER = 19999
535 if _USE_C_DESCRIPTORS:
536 _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
538 def __new__(cls, name, full_name, index, number, type, cpp_type, label,
539 default_value, message_type, enum_type, containing_type,
540 is_extension, extension_scope, options=None,
541 serialized_options=None,
542 has_default_value=True, containing_oneof=None, json_name=None,
543 file=None, create_key=None): # pylint: disable=redefined-builtin
544 _message.Message._CheckCalledFromGeneratedFile()
545 if is_extension:
546 return _message.default_pool.FindExtensionByName(full_name)
547 else:
548 return _message.default_pool.FindFieldByName(full_name)
550 def __init__(self, name, full_name, index, number, type, cpp_type, label,
551 default_value, message_type, enum_type, containing_type,
552 is_extension, extension_scope, options=None,
553 serialized_options=None,
554 has_default_value=True, containing_oneof=None, json_name=None,
555 file=None, create_key=None): # pylint: disable=redefined-builtin
556 """The arguments are as described in the description of FieldDescriptor
557 attributes above.
559 Note that containing_type may be None, and may be set later if necessary
560 (to deal with circular references between message types, for example).
561 Likewise for extension_scope.
562 """
563 if create_key is not _internal_create_key:
564 _Deprecated('FieldDescriptor')
566 super(FieldDescriptor, self).__init__(
567 file, options, serialized_options, 'FieldOptions'
568 )
569 self.name = name
570 self.full_name = full_name
571 self._camelcase_name = None
572 if json_name is None:
573 self.json_name = _ToJsonName(name)
574 else:
575 self.json_name = json_name
576 self.index = index
577 self.number = number
578 self.type = type
579 self.cpp_type = cpp_type
580 self.label = label
581 self.has_default_value = has_default_value
582 self.default_value = default_value
583 self.containing_type = containing_type
584 self.message_type = message_type
585 self.enum_type = enum_type
586 self.is_extension = is_extension
587 self.extension_scope = extension_scope
588 self.containing_oneof = containing_oneof
589 if api_implementation.Type() == 'python':
590 self._cdescriptor = None
591 else:
592 if is_extension:
593 self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
594 else:
595 self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
597 @property
598 def camelcase_name(self):
599 """Camelcase name of this field.
601 Returns:
602 str: the name in CamelCase.
603 """
604 if self._camelcase_name is None:
605 self._camelcase_name = _ToCamelCase(self.name)
606 return self._camelcase_name
608 @property
609 def has_presence(self):
610 """Whether the field distinguishes between unpopulated and default values.
612 Raises:
613 RuntimeError: singular field that is not linked with message nor file.
614 """
615 if self.label == FieldDescriptor.LABEL_REPEATED:
616 return False
617 if (self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE or
618 self.containing_oneof):
619 return True
620 # self.containing_type is used here instead of self.file for legacy
621 # compatibility. FieldDescriptor.file was added in cl/153110619
622 # Some old/generated code didn't link file to FieldDescriptor.
623 # TODO: remove syntax usage b/240619313
624 return self.containing_type.syntax == 'proto2'
626 @property
627 def is_packed(self):
628 """Returns if the field is packed."""
629 if self.label != FieldDescriptor.LABEL_REPEATED:
630 return False
631 field_type = self.type
632 if (field_type == FieldDescriptor.TYPE_STRING or
633 field_type == FieldDescriptor.TYPE_GROUP or
634 field_type == FieldDescriptor.TYPE_MESSAGE or
635 field_type == FieldDescriptor.TYPE_BYTES):
636 return False
637 if self.containing_type.syntax == 'proto2':
638 return self.has_options and self.GetOptions().packed
639 else:
640 return (not self.has_options or
641 not self.GetOptions().HasField('packed') or
642 self.GetOptions().packed)
644 @staticmethod
645 def ProtoTypeToCppProtoType(proto_type):
646 """Converts from a Python proto type to a C++ Proto Type.
648 The Python ProtocolBuffer classes specify both the 'Python' datatype and the
649 'C++' datatype - and they're not the same. This helper method should
650 translate from one to another.
652 Args:
653 proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
654 Returns:
655 int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
656 Raises:
657 TypeTransformationError: when the Python proto type isn't known.
658 """
659 try:
660 return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
661 except KeyError:
662 raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
665class EnumDescriptor(_NestedDescriptorBase):
667 """Descriptor for an enum defined in a .proto file.
669 Attributes:
670 name (str): Name of the enum type.
671 full_name (str): Full name of the type, including package name
672 and any enclosing type(s).
674 values (list[EnumValueDescriptor]): List of the values
675 in this enum.
676 values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`,
677 but indexed by the "name" field of each EnumValueDescriptor.
678 values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`,
679 but indexed by the "number" field of each EnumValueDescriptor.
680 containing_type (Descriptor): Descriptor of the immediate containing
681 type of this enum, or None if this is an enum defined at the
682 top level in a .proto file. Set by Descriptor's constructor
683 if we're passed into one.
684 file (FileDescriptor): Reference to file descriptor.
685 options (descriptor_pb2.EnumOptions): Enum options message or
686 None to use default enum options.
687 """
689 if _USE_C_DESCRIPTORS:
690 _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
692 def __new__(cls, name, full_name, filename, values,
693 containing_type=None, options=None,
694 serialized_options=None, file=None, # pylint: disable=redefined-builtin
695 serialized_start=None, serialized_end=None, create_key=None):
696 _message.Message._CheckCalledFromGeneratedFile()
697 return _message.default_pool.FindEnumTypeByName(full_name)
699 def __init__(self, name, full_name, filename, values,
700 containing_type=None, options=None,
701 serialized_options=None, file=None, # pylint: disable=redefined-builtin
702 serialized_start=None, serialized_end=None, create_key=None):
703 """Arguments are as described in the attribute description above.
705 Note that filename is an obsolete argument, that is not used anymore.
706 Please use file.name to access this as an attribute.
707 """
708 if create_key is not _internal_create_key:
709 _Deprecated('EnumDescriptor')
711 super(EnumDescriptor, self).__init__(
712 options, 'EnumOptions', name, full_name, file,
713 containing_type, serialized_start=serialized_start,
714 serialized_end=serialized_end, serialized_options=serialized_options)
716 self.values = values
717 for value in self.values:
718 value.file = file
719 value.type = self
720 self.values_by_name = dict((v.name, v) for v in values)
721 # Values are reversed to ensure that the first alias is retained.
722 self.values_by_number = dict((v.number, v) for v in reversed(values))
724 @property
725 def is_closed(self):
726 """Returns true whether this is a "closed" enum.
728 This means that it:
729 - Has a fixed set of values, rather than being equivalent to an int32.
730 - Encountering values not in this set causes them to be treated as unknown
731 fields.
732 - The first value (i.e., the default) may be nonzero.
734 WARNING: Some runtimes currently have a quirk where non-closed enums are
735 treated as closed when used as the type of fields defined in a
736 `syntax = proto2;` file. This quirk is not present in all runtimes; as of
737 writing, we know that:
739 - C++, Java, and C++-based Python share this quirk.
740 - UPB and UPB-based Python do not.
741 - PHP and Ruby treat all enums as open regardless of declaration.
743 Care should be taken when using this function to respect the target
744 runtime's enum handling quirks.
745 """
746 return self.file.syntax == 'proto2'
748 def CopyToProto(self, proto):
749 """Copies this to a descriptor_pb2.EnumDescriptorProto.
751 Args:
752 proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto.
753 """
754 # This function is overridden to give a better doc comment.
755 super(EnumDescriptor, self).CopyToProto(proto)
758class EnumValueDescriptor(DescriptorBase):
760 """Descriptor for a single value within an enum.
762 Attributes:
763 name (str): Name of this value.
764 index (int): Dense, 0-indexed index giving the order that this
765 value appears textually within its enum in the .proto file.
766 number (int): Actual number assigned to this enum value.
767 type (EnumDescriptor): :class:`EnumDescriptor` to which this value
768 belongs. Set by :class:`EnumDescriptor`'s constructor if we're
769 passed into one.
770 options (descriptor_pb2.EnumValueOptions): Enum value options message or
771 None to use default enum value options options.
772 """
774 if _USE_C_DESCRIPTORS:
775 _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
777 def __new__(cls, name, index, number,
778 type=None, # pylint: disable=redefined-builtin
779 options=None, serialized_options=None, create_key=None):
780 _message.Message._CheckCalledFromGeneratedFile()
781 # There is no way we can build a complete EnumValueDescriptor with the
782 # given parameters (the name of the Enum is not known, for example).
783 # Fortunately generated files just pass it to the EnumDescriptor()
784 # constructor, which will ignore it, so returning None is good enough.
785 return None
787 def __init__(self, name, index, number,
788 type=None, # pylint: disable=redefined-builtin
789 options=None, serialized_options=None, create_key=None):
790 """Arguments are as described in the attribute description above."""
791 if create_key is not _internal_create_key:
792 _Deprecated('EnumValueDescriptor')
794 super(EnumValueDescriptor, self).__init__(
795 type.file if type else None,
796 options,
797 serialized_options,
798 'EnumValueOptions',
799 )
800 self.name = name
801 self.index = index
802 self.number = number
803 self.type = type
806class OneofDescriptor(DescriptorBase):
807 """Descriptor for a oneof field.
809 Attributes:
810 name (str): Name of the oneof field.
811 full_name (str): Full name of the oneof field, including package name.
812 index (int): 0-based index giving the order of the oneof field inside
813 its containing type.
814 containing_type (Descriptor): :class:`Descriptor` of the protocol message
815 type that contains this field. Set by the :class:`Descriptor` constructor
816 if we're passed into one.
817 fields (list[FieldDescriptor]): The list of field descriptors this
818 oneof can contain.
819 """
821 if _USE_C_DESCRIPTORS:
822 _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
824 def __new__(
825 cls, name, full_name, index, containing_type, fields, options=None,
826 serialized_options=None, create_key=None):
827 _message.Message._CheckCalledFromGeneratedFile()
828 return _message.default_pool.FindOneofByName(full_name)
830 def __init__(
831 self, name, full_name, index, containing_type, fields, options=None,
832 serialized_options=None, create_key=None):
833 """Arguments are as described in the attribute description above."""
834 if create_key is not _internal_create_key:
835 _Deprecated('OneofDescriptor')
837 super(OneofDescriptor, self).__init__(
838 containing_type.file if containing_type else None,
839 options,
840 serialized_options,
841 'OneofOptions',
842 )
843 self.name = name
844 self.full_name = full_name
845 self.index = index
846 self.containing_type = containing_type
847 self.fields = fields
850class ServiceDescriptor(_NestedDescriptorBase):
852 """Descriptor for a service.
854 Attributes:
855 name (str): Name of the service.
856 full_name (str): Full name of the service, including package name.
857 index (int): 0-indexed index giving the order that this services
858 definition appears within the .proto file.
859 methods (list[MethodDescriptor]): List of methods provided by this
860 service.
861 methods_by_name (dict(str, MethodDescriptor)): Same
862 :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but
863 indexed by "name" attribute in each :class:`MethodDescriptor`.
864 options (descriptor_pb2.ServiceOptions): Service options message or
865 None to use default service options.
866 file (FileDescriptor): Reference to file info.
867 """
869 if _USE_C_DESCRIPTORS:
870 _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
872 def __new__(
873 cls,
874 name=None,
875 full_name=None,
876 index=None,
877 methods=None,
878 options=None,
879 serialized_options=None,
880 file=None, # pylint: disable=redefined-builtin
881 serialized_start=None,
882 serialized_end=None,
883 create_key=None):
884 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
885 return _message.default_pool.FindServiceByName(full_name)
887 def __init__(self, name, full_name, index, methods, options=None,
888 serialized_options=None, file=None, # pylint: disable=redefined-builtin
889 serialized_start=None, serialized_end=None, create_key=None):
890 if create_key is not _internal_create_key:
891 _Deprecated('ServiceDescriptor')
893 super(ServiceDescriptor, self).__init__(
894 options, 'ServiceOptions', name, full_name, file,
895 None, serialized_start=serialized_start,
896 serialized_end=serialized_end, serialized_options=serialized_options)
897 self.index = index
898 self.methods = methods
899 self.methods_by_name = dict((m.name, m) for m in methods)
900 # Set the containing service for each method in this service.
901 for method in self.methods:
902 method.file = self.file
903 method.containing_service = self
905 def FindMethodByName(self, name):
906 """Searches for the specified method, and returns its descriptor.
908 Args:
909 name (str): Name of the method.
911 Returns:
912 MethodDescriptor: The descriptor for the requested method.
914 Raises:
915 KeyError: if the method cannot be found in the service.
916 """
917 return self.methods_by_name[name]
919 def CopyToProto(self, proto):
920 """Copies this to a descriptor_pb2.ServiceDescriptorProto.
922 Args:
923 proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto.
924 """
925 # This function is overridden to give a better doc comment.
926 super(ServiceDescriptor, self).CopyToProto(proto)
929class MethodDescriptor(DescriptorBase):
931 """Descriptor for a method in a service.
933 Attributes:
934 name (str): Name of the method within the service.
935 full_name (str): Full name of method.
936 index (int): 0-indexed index of the method inside the service.
937 containing_service (ServiceDescriptor): The service that contains this
938 method.
939 input_type (Descriptor): The descriptor of the message that this method
940 accepts.
941 output_type (Descriptor): The descriptor of the message that this method
942 returns.
943 client_streaming (bool): Whether this method uses client streaming.
944 server_streaming (bool): Whether this method uses server streaming.
945 options (descriptor_pb2.MethodOptions or None): Method options message, or
946 None to use default method options.
947 """
949 if _USE_C_DESCRIPTORS:
950 _C_DESCRIPTOR_CLASS = _message.MethodDescriptor
952 def __new__(cls,
953 name,
954 full_name,
955 index,
956 containing_service,
957 input_type,
958 output_type,
959 client_streaming=False,
960 server_streaming=False,
961 options=None,
962 serialized_options=None,
963 create_key=None):
964 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
965 return _message.default_pool.FindMethodByName(full_name)
967 def __init__(self,
968 name,
969 full_name,
970 index,
971 containing_service,
972 input_type,
973 output_type,
974 client_streaming=False,
975 server_streaming=False,
976 options=None,
977 serialized_options=None,
978 create_key=None):
979 """The arguments are as described in the description of MethodDescriptor
980 attributes above.
982 Note that containing_service may be None, and may be set later if necessary.
983 """
984 if create_key is not _internal_create_key:
985 _Deprecated('MethodDescriptor')
987 super(MethodDescriptor, self).__init__(
988 containing_service.file if containing_service else None,
989 options,
990 serialized_options,
991 'MethodOptions',
992 )
993 self.name = name
994 self.full_name = full_name
995 self.index = index
996 self.containing_service = containing_service
997 self.input_type = input_type
998 self.output_type = output_type
999 self.client_streaming = client_streaming
1000 self.server_streaming = server_streaming
1002 def CopyToProto(self, proto):
1003 """Copies this to a descriptor_pb2.MethodDescriptorProto.
1005 Args:
1006 proto (descriptor_pb2.MethodDescriptorProto): An empty descriptor proto.
1008 Raises:
1009 Error: If self couldn't be serialized, due to too few constructor
1010 arguments.
1011 """
1012 if self.containing_service is not None:
1013 from google.protobuf import descriptor_pb2
1014 service_proto = descriptor_pb2.ServiceDescriptorProto()
1015 self.containing_service.CopyToProto(service_proto)
1016 proto.CopyFrom(service_proto.method[self.index])
1017 else:
1018 raise Error('Descriptor does not contain a service.')
1021class FileDescriptor(DescriptorBase):
1022 """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
1024 Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and
1025 :attr:`dependencies` fields are only set by the
1026 :py:mod:`google.protobuf.message_factory` module, and not by the generated
1027 proto code.
1029 Attributes:
1030 name (str): Name of file, relative to root of source tree.
1031 package (str): Name of the package
1032 syntax (str): string indicating syntax of the file (can be "proto2" or
1033 "proto3")
1034 serialized_pb (bytes): Byte string of serialized
1035 :class:`descriptor_pb2.FileDescriptorProto`.
1036 dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`
1037 objects this :class:`FileDescriptor` depends on.
1038 public_dependencies (list[FileDescriptor]): A subset of
1039 :attr:`dependencies`, which were declared as "public".
1040 message_types_by_name (dict(str, Descriptor)): Mapping from message names
1041 to their :class:`Descriptor`.
1042 enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to
1043 their :class:`EnumDescriptor`.
1044 extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension
1045 names declared at file scope to their :class:`FieldDescriptor`.
1046 services_by_name (dict(str, ServiceDescriptor)): Mapping from services'
1047 names to their :class:`ServiceDescriptor`.
1048 pool (DescriptorPool): The pool this descriptor belongs to. When not
1049 passed to the constructor, the global default pool is used.
1050 """
1052 if _USE_C_DESCRIPTORS:
1053 _C_DESCRIPTOR_CLASS = _message.FileDescriptor
1055 def __new__(cls, name, package, options=None,
1056 serialized_options=None, serialized_pb=None,
1057 dependencies=None, public_dependencies=None,
1058 syntax=None, pool=None, create_key=None):
1059 # FileDescriptor() is called from various places, not only from generated
1060 # files, to register dynamic proto files and messages.
1061 # pylint: disable=g-explicit-bool-comparison
1062 if serialized_pb:
1063 return _message.default_pool.AddSerializedFile(serialized_pb)
1064 else:
1065 return super(FileDescriptor, cls).__new__(cls)
1067 def __init__(self, name, package, options=None,
1068 serialized_options=None, serialized_pb=None,
1069 dependencies=None, public_dependencies=None,
1070 syntax=None, pool=None, create_key=None):
1071 """Constructor."""
1072 if create_key is not _internal_create_key:
1073 _Deprecated('FileDescriptor')
1075 super(FileDescriptor, self).__init__(
1076 None, options, serialized_options, 'FileOptions'
1077 )
1079 if pool is None:
1080 from google.protobuf import descriptor_pool
1081 pool = descriptor_pool.Default()
1082 self.pool = pool
1083 self.message_types_by_name = {}
1084 self.name = name
1085 self.package = package
1086 self.syntax = syntax or "proto2"
1087 self.serialized_pb = serialized_pb
1089 self.enum_types_by_name = {}
1090 self.extensions_by_name = {}
1091 self.services_by_name = {}
1092 self.dependencies = (dependencies or [])
1093 self.public_dependencies = (public_dependencies or [])
1095 def CopyToProto(self, proto):
1096 """Copies this to a descriptor_pb2.FileDescriptorProto.
1098 Args:
1099 proto: An empty descriptor_pb2.FileDescriptorProto.
1100 """
1101 proto.ParseFromString(self.serialized_pb)
1104def _ParseOptions(message, string):
1105 """Parses serialized options.
1107 This helper function is used to parse serialized options in generated
1108 proto2 files. It must not be used outside proto2.
1109 """
1110 message.ParseFromString(string)
1111 return message
1114def _ToCamelCase(name):
1115 """Converts name to camel-case and returns it."""
1116 capitalize_next = False
1117 result = []
1119 for c in name:
1120 if c == '_':
1121 if result:
1122 capitalize_next = True
1123 elif capitalize_next:
1124 result.append(c.upper())
1125 capitalize_next = False
1126 else:
1127 result += c
1129 # Lower-case the first letter.
1130 if result and result[0].isupper():
1131 result[0] = result[0].lower()
1132 return ''.join(result)
1135def _OptionsOrNone(descriptor_proto):
1136 """Returns the value of the field `options`, or None if it is not set."""
1137 if descriptor_proto.HasField('options'):
1138 return descriptor_proto.options
1139 else:
1140 return None
1143def _ToJsonName(name):
1144 """Converts name to Json name and returns it."""
1145 capitalize_next = False
1146 result = []
1148 for c in name:
1149 if c == '_':
1150 capitalize_next = True
1151 elif capitalize_next:
1152 result.append(c.upper())
1153 capitalize_next = False
1154 else:
1155 result += c
1157 return ''.join(result)
1160def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
1161 syntax=None):
1162 """Make a protobuf Descriptor given a DescriptorProto protobuf.
1164 Handles nested descriptors. Note that this is limited to the scope of defining
1165 a message inside of another message. Composite fields can currently only be
1166 resolved if the message is defined in the same scope as the field.
1168 Args:
1169 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
1170 package: Optional package name for the new message Descriptor (string).
1171 build_file_if_cpp: Update the C++ descriptor pool if api matches.
1172 Set to False on recursion, so no duplicates are created.
1173 syntax: The syntax/semantics that should be used. Set to "proto3" to get
1174 proto3 field presence semantics.
1175 Returns:
1176 A Descriptor for protobuf messages.
1177 """
1178 if api_implementation.Type() != 'python' and build_file_if_cpp:
1179 # The C++ implementation requires all descriptors to be backed by the same
1180 # definition in the C++ descriptor pool. To do this, we build a
1181 # FileDescriptorProto with the same definition as this descriptor and build
1182 # it into the pool.
1183 from google.protobuf import descriptor_pb2
1184 file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
1185 file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
1187 # Generate a random name for this proto file to prevent conflicts with any
1188 # imported ones. We need to specify a file name so the descriptor pool
1189 # accepts our FileDescriptorProto, but it is not important what that file
1190 # name is actually set to.
1191 proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
1193 if package:
1194 file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
1195 proto_name + '.proto')
1196 file_descriptor_proto.package = package
1197 else:
1198 file_descriptor_proto.name = proto_name + '.proto'
1200 _message.default_pool.Add(file_descriptor_proto)
1201 result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
1203 if _USE_C_DESCRIPTORS:
1204 return result.message_types_by_name[desc_proto.name]
1206 full_message_name = [desc_proto.name]
1207 if package: full_message_name.insert(0, package)
1209 # Create Descriptors for enum types
1210 enum_types = {}
1211 for enum_proto in desc_proto.enum_type:
1212 full_name = '.'.join(full_message_name + [enum_proto.name])
1213 enum_desc = EnumDescriptor(
1214 enum_proto.name, full_name, None, [
1215 EnumValueDescriptor(enum_val.name, ii, enum_val.number,
1216 create_key=_internal_create_key)
1217 for ii, enum_val in enumerate(enum_proto.value)],
1218 create_key=_internal_create_key)
1219 enum_types[full_name] = enum_desc
1221 # Create Descriptors for nested types
1222 nested_types = {}
1223 for nested_proto in desc_proto.nested_type:
1224 full_name = '.'.join(full_message_name + [nested_proto.name])
1225 # Nested types are just those defined inside of the message, not all types
1226 # used by fields in the message, so no loops are possible here.
1227 nested_desc = MakeDescriptor(nested_proto,
1228 package='.'.join(full_message_name),
1229 build_file_if_cpp=False,
1230 syntax=syntax)
1231 nested_types[full_name] = nested_desc
1233 fields = []
1234 for field_proto in desc_proto.field:
1235 full_name = '.'.join(full_message_name + [field_proto.name])
1236 enum_desc = None
1237 nested_desc = None
1238 if field_proto.json_name:
1239 json_name = field_proto.json_name
1240 else:
1241 json_name = None
1242 if field_proto.HasField('type_name'):
1243 type_name = field_proto.type_name
1244 full_type_name = '.'.join(full_message_name +
1245 [type_name[type_name.rfind('.')+1:]])
1246 if full_type_name in nested_types:
1247 nested_desc = nested_types[full_type_name]
1248 elif full_type_name in enum_types:
1249 enum_desc = enum_types[full_type_name]
1250 # Else type_name references a non-local type, which isn't implemented
1251 field = FieldDescriptor(
1252 field_proto.name, full_name, field_proto.number - 1,
1253 field_proto.number, field_proto.type,
1254 FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
1255 field_proto.label, None, nested_desc, enum_desc, None, False, None,
1256 options=_OptionsOrNone(field_proto), has_default_value=False,
1257 json_name=json_name, create_key=_internal_create_key)
1258 fields.append(field)
1260 desc_name = '.'.join(full_message_name)
1261 return Descriptor(desc_proto.name, desc_name, None, None, fields,
1262 list(nested_types.values()), list(enum_types.values()), [],
1263 options=_OptionsOrNone(desc_proto),
1264 create_key=_internal_create_key)