Voice et bot modif

This commit is contained in:
pi 2026-06-16 17:09:34 +00:00
parent 189d56026b
commit 7333a22bcd
10774 changed files with 634644 additions and 933308 deletions

View file

@ -7,4 +7,4 @@
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '6.33.4'
__version__ = '7.35.1'

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/any.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/any.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/api.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/api.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/compiler/plugin.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/compiler/plugin.proto'
)

View file

@ -791,17 +791,6 @@ class FieldDescriptor(DescriptorBase):
def type(self, val):
self._type = val
@property
def label(self):
_Deprecated('label property', 'is_required or is_repeated properties')
if (
self._GetFeatures().field_presence
== _FEATURESET_FIELD_PRESENCE_LEGACY_REQUIRED
):
return FieldDescriptor.LABEL_REQUIRED
return self._label
@property
def is_required(self):
"""Returns if the field is required."""

View file

@ -9,6 +9,7 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
from typing import Dict, Iterator, Optional
import warnings
@ -23,11 +24,15 @@ class DescriptorDatabaseConflictingDefinitionError(Error):
class DescriptorDatabase(object):
"""A container accepting FileDescriptorProtos and maps DescriptorProtos."""
def __init__(self):
self._file_desc_protos_by_file = {}
self._file_desc_protos_by_symbol = {}
def __init__(self) -> None:
self._file_desc_protos_by_file: Dict[
str, 'descriptor_pb2.FileDescriptorProto'
] = {}
self._file_desc_protos_by_symbol: Dict[
str, 'descriptor_pb2.FileDescriptorProto'
] = {}
def Add(self, file_desc_proto):
def Add(self, file_desc_proto: 'descriptor_pb2.FileDescriptorProto') -> None:
"""Adds the FileDescriptorProto and its types to this database.
Args:
@ -71,7 +76,7 @@ class DescriptorDatabase(object):
file_desc_proto,
)
def FindFileByName(self, name):
def FindFileByName(self, name: str) -> 'descriptor_pb2.FileDescriptorProto':
"""Finds the file descriptor proto by file name.
Typically the file name is a relative path ending to a .proto file. The
@ -90,7 +95,9 @@ class DescriptorDatabase(object):
return self._file_desc_protos_by_file[name]
def FindFileContainingSymbol(self, symbol):
def FindFileContainingSymbol(
self, symbol: str
) -> 'descriptor_pb2.FileDescriptorProto':
"""Finds the file descriptor proto containing the specified symbol.
The symbol should be a fully qualified name including the file descriptor's
@ -135,15 +142,19 @@ class DescriptorDatabase(object):
# Raise the original symbol as a KeyError for better diagnostics.
raise KeyError(symbol)
def FindFileContainingExtension(self, extendee_name, extension_number):
def FindFileContainingExtension(
self, extendee_name: str, extension_number: int # pylint: disable=unused-argument
) -> Optional['descriptor_pb2.FileDescriptorProto']:
# TODO: implement this API.
return None
def FindAllExtensionNumbers(self, extendee_name):
def FindAllExtensionNumbers(self, extendee_name: str) -> list[int]: # pylint: disable=unused-argument
# TODO: implement this API.
return []
def _AddSymbol(self, name, file_desc_proto):
def _AddSymbol(
self, name: str, file_desc_proto: 'descriptor_pb2.FileDescriptorProto'
) -> None:
if name in self._file_desc_protos_by_symbol:
warn_msg = ('Conflict register for file "' + file_desc_proto.name +
'": ' + name +
@ -153,7 +164,9 @@ class DescriptorDatabase(object):
self._file_desc_protos_by_symbol[name] = file_desc_proto
def _ExtractSymbols(desc_proto, package):
def _ExtractSymbols(
desc_proto: 'descriptor_pb2.DescriptorProto', package: str
) -> Iterator[str]:
"""Pulls out all the symbols from a descriptor proto.
Args:

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/duration.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/duration.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/empty.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/empty.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/field_mask.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/field_mask.proto'
)

View file

@ -23,6 +23,15 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
def _BuildNestedDescriptors(module, msg_des, prefix):
for name, nested_msg in msg_des.nested_types_by_name.items():
module_name = prefix + name.upper()
module[module_name] = nested_msg
_BuildNestedDescriptors(module, nested_msg, module_name + '_')
for enum_des in msg_des.enum_types:
module[prefix + enum_des.name.upper()] = enum_des
def BuildMessageAndEnumDescriptors(file_des, module):
"""Builds message and enum descriptors.
@ -30,19 +39,26 @@ def BuildMessageAndEnumDescriptors(file_des, module):
file_des: FileDescriptor of the .proto file
module: Generated _pb2 module
"""
def BuildNestedDescriptors(msg_des, prefix):
for (name, nested_msg) in msg_des.nested_types_by_name.items():
module_name = prefix + name.upper()
module[module_name] = nested_msg
BuildNestedDescriptors(nested_msg, module_name + '_')
for enum_des in msg_des.enum_types:
module[prefix + enum_des.name.upper()] = enum_des
for (name, msg_des) in file_des.message_types_by_name.items():
module_name = '_' + name.upper()
module[module_name] = msg_des
BuildNestedDescriptors(msg_des, module_name + '_')
_BuildNestedDescriptors(module, msg_des, module_name + '_')
def _BuildMessage(module_name, msg_des, prefix):
create_dict = {}
for name, nested_msg in msg_des.nested_types_by_name.items():
create_dict[name] = _BuildMessage(
module_name, nested_msg, prefix + msg_des.name + '.'
)
create_dict['DESCRIPTOR'] = msg_des
create_dict['__module__'] = module_name
create_dict['__qualname__'] = prefix + msg_des.name
message_class = _reflection.GeneratedProtocolMessageType(
msg_des.name, (_message.Message,), create_dict
)
_sym_db.RegisterMessage(message_class)
return message_class
def BuildTopDescriptorsAndMessages(file_des, module_name, module):
@ -54,18 +70,6 @@ def BuildTopDescriptorsAndMessages(file_des, module_name, module):
module: Generated _pb2 module
"""
def BuildMessage(msg_des, prefix):
create_dict = {}
for (name, nested_msg) in msg_des.nested_types_by_name.items():
create_dict[name] = BuildMessage(nested_msg, prefix + msg_des.name + '.')
create_dict['DESCRIPTOR'] = msg_des
create_dict['__module__'] = module_name
create_dict['__qualname__'] = prefix + msg_des.name
message_class = _reflection.GeneratedProtocolMessageType(
msg_des.name, (_message.Message,), create_dict)
_sym_db.RegisterMessage(message_class)
return message_class
# top level enums
for (name, enum_des) in file_des.enum_types_by_name.items():
module['_' + name.upper()] = enum_des
@ -84,7 +88,7 @@ def BuildTopDescriptorsAndMessages(file_des, module_name, module):
# Build messages.
for (name, msg_des) in file_des.message_types_by_name.items():
module[name] = BuildMessage(msg_des, '')
module[name] = _BuildMessage(module_name, msg_des, '')
def AddHelpersToExtensions(file_des):

View file

@ -40,6 +40,7 @@ _T = TypeVar('_T')
_K = TypeVar('_K')
_V = TypeVar('_V')
from google.protobuf.descriptor import FieldDescriptor
class BaseContainer(Sequence[_T]):
"""Base container class."""
@ -104,12 +105,13 @@ class RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]):
"""Simple, type-checked, list-like container for holding repeated scalars."""
# Disallows assignment to other attributes.
__slots__ = ['_type_checker']
__slots__ = ['_type_checker', '_field']
def __init__(
self,
message_listener: Any,
type_checker: Any,
field: Any = None,
) -> None:
"""Args:
@ -121,6 +123,7 @@ class RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]):
"""
super().__init__(message_listener)
self._type_checker = type_checker
self._field = field
def append(self, value: _T) -> None:
"""Appends an item to the list. Similar to list.append()."""
@ -202,7 +205,8 @@ class RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]):
unused_memo: Any = None,
) -> 'RepeatedScalarFieldContainer[_T]':
clone = RepeatedScalarFieldContainer(
copy.deepcopy(self._message_listener), self._type_checker)
copy.deepcopy(self._message_listener), self._type_checker, self._field
)
clone.MergeFrom(self)
return clone
@ -210,6 +214,38 @@ class RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]):
raise pickle.PickleError(
"Can't pickle repeated scalar fields, convert to list first")
def __array__(self, dtype=None, copy=None):
import numpy as np
if dtype is None:
cpp_type = self._field.cpp_type
if cpp_type == FieldDescriptor.CPPTYPE_INT32:
dtype = np.int32
elif cpp_type == FieldDescriptor.CPPTYPE_INT64:
dtype = np.int64
elif cpp_type == FieldDescriptor.CPPTYPE_UINT32:
dtype = np.uint32
elif cpp_type == FieldDescriptor.CPPTYPE_UINT64:
dtype = np.uint64
elif cpp_type == FieldDescriptor.CPPTYPE_DOUBLE:
dtype = np.float64
elif cpp_type == FieldDescriptor.CPPTYPE_FLOAT:
dtype = np.float32
elif cpp_type == FieldDescriptor.CPPTYPE_BOOL:
dtype = np.bool
elif cpp_type == FieldDescriptor.CPPTYPE_ENUM:
dtype = np.int32
elif self._field.type == FieldDescriptor.TYPE_BYTES:
dtype = 'S'
elif self._field.type == FieldDescriptor.TYPE_STRING:
dtype = str
else:
raise SystemError(
'Code should never reach here: message type detected in'
' RepeatedScalarFieldContainer'
)
return np.array(self._values, dtype=dtype, copy=True)
# TODO: Constrain T to be a subtype of Message.
class RepeatedCompositeFieldContainer(BaseContainer[_T], MutableSequence[_T]):

View file

@ -835,7 +835,7 @@ def MessageSetItemDecoder(descriptor):
local_ReadTag = ReadTag
local_DecodeVarint = _DecodeVarint
def DecodeItem(buffer, pos, end, message, field_dict):
def DecodeItem(buffer, pos, end, message, field_dict, current_depth=0):
"""Decode serialized message set to its value and new position.
Args:
@ -888,10 +888,19 @@ def MessageSetItemDecoder(descriptor):
message_factory.GetMessageClass(message_type)
value = field_dict.setdefault(
extension, message_type._concrete_class())
if value._InternalParse(buffer, message_start,message_end) != message_end:
current_depth += 1
if current_depth > _recursion_limit:
raise _DecodeError('Error parsing message: too many levels of nesting.')
if (
value._InternalParse(
buffer, message_start, message_end, current_depth
)
!= message_end
):
# The only reason _InternalParse would return early is if it encountered
# an end-group tag.
raise _DecodeError('Unexpected end-group tag.')
current_depth -= 1
else:
if not message._unknown_fields:
message._unknown_fields = []
@ -957,7 +966,6 @@ def MapDecoder(field_descriptor, new_default, is_message_map):
message_type = field_descriptor.message_type
def DecodeMap(buffer, pos, end, message, field_dict, current_depth=0):
del current_depth # Unused.
submsg = message_type._concrete_class()
value = field_dict.get(key)
if value is None:
@ -970,10 +978,14 @@ def MapDecoder(field_descriptor, new_default, is_message_map):
raise _DecodeError('Truncated message.')
# Read sub-message.
submsg.Clear()
if submsg._InternalParse(buffer, pos, new_pos) != new_pos:
current_depth += 1
if current_depth > _recursion_limit:
raise _DecodeError('Error parsing message: too many levels of nesting.')
if submsg._InternalParse(buffer, pos, new_pos, current_depth) != new_pos:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise _DecodeError('Unexpected end-group tag.')
current_depth -= 1
if is_message_map:
value[submsg.key].CopyFrom(submsg.value)

View file

@ -16,14 +16,14 @@ class FieldMask(object):
__slots__ = ()
def ToJsonString(self):
"""Converts FieldMask to string according to proto3 JSON spec."""
"""Converts FieldMask to string according to ProtoJSON spec."""
camelcase_paths = []
for path in self.paths:
camelcase_paths.append(_SnakeCaseToCamelCase(path))
return ','.join(camelcase_paths)
def FromJsonString(self, value):
"""Converts string to FieldMask according to proto3 JSON spec."""
"""Converts string to FieldMask according to ProtoJSON spec."""
if not isinstance(value, str):
raise ValueError('FieldMask JSON value not a string: {!r}'.format(value))
self.Clear()
@ -237,9 +237,16 @@ class _FieldMaskTree(object):
"""Adds leaf nodes begin with prefix to this tree."""
if not node:
self.AddPath(prefix)
for name in node:
child_path = prefix + '.' + name
self.AddLeafNodes(child_path, node[name])
return
stack = [(prefix, node)]
while stack:
current_prefix, current_node = stack.pop()
if not current_node:
self.AddPath(current_prefix)
continue
for name in current_node:
child_path = current_prefix + '.' + name
stack.append((child_path, current_node[name]))
def MergeMessage(
self, source, destination,
@ -262,51 +269,58 @@ def _StrConvert(value):
def _MergeMessage(
node, source, destination, replace_message, replace_repeated):
"""Merge all fields specified by a sub-tree from source to destination."""
source_descriptor = source.DESCRIPTOR
for name in node:
child = node[name]
field = source_descriptor.fields_by_name[name]
if field is None:
raise ValueError('Error: Can\'t find field {0} in message {1}.'.format(
name, source_descriptor.full_name))
if child:
# Sub-paths are only allowed for singular message fields.
if (field.is_repeated or
field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE):
raise ValueError('Error: Field {0} in message {1} is not a singular '
'message field and cannot have sub-fields.'.format(
name, source_descriptor.full_name))
if source.HasField(name):
_MergeMessage(
child, getattr(source, name), getattr(destination, name),
replace_message, replace_repeated)
continue
if field.is_repeated:
if replace_repeated:
destination.ClearField(_StrConvert(name))
repeated_source = getattr(source, name)
repeated_destination = getattr(destination, name)
repeated_destination.MergeFrom(repeated_source)
else:
if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
if replace_message:
destination.ClearField(_StrConvert(name))
if source.HasField(name):
getattr(destination, name).MergeFrom(getattr(source, name))
elif not field.has_presence or source.HasField(name):
setattr(destination, name, getattr(source, name))
stack = [(node, source, destination)]
while stack:
current_node, current_source, current_destination = stack.pop()
source_descriptor = current_source.DESCRIPTOR
for name in current_node:
child = current_node[name]
field = source_descriptor.fields_by_name[name]
if field is None:
raise ValueError('Error: Can\'t find field {0} in message {1}.'.format(
name, source_descriptor.full_name))
if child:
# Sub-paths are only allowed for singular message fields.
if (field.is_repeated or
field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE):
raise ValueError('Error: Field {0} in message {1} is not a singular '
'message field and cannot have sub-fields.'.format(
name, source_descriptor.full_name))
if current_source.HasField(name):
stack.append(
(child, getattr(current_source, name),
getattr(current_destination, name)))
continue
if field.is_repeated:
if replace_repeated:
current_destination.ClearField(_StrConvert(name))
repeated_source = getattr(current_source, name)
repeated_destination = getattr(current_destination, name)
repeated_destination.MergeFrom(repeated_source)
else:
destination.ClearField(_StrConvert(name))
if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
if replace_message:
current_destination.ClearField(_StrConvert(name))
if current_source.HasField(name):
getattr(current_destination, name).MergeFrom(
getattr(current_source, name))
elif not field.has_presence or current_source.HasField(name):
setattr(current_destination, name, getattr(current_source, name))
else:
current_destination.ClearField(_StrConvert(name))
def _AddFieldPaths(node, prefix, field_mask):
"""Adds the field paths descended from node to field_mask."""
if not node and prefix:
field_mask.paths.append(prefix)
return
for name in sorted(node):
if prefix:
child_path = prefix + '.' + name
else:
child_path = name
_AddFieldPaths(node[name], child_path, field_mask)
stack = [(node, prefix)]
while stack:
current_node, current_prefix = stack.pop()
if not current_node and current_prefix:
field_mask.paths.append(current_prefix)
continue
for name in sorted(current_node, reverse=True):
if current_prefix:
child_path = current_prefix + '.' + name
else:
child_path = name
stack.append((current_node[name], child_path))

View file

@ -2,4 +2,4 @@
This file contains the serialized FeatureSetDefaults object corresponding to
the Pure Python runtime. This is used for feature resolution under Editions.
"""
_PROTOBUF_INTERNAL_PYTHON_EDITION_DEFAULTS = b"\n\027\030\204\007\"\000*\020\010\001\020\002\030\002 \003(\0010\0028\002@\001\n\027\030\347\007\"\000*\020\010\002\020\001\030\001 \002(\0010\0018\002@\001\n\027\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\0048\002@\001\n\027\030\351\007\"\020\010\001\020\001\030\001 \002(\0010\0018\001@\002*\000 \346\007(\351\007"
_PROTOBUF_INTERNAL_PYTHON_EDITION_DEFAULTS = b"\n\027\030\204\007\"\000*\020\010\001\020\002\030\002 \003(\0010\0028\002@\001\n\027\030\347\007\"\000*\020\010\002\020\001\030\001 \002(\0010\0018\002@\001\n\027\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\0048\002@\001\n\027\030\351\007\"\020\010\001\020\001\030\001 \002(\0010\0018\001@\002*\000\n\027\030\217N\"\020\010\001\020\001\030\001 \002(\0010\0018\003@\002*\000 \346\007(\351\007"

View file

@ -443,7 +443,8 @@ def _DefaultValueConstructorForField(field):
type_checker = type_checkers.GetTypeChecker(field)
def MakeRepeatedScalarDefault(message):
return containers.RepeatedScalarFieldContainer(
message._listener_for_children, type_checker)
message._listener_for_children, type_checker, field
)
return MakeRepeatedScalarDefault
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
@ -1240,7 +1241,9 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
tag_bytes, (None, None)
)
if field_decoder:
pos = field_decoder(buffer, new_pos, end, self, field_dict)
pos = field_decoder(
buffer, new_pos, end, self, field_dict, current_depth
)
continue
field_des, is_packed = fields_by_tag.get(tag_bytes, (None, None))
if field_des is None:

View file

@ -32,10 +32,6 @@ from google.protobuf.internal import encoder
from google.protobuf.internal import wire_format
_FieldDescriptor = descriptor.FieldDescriptor
# TODO: Remove this warning count after 34.0
# Assign bool to int/enum warnings will print 100 times at most which should
# be enough for users to notice and do not cause timeout.
_BoolWarningCount = 100
def TruncateToFourByteFloat(original):
return struct.unpack('<f', struct.pack('<f', original))[0]
@ -145,20 +141,15 @@ class IntValueChecker(object):
"""Checker used for integer fields. Performs type-check and range check."""
def CheckValue(self, proposed_value):
global _BoolWarningCount
if type(proposed_value) == bool and _BoolWarningCount > 0:
_BoolWarningCount -= 1
if type(proposed_value) == bool:
message = (
'%.1024r has type %s, but expected one of: %s. This warning '
'will turn into error in 7.34.0, please fix it before that.'
'%.1024r has type %s, but expected one of: (int).'
% (
proposed_value,
type(proposed_value),
(int,),
)
)
# TODO: Raise errors in 2026 Q1 release
warnings.warn(message)
raise TypeError(message)
if not hasattr(proposed_value, '__index__') or (
type(proposed_value).__module__ == 'numpy' and
@ -186,20 +177,16 @@ class EnumValueChecker(object):
self._enum_type = enum_type
def CheckValue(self, proposed_value):
global _BoolWarningCount
if type(proposed_value) == bool and _BoolWarningCount > 0:
_BoolWarningCount -= 1
if type(proposed_value) == bool:
message = (
'%.1024r has type %s, but expected one of: %s. This warning '
'will turn into error in 7.34.0, please fix it before that.'
'%.1024r has type %s, but expected one of: (int).'
% (
proposed_value,
type(proposed_value),
(int,),
)
)
# TODO: Raise errors in 2026 Q1 release
warnings.warn(message)
raise TypeError(message)
if not isinstance(proposed_value, numbers.Integral):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), (int,)))

View file

@ -279,6 +279,13 @@ class Timestamp(object):
# manipulated into a long value of seconds. During the conversion from
# struct_time to long, the source date in UTC, and so it follows that the
# correct transformation is calendar.timegm()
if type(dt).__name__ != 'datetime' and not isinstance(
dt, datetime.datetime
):
raise TypeError(
'Fail to convert to Timestamp. Expected a datetime object '
'got {0}'.format(type(dt).__name__)
)
try:
seconds = calendar.timegm(dt.utctimetuple())
nanos = dt.microsecond * _NANOS_PER_MICROSECOND
@ -445,6 +452,13 @@ class Duration(object):
def FromTimedelta(self, td):
"""Converts timedelta to Duration."""
if type(td).__name__ != 'timedelta' and not isinstance(
td, datetime.timedelta
):
raise TypeError(
'Fail to convert to Duration. Expected a timedelta object '
'got {0}'.format(type(td).__name__)
)
try:
self._NormalizeDuration(
td.seconds + td.days * _SECONDS_PER_DAY,

View file

@ -26,7 +26,6 @@ import json
import math
from operator import methodcaller
import re
import warnings
from google.protobuf import descriptor
from google.protobuf import message_factory
@ -85,9 +84,10 @@ def MessageToJson(
sort_keys=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None,
ensure_ascii=True,
always_print_fields_with_no_presence=False,
*,
unquote_int64_if_possible=False,
):
"""Converts protobuf message to JSON format.
@ -107,10 +107,11 @@ def MessageToJson(
use_integers_for_enums: If true, print integers instead of enum names.
descriptor_pool: A Descriptor Pool for resolving types. If None use the
default.
float_precision: Deprecated. If set, use this to specify float field valid
digits.
ensure_ascii: If True, strings with non-ASCII characters are escaped. If
False, Unicode strings are returned unchanged.
unquote_int64_if_possible: If True, unquote int64 fields for values that
are safe to emit as numbers (all values smaller than 2^53 and a sparse
set of values that are larger).
Returns:
A string containing the JSON formatted protocol buffer message.
@ -119,8 +120,8 @@ def MessageToJson(
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
float_precision,
always_print_fields_with_no_presence,
unquote_int64_if_possible=unquote_int64_if_possible,
)
return printer.ToJsonString(message, indent, sort_keys, ensure_ascii)
@ -131,11 +132,12 @@ def MessageToDict(
preserving_proto_field_name=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None,
*,
unquote_int64_if_possible=False,
):
"""Converts protobuf message to a dictionary.
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
When the dictionary is encoded to JSON, it conforms to ProtoJSON spec.
Args:
message: The protocol buffers message instance to serialize.
@ -149,8 +151,9 @@ def MessageToDict(
use_integers_for_enums: If true, print integers instead of enum names.
descriptor_pool: A Descriptor Pool for resolving types. If None use the
default.
float_precision: Deprecated. If set, use this to specify float field valid
digits.
unquote_int64_if_possible: If True, unquote int64 fields for values that
are safe to emit as numbers (all values smaller than 2^53 and a sparse
set of values that are larger).
Returns:
A dict representation of the protocol buffer message.
@ -159,8 +162,8 @@ def MessageToDict(
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
float_precision,
always_print_fields_with_no_presence,
unquote_int64_if_possible=unquote_int64_if_possible,
)
# pylint: disable=protected-access
return printer._MessageToJsonObject(message)
@ -182,8 +185,9 @@ class _Printer(object):
preserving_proto_field_name=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None,
always_print_fields_with_no_presence=False,
*,
unquote_int64_if_possible=False,
):
self.always_print_fields_with_no_presence = (
always_print_fields_with_no_presence
@ -191,15 +195,7 @@ class _Printer(object):
self.preserving_proto_field_name = preserving_proto_field_name
self.use_integers_for_enums = use_integers_for_enums
self.descriptor_pool = descriptor_pool
if float_precision:
warnings.warn(
'float_precision option is deprecated for json_format. '
'This will turn into error in 7.34.0, please remove it '
'before that.'
)
self.float_format = '.{}g'.format(float_precision)
else:
self.float_format = None
self.unquote_int64_if_possible = unquote_int64_if_possible
def ToJsonString(self, message, indent, sort_keys, ensure_ascii):
js = self._MessageToJsonObject(message)
@ -208,7 +204,7 @@ class _Printer(object):
)
def _MessageToJsonObject(self, message):
"""Converts message to an object according to Proto3 JSON Specification."""
"""Converts message to an object according to ProtoJSON Specification."""
message_descriptor = message.DESCRIPTOR
full_name = message_descriptor.full_name
if _IsWrapperMessage(message_descriptor):
@ -219,7 +215,7 @@ class _Printer(object):
return self._RegularMessageToJsonObject(message, js)
def _RegularMessageToJsonObject(self, message, js):
"""Converts normal message according to Proto3 JSON Specification."""
"""Converts normal message according to ProtoJSON Specification."""
fields = message.ListFields()
try:
@ -285,7 +281,7 @@ class _Printer(object):
return js
def _FieldToJsonObject(self, field, value):
"""Converts field value according to Proto3 JSON Specification."""
"""Converts field value according to ProtoJSON Specification."""
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
return self._MessageToJsonObject(value)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
@ -313,7 +309,10 @@ class _Printer(object):
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
return bool(value)
elif field.cpp_type in _INT64_TYPES:
return str(value)
if self.unquote_int64_if_possible and float(value) == value:
return value
else:
return str(value)
elif field.cpp_type in _FLOAT_TYPES:
if math.isinf(value):
if value < 0.0:
@ -322,15 +321,13 @@ class _Printer(object):
return _INFINITY
if math.isnan(value):
return _NAN
if self.float_format:
return float(format(value, self.float_format))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
return type_checkers.ToShortestFloat(value)
return value
def _AnyMessageToJsonObject(self, message):
"""Converts Any message according to Proto3 JSON Specification."""
"""Converts Any message according to ProtoJSON Specification."""
if not message.ListFields():
return {}
# Must print @type first, use OrderedDict instead of {}
@ -352,13 +349,13 @@ class _Printer(object):
return self._RegularMessageToJsonObject(sub_message, js)
def _GenericMessageToJsonObject(self, message):
"""Converts message according to Proto3 JSON Specification."""
"""Converts message according to ProtoJSON Specification."""
# Duration, Timestamp and FieldMask have ToJsonString method to do the
# convert. Users can also call the method directly.
return message.ToJsonString()
def _ValueMessageToJsonObject(self, message):
"""Converts Value message according to Proto3 JSON Specification."""
"""Converts Value message according to ProtoJSON Specification."""
which = message.WhichOneof('kind')
# If the Value message is not set treat as null_value when serialize
# to JSON. The parse back result will be different from original message.
@ -384,11 +381,11 @@ class _Printer(object):
return self._FieldToJsonObject(oneof_descriptor, value)
def _ListValueMessageToJsonObject(self, message):
"""Converts ListValue message according to Proto3 JSON Specification."""
"""Converts ListValue message according to ProtoJSON Specification."""
return [self._ValueMessageToJsonObject(value) for value in message.values]
def _StructMessageToJsonObject(self, message):
"""Converts Struct message according to Proto3 JSON Specification."""
"""Converts Struct message according to ProtoJSON Specification."""
fields = message.fields
ret = {}
for key in fields:
@ -527,6 +524,10 @@ class _Parser(object):
Raises:
ParseError: In case of convert problems.
"""
# Increment recursion depth at message entry. The max_recursion_depth limit
# is exclusive: a depth value equal to max_recursion_depth will trigger an
# error. For example, with max_recursion_depth=5, nesting up to depth 4 is
# allowed, but attempting depth 5 raises ParseError.
self.recursion_depth += 1
if self.recursion_depth > self.max_recursion_depth:
raise ParseError(
@ -747,12 +748,11 @@ class _Parser(object):
value['value'], sub_message, '{0}.value'.format(path)
)
elif full_name in _WKTJSONMETHODS:
methodcaller(
_WKTJSONMETHODS[full_name][1],
value['value'],
sub_message,
'{0}.value'.format(path),
)(self)
# For well-known types (including nested Any), use ConvertMessage
# to ensure recursion depth is properly tracked
self.ConvertMessage(
value['value'], sub_message, '{0}.value'.format(path)
)
else:
del value['@type']
try:

View file

@ -19,25 +19,23 @@ def serialize(
preserving_proto_field_name: bool=False,
use_integers_for_enums: bool=False,
descriptor_pool: Optional[DescriptorPool]=None,
float_precision: int=None,
) -> dict:
"""Converts protobuf message to a dictionary.
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
When the dictionary is encoded to JSON, it conforms to ProtoJSON spec.
Args:
message: The protocol buffers message instance to serialize.
always_print_fields_with_no_presence: If True, fields without
presence (implicit presence scalars, repeated fields, and map fields) will
always be serialized. Any field that supports presence is not affected by
this option (including singular message fields and oneof fields).
always_print_fields_with_no_presence: If True, fields without presence
(implicit presence scalars, repeated fields, and map fields) will always
be serialized. Any field that supports presence is not affected by this
option (including singular message fields and oneof fields).
preserving_proto_field_name: If True, use the original proto field names as
defined in the .proto file. If False, convert the field names to
lowerCamelCase.
use_integers_for_enums: If true, print integers instead of enum names.
descriptor_pool: A Descriptor Pool for resolving types. If None use the
default.
float_precision: If set, use this to specify float field valid digits.
Returns:
A dict representation of the protocol buffer message.
@ -47,7 +45,6 @@ def serialize(
always_print_fields_with_no_presence=always_print_fields_with_no_presence,
preserving_proto_field_name=preserving_proto_field_name,
use_integers_for_enums=use_integers_for_enums,
float_precision=float_precision,
)
def parse(

View file

@ -22,8 +22,6 @@ def serialize(
use_short_repeated_primitives: bool = False,
pointy_brackets: bool = False,
use_index_order: bool = False,
float_format: Optional[str] = None,
double_format: Optional[str] = None,
use_field_number: bool = False,
descriptor_pool: Optional[DescriptorPool] = None,
indent: int = 0,
@ -50,13 +48,6 @@ def serialize(
will be printed at the end of the message and their relative order is
determined by the extension number. By default, use the field number
order.
float_format (str): If set, use this to specify float field formatting (per
the "Format Specification Mini-Language"); otherwise, shortest float that
has same value in wire will be printed. Also affect double field if
double_format is not set but float_format is set.
double_format (str): If set, use this to specify double field formatting
(per the "Format Specification Mini-Language"); if it is not set but
float_format is set, use float_format. Otherwise, use ``str()``
use_field_number: If True, print field numbers instead of names.
descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.
indent (int): The initial indent level, in terms of spaces, for pretty
@ -78,8 +69,6 @@ def serialize(
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
float_format=float_format,
double_format=double_format,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
indent=indent,

View file

@ -27,9 +27,9 @@ class Domain(Enum):
# the Protobuf release process. Do not edit them manually.
# These OSS versions are not stripped to avoid merging conflicts.
OSS_DOMAIN = Domain.PUBLIC
OSS_MAJOR = 6
OSS_MINOR = 33
OSS_PATCH = 4
OSS_MAJOR = 7
OSS_MINOR = 35
OSS_PATCH = 1
OSS_SUFFIX = ''
DOMAIN = OSS_DOMAIN

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/source_context.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/source_context.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/struct.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/struct.proto'
)

View file

@ -44,6 +44,8 @@ _INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(),
_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?$', re.IGNORECASE)
_FLOAT_NAN = re.compile('nanf?$', re.IGNORECASE)
_FLOAT_OCTAL_PREFIX = re.compile('-?0[0-9]+')
_PERCENT_ENCODING = re.compile(r'^%[\da-fA-F][\da-fA-F]$')
_TYPE_NAME = re.compile(r'^[^\d\W]\w*(\.[^\d\W]\w*)*$')
_QUOTES = frozenset(("'", '"'))
_ANY_FULL_TYPE_NAME = 'google.protobuf.Any'
_DEBUG_STRING_SILENT_MARKER = '\t '
@ -100,8 +102,6 @@ def MessageToString(
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
indent=0,
@ -110,11 +110,6 @@ def MessageToString(
force_colon=False) -> str:
"""Convert protobuf message to text format.
Double values can be formatted compactly with 15 digits of
precision (which is the most that IEEE 754 "double" can guarantee)
using double_format='.15g'. To ensure that converting to text and back to a
proto will result in an identical value, double_format='.17g' should be used.
Args:
message: The protocol buffers message.
as_utf8: Return unescaped Unicode for non-ASCII characters.
@ -127,13 +122,6 @@ def MessageToString(
will be printed at the end of the message and their relative order is
determined by the extension number. By default, use the field number
order.
float_format (str): Deprecated. If set, use this to specify float field
formatting (per the "Format Specification Mini-Language"); otherwise,
shortest float that has same value in wire will be printed. Also affect
double field if double_format is not set but float_format is set.
double_format (str): Deprecated. If set, use this to specify double field
formatting (per the "Format Specification Mini-Language"); if it is not
set but float_format is set, use float_format. Otherwise, use ``str()``
use_field_number: If True, print field numbers instead of names.
descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.
indent (int): The initial indent level, in terms of spaces, for pretty
@ -150,20 +138,19 @@ def MessageToString(
"""
out = TextWriter(as_utf8)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
float_format,
double_format,
use_field_number,
descriptor_pool,
message_formatter,
out=out,
indent=indent,
as_utf8=as_utf8,
as_one_line=as_one_line,
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
force_colon=force_colon,
)
printer.PrintMessage(message)
result = out.getvalue()
out.close()
@ -225,8 +212,6 @@ def PrintMessage(message,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
@ -246,13 +231,6 @@ def PrintMessage(message,
use_index_order: If True, print fields of a proto message using the order
defined in source code instead of the field number. By default, use the
field number order.
float_format: If set, use this to specify float field formatting
(per the "Format Specification Mini-Language"); otherwise, shortest
float that has same value in wire will be printed. Also affect double
field if double_format is not set but float_format is set.
double_format: If set, use this to specify double field formatting
(per the "Format Specification Mini-Language"); if it is not set but
float_format is set, use float_format. Otherwise, str() is used.
use_field_number: If True, print field numbers instead of names.
descriptor_pool: A DescriptorPool used to resolve Any types.
message_formatter: A function(message, indent, as_one_line): unicode|None
@ -268,8 +246,6 @@ def PrintMessage(message,
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
float_format=float_format,
double_format=double_format,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
message_formatter=message_formatter,
@ -287,18 +263,22 @@ def PrintField(field,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
"""Print a single field name/value pair."""
printer = _Printer(out, indent, as_utf8, as_one_line,
use_short_repeated_primitives, pointy_brackets,
use_index_order, float_format, double_format,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon,
)
printer.PrintField(field, value)
@ -311,18 +291,22 @@ def PrintFieldValue(field,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
"""Print a single field value (not including name)."""
printer = _Printer(out, indent, as_utf8, as_one_line,
use_short_repeated_primitives, pointy_brackets,
use_index_order, float_format, double_format,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon,
)
printer.PrintFieldValue(field, value)
@ -340,8 +324,10 @@ def _BuildMessageFromTypeName(type_name, descriptor_pool):
# pylint: disable=g-import-not-at-top
if descriptor_pool is None:
from google.protobuf import descriptor_pool as pool_mod
descriptor_pool = pool_mod.Default()
from google.protobuf import message_factory
try:
message_descriptor = descriptor_pool.FindMessageTypeByName(type_name)
except KeyError:
@ -367,20 +353,14 @@ class _Printer(object):
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
force_colon=False,
):
"""Initialize the Printer.
Double values can be formatted compactly with 15 digits of precision
(which is the most that IEEE 754 "double" can guarantee) using
double_format='.15g'. To ensure that converting to text and back to a proto
will result in an identical value, double_format='.17g' should be used.
Args:
out: To record the text format result.
indent: The initial indent level for pretty print.
@ -392,13 +372,6 @@ class _Printer(object):
use_index_order: If True, print fields of a proto message using the order
defined in source code instead of the field number. By default, use the
field number order.
float_format: Deprecated. If set, use this to specify float field
formatting (per the "Format Specification Mini-Language"); otherwise,
shortest float that has same value in wire will be printed. Also affect
double field if double_format is not set but float_format is set.
double_format: Deprecated. If set, use this to specify double field
formatting (per the "Format Specification Mini-Language"); if it is not
set but float_format is set, use float_format. Otherwise, str() is used.
use_field_number: If True, print field numbers instead of names.
descriptor_pool: A DescriptorPool used to resolve Any types.
message_formatter: A function(message, indent, as_one_line): unicode|None
@ -415,15 +388,6 @@ class _Printer(object):
self.use_short_repeated_primitives = use_short_repeated_primitives
self.pointy_brackets = pointy_brackets
self.use_index_order = use_index_order
self.float_format = float_format
if double_format is not None:
warnings.warn(
'double_format is deprecated for text_format. This will '
'turn into error in 7.34.0, please remove it before that.'
)
self.double_format = double_format
else:
self.double_format = float_format
self.use_field_number = use_field_number
self.descriptor_pool = descriptor_pool
self.message_formatter = message_formatter
@ -656,21 +620,10 @@ class _Printer(object):
else:
out.write('false')
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
if self.float_format is not None:
warnings.warn(
'float_format is deprecated for text_format. This '
'will turn into error in 7.34.0, please remove it '
'before that.'
)
out.write('{1:{0}}'.format(self.float_format, value))
if math.isnan(value):
out.write(str(value))
else:
if math.isnan(value):
out.write(str(value))
else:
out.write(str(type_checkers.ToShortestFloat(value)))
elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and
self.double_format is not None):
out.write('{1:{0}}'.format(self.double_format, value))
out.write(str(type_checkers.ToShortestFloat(value)))
else:
out.write(str(value))
@ -680,7 +633,8 @@ def Parse(text,
allow_unknown_extension=False,
allow_field_number=False,
descriptor_pool=None,
allow_unknown_field=False):
allow_unknown_field=False,
max_recursion_depth=None):
"""Parses a text representation of a protocol message into a message.
NOTE: for historical reasons this function does not clear the input
@ -718,6 +672,9 @@ def Parse(text,
allow_unknown_field: if True, skip over unknown field and keep
parsing. Avoid to use this option if possible. It may hide some
errors (e.g. spelling error on field name)
max_recursion_depth: Optional maximum recursion depth of a text proto
message to be deserialized. Text proto messages over this depth will
fail to parse. ``None`` keeps the historical unbounded behavior.
Returns:
Message: The same message passed as argument.
@ -730,7 +687,8 @@ def Parse(text,
allow_unknown_extension,
allow_field_number,
descriptor_pool=descriptor_pool,
allow_unknown_field=allow_unknown_field)
allow_unknown_field=allow_unknown_field,
max_recursion_depth=max_recursion_depth)
def Merge(text,
@ -738,7 +696,8 @@ def Merge(text,
allow_unknown_extension=False,
allow_field_number=False,
descriptor_pool=None,
allow_unknown_field=False):
allow_unknown_field=False,
max_recursion_depth=None):
"""Parses a text representation of a protocol message into a message.
Like Parse(), but allows repeated values for a non-repeated field, and uses
@ -755,6 +714,9 @@ def Merge(text,
allow_unknown_field: if True, skip over unknown field and keep
parsing. Avoid to use this option if possible. It may hide some
errors (e.g. spelling error on field name)
max_recursion_depth: Optional maximum recursion depth of a text proto
message to be deserialized. Text proto messages over this depth will
fail to parse. ``None`` keeps the historical unbounded behavior.
Returns:
Message: The same message passed as argument.
@ -768,7 +730,8 @@ def Merge(text,
allow_unknown_extension,
allow_field_number,
descriptor_pool=descriptor_pool,
allow_unknown_field=allow_unknown_field)
allow_unknown_field=allow_unknown_field,
max_recursion_depth=max_recursion_depth)
def ParseLines(lines,
@ -776,7 +739,8 @@ def ParseLines(lines,
allow_unknown_extension=False,
allow_field_number=False,
descriptor_pool=None,
allow_unknown_field=False):
allow_unknown_field=False,
max_recursion_depth=None):
"""Parses a text representation of a protocol message into a message.
See Parse() for caveats.
@ -791,6 +755,9 @@ def ParseLines(lines,
allow_unknown_field: if True, skip over unknown field and keep
parsing. Avoid to use this option if possible. It may hide some
errors (e.g. spelling error on field name)
max_recursion_depth: Optional maximum recursion depth of a text proto
message to be deserialized. Text proto messages over this depth will
fail to parse. ``None`` keeps the historical unbounded behavior.
Returns:
The same message passed as argument.
@ -801,7 +768,8 @@ def ParseLines(lines,
parser = _Parser(allow_unknown_extension,
allow_field_number,
descriptor_pool=descriptor_pool,
allow_unknown_field=allow_unknown_field)
allow_unknown_field=allow_unknown_field,
max_recursion_depth=max_recursion_depth)
return parser.ParseLines(lines, message)
@ -810,7 +778,8 @@ def MergeLines(lines,
allow_unknown_extension=False,
allow_field_number=False,
descriptor_pool=None,
allow_unknown_field=False):
allow_unknown_field=False,
max_recursion_depth=None):
"""Parses a text representation of a protocol message into a message.
See Merge() for more details.
@ -825,6 +794,9 @@ def MergeLines(lines,
allow_unknown_field: if True, skip over unknown field and keep
parsing. Avoid to use this option if possible. It may hide some
errors (e.g. spelling error on field name)
max_recursion_depth: Optional maximum recursion depth of a text proto
message to be deserialized. Text proto messages over this depth will
fail to parse. ``None`` keeps the historical unbounded behavior.
Returns:
The same message passed as argument.
@ -835,7 +807,8 @@ def MergeLines(lines,
parser = _Parser(allow_unknown_extension,
allow_field_number,
descriptor_pool=descriptor_pool,
allow_unknown_field=allow_unknown_field)
allow_unknown_field=allow_unknown_field,
max_recursion_depth=max_recursion_depth)
return parser.MergeLines(lines, message)
@ -846,11 +819,14 @@ class _Parser(object):
allow_unknown_extension=False,
allow_field_number=False,
descriptor_pool=None,
allow_unknown_field=False):
allow_unknown_field=False,
max_recursion_depth=None):
self.allow_unknown_extension = allow_unknown_extension
self.allow_field_number = allow_field_number
self.descriptor_pool = descriptor_pool
self.allow_unknown_field = allow_unknown_field
self.max_recursion_depth = max_recursion_depth
self.recursion_depth = 0
def ParseLines(self, lines, message):
"""Parses a text representation of a protocol message into a message."""
@ -884,8 +860,38 @@ class _Parser(object):
raise ParseError from e
if message:
self.root_type = message.DESCRIPTOR.full_name
self.recursion_depth += 1
if (
self.max_recursion_depth is not None
and self.recursion_depth > self.max_recursion_depth
):
raise ParseError(
'Message too deep. Max recursion depth is {0}'.format(
self.max_recursion_depth
)
)
while not tokenizer.AtEnd():
self._MergeField(tokenizer, message)
self.recursion_depth -= 1
def _MergeMessage(self, tokenizer, message, end_token):
self.recursion_depth += 1
if (
self.max_recursion_depth is not None
and self.recursion_depth > self.max_recursion_depth
):
raise ParseError(
'Message too deep. Max recursion depth is {0}'.format(
self.max_recursion_depth
)
)
while not tokenizer.TryConsume(end_token):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken(
'Expected "%s".' % (end_token,)
)
self._MergeField(tokenizer, message)
self.recursion_depth -= 1
def _MergeField(self, tokenizer, message):
"""Merges a single protocol message field into a message.
@ -901,10 +907,12 @@ class _Parser(object):
if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and
tokenizer.TryConsume('[')):
type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
tokenizer.Consume(']')
tokenizer.TryConsume(':')
self._DetectSilentMarker(tokenizer, message_descriptor.full_name,
type_url_prefix + '/' + packed_type_name)
self._DetectSilentMarker(
tokenizer,
message_descriptor.full_name,
type_url_prefix + '/' + packed_type_name,
)
if tokenizer.TryConsume('<'):
expanded_any_end_token = '>'
else:
@ -918,16 +926,16 @@ class _Parser(object):
if expanded_any_sub_message is None:
raise ParseError('Type %s not found in descriptor pool' %
packed_type_name)
while not tokenizer.TryConsume(expanded_any_end_token):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' %
(expanded_any_end_token,))
self._MergeField(tokenizer, expanded_any_sub_message)
self._MergeMessage(
tokenizer, expanded_any_sub_message, expanded_any_end_token
)
deterministic = False
message.Pack(expanded_any_sub_message,
type_url_prefix=type_url_prefix,
deterministic=deterministic)
message.Pack(
expanded_any_sub_message,
type_url_prefix=type_url_prefix + '/',
deterministic=deterministic,
)
return
if tokenizer.TryConsume('['):
@ -1039,19 +1047,59 @@ class _Parser(object):
self._LogSilentMarker(immediate_message_type, field_name)
def _ConsumeAnyTypeUrl(self, tokenizer):
"""Consumes a google.protobuf.Any type URL and returns the type name."""
# Consume "type.googleapis.com/".
prefix = [tokenizer.ConsumeIdentifier()]
tokenizer.Consume('.')
prefix.append(tokenizer.ConsumeIdentifier())
tokenizer.Consume('.')
prefix.append(tokenizer.ConsumeIdentifier())
tokenizer.Consume('/')
# Consume the fully-qualified type name.
name = [tokenizer.ConsumeIdentifier()]
while tokenizer.TryConsume('.'):
name.append(tokenizer.ConsumeIdentifier())
return '.'.join(prefix), '.'.join(name)
"""Consumes a google.protobuf.Any type URL.
Assumes the caller has already consumed the opening [ and consumes up to the
closing ].
Args:
tokenizer: A tokenizer to parse the type URL.
Returns:
A tuple of type URL prefix (without trailing slash) and type name.
"""
# Consume all tokens with valid URL characters until ]. Whitespace and
# comments are ignored/skipped by the Tokenizer.
tokens = []
last_slash = -1
while True:
try:
tokens.append(tokenizer.ConsumeUrlChars())
continue
except ParseError:
pass
if tokenizer.TryConsume('/'):
last_slash = len(tokens)
tokens.append('/')
else:
tokenizer.Consume(']')
break
if last_slash == -1:
raise tokenizer.ParseError('Type URL does not contain "/".')
prefix = ''.join(tokens[:last_slash])
name = ''.join(tokens[last_slash + 1 :])
if not prefix:
raise tokenizer.ParseError('Type URL prefix is empty.')
if prefix.startswith('/'):
raise tokenizer.ParseError('Type URL prefix starts with "/".')
# Check for invalid percent encodings. '%' needs to be followed by exactly
# two valid hexadecimal digits.
for i, char in enumerate(prefix):
if char == '%' and not _PERCENT_ENCODING.match(prefix[i : i + 3]):
raise tokenizer.ParseError(
f'Invalid percent escape, got "{prefix[i : i + 3]}".'
)
# After the last slash we expect a valid type name, not just any sequence of
# URL characters.
if not _TYPE_NAME.match(name):
raise tokenizer.ParseError('Expected type name, got "%s".' % name)
return prefix, name
def _MergeMessageField(self, tokenizer, message, field):
"""Merges a single scalar field into a message.
@ -1098,10 +1146,7 @@ class _Parser(object):
sub_message = getattr(message, field.name)
sub_message.SetInParent()
while not tokenizer.TryConsume(end_token):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,))
self._MergeField(tokenizer, sub_message)
self._MergeMessage(tokenizer, sub_message, end_token)
if is_map_entry:
value_cpptype = field.message_type.fields_by_name['value'].cpp_type
@ -1312,17 +1357,26 @@ class Tokenizer(object):
_WHITESPACE = re.compile(r'\s+')
_COMMENT = re.compile(r'(\s*#.*$)', re.MULTILINE)
_WHITESPACE_OR_COMMENT = re.compile(r'(\s|(#.*$))+', re.MULTILINE)
_TOKEN = re.compile('|'.join([
r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier
r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number
] + [ # quoted str for each quote mark
# Avoid backtracking! https://stackoverflow.com/a/844267
r'{qt}[^{qt}\n\\]*((\\.)+[^{qt}\n\\]*)*({qt}|\\?$)'.format(qt=mark)
for mark in _QUOTES
]))
_TOKEN = re.compile(
'|'.join(
[
r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier
r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number
]
+ [ # quoted str for each quote mark
# Avoid backtracking! https://stackoverflow.com/a/844267
r'{qt}[^{qt}\n\\]*((\\.)+[^{qt}\n\\]*)*({qt}|\\?$)'.format(
qt=mark
)
for mark in _QUOTES
]
)
)
_IDENTIFIER = re.compile(r'[^\d\W]\w*')
_IDENTIFIER_OR_NUMBER = re.compile(r'\w+')
# Accepted URL characters (excluding "/")
_URL_CHARS = re.compile(r'^[0-9a-zA-Z-.~_ !$&()*+,;=%]+$')
def __init__(self, lines, skip_comments=True):
self._position = 0
@ -1602,6 +1656,31 @@ class Tokenizer(object):
self.NextToken()
return result
def ConsumeUrlChars(self):
"""Consumes a token containing valid URL characters.
Excludes '/' so that it can be treated specially as a delimiter.
Returns:
The next token containing one or more URL characters.
Raises:
ParseError: If the next token contains unaccepted URL characters.
"""
if not self._URL_CHARS.match(self.token):
raise self.ParseError('Expected URL character(s), got "%s"' % self.token)
result = self.token
self.NextToken()
return result
def TryConsumeUrlChars(self):
try:
self.ConsumeUrlChars()
return True
except ParseError:
return False
def ParseErrorPreviousToken(self, message):
"""Creates and *returns* a ParseError for the previously read token.

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/timestamp.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/timestamp.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/type.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/type.proto'
)

View file

@ -2,7 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/wrappers.proto
# Protobuf Python Version: 6.33.4
# Protobuf Python Version: 7.35.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
7,
35,
1,
'',
'google/protobuf/wrappers.proto'
)