protobuf 5.29.0rc3__py3-none-any.whl → 6.33.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of protobuf might be problematic. Click here for more details.
- google/protobuf/__init__.py +1 -1
- google/protobuf/any.py +15 -1
- google/protobuf/any_pb2.py +5 -5
- google/protobuf/api_pb2.py +15 -11
- google/protobuf/compiler/plugin_pb2.py +5 -5
- google/protobuf/descriptor.py +413 -248
- google/protobuf/descriptor_database.py +22 -4
- google/protobuf/descriptor_pb2.py +320 -120
- google/protobuf/descriptor_pool.py +31 -13
- google/protobuf/duration_pb2.py +5 -5
- google/protobuf/empty_pb2.py +5 -5
- google/protobuf/field_mask_pb2.py +5 -5
- google/protobuf/internal/api_implementation.py +0 -6
- google/protobuf/internal/builder.py +4 -3
- google/protobuf/internal/containers.py +13 -0
- google/protobuf/internal/decoder.py +163 -133
- google/protobuf/internal/extension_dict.py +3 -3
- google/protobuf/internal/field_mask.py +6 -4
- google/protobuf/internal/python_edition_defaults.py +1 -1
- google/protobuf/internal/python_message.py +86 -70
- google/protobuf/internal/testing_refleaks.py +11 -2
- google/protobuf/internal/type_checkers.py +52 -5
- google/protobuf/internal/well_known_types.py +63 -46
- google/protobuf/json_format.py +113 -71
- google/protobuf/message.py +26 -0
- google/protobuf/message_factory.py +16 -63
- google/protobuf/proto.py +38 -1
- google/protobuf/proto_text.py +129 -0
- google/protobuf/reflection.py +0 -49
- google/protobuf/runtime_version.py +9 -29
- google/protobuf/source_context_pb2.py +5 -5
- google/protobuf/struct_pb2.py +5 -5
- google/protobuf/symbol_database.py +0 -18
- google/protobuf/text_format.py +49 -29
- google/protobuf/timestamp_pb2.py +5 -5
- google/protobuf/type_pb2.py +5 -5
- google/protobuf/unknown_fields.py +3 -4
- google/protobuf/wrappers_pb2.py +5 -5
- {protobuf-5.29.0rc3.dist-info → protobuf-6.33.3.dist-info}/METADATA +3 -3
- protobuf-6.33.3.dist-info/RECORD +58 -0
- google/protobuf/internal/_parameterized.py +0 -420
- google/protobuf/service.py +0 -213
- protobuf-5.29.0rc3.dist-info/RECORD +0 -59
- {protobuf-5.29.0rc3.dist-info → protobuf-6.33.3.dist-info}/LICENSE +0 -0
- {protobuf-5.29.0rc3.dist-info → protobuf-6.33.3.dist-info}/WHEEL +0 -0
|
@@ -29,6 +29,7 @@ __author__ = 'robinson@google.com (Will Robinson)'
|
|
|
29
29
|
|
|
30
30
|
import datetime
|
|
31
31
|
from io import BytesIO
|
|
32
|
+
import math
|
|
32
33
|
import struct
|
|
33
34
|
import sys
|
|
34
35
|
import warnings
|
|
@@ -255,7 +256,8 @@ def _IsMessageSetExtension(field):
|
|
|
255
256
|
field.containing_type.has_options and
|
|
256
257
|
field.containing_type.GetOptions().message_set_wire_format and
|
|
257
258
|
field.type == _FieldDescriptor.TYPE_MESSAGE and
|
|
258
|
-
field.
|
|
259
|
+
not field.is_required and
|
|
260
|
+
not field.is_repeated)
|
|
259
261
|
|
|
260
262
|
|
|
261
263
|
def _IsMapField(field):
|
|
@@ -268,7 +270,6 @@ def _IsMessageMapField(field):
|
|
|
268
270
|
return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
|
|
269
271
|
|
|
270
272
|
def _AttachFieldHelpers(cls, field_descriptor):
|
|
271
|
-
is_repeated = field_descriptor.label == _FieldDescriptor.LABEL_REPEATED
|
|
272
273
|
field_descriptor._default_constructor = _DefaultValueConstructorForField(
|
|
273
274
|
field_descriptor
|
|
274
275
|
)
|
|
@@ -281,7 +282,9 @@ def _AttachFieldHelpers(cls, field_descriptor):
|
|
|
281
282
|
type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False
|
|
282
283
|
)
|
|
283
284
|
|
|
284
|
-
if is_repeated and wire_format.IsTypePackable(
|
|
285
|
+
if field_descriptor.is_repeated and wire_format.IsTypePackable(
|
|
286
|
+
field_descriptor.type
|
|
287
|
+
):
|
|
285
288
|
# To support wire compatibility of adding packed = true, add a decoder for
|
|
286
289
|
# packed values regardless of the field's options.
|
|
287
290
|
AddFieldByTag(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
|
|
@@ -290,7 +293,7 @@ def _AttachFieldHelpers(cls, field_descriptor):
|
|
|
290
293
|
def _MaybeAddEncoder(cls, field_descriptor):
|
|
291
294
|
if hasattr(field_descriptor, '_encoder'):
|
|
292
295
|
return
|
|
293
|
-
is_repeated =
|
|
296
|
+
is_repeated = field_descriptor.is_repeated
|
|
294
297
|
is_map_entry = _IsMapField(field_descriptor)
|
|
295
298
|
is_packed = field_descriptor.is_packed
|
|
296
299
|
|
|
@@ -315,7 +318,7 @@ def _MaybeAddDecoder(cls, field_descriptor):
|
|
|
315
318
|
if hasattr(field_descriptor, '_decoders'):
|
|
316
319
|
return
|
|
317
320
|
|
|
318
|
-
is_repeated = field_descriptor.
|
|
321
|
+
is_repeated = field_descriptor.is_repeated
|
|
319
322
|
is_map_entry = _IsMapField(field_descriptor)
|
|
320
323
|
helper_decoders = {}
|
|
321
324
|
|
|
@@ -386,7 +389,7 @@ def _AddEnumValues(descriptor, cls):
|
|
|
386
389
|
|
|
387
390
|
|
|
388
391
|
def _GetInitializeDefaultForMap(field):
|
|
389
|
-
if field.
|
|
392
|
+
if not field.is_repeated:
|
|
390
393
|
raise ValueError('map_entry set on non-repeated field %s' % (
|
|
391
394
|
field.name))
|
|
392
395
|
fields_by_name = field.message_type.fields_by_name
|
|
@@ -424,7 +427,7 @@ def _DefaultValueConstructorForField(field):
|
|
|
424
427
|
if _IsMapField(field):
|
|
425
428
|
return _GetInitializeDefaultForMap(field)
|
|
426
429
|
|
|
427
|
-
if field.
|
|
430
|
+
if field.is_repeated:
|
|
428
431
|
if field.has_default_value and field.default_value != []:
|
|
429
432
|
raise ValueError('Repeated field default value not empty list: %s' % (
|
|
430
433
|
field.default_value))
|
|
@@ -495,6 +498,35 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
495
498
|
return value
|
|
496
499
|
|
|
497
500
|
def init(self, **kwargs):
|
|
501
|
+
|
|
502
|
+
def init_wkt_or_merge(field, msg, value):
|
|
503
|
+
if isinstance(value, message_mod.Message):
|
|
504
|
+
msg.MergeFrom(value)
|
|
505
|
+
elif (
|
|
506
|
+
isinstance(value, dict)
|
|
507
|
+
and field.message_type.full_name == _StructFullTypeName
|
|
508
|
+
):
|
|
509
|
+
msg.Clear()
|
|
510
|
+
if len(value) == 1 and 'fields' in value:
|
|
511
|
+
try:
|
|
512
|
+
msg.update(value)
|
|
513
|
+
except:
|
|
514
|
+
msg.Clear()
|
|
515
|
+
msg.__init__(**value)
|
|
516
|
+
else:
|
|
517
|
+
msg.update(value)
|
|
518
|
+
elif hasattr(msg, '_internal_assign'):
|
|
519
|
+
msg._internal_assign(value)
|
|
520
|
+
else:
|
|
521
|
+
raise TypeError(
|
|
522
|
+
'Message field {0}.{1} must be initialized with a '
|
|
523
|
+
'dict or instance of same class, got {2}.'.format(
|
|
524
|
+
message_descriptor.name,
|
|
525
|
+
field.name,
|
|
526
|
+
type(value).__name__,
|
|
527
|
+
)
|
|
528
|
+
)
|
|
529
|
+
|
|
498
530
|
self._cached_byte_size = 0
|
|
499
531
|
self._cached_byte_size_dirty = len(kwargs) > 0
|
|
500
532
|
self._fields = {}
|
|
@@ -516,21 +548,28 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
516
548
|
if field_value is None:
|
|
517
549
|
# field=None is the same as no field at all.
|
|
518
550
|
continue
|
|
519
|
-
if field.
|
|
551
|
+
if field.is_repeated:
|
|
520
552
|
field_copy = field._default_constructor(self)
|
|
521
553
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite
|
|
522
554
|
if _IsMapField(field):
|
|
523
555
|
if _IsMessageMapField(field):
|
|
524
556
|
for key in field_value:
|
|
525
|
-
|
|
557
|
+
item_value = field_value[key]
|
|
558
|
+
if isinstance(item_value, dict):
|
|
559
|
+
field_copy[key].__init__(**item_value)
|
|
560
|
+
else:
|
|
561
|
+
field_copy[key].MergeFrom(item_value)
|
|
526
562
|
else:
|
|
527
563
|
field_copy.update(field_value)
|
|
528
564
|
else:
|
|
529
565
|
for val in field_value:
|
|
530
|
-
if isinstance(val, dict)
|
|
566
|
+
if isinstance(val, dict) and (
|
|
567
|
+
field.message_type.full_name != _StructFullTypeName
|
|
568
|
+
):
|
|
531
569
|
field_copy.add(**val)
|
|
532
570
|
else:
|
|
533
|
-
field_copy.add()
|
|
571
|
+
new_msg = field_copy.add()
|
|
572
|
+
init_wkt_or_merge(field, new_msg, val)
|
|
534
573
|
else: # Scalar
|
|
535
574
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
|
|
536
575
|
field_value = [_GetIntegerEnumValue(field.enum_type, val)
|
|
@@ -539,38 +578,14 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
539
578
|
self._fields[field] = field_copy
|
|
540
579
|
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
541
580
|
field_copy = field._default_constructor(self)
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
field_copy.Clear()
|
|
548
|
-
if len(field_value) == 1 and 'fields' in field_value:
|
|
549
|
-
try:
|
|
550
|
-
field_copy.update(field_value)
|
|
551
|
-
except:
|
|
552
|
-
# Fall back to init normal message field
|
|
553
|
-
field_copy.Clear()
|
|
554
|
-
new_val = field.message_type._concrete_class(**field_value)
|
|
555
|
-
else:
|
|
556
|
-
field_copy.update(field_value)
|
|
557
|
-
else:
|
|
558
|
-
new_val = field.message_type._concrete_class(**field_value)
|
|
559
|
-
elif hasattr(field_copy, '_internal_assign'):
|
|
560
|
-
field_copy._internal_assign(field_value)
|
|
581
|
+
if isinstance(field_value, dict) and (
|
|
582
|
+
field.message_type.full_name != _StructFullTypeName
|
|
583
|
+
):
|
|
584
|
+
new_val = field.message_type._concrete_class(**field_value)
|
|
585
|
+
field_copy.MergeFrom(new_val)
|
|
561
586
|
else:
|
|
562
|
-
raise TypeError(
|
|
563
|
-
'Message field {0}.{1} must be initialized with a '
|
|
564
|
-
'dict or instance of same class, got {2}.'.format(
|
|
565
|
-
message_descriptor.name,
|
|
566
|
-
field_name,
|
|
567
|
-
type(field_value).__name__,
|
|
568
|
-
)
|
|
569
|
-
)
|
|
570
|
-
|
|
571
|
-
if new_val != None:
|
|
572
587
|
try:
|
|
573
|
-
field_copy
|
|
588
|
+
init_wkt_or_merge(field, field_copy, field_value)
|
|
574
589
|
except TypeError:
|
|
575
590
|
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
|
|
576
591
|
self._fields[field] = field_copy
|
|
@@ -631,7 +646,7 @@ def _AddPropertiesForField(field, cls):
|
|
|
631
646
|
constant_name = field.name.upper() + '_FIELD_NUMBER'
|
|
632
647
|
setattr(cls, constant_name, field.number)
|
|
633
648
|
|
|
634
|
-
if field.
|
|
649
|
+
if field.is_repeated:
|
|
635
650
|
_AddPropertiesForRepeatedField(field, cls)
|
|
636
651
|
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
637
652
|
_AddPropertiesForNonRepeatedCompositeField(field, cls)
|
|
@@ -716,14 +731,14 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
|
|
|
716
731
|
|
|
717
732
|
def field_setter(self, new_value):
|
|
718
733
|
# pylint: disable=protected-access
|
|
719
|
-
# Testing the value for truthiness captures all of the
|
|
720
|
-
# (0, 0.0, enum 0, and False).
|
|
734
|
+
# Testing the value for truthiness captures all of the implicit presence
|
|
735
|
+
# defaults (0, 0.0, enum 0, and False), except for -0.0.
|
|
721
736
|
try:
|
|
722
737
|
new_value = type_checker.CheckValue(new_value)
|
|
723
738
|
except TypeError as e:
|
|
724
739
|
raise TypeError(
|
|
725
740
|
'Cannot set %s to %.1024r: %s' % (field.full_name, new_value, e))
|
|
726
|
-
if not field.has_presence and
|
|
741
|
+
if not field.has_presence and decoder.IsDefaultScalarValue(new_value):
|
|
727
742
|
self._fields.pop(field, None)
|
|
728
743
|
else:
|
|
729
744
|
self._fields[field] = new_value
|
|
@@ -822,6 +837,13 @@ def _AddPropertiesForExtensions(descriptor, cls):
|
|
|
822
837
|
pool = descriptor.file.pool
|
|
823
838
|
|
|
824
839
|
def _AddStaticMethods(cls):
|
|
840
|
+
|
|
841
|
+
def RegisterExtension(_):
|
|
842
|
+
"""no-op to keep generated code <=4.23 working with new runtimes."""
|
|
843
|
+
# This was originally removed in 5.26 (cl/595989309).
|
|
844
|
+
pass
|
|
845
|
+
|
|
846
|
+
cls.RegisterExtension = staticmethod(RegisterExtension)
|
|
825
847
|
def FromString(s):
|
|
826
848
|
message = cls()
|
|
827
849
|
message.MergeFromString(s)
|
|
@@ -833,7 +855,7 @@ def _IsPresent(item):
|
|
|
833
855
|
"""Given a (FieldDescriptor, value) tuple from _fields, return true if the
|
|
834
856
|
value should be included in the list returned by ListFields()."""
|
|
835
857
|
|
|
836
|
-
if item[0].
|
|
858
|
+
if item[0].is_repeated:
|
|
837
859
|
return bool(item[1])
|
|
838
860
|
elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
839
861
|
return item[1]._is_present_in_parent
|
|
@@ -857,7 +879,7 @@ def _AddHasFieldMethod(message_descriptor, cls):
|
|
|
857
879
|
|
|
858
880
|
hassable_fields = {}
|
|
859
881
|
for field in message_descriptor.fields:
|
|
860
|
-
if field.
|
|
882
|
+
if field.is_repeated:
|
|
861
883
|
continue
|
|
862
884
|
# For proto3, only submessages and fields inside a oneof have presence.
|
|
863
885
|
if not field.has_presence:
|
|
@@ -945,7 +967,7 @@ def _AddHasExtensionMethod(cls):
|
|
|
945
967
|
"""Helper for _AddMessageMethods()."""
|
|
946
968
|
def HasExtension(self, field_descriptor):
|
|
947
969
|
extension_dict._VerifyExtensionHandle(self, field_descriptor)
|
|
948
|
-
if field_descriptor.
|
|
970
|
+
if field_descriptor.is_repeated:
|
|
949
971
|
raise KeyError('"%s" is repeated.' % field_descriptor.full_name)
|
|
950
972
|
|
|
951
973
|
if field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
@@ -1192,12 +1214,10 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
|
|
|
1192
1214
|
return length # Return this for legacy reasons.
|
|
1193
1215
|
cls.MergeFromString = MergeFromString
|
|
1194
1216
|
|
|
1195
|
-
local_ReadTag = decoder.ReadTag
|
|
1196
|
-
local_SkipField = decoder.SkipField
|
|
1197
1217
|
fields_by_tag = cls._fields_by_tag
|
|
1198
1218
|
message_set_decoders_by_tag = cls._message_set_decoders_by_tag
|
|
1199
1219
|
|
|
1200
|
-
def InternalParse(self, buffer, pos, end):
|
|
1220
|
+
def InternalParse(self, buffer, pos, end, current_depth=0):
|
|
1201
1221
|
"""Create a message from serialized bytes.
|
|
1202
1222
|
|
|
1203
1223
|
Args:
|
|
@@ -1215,7 +1235,7 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
|
|
|
1215
1235
|
self._Modified()
|
|
1216
1236
|
field_dict = self._fields
|
|
1217
1237
|
while pos != end:
|
|
1218
|
-
(tag_bytes, new_pos) =
|
|
1238
|
+
(tag_bytes, new_pos) = decoder.ReadTag(buffer, pos)
|
|
1219
1239
|
field_decoder, field_des = message_set_decoders_by_tag.get(
|
|
1220
1240
|
tag_bytes, (None, None)
|
|
1221
1241
|
)
|
|
@@ -1226,31 +1246,28 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
|
|
|
1226
1246
|
if field_des is None:
|
|
1227
1247
|
if not self._unknown_fields: # pylint: disable=protected-access
|
|
1228
1248
|
self._unknown_fields = [] # pylint: disable=protected-access
|
|
1229
|
-
|
|
1230
|
-
(tag, _) = decoder._DecodeVarint(tag_bytes, 0)
|
|
1231
|
-
field_number, wire_type = wire_format.UnpackTag(tag)
|
|
1249
|
+
field_number, wire_type = decoder.DecodeTag(tag_bytes)
|
|
1232
1250
|
if field_number == 0:
|
|
1233
1251
|
raise message_mod.DecodeError('Field number 0 is illegal.')
|
|
1234
|
-
# TODO: remove old_pos.
|
|
1235
|
-
old_pos = new_pos
|
|
1236
1252
|
(data, new_pos) = decoder._DecodeUnknownField(
|
|
1237
|
-
buffer, new_pos,
|
|
1238
|
-
|
|
1239
|
-
return pos
|
|
1240
|
-
# TODO: remove _unknown_fields.
|
|
1241
|
-
new_pos = local_SkipField(buffer, old_pos, end, tag_bytes)
|
|
1253
|
+
buffer, new_pos, end, field_number, wire_type
|
|
1254
|
+
) # pylint: disable=protected-access
|
|
1242
1255
|
if new_pos == -1:
|
|
1243
1256
|
return pos
|
|
1244
1257
|
self._unknown_fields.append(
|
|
1245
|
-
(tag_bytes, buffer[
|
|
1258
|
+
(tag_bytes, buffer[pos + len(tag_bytes) : new_pos].tobytes())
|
|
1259
|
+
)
|
|
1246
1260
|
pos = new_pos
|
|
1247
1261
|
else:
|
|
1248
1262
|
_MaybeAddDecoder(cls, field_des)
|
|
1249
1263
|
field_decoder = field_des._decoders[is_packed]
|
|
1250
|
-
pos = field_decoder(
|
|
1264
|
+
pos = field_decoder(
|
|
1265
|
+
buffer, new_pos, end, self, field_dict, current_depth
|
|
1266
|
+
)
|
|
1251
1267
|
if field_des.containing_oneof:
|
|
1252
1268
|
self._UpdateOneofState(field_des)
|
|
1253
1269
|
return pos
|
|
1270
|
+
|
|
1254
1271
|
cls._InternalParse = InternalParse
|
|
1255
1272
|
|
|
1256
1273
|
|
|
@@ -1259,7 +1276,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1259
1276
|
protocol message class."""
|
|
1260
1277
|
|
|
1261
1278
|
required_fields = [field for field in message_descriptor.fields
|
|
1262
|
-
if field.
|
|
1279
|
+
if field.is_required]
|
|
1263
1280
|
|
|
1264
1281
|
def IsInitialized(self, errors=None):
|
|
1265
1282
|
"""Checks if all required fields of a message are set.
|
|
@@ -1284,7 +1301,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1284
1301
|
|
|
1285
1302
|
for field, value in list(self._fields.items()): # dict can change size!
|
|
1286
1303
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
1287
|
-
if field.
|
|
1304
|
+
if field.is_repeated:
|
|
1288
1305
|
if (field.message_type._is_map_entry):
|
|
1289
1306
|
continue
|
|
1290
1307
|
for element in value:
|
|
@@ -1332,7 +1349,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1332
1349
|
else:
|
|
1333
1350
|
# ScalarMaps can't have any initialization errors.
|
|
1334
1351
|
pass
|
|
1335
|
-
elif field.
|
|
1352
|
+
elif field.is_repeated:
|
|
1336
1353
|
for i in range(len(value)):
|
|
1337
1354
|
element = value[i]
|
|
1338
1355
|
prefix = '%s[%d].' % (name, i)
|
|
@@ -1357,7 +1374,6 @@ def _FullyQualifiedClassName(klass):
|
|
|
1357
1374
|
|
|
1358
1375
|
|
|
1359
1376
|
def _AddMergeFromMethod(cls):
|
|
1360
|
-
LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
|
|
1361
1377
|
CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
|
|
1362
1378
|
|
|
1363
1379
|
def MergeFrom(self, msg):
|
|
@@ -1373,7 +1389,7 @@ def _AddMergeFromMethod(cls):
|
|
|
1373
1389
|
fields = self._fields
|
|
1374
1390
|
|
|
1375
1391
|
for field, value in msg._fields.items():
|
|
1376
|
-
if field.
|
|
1392
|
+
if field.is_repeated:
|
|
1377
1393
|
field_value = fields.get(field)
|
|
1378
1394
|
if field_value is None:
|
|
1379
1395
|
# Construct a new object to represent this field.
|
|
@@ -1442,7 +1458,7 @@ def _DiscardUnknownFields(self):
|
|
|
1442
1458
|
if _IsMessageMapField(field):
|
|
1443
1459
|
for key in value:
|
|
1444
1460
|
value[key].DiscardUnknownFields()
|
|
1445
|
-
elif field.
|
|
1461
|
+
elif field.is_repeated:
|
|
1446
1462
|
for sub_message in value:
|
|
1447
1463
|
sub_message.DiscardUnknownFields()
|
|
1448
1464
|
else:
|
|
@@ -37,6 +37,9 @@ class LocalTestResult(unittest.TestResult):
|
|
|
37
37
|
def addSkip(self, test, reason):
|
|
38
38
|
pass
|
|
39
39
|
|
|
40
|
+
def addDuration(self, test, duration):
|
|
41
|
+
pass
|
|
42
|
+
|
|
40
43
|
|
|
41
44
|
class ReferenceLeakCheckerMixin(object):
|
|
42
45
|
"""A mixin class for TestCase, which checks reference counts."""
|
|
@@ -59,11 +62,13 @@ class ReferenceLeakCheckerMixin(object):
|
|
|
59
62
|
super(ReferenceLeakCheckerMixin, self).run(result=result)
|
|
60
63
|
super(ReferenceLeakCheckerMixin, self).run(result=result)
|
|
61
64
|
|
|
62
|
-
oldrefcount = 0
|
|
63
65
|
local_result = LocalTestResult(result)
|
|
64
66
|
num_flakes = 0
|
|
65
|
-
|
|
66
67
|
refcount_deltas = []
|
|
68
|
+
|
|
69
|
+
# Observe the refcount, then create oldrefcount which actually makes the
|
|
70
|
+
# refcount 1 higher than the recorded value immediately
|
|
71
|
+
oldrefcount = self._getRefcounts()
|
|
67
72
|
while len(refcount_deltas) < self.NB_RUNS:
|
|
68
73
|
oldrefcount = self._getRefcounts()
|
|
69
74
|
super(ReferenceLeakCheckerMixin, self).run(result=local_result)
|
|
@@ -87,6 +92,10 @@ class ReferenceLeakCheckerMixin(object):
|
|
|
87
92
|
result.addError(self, sys.exc_info())
|
|
88
93
|
|
|
89
94
|
def _getRefcounts(self):
|
|
95
|
+
if hasattr(sys, "_clear_internal_caches"): # Since 3.13
|
|
96
|
+
sys._clear_internal_caches() # pylint: disable=protected-access
|
|
97
|
+
else:
|
|
98
|
+
sys._clear_type_cache() # pylint: disable=protected-access
|
|
90
99
|
copyreg.dispatch_table.clear()
|
|
91
100
|
copyreg.dispatch_table.update(self._saved_pickle_registry)
|
|
92
101
|
# It is sometimes necessary to gc.collect() multiple times, to ensure
|
|
@@ -22,16 +22,20 @@ TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
|
|
|
22
22
|
|
|
23
23
|
__author__ = 'robinson@google.com (Will Robinson)'
|
|
24
24
|
|
|
25
|
-
import struct
|
|
26
25
|
import numbers
|
|
26
|
+
import struct
|
|
27
|
+
import warnings
|
|
27
28
|
|
|
29
|
+
from google.protobuf import descriptor
|
|
28
30
|
from google.protobuf.internal import decoder
|
|
29
31
|
from google.protobuf.internal import encoder
|
|
30
32
|
from google.protobuf.internal import wire_format
|
|
31
|
-
from google.protobuf import descriptor
|
|
32
33
|
|
|
33
34
|
_FieldDescriptor = descriptor.FieldDescriptor
|
|
34
|
-
|
|
35
|
+
# TODO: Remove this warning count after 34.0
|
|
36
|
+
# Assign bool to int/enum warnings will print 100 times at most which should
|
|
37
|
+
# be enough for users to notice and do not cause timeout.
|
|
38
|
+
_BoolWarningCount = 100
|
|
35
39
|
|
|
36
40
|
def TruncateToFourByteFloat(original):
|
|
37
41
|
return struct.unpack('<f', struct.pack('<f', original))[0]
|
|
@@ -113,12 +117,21 @@ class BoolValueChecker(object):
|
|
|
113
117
|
"""Type checker used for bool fields."""
|
|
114
118
|
|
|
115
119
|
def CheckValue(self, proposed_value):
|
|
116
|
-
if not hasattr(proposed_value, '__index__')
|
|
117
|
-
|
|
120
|
+
if not hasattr(proposed_value, '__index__'):
|
|
121
|
+
# Under NumPy 2.3, numpy.bool does not have an __index__ method.
|
|
122
|
+
if (type(proposed_value).__module__ == 'numpy' and
|
|
123
|
+
type(proposed_value).__name__ == 'bool'):
|
|
124
|
+
return bool(proposed_value)
|
|
125
|
+
message = ('%.1024r has type %s, but expected one of: %s' %
|
|
126
|
+
(proposed_value, type(proposed_value), (bool, int)))
|
|
127
|
+
raise TypeError(message)
|
|
128
|
+
|
|
129
|
+
if (type(proposed_value).__module__ == 'numpy' and
|
|
118
130
|
type(proposed_value).__name__ == 'ndarray'):
|
|
119
131
|
message = ('%.1024r has type %s, but expected one of: %s' %
|
|
120
132
|
(proposed_value, type(proposed_value), (bool, int)))
|
|
121
133
|
raise TypeError(message)
|
|
134
|
+
|
|
122
135
|
return bool(proposed_value)
|
|
123
136
|
|
|
124
137
|
def DefaultValue(self):
|
|
@@ -132,6 +145,21 @@ class IntValueChecker(object):
|
|
|
132
145
|
"""Checker used for integer fields. Performs type-check and range check."""
|
|
133
146
|
|
|
134
147
|
def CheckValue(self, proposed_value):
|
|
148
|
+
global _BoolWarningCount
|
|
149
|
+
if type(proposed_value) == bool and _BoolWarningCount > 0:
|
|
150
|
+
_BoolWarningCount -= 1
|
|
151
|
+
message = (
|
|
152
|
+
'%.1024r has type %s, but expected one of: %s. This warning '
|
|
153
|
+
'will turn into error in 7.34.0, please fix it before that.'
|
|
154
|
+
% (
|
|
155
|
+
proposed_value,
|
|
156
|
+
type(proposed_value),
|
|
157
|
+
(int,),
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
# TODO: Raise errors in 2026 Q1 release
|
|
161
|
+
warnings.warn(message)
|
|
162
|
+
|
|
135
163
|
if not hasattr(proposed_value, '__index__') or (
|
|
136
164
|
type(proposed_value).__module__ == 'numpy' and
|
|
137
165
|
type(proposed_value).__name__ == 'ndarray'):
|
|
@@ -158,6 +186,20 @@ class EnumValueChecker(object):
|
|
|
158
186
|
self._enum_type = enum_type
|
|
159
187
|
|
|
160
188
|
def CheckValue(self, proposed_value):
|
|
189
|
+
global _BoolWarningCount
|
|
190
|
+
if type(proposed_value) == bool and _BoolWarningCount > 0:
|
|
191
|
+
_BoolWarningCount -= 1
|
|
192
|
+
message = (
|
|
193
|
+
'%.1024r has type %s, but expected one of: %s. This warning '
|
|
194
|
+
'will turn into error in 7.34.0, please fix it before that.'
|
|
195
|
+
% (
|
|
196
|
+
proposed_value,
|
|
197
|
+
type(proposed_value),
|
|
198
|
+
(int,),
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
# TODO: Raise errors in 2026 Q1 release
|
|
202
|
+
warnings.warn(message)
|
|
161
203
|
if not isinstance(proposed_value, numbers.Integral):
|
|
162
204
|
message = ('%.1024r has type %s, but expected one of: %s' %
|
|
163
205
|
(proposed_value, type(proposed_value), (int,)))
|
|
@@ -231,6 +273,7 @@ class Uint64ValueChecker(IntValueChecker):
|
|
|
231
273
|
# The max 4 bytes float is about 3.4028234663852886e+38
|
|
232
274
|
_FLOAT_MAX = float.fromhex('0x1.fffffep+127')
|
|
233
275
|
_FLOAT_MIN = -_FLOAT_MAX
|
|
276
|
+
_MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e38
|
|
234
277
|
_INF = float('inf')
|
|
235
278
|
_NEG_INF = float('-inf')
|
|
236
279
|
|
|
@@ -269,8 +312,12 @@ class FloatValueChecker(DoubleValueChecker):
|
|
|
269
312
|
converted_value = super().CheckValue(proposed_value)
|
|
270
313
|
# This inf rounding matches the C++ proto SafeDoubleToFloat logic.
|
|
271
314
|
if converted_value > _FLOAT_MAX:
|
|
315
|
+
if converted_value <= _MAX_FLOAT_AS_DOUBLE_ROUNDED:
|
|
316
|
+
return _FLOAT_MAX
|
|
272
317
|
return _INF
|
|
273
318
|
if converted_value < _FLOAT_MIN:
|
|
319
|
+
if converted_value >= -_MAX_FLOAT_AS_DOUBLE_ROUNDED:
|
|
320
|
+
return _FLOAT_MIN
|
|
274
321
|
return _NEG_INF
|
|
275
322
|
|
|
276
323
|
return TruncateToFourByteFloat(converted_value)
|