Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/protobuf/descriptor.py: 32%
423 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc. All rights reserved.
3# https://developers.google.com/protocol-buffers/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31"""Descriptors essentially contain exactly the information found in a .proto
32file, in types that make this information accessible in Python.
33"""
35__author__ = 'robinson@google.com (Will Robinson)'
37import threading
38import warnings
40from google.protobuf.internal import api_implementation
42_USE_C_DESCRIPTORS = False
43if api_implementation.Type() != 'python':
44 # Used by MakeDescriptor in cpp mode
45 import binascii
46 import os
47 # pylint: disable=protected-access
48 _message = api_implementation._c_module
49 # TODO(jieluo): Remove this import after fix api_implementation
50 if _message is None:
51 from google.protobuf.pyext import _message
52 _USE_C_DESCRIPTORS = True
55class Error(Exception):
56 """Base error for this module."""
59class TypeTransformationError(Error):
60 """Error transforming between python proto type and corresponding C++ type."""
63if _USE_C_DESCRIPTORS:
64 # This metaclass allows to override the behavior of code like
65 # isinstance(my_descriptor, FieldDescriptor)
66 # and make it return True when the descriptor is an instance of the extension
67 # type written in C++.
68 class DescriptorMetaclass(type):
70 def __instancecheck__(cls, obj):
71 if super(DescriptorMetaclass, cls).__instancecheck__(obj):
72 return True
73 if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
74 return True
75 return False
76else:
77 # The standard metaclass; nothing changes.
78 DescriptorMetaclass = type
81class _Lock(object):
82 """Wrapper class of threading.Lock(), which is allowed by 'with'."""
84 def __new__(cls):
85 self = object.__new__(cls)
86 self._lock = threading.Lock() # pylint: disable=protected-access
87 return self
89 def __enter__(self):
90 self._lock.acquire()
92 def __exit__(self, exc_type, exc_value, exc_tb):
93 self._lock.release()
96_lock = threading.Lock()
99def _Deprecated(name):
100 if _Deprecated.count > 0:
101 _Deprecated.count -= 1
102 warnings.warn(
103 'Call to deprecated create function %s(). Note: Create unlinked '
104 'descriptors is going to go away. Please use get/find descriptors from '
105 'generated code or query the descriptor_pool.'
106 % name,
107 category=DeprecationWarning, stacklevel=3)
110# Deprecated warnings will print 100 times at most which should be enough for
111# users to notice and do not cause timeout.
112_Deprecated.count = 100
115_internal_create_key = object()
118class DescriptorBase(metaclass=DescriptorMetaclass):
120 """Descriptors base class.
122 This class is the base of all descriptor classes. It provides common options
123 related functionality.
125 Attributes:
126 has_options: True if the descriptor has non-default options. Usually it
127 is not necessary to read this -- just call GetOptions() which will
128 happily return the default instance. However, it's sometimes useful
129 for efficiency, and also useful inside the protobuf implementation to
130 avoid some bootstrapping issues.
131 """
133 if _USE_C_DESCRIPTORS:
134 # The class, or tuple of classes, that are considered as "virtual
135 # subclasses" of this descriptor class.
136 _C_DESCRIPTOR_CLASS = ()
138 def __init__(self, options, serialized_options, options_class_name):
139 """Initialize the descriptor given its options message and the name of the
140 class of the options message. The name of the class is required in case
141 the options message is None and has to be created.
142 """
143 self._options = options
144 self._options_class_name = options_class_name
145 self._serialized_options = serialized_options
147 # Does this descriptor have non-default options?
148 self.has_options = (options is not None) or (serialized_options is not None)
150 def _SetOptions(self, options, options_class_name):
151 """Sets the descriptor's options
153 This function is used in generated proto2 files to update descriptor
154 options. It must not be used outside proto2.
155 """
156 self._options = options
157 self._options_class_name = options_class_name
159 # Does this descriptor have non-default options?
160 self.has_options = options is not None
162 def GetOptions(self):
163 """Retrieves descriptor options.
165 This method returns the options set or creates the default options for the
166 descriptor.
167 """
168 if self._options:
169 return self._options
171 from google.protobuf import descriptor_pb2
172 try:
173 options_class = getattr(descriptor_pb2,
174 self._options_class_name)
175 except AttributeError:
176 raise RuntimeError('Unknown options class name %s!' %
177 (self._options_class_name))
179 with _lock:
180 if self._serialized_options is None:
181 self._options = options_class()
182 else:
183 self._options = _ParseOptions(options_class(),
184 self._serialized_options)
186 return self._options
189class _NestedDescriptorBase(DescriptorBase):
190 """Common class for descriptors that can be nested."""
192 def __init__(self, options, options_class_name, name, full_name,
193 file, containing_type, serialized_start=None,
194 serialized_end=None, serialized_options=None):
195 """Constructor.
197 Args:
198 options: Protocol message options or None
199 to use default message options.
200 options_class_name (str): The class name of the above options.
201 name (str): Name of this protocol message type.
202 full_name (str): Fully-qualified name of this protocol message type,
203 which will include protocol "package" name and the name of any
204 enclosing types.
205 file (FileDescriptor): Reference to file info.
206 containing_type: if provided, this is a nested descriptor, with this
207 descriptor as parent, otherwise None.
208 serialized_start: The start index (inclusive) in block in the
209 file.serialized_pb that describes this descriptor.
210 serialized_end: The end index (exclusive) in block in the
211 file.serialized_pb that describes this descriptor.
212 serialized_options: Protocol message serialized options or None.
213 """
214 super(_NestedDescriptorBase, self).__init__(
215 options, serialized_options, options_class_name)
217 self.name = name
218 # TODO(falk): Add function to calculate full_name instead of having it in
219 # memory?
220 self.full_name = full_name
221 self.file = file
222 self.containing_type = containing_type
224 self._serialized_start = serialized_start
225 self._serialized_end = serialized_end
227 def CopyToProto(self, proto):
228 """Copies this to the matching proto in descriptor_pb2.
230 Args:
231 proto: An empty proto instance from descriptor_pb2.
233 Raises:
234 Error: If self couldn't be serialized, due to to few constructor
235 arguments.
236 """
237 if (self.file is not None and
238 self._serialized_start is not None and
239 self._serialized_end is not None):
240 proto.ParseFromString(self.file.serialized_pb[
241 self._serialized_start:self._serialized_end])
242 else:
243 raise Error('Descriptor does not contain serialization.')
246class Descriptor(_NestedDescriptorBase):
248 """Descriptor for a protocol message type.
250 Attributes:
251 name (str): Name of this protocol message type.
252 full_name (str): Fully-qualified name of this protocol message type,
253 which will include protocol "package" name and the name of any
254 enclosing types.
255 containing_type (Descriptor): Reference to the descriptor of the type
256 containing us, or None if this is top-level.
257 fields (list[FieldDescriptor]): Field descriptors for all fields in
258 this type.
259 fields_by_number (dict(int, FieldDescriptor)): Same
260 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed
261 by "number" attribute in each FieldDescriptor.
262 fields_by_name (dict(str, FieldDescriptor)): Same
263 :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by
264 "name" attribute in each :class:`FieldDescriptor`.
265 nested_types (list[Descriptor]): Descriptor references
266 for all protocol message types nested within this one.
267 nested_types_by_name (dict(str, Descriptor)): Same Descriptor
268 objects as in :attr:`nested_types`, but indexed by "name" attribute
269 in each Descriptor.
270 enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references
271 for all enums contained within this type.
272 enum_types_by_name (dict(str, EnumDescriptor)): Same
273 :class:`EnumDescriptor` objects as in :attr:`enum_types`, but
274 indexed by "name" attribute in each EnumDescriptor.
275 enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping
276 from enum value name to :class:`EnumValueDescriptor` for that value.
277 extensions (list[FieldDescriptor]): All extensions defined directly
278 within this message type (NOT within a nested type).
279 extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor
280 objects as :attr:`extensions`, but indexed by "name" attribute of each
281 FieldDescriptor.
282 is_extendable (bool): Does this type define any extension ranges?
283 oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields
284 in this message.
285 oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in
286 :attr:`oneofs`, but indexed by "name" attribute.
287 file (FileDescriptor): Reference to file descriptor.
289 """
291 if _USE_C_DESCRIPTORS:
292 _C_DESCRIPTOR_CLASS = _message.Descriptor
294 def __new__(
295 cls,
296 name=None,
297 full_name=None,
298 filename=None,
299 containing_type=None,
300 fields=None,
301 nested_types=None,
302 enum_types=None,
303 extensions=None,
304 options=None,
305 serialized_options=None,
306 is_extendable=True,
307 extension_ranges=None,
308 oneofs=None,
309 file=None, # pylint: disable=redefined-builtin
310 serialized_start=None,
311 serialized_end=None,
312 syntax=None,
313 create_key=None):
314 _message.Message._CheckCalledFromGeneratedFile()
315 return _message.default_pool.FindMessageTypeByName(full_name)
317 # NOTE(tmarek): The file argument redefining a builtin is nothing we can
318 # fix right now since we don't know how many clients already rely on the
319 # name of the argument.
320 def __init__(self, name, full_name, filename, containing_type, fields,
321 nested_types, enum_types, extensions, options=None,
322 serialized_options=None,
323 is_extendable=True, extension_ranges=None, oneofs=None,
324 file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin
325 syntax=None, create_key=None):
326 """Arguments to __init__() are as described in the description
327 of Descriptor fields above.
329 Note that filename is an obsolete argument, that is not used anymore.
330 Please use file.name to access this as an attribute.
331 """
332 if create_key is not _internal_create_key:
333 _Deprecated('Descriptor')
335 super(Descriptor, self).__init__(
336 options, 'MessageOptions', name, full_name, file,
337 containing_type, serialized_start=serialized_start,
338 serialized_end=serialized_end, serialized_options=serialized_options)
340 # We have fields in addition to fields_by_name and fields_by_number,
341 # so that:
342 # 1. Clients can index fields by "order in which they're listed."
343 # 2. Clients can easily iterate over all fields with the terse
344 # syntax: for f in descriptor.fields: ...
345 self.fields = fields
346 for field in self.fields:
347 field.containing_type = self
348 self.fields_by_number = dict((f.number, f) for f in fields)
349 self.fields_by_name = dict((f.name, f) for f in fields)
350 self._fields_by_camelcase_name = None
352 self.nested_types = nested_types
353 for nested_type in nested_types:
354 nested_type.containing_type = self
355 self.nested_types_by_name = dict((t.name, t) for t in nested_types)
357 self.enum_types = enum_types
358 for enum_type in self.enum_types:
359 enum_type.containing_type = self
360 self.enum_types_by_name = dict((t.name, t) for t in enum_types)
361 self.enum_values_by_name = dict(
362 (v.name, v) for t in enum_types for v in t.values)
364 self.extensions = extensions
365 for extension in self.extensions:
366 extension.extension_scope = self
367 self.extensions_by_name = dict((f.name, f) for f in extensions)
368 self.is_extendable = is_extendable
369 self.extension_ranges = extension_ranges
370 self.oneofs = oneofs if oneofs is not None else []
371 self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
372 for oneof in self.oneofs:
373 oneof.containing_type = self
374 self.syntax = syntax or "proto2"
376 @property
377 def fields_by_camelcase_name(self):
378 """Same FieldDescriptor objects as in :attr:`fields`, but indexed by
379 :attr:`FieldDescriptor.camelcase_name`.
380 """
381 if self._fields_by_camelcase_name is None:
382 self._fields_by_camelcase_name = dict(
383 (f.camelcase_name, f) for f in self.fields)
384 return self._fields_by_camelcase_name
386 def EnumValueName(self, enum, value):
387 """Returns the string name of an enum value.
389 This is just a small helper method to simplify a common operation.
391 Args:
392 enum: string name of the Enum.
393 value: int, value of the enum.
395 Returns:
396 string name of the enum value.
398 Raises:
399 KeyError if either the Enum doesn't exist or the value is not a valid
400 value for the enum.
401 """
402 return self.enum_types_by_name[enum].values_by_number[value].name
404 def CopyToProto(self, proto):
405 """Copies this to a descriptor_pb2.DescriptorProto.
407 Args:
408 proto: An empty descriptor_pb2.DescriptorProto.
409 """
410 # This function is overridden to give a better doc comment.
411 super(Descriptor, self).CopyToProto(proto)
414# TODO(robinson): We should have aggressive checking here,
415# for example:
416# * If you specify a repeated field, you should not be allowed
417# to specify a default value.
418# * [Other examples here as needed].
419#
420# TODO(robinson): for this and other *Descriptor classes, we
421# might also want to lock things down aggressively (e.g.,
422# prevent clients from setting the attributes). Having
423# stronger invariants here in general will reduce the number
424# of runtime checks we must do in reflection.py...
425class FieldDescriptor(DescriptorBase):
427 """Descriptor for a single field in a .proto file.
429 Attributes:
430 name (str): Name of this field, exactly as it appears in .proto.
431 full_name (str): Name of this field, including containing scope. This is
432 particularly relevant for extensions.
433 index (int): Dense, 0-indexed index giving the order that this
434 field textually appears within its message in the .proto file.
435 number (int): Tag number declared for this field in the .proto file.
437 type (int): (One of the TYPE_* constants below) Declared type.
438 cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to
439 represent this field.
441 label (int): (One of the LABEL_* constants below) Tells whether this
442 field is optional, required, or repeated.
443 has_default_value (bool): True if this field has a default value defined,
444 otherwise false.
445 default_value (Varies): Default value of this field. Only
446 meaningful for non-repeated scalar fields. Repeated fields
447 should always set this to [], and non-repeated composite
448 fields should always set this to None.
450 containing_type (Descriptor): Descriptor of the protocol message
451 type that contains this field. Set by the Descriptor constructor
452 if we're passed into one.
453 Somewhat confusingly, for extension fields, this is the
454 descriptor of the EXTENDED message, not the descriptor
455 of the message containing this field. (See is_extension and
456 extension_scope below).
457 message_type (Descriptor): If a composite field, a descriptor
458 of the message type contained in this field. Otherwise, this is None.
459 enum_type (EnumDescriptor): If this field contains an enum, a
460 descriptor of that enum. Otherwise, this is None.
462 is_extension: True iff this describes an extension field.
463 extension_scope (Descriptor): Only meaningful if is_extension is True.
464 Gives the message that immediately contains this extension field.
465 Will be None iff we're a top-level (file-level) extension field.
467 options (descriptor_pb2.FieldOptions): Protocol message field options or
468 None to use default field options.
470 containing_oneof (OneofDescriptor): If the field is a member of a oneof
471 union, contains its descriptor. Otherwise, None.
473 file (FileDescriptor): Reference to file descriptor.
474 """
476 # Must be consistent with C++ FieldDescriptor::Type enum in
477 # descriptor.h.
478 #
479 # TODO(robinson): Find a way to eliminate this repetition.
480 TYPE_DOUBLE = 1
481 TYPE_FLOAT = 2
482 TYPE_INT64 = 3
483 TYPE_UINT64 = 4
484 TYPE_INT32 = 5
485 TYPE_FIXED64 = 6
486 TYPE_FIXED32 = 7
487 TYPE_BOOL = 8
488 TYPE_STRING = 9
489 TYPE_GROUP = 10
490 TYPE_MESSAGE = 11
491 TYPE_BYTES = 12
492 TYPE_UINT32 = 13
493 TYPE_ENUM = 14
494 TYPE_SFIXED32 = 15
495 TYPE_SFIXED64 = 16
496 TYPE_SINT32 = 17
497 TYPE_SINT64 = 18
498 MAX_TYPE = 18
500 # Must be consistent with C++ FieldDescriptor::CppType enum in
501 # descriptor.h.
502 #
503 # TODO(robinson): Find a way to eliminate this repetition.
504 CPPTYPE_INT32 = 1
505 CPPTYPE_INT64 = 2
506 CPPTYPE_UINT32 = 3
507 CPPTYPE_UINT64 = 4
508 CPPTYPE_DOUBLE = 5
509 CPPTYPE_FLOAT = 6
510 CPPTYPE_BOOL = 7
511 CPPTYPE_ENUM = 8
512 CPPTYPE_STRING = 9
513 CPPTYPE_MESSAGE = 10
514 MAX_CPPTYPE = 10
516 _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
517 TYPE_DOUBLE: CPPTYPE_DOUBLE,
518 TYPE_FLOAT: CPPTYPE_FLOAT,
519 TYPE_ENUM: CPPTYPE_ENUM,
520 TYPE_INT64: CPPTYPE_INT64,
521 TYPE_SINT64: CPPTYPE_INT64,
522 TYPE_SFIXED64: CPPTYPE_INT64,
523 TYPE_UINT64: CPPTYPE_UINT64,
524 TYPE_FIXED64: CPPTYPE_UINT64,
525 TYPE_INT32: CPPTYPE_INT32,
526 TYPE_SFIXED32: CPPTYPE_INT32,
527 TYPE_SINT32: CPPTYPE_INT32,
528 TYPE_UINT32: CPPTYPE_UINT32,
529 TYPE_FIXED32: CPPTYPE_UINT32,
530 TYPE_BYTES: CPPTYPE_STRING,
531 TYPE_STRING: CPPTYPE_STRING,
532 TYPE_BOOL: CPPTYPE_BOOL,
533 TYPE_MESSAGE: CPPTYPE_MESSAGE,
534 TYPE_GROUP: CPPTYPE_MESSAGE
535 }
537 # Must be consistent with C++ FieldDescriptor::Label enum in
538 # descriptor.h.
539 #
540 # TODO(robinson): Find a way to eliminate this repetition.
541 LABEL_OPTIONAL = 1
542 LABEL_REQUIRED = 2
543 LABEL_REPEATED = 3
544 MAX_LABEL = 3
546 # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber,
547 # and kLastReservedNumber in descriptor.h
548 MAX_FIELD_NUMBER = (1 << 29) - 1
549 FIRST_RESERVED_FIELD_NUMBER = 19000
550 LAST_RESERVED_FIELD_NUMBER = 19999
552 if _USE_C_DESCRIPTORS:
553 _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
555 def __new__(cls, name, full_name, index, number, type, cpp_type, label,
556 default_value, message_type, enum_type, containing_type,
557 is_extension, extension_scope, options=None,
558 serialized_options=None,
559 has_default_value=True, containing_oneof=None, json_name=None,
560 file=None, create_key=None): # pylint: disable=redefined-builtin
561 _message.Message._CheckCalledFromGeneratedFile()
562 if is_extension:
563 return _message.default_pool.FindExtensionByName(full_name)
564 else:
565 return _message.default_pool.FindFieldByName(full_name)
567 def __init__(self, name, full_name, index, number, type, cpp_type, label,
568 default_value, message_type, enum_type, containing_type,
569 is_extension, extension_scope, options=None,
570 serialized_options=None,
571 has_default_value=True, containing_oneof=None, json_name=None,
572 file=None, create_key=None): # pylint: disable=redefined-builtin
573 """The arguments are as described in the description of FieldDescriptor
574 attributes above.
576 Note that containing_type may be None, and may be set later if necessary
577 (to deal with circular references between message types, for example).
578 Likewise for extension_scope.
579 """
580 if create_key is not _internal_create_key:
581 _Deprecated('FieldDescriptor')
583 super(FieldDescriptor, self).__init__(
584 options, serialized_options, 'FieldOptions')
585 self.name = name
586 self.full_name = full_name
587 self.file = file
588 self._camelcase_name = None
589 if json_name is None:
590 self.json_name = _ToJsonName(name)
591 else:
592 self.json_name = json_name
593 self.index = index
594 self.number = number
595 self.type = type
596 self.cpp_type = cpp_type
597 self.label = label
598 self.has_default_value = has_default_value
599 self.default_value = default_value
600 self.containing_type = containing_type
601 self.message_type = message_type
602 self.enum_type = enum_type
603 self.is_extension = is_extension
604 self.extension_scope = extension_scope
605 self.containing_oneof = containing_oneof
606 if api_implementation.Type() == 'python':
607 self._cdescriptor = None
608 else:
609 if is_extension:
610 self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
611 else:
612 self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
614 @property
615 def camelcase_name(self):
616 """Camelcase name of this field.
618 Returns:
619 str: the name in CamelCase.
620 """
621 if self._camelcase_name is None:
622 self._camelcase_name = _ToCamelCase(self.name)
623 return self._camelcase_name
625 @property
626 def has_presence(self):
627 """Whether the field distinguishes between unpopulated and default values.
629 Raises:
630 RuntimeError: singular field that is not linked with message nor file.
631 """
632 if self.label == FieldDescriptor.LABEL_REPEATED:
633 return False
634 if (self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE or
635 self.containing_oneof):
636 return True
637 # self.containing_type is used here instead of self.file for legacy
638 # compatibility. FieldDescriptor.file was added in cl/153110619
639 # Some old/generated code didn't link file to FieldDescriptor.
640 # TODO(jieluo): remove syntax usage b/240619313
641 return self.containing_type.syntax == 'proto2'
643 @property
644 def is_packed(self):
645 """Returns if the field is packed."""
646 if self.label != FieldDescriptor.LABEL_REPEATED:
647 return False
648 field_type = self.type
649 if (field_type == FieldDescriptor.TYPE_STRING or
650 field_type == FieldDescriptor.TYPE_GROUP or
651 field_type == FieldDescriptor.TYPE_MESSAGE or
652 field_type == FieldDescriptor.TYPE_BYTES):
653 return False
654 if self.containing_type.syntax == 'proto2':
655 return self.has_options and self.GetOptions().packed
656 else:
657 return (not self.has_options or
658 not self.GetOptions().HasField('packed') or
659 self.GetOptions().packed)
661 @staticmethod
662 def ProtoTypeToCppProtoType(proto_type):
663 """Converts from a Python proto type to a C++ Proto Type.
665 The Python ProtocolBuffer classes specify both the 'Python' datatype and the
666 'C++' datatype - and they're not the same. This helper method should
667 translate from one to another.
669 Args:
670 proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
671 Returns:
672 int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
673 Raises:
674 TypeTransformationError: when the Python proto type isn't known.
675 """
676 try:
677 return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
678 except KeyError:
679 raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
682class EnumDescriptor(_NestedDescriptorBase):
684 """Descriptor for an enum defined in a .proto file.
686 Attributes:
687 name (str): Name of the enum type.
688 full_name (str): Full name of the type, including package name
689 and any enclosing type(s).
691 values (list[EnumValueDescriptor]): List of the values
692 in this enum.
693 values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`,
694 but indexed by the "name" field of each EnumValueDescriptor.
695 values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`,
696 but indexed by the "number" field of each EnumValueDescriptor.
697 containing_type (Descriptor): Descriptor of the immediate containing
698 type of this enum, or None if this is an enum defined at the
699 top level in a .proto file. Set by Descriptor's constructor
700 if we're passed into one.
701 file (FileDescriptor): Reference to file descriptor.
702 options (descriptor_pb2.EnumOptions): Enum options message or
703 None to use default enum options.
704 """
706 if _USE_C_DESCRIPTORS:
707 _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
709 def __new__(cls, name, full_name, filename, values,
710 containing_type=None, options=None,
711 serialized_options=None, file=None, # pylint: disable=redefined-builtin
712 serialized_start=None, serialized_end=None, create_key=None):
713 _message.Message._CheckCalledFromGeneratedFile()
714 return _message.default_pool.FindEnumTypeByName(full_name)
716 def __init__(self, name, full_name, filename, values,
717 containing_type=None, options=None,
718 serialized_options=None, file=None, # pylint: disable=redefined-builtin
719 serialized_start=None, serialized_end=None, create_key=None):
720 """Arguments are as described in the attribute description above.
722 Note that filename is an obsolete argument, that is not used anymore.
723 Please use file.name to access this as an attribute.
724 """
725 if create_key is not _internal_create_key:
726 _Deprecated('EnumDescriptor')
728 super(EnumDescriptor, self).__init__(
729 options, 'EnumOptions', name, full_name, file,
730 containing_type, serialized_start=serialized_start,
731 serialized_end=serialized_end, serialized_options=serialized_options)
733 self.values = values
734 for value in self.values:
735 value.type = self
736 self.values_by_name = dict((v.name, v) for v in values)
737 # Values are reversed to ensure that the first alias is retained.
738 self.values_by_number = dict((v.number, v) for v in reversed(values))
740 @property
741 def is_closed(self):
742 """Returns true whether this is a "closed" enum.
744 This means that it:
745 - Has a fixed set of values, rather than being equivalent to an int32.
746 - Encountering values not in this set causes them to be treated as unknown
747 fields.
748 - The first value (i.e., the default) may be nonzero.
750 WARNING: Some runtimes currently have a quirk where non-closed enums are
751 treated as closed when used as the type of fields defined in a
752 `syntax = proto2;` file. This quirk is not present in all runtimes; as of
753 writing, we know that:
755 - C++, Java, and C++-based Python share this quirk.
756 - UPB and UPB-based Python do not.
757 - PHP and Ruby treat all enums as open regardless of declaration.
759 Care should be taken when using this function to respect the target
760 runtime's enum handling quirks.
761 """
762 return self.file.syntax == 'proto2'
764 def CopyToProto(self, proto):
765 """Copies this to a descriptor_pb2.EnumDescriptorProto.
767 Args:
768 proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto.
769 """
770 # This function is overridden to give a better doc comment.
771 super(EnumDescriptor, self).CopyToProto(proto)
774class EnumValueDescriptor(DescriptorBase):
776 """Descriptor for a single value within an enum.
778 Attributes:
779 name (str): Name of this value.
780 index (int): Dense, 0-indexed index giving the order that this
781 value appears textually within its enum in the .proto file.
782 number (int): Actual number assigned to this enum value.
783 type (EnumDescriptor): :class:`EnumDescriptor` to which this value
784 belongs. Set by :class:`EnumDescriptor`'s constructor if we're
785 passed into one.
786 options (descriptor_pb2.EnumValueOptions): Enum value options message or
787 None to use default enum value options options.
788 """
790 if _USE_C_DESCRIPTORS:
791 _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
793 def __new__(cls, name, index, number,
794 type=None, # pylint: disable=redefined-builtin
795 options=None, serialized_options=None, create_key=None):
796 _message.Message._CheckCalledFromGeneratedFile()
797 # There is no way we can build a complete EnumValueDescriptor with the
798 # given parameters (the name of the Enum is not known, for example).
799 # Fortunately generated files just pass it to the EnumDescriptor()
800 # constructor, which will ignore it, so returning None is good enough.
801 return None
803 def __init__(self, name, index, number,
804 type=None, # pylint: disable=redefined-builtin
805 options=None, serialized_options=None, create_key=None):
806 """Arguments are as described in the attribute description above."""
807 if create_key is not _internal_create_key:
808 _Deprecated('EnumValueDescriptor')
810 super(EnumValueDescriptor, self).__init__(
811 options, serialized_options, 'EnumValueOptions')
812 self.name = name
813 self.index = index
814 self.number = number
815 self.type = type
818class OneofDescriptor(DescriptorBase):
819 """Descriptor for a oneof field.
821 Attributes:
822 name (str): Name of the oneof field.
823 full_name (str): Full name of the oneof field, including package name.
824 index (int): 0-based index giving the order of the oneof field inside
825 its containing type.
826 containing_type (Descriptor): :class:`Descriptor` of the protocol message
827 type that contains this field. Set by the :class:`Descriptor` constructor
828 if we're passed into one.
829 fields (list[FieldDescriptor]): The list of field descriptors this
830 oneof can contain.
831 """
833 if _USE_C_DESCRIPTORS:
834 _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
836 def __new__(
837 cls, name, full_name, index, containing_type, fields, options=None,
838 serialized_options=None, create_key=None):
839 _message.Message._CheckCalledFromGeneratedFile()
840 return _message.default_pool.FindOneofByName(full_name)
842 def __init__(
843 self, name, full_name, index, containing_type, fields, options=None,
844 serialized_options=None, create_key=None):
845 """Arguments are as described in the attribute description above."""
846 if create_key is not _internal_create_key:
847 _Deprecated('OneofDescriptor')
849 super(OneofDescriptor, self).__init__(
850 options, serialized_options, 'OneofOptions')
851 self.name = name
852 self.full_name = full_name
853 self.index = index
854 self.containing_type = containing_type
855 self.fields = fields
858class ServiceDescriptor(_NestedDescriptorBase):
860 """Descriptor for a service.
862 Attributes:
863 name (str): Name of the service.
864 full_name (str): Full name of the service, including package name.
865 index (int): 0-indexed index giving the order that this services
866 definition appears within the .proto file.
867 methods (list[MethodDescriptor]): List of methods provided by this
868 service.
869 methods_by_name (dict(str, MethodDescriptor)): Same
870 :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but
871 indexed by "name" attribute in each :class:`MethodDescriptor`.
872 options (descriptor_pb2.ServiceOptions): Service options message or
873 None to use default service options.
874 file (FileDescriptor): Reference to file info.
875 """
877 if _USE_C_DESCRIPTORS:
878 _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
880 def __new__(
881 cls,
882 name=None,
883 full_name=None,
884 index=None,
885 methods=None,
886 options=None,
887 serialized_options=None,
888 file=None, # pylint: disable=redefined-builtin
889 serialized_start=None,
890 serialized_end=None,
891 create_key=None):
892 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
893 return _message.default_pool.FindServiceByName(full_name)
895 def __init__(self, name, full_name, index, methods, options=None,
896 serialized_options=None, file=None, # pylint: disable=redefined-builtin
897 serialized_start=None, serialized_end=None, create_key=None):
898 if create_key is not _internal_create_key:
899 _Deprecated('ServiceDescriptor')
901 super(ServiceDescriptor, self).__init__(
902 options, 'ServiceOptions', name, full_name, file,
903 None, serialized_start=serialized_start,
904 serialized_end=serialized_end, serialized_options=serialized_options)
905 self.index = index
906 self.methods = methods
907 self.methods_by_name = dict((m.name, m) for m in methods)
908 # Set the containing service for each method in this service.
909 for method in self.methods:
910 method.containing_service = self
912 def FindMethodByName(self, name):
913 """Searches for the specified method, and returns its descriptor.
915 Args:
916 name (str): Name of the method.
918 Returns:
919 MethodDescriptor: The descriptor for the requested method.
921 Raises:
922 KeyError: if the method cannot be found in the service.
923 """
924 return self.methods_by_name[name]
926 def CopyToProto(self, proto):
927 """Copies this to a descriptor_pb2.ServiceDescriptorProto.
929 Args:
930 proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto.
931 """
932 # This function is overridden to give a better doc comment.
933 super(ServiceDescriptor, self).CopyToProto(proto)
936class MethodDescriptor(DescriptorBase):
938 """Descriptor for a method in a service.
940 Attributes:
941 name (str): Name of the method within the service.
942 full_name (str): Full name of method.
943 index (int): 0-indexed index of the method inside the service.
944 containing_service (ServiceDescriptor): The service that contains this
945 method.
946 input_type (Descriptor): The descriptor of the message that this method
947 accepts.
948 output_type (Descriptor): The descriptor of the message that this method
949 returns.
950 client_streaming (bool): Whether this method uses client streaming.
951 server_streaming (bool): Whether this method uses server streaming.
952 options (descriptor_pb2.MethodOptions or None): Method options message, or
953 None to use default method options.
954 """
956 if _USE_C_DESCRIPTORS:
957 _C_DESCRIPTOR_CLASS = _message.MethodDescriptor
959 def __new__(cls,
960 name,
961 full_name,
962 index,
963 containing_service,
964 input_type,
965 output_type,
966 client_streaming=False,
967 server_streaming=False,
968 options=None,
969 serialized_options=None,
970 create_key=None):
971 _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
972 return _message.default_pool.FindMethodByName(full_name)
974 def __init__(self,
975 name,
976 full_name,
977 index,
978 containing_service,
979 input_type,
980 output_type,
981 client_streaming=False,
982 server_streaming=False,
983 options=None,
984 serialized_options=None,
985 create_key=None):
986 """The arguments are as described in the description of MethodDescriptor
987 attributes above.
989 Note that containing_service may be None, and may be set later if necessary.
990 """
991 if create_key is not _internal_create_key:
992 _Deprecated('MethodDescriptor')
994 super(MethodDescriptor, self).__init__(
995 options, serialized_options, 'MethodOptions')
996 self.name = name
997 self.full_name = full_name
998 self.index = index
999 self.containing_service = containing_service
1000 self.input_type = input_type
1001 self.output_type = output_type
1002 self.client_streaming = client_streaming
1003 self.server_streaming = server_streaming
1005 def CopyToProto(self, proto):
1006 """Copies this to a descriptor_pb2.MethodDescriptorProto.
1008 Args:
1009 proto (descriptor_pb2.MethodDescriptorProto): An empty descriptor proto.
1011 Raises:
1012 Error: If self couldn't be serialized, due to too few constructor
1013 arguments.
1014 """
1015 if self.containing_service is not None:
1016 from google.protobuf import descriptor_pb2
1017 service_proto = descriptor_pb2.ServiceDescriptorProto()
1018 self.containing_service.CopyToProto(service_proto)
1019 proto.CopyFrom(service_proto.method[self.index])
1020 else:
1021 raise Error('Descriptor does not contain a service.')
1024class FileDescriptor(DescriptorBase):
1025 """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
1027 Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and
1028 :attr:`dependencies` fields are only set by the
1029 :py:mod:`google.protobuf.message_factory` module, and not by the generated
1030 proto code.
1032 Attributes:
1033 name (str): Name of file, relative to root of source tree.
1034 package (str): Name of the package
1035 syntax (str): string indicating syntax of the file (can be "proto2" or
1036 "proto3")
1037 serialized_pb (bytes): Byte string of serialized
1038 :class:`descriptor_pb2.FileDescriptorProto`.
1039 dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`
1040 objects this :class:`FileDescriptor` depends on.
1041 public_dependencies (list[FileDescriptor]): A subset of
1042 :attr:`dependencies`, which were declared as "public".
1043 message_types_by_name (dict(str, Descriptor)): Mapping from message names
1044 to their :class:`Descriptor`.
1045 enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to
1046 their :class:`EnumDescriptor`.
1047 extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension
1048 names declared at file scope to their :class:`FieldDescriptor`.
1049 services_by_name (dict(str, ServiceDescriptor)): Mapping from services'
1050 names to their :class:`ServiceDescriptor`.
1051 pool (DescriptorPool): The pool this descriptor belongs to. When not
1052 passed to the constructor, the global default pool is used.
1053 """
1055 if _USE_C_DESCRIPTORS:
1056 _C_DESCRIPTOR_CLASS = _message.FileDescriptor
1058 def __new__(cls, name, package, options=None,
1059 serialized_options=None, serialized_pb=None,
1060 dependencies=None, public_dependencies=None,
1061 syntax=None, pool=None, create_key=None):
1062 # FileDescriptor() is called from various places, not only from generated
1063 # files, to register dynamic proto files and messages.
1064 # pylint: disable=g-explicit-bool-comparison
1065 if serialized_pb:
1066 return _message.default_pool.AddSerializedFile(serialized_pb)
1067 else:
1068 return super(FileDescriptor, cls).__new__(cls)
1070 def __init__(self, name, package, options=None,
1071 serialized_options=None, serialized_pb=None,
1072 dependencies=None, public_dependencies=None,
1073 syntax=None, pool=None, create_key=None):
1074 """Constructor."""
1075 if create_key is not _internal_create_key:
1076 _Deprecated('FileDescriptor')
1078 super(FileDescriptor, self).__init__(
1079 options, serialized_options, 'FileOptions')
1081 if pool is None:
1082 from google.protobuf import descriptor_pool
1083 pool = descriptor_pool.Default()
1084 self.pool = pool
1085 self.message_types_by_name = {}
1086 self.name = name
1087 self.package = package
1088 self.syntax = syntax or "proto2"
1089 self.serialized_pb = serialized_pb
1091 self.enum_types_by_name = {}
1092 self.extensions_by_name = {}
1093 self.services_by_name = {}
1094 self.dependencies = (dependencies or [])
1095 self.public_dependencies = (public_dependencies or [])
1097 def CopyToProto(self, proto):
1098 """Copies this to a descriptor_pb2.FileDescriptorProto.
1100 Args:
1101 proto: An empty descriptor_pb2.FileDescriptorProto.
1102 """
1103 proto.ParseFromString(self.serialized_pb)
1106def _ParseOptions(message, string):
1107 """Parses serialized options.
1109 This helper function is used to parse serialized options in generated
1110 proto2 files. It must not be used outside proto2.
1111 """
1112 message.ParseFromString(string)
1113 return message
1116def _ToCamelCase(name):
1117 """Converts name to camel-case and returns it."""
1118 capitalize_next = False
1119 result = []
1121 for c in name:
1122 if c == '_':
1123 if result:
1124 capitalize_next = True
1125 elif capitalize_next:
1126 result.append(c.upper())
1127 capitalize_next = False
1128 else:
1129 result += c
1131 # Lower-case the first letter.
1132 if result and result[0].isupper():
1133 result[0] = result[0].lower()
1134 return ''.join(result)
1137def _OptionsOrNone(descriptor_proto):
1138 """Returns the value of the field `options`, or None if it is not set."""
1139 if descriptor_proto.HasField('options'):
1140 return descriptor_proto.options
1141 else:
1142 return None
1145def _ToJsonName(name):
1146 """Converts name to Json name and returns it."""
1147 capitalize_next = False
1148 result = []
1150 for c in name:
1151 if c == '_':
1152 capitalize_next = True
1153 elif capitalize_next:
1154 result.append(c.upper())
1155 capitalize_next = False
1156 else:
1157 result += c
1159 return ''.join(result)
1162def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
1163 syntax=None):
1164 """Make a protobuf Descriptor given a DescriptorProto protobuf.
1166 Handles nested descriptors. Note that this is limited to the scope of defining
1167 a message inside of another message. Composite fields can currently only be
1168 resolved if the message is defined in the same scope as the field.
1170 Args:
1171 desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
1172 package: Optional package name for the new message Descriptor (string).
1173 build_file_if_cpp: Update the C++ descriptor pool if api matches.
1174 Set to False on recursion, so no duplicates are created.
1175 syntax: The syntax/semantics that should be used. Set to "proto3" to get
1176 proto3 field presence semantics.
1177 Returns:
1178 A Descriptor for protobuf messages.
1179 """
1180 if api_implementation.Type() != 'python' and build_file_if_cpp:
1181 # The C++ implementation requires all descriptors to be backed by the same
1182 # definition in the C++ descriptor pool. To do this, we build a
1183 # FileDescriptorProto with the same definition as this descriptor and build
1184 # it into the pool.
1185 from google.protobuf import descriptor_pb2
1186 file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
1187 file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
1189 # Generate a random name for this proto file to prevent conflicts with any
1190 # imported ones. We need to specify a file name so the descriptor pool
1191 # accepts our FileDescriptorProto, but it is not important what that file
1192 # name is actually set to.
1193 proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
1195 if package:
1196 file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
1197 proto_name + '.proto')
1198 file_descriptor_proto.package = package
1199 else:
1200 file_descriptor_proto.name = proto_name + '.proto'
1202 _message.default_pool.Add(file_descriptor_proto)
1203 result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
1205 if _USE_C_DESCRIPTORS:
1206 return result.message_types_by_name[desc_proto.name]
1208 full_message_name = [desc_proto.name]
1209 if package: full_message_name.insert(0, package)
1211 # Create Descriptors for enum types
1212 enum_types = {}
1213 for enum_proto in desc_proto.enum_type:
1214 full_name = '.'.join(full_message_name + [enum_proto.name])
1215 enum_desc = EnumDescriptor(
1216 enum_proto.name, full_name, None, [
1217 EnumValueDescriptor(enum_val.name, ii, enum_val.number,
1218 create_key=_internal_create_key)
1219 for ii, enum_val in enumerate(enum_proto.value)],
1220 create_key=_internal_create_key)
1221 enum_types[full_name] = enum_desc
1223 # Create Descriptors for nested types
1224 nested_types = {}
1225 for nested_proto in desc_proto.nested_type:
1226 full_name = '.'.join(full_message_name + [nested_proto.name])
1227 # Nested types are just those defined inside of the message, not all types
1228 # used by fields in the message, so no loops are possible here.
1229 nested_desc = MakeDescriptor(nested_proto,
1230 package='.'.join(full_message_name),
1231 build_file_if_cpp=False,
1232 syntax=syntax)
1233 nested_types[full_name] = nested_desc
1235 fields = []
1236 for field_proto in desc_proto.field:
1237 full_name = '.'.join(full_message_name + [field_proto.name])
1238 enum_desc = None
1239 nested_desc = None
1240 if field_proto.json_name:
1241 json_name = field_proto.json_name
1242 else:
1243 json_name = None
1244 if field_proto.HasField('type_name'):
1245 type_name = field_proto.type_name
1246 full_type_name = '.'.join(full_message_name +
1247 [type_name[type_name.rfind('.')+1:]])
1248 if full_type_name in nested_types:
1249 nested_desc = nested_types[full_type_name]
1250 elif full_type_name in enum_types:
1251 enum_desc = enum_types[full_type_name]
1252 # Else type_name references a non-local type, which isn't implemented
1253 field = FieldDescriptor(
1254 field_proto.name, full_name, field_proto.number - 1,
1255 field_proto.number, field_proto.type,
1256 FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
1257 field_proto.label, None, nested_desc, enum_desc, None, False, None,
1258 options=_OptionsOrNone(field_proto), has_default_value=False,
1259 json_name=json_name, create_key=_internal_create_key)
1260 fields.append(field)
1262 desc_name = '.'.join(full_message_name)
1263 return Descriptor(desc_proto.name, desc_name, None, None, fields,
1264 list(nested_types.values()), list(enum_types.values()), [],
1265 options=_OptionsOrNone(desc_proto),
1266 create_key=_internal_create_key)