protobuf 6.30.0__cp39-cp39-win_amd64.whl → 6.33.2__cp39-cp39-win_amd64.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.
- google/_upb/_message.cp39-win_amd64.pyd +0 -0
- google/protobuf/__init__.py +1 -1
- google/protobuf/any.py +15 -1
- google/protobuf/any_pb2.py +3 -3
- google/protobuf/api_pb2.py +13 -9
- google/protobuf/compiler/plugin_pb2.py +3 -3
- google/protobuf/descriptor.py +413 -248
- google/protobuf/descriptor_pb2.py +273 -120
- google/protobuf/descriptor_pool.py +27 -12
- google/protobuf/duration_pb2.py +3 -3
- google/protobuf/empty_pb2.py +3 -3
- google/protobuf/field_mask_pb2.py +3 -3
- google/protobuf/internal/api_implementation.py +0 -6
- google/protobuf/internal/decoder.py +106 -23
- 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 +71 -52
- google/protobuf/internal/testing_refleaks.py +8 -2
- google/protobuf/internal/type_checkers.py +47 -5
- google/protobuf/internal/well_known_types.py +60 -43
- google/protobuf/json_format.py +88 -62
- google/protobuf/message_factory.py +16 -0
- google/protobuf/runtime_version.py +7 -27
- google/protobuf/source_context_pb2.py +3 -3
- google/protobuf/struct_pb2.py +3 -3
- google/protobuf/text_format.py +41 -26
- google/protobuf/timestamp_pb2.py +3 -3
- google/protobuf/type_pb2.py +3 -3
- google/protobuf/wrappers_pb2.py +3 -3
- {protobuf-6.30.0.dist-info → protobuf-6.33.2.dist-info}/METADATA +1 -1
- protobuf-6.33.2.dist-info/RECORD +59 -0
- protobuf-6.30.0.dist-info/RECORD +0 -59
- {protobuf-6.30.0.dist-info → protobuf-6.33.2.dist-info}/LICENSE +0 -0
- {protobuf-6.30.0.dist-info → protobuf-6.33.2.dist-info}/WHEEL +0 -0
|
@@ -256,7 +256,8 @@ def _IsMessageSetExtension(field):
|
|
|
256
256
|
field.containing_type.has_options and
|
|
257
257
|
field.containing_type.GetOptions().message_set_wire_format and
|
|
258
258
|
field.type == _FieldDescriptor.TYPE_MESSAGE and
|
|
259
|
-
field.
|
|
259
|
+
not field.is_required and
|
|
260
|
+
not field.is_repeated)
|
|
260
261
|
|
|
261
262
|
|
|
262
263
|
def _IsMapField(field):
|
|
@@ -269,7 +270,6 @@ def _IsMessageMapField(field):
|
|
|
269
270
|
return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
|
|
270
271
|
|
|
271
272
|
def _AttachFieldHelpers(cls, field_descriptor):
|
|
272
|
-
is_repeated = field_descriptor.label == _FieldDescriptor.LABEL_REPEATED
|
|
273
273
|
field_descriptor._default_constructor = _DefaultValueConstructorForField(
|
|
274
274
|
field_descriptor
|
|
275
275
|
)
|
|
@@ -282,7 +282,9 @@ def _AttachFieldHelpers(cls, field_descriptor):
|
|
|
282
282
|
type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False
|
|
283
283
|
)
|
|
284
284
|
|
|
285
|
-
if is_repeated and wire_format.IsTypePackable(
|
|
285
|
+
if field_descriptor.is_repeated and wire_format.IsTypePackable(
|
|
286
|
+
field_descriptor.type
|
|
287
|
+
):
|
|
286
288
|
# To support wire compatibility of adding packed = true, add a decoder for
|
|
287
289
|
# packed values regardless of the field's options.
|
|
288
290
|
AddFieldByTag(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
|
|
@@ -291,7 +293,7 @@ def _AttachFieldHelpers(cls, field_descriptor):
|
|
|
291
293
|
def _MaybeAddEncoder(cls, field_descriptor):
|
|
292
294
|
if hasattr(field_descriptor, '_encoder'):
|
|
293
295
|
return
|
|
294
|
-
is_repeated =
|
|
296
|
+
is_repeated = field_descriptor.is_repeated
|
|
295
297
|
is_map_entry = _IsMapField(field_descriptor)
|
|
296
298
|
is_packed = field_descriptor.is_packed
|
|
297
299
|
|
|
@@ -316,7 +318,7 @@ def _MaybeAddDecoder(cls, field_descriptor):
|
|
|
316
318
|
if hasattr(field_descriptor, '_decoders'):
|
|
317
319
|
return
|
|
318
320
|
|
|
319
|
-
is_repeated = field_descriptor.
|
|
321
|
+
is_repeated = field_descriptor.is_repeated
|
|
320
322
|
is_map_entry = _IsMapField(field_descriptor)
|
|
321
323
|
helper_decoders = {}
|
|
322
324
|
|
|
@@ -387,7 +389,7 @@ def _AddEnumValues(descriptor, cls):
|
|
|
387
389
|
|
|
388
390
|
|
|
389
391
|
def _GetInitializeDefaultForMap(field):
|
|
390
|
-
if field.
|
|
392
|
+
if not field.is_repeated:
|
|
391
393
|
raise ValueError('map_entry set on non-repeated field %s' % (
|
|
392
394
|
field.name))
|
|
393
395
|
fields_by_name = field.message_type.fields_by_name
|
|
@@ -425,7 +427,7 @@ def _DefaultValueConstructorForField(field):
|
|
|
425
427
|
if _IsMapField(field):
|
|
426
428
|
return _GetInitializeDefaultForMap(field)
|
|
427
429
|
|
|
428
|
-
if field.
|
|
430
|
+
if field.is_repeated:
|
|
429
431
|
if field.has_default_value and field.default_value != []:
|
|
430
432
|
raise ValueError('Repeated field default value not empty list: %s' % (
|
|
431
433
|
field.default_value))
|
|
@@ -496,6 +498,35 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
496
498
|
return value
|
|
497
499
|
|
|
498
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
|
+
|
|
499
530
|
self._cached_byte_size = 0
|
|
500
531
|
self._cached_byte_size_dirty = len(kwargs) > 0
|
|
501
532
|
self._fields = {}
|
|
@@ -517,7 +548,7 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
517
548
|
if field_value is None:
|
|
518
549
|
# field=None is the same as no field at all.
|
|
519
550
|
continue
|
|
520
|
-
if field.
|
|
551
|
+
if field.is_repeated:
|
|
521
552
|
field_copy = field._default_constructor(self)
|
|
522
553
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite
|
|
523
554
|
if _IsMapField(field):
|
|
@@ -532,10 +563,13 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
532
563
|
field_copy.update(field_value)
|
|
533
564
|
else:
|
|
534
565
|
for val in field_value:
|
|
535
|
-
if isinstance(val, dict)
|
|
566
|
+
if isinstance(val, dict) and (
|
|
567
|
+
field.message_type.full_name != _StructFullTypeName
|
|
568
|
+
):
|
|
536
569
|
field_copy.add(**val)
|
|
537
570
|
else:
|
|
538
|
-
field_copy.add()
|
|
571
|
+
new_msg = field_copy.add()
|
|
572
|
+
init_wkt_or_merge(field, new_msg, val)
|
|
539
573
|
else: # Scalar
|
|
540
574
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
|
|
541
575
|
field_value = [_GetIntegerEnumValue(field.enum_type, val)
|
|
@@ -544,38 +578,14 @@ def _AddInitMethod(message_descriptor, cls):
|
|
|
544
578
|
self._fields[field] = field_copy
|
|
545
579
|
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
546
580
|
field_copy = field._default_constructor(self)
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
field_copy.Clear()
|
|
553
|
-
if len(field_value) == 1 and 'fields' in field_value:
|
|
554
|
-
try:
|
|
555
|
-
field_copy.update(field_value)
|
|
556
|
-
except:
|
|
557
|
-
# Fall back to init normal message field
|
|
558
|
-
field_copy.Clear()
|
|
559
|
-
new_val = field.message_type._concrete_class(**field_value)
|
|
560
|
-
else:
|
|
561
|
-
field_copy.update(field_value)
|
|
562
|
-
else:
|
|
563
|
-
new_val = field.message_type._concrete_class(**field_value)
|
|
564
|
-
elif hasattr(field_copy, '_internal_assign'):
|
|
565
|
-
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)
|
|
566
586
|
else:
|
|
567
|
-
raise TypeError(
|
|
568
|
-
'Message field {0}.{1} must be initialized with a '
|
|
569
|
-
'dict or instance of same class, got {2}.'.format(
|
|
570
|
-
message_descriptor.name,
|
|
571
|
-
field_name,
|
|
572
|
-
type(field_value).__name__,
|
|
573
|
-
)
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
if new_val != None:
|
|
577
587
|
try:
|
|
578
|
-
field_copy
|
|
588
|
+
init_wkt_or_merge(field, field_copy, field_value)
|
|
579
589
|
except TypeError:
|
|
580
590
|
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
|
|
581
591
|
self._fields[field] = field_copy
|
|
@@ -636,7 +646,7 @@ def _AddPropertiesForField(field, cls):
|
|
|
636
646
|
constant_name = field.name.upper() + '_FIELD_NUMBER'
|
|
637
647
|
setattr(cls, constant_name, field.number)
|
|
638
648
|
|
|
639
|
-
if field.
|
|
649
|
+
if field.is_repeated:
|
|
640
650
|
_AddPropertiesForRepeatedField(field, cls)
|
|
641
651
|
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
642
652
|
_AddPropertiesForNonRepeatedCompositeField(field, cls)
|
|
@@ -827,6 +837,13 @@ def _AddPropertiesForExtensions(descriptor, cls):
|
|
|
827
837
|
pool = descriptor.file.pool
|
|
828
838
|
|
|
829
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)
|
|
830
847
|
def FromString(s):
|
|
831
848
|
message = cls()
|
|
832
849
|
message.MergeFromString(s)
|
|
@@ -838,7 +855,7 @@ def _IsPresent(item):
|
|
|
838
855
|
"""Given a (FieldDescriptor, value) tuple from _fields, return true if the
|
|
839
856
|
value should be included in the list returned by ListFields()."""
|
|
840
857
|
|
|
841
|
-
if item[0].
|
|
858
|
+
if item[0].is_repeated:
|
|
842
859
|
return bool(item[1])
|
|
843
860
|
elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
844
861
|
return item[1]._is_present_in_parent
|
|
@@ -862,7 +879,7 @@ def _AddHasFieldMethod(message_descriptor, cls):
|
|
|
862
879
|
|
|
863
880
|
hassable_fields = {}
|
|
864
881
|
for field in message_descriptor.fields:
|
|
865
|
-
if field.
|
|
882
|
+
if field.is_repeated:
|
|
866
883
|
continue
|
|
867
884
|
# For proto3, only submessages and fields inside a oneof have presence.
|
|
868
885
|
if not field.has_presence:
|
|
@@ -950,7 +967,7 @@ def _AddHasExtensionMethod(cls):
|
|
|
950
967
|
"""Helper for _AddMessageMethods()."""
|
|
951
968
|
def HasExtension(self, field_descriptor):
|
|
952
969
|
extension_dict._VerifyExtensionHandle(self, field_descriptor)
|
|
953
|
-
if field_descriptor.
|
|
970
|
+
if field_descriptor.is_repeated:
|
|
954
971
|
raise KeyError('"%s" is repeated.' % field_descriptor.full_name)
|
|
955
972
|
|
|
956
973
|
if field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
@@ -1200,7 +1217,7 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
|
|
|
1200
1217
|
fields_by_tag = cls._fields_by_tag
|
|
1201
1218
|
message_set_decoders_by_tag = cls._message_set_decoders_by_tag
|
|
1202
1219
|
|
|
1203
|
-
def InternalParse(self, buffer, pos, end):
|
|
1220
|
+
def InternalParse(self, buffer, pos, end, current_depth=0):
|
|
1204
1221
|
"""Create a message from serialized bytes.
|
|
1205
1222
|
|
|
1206
1223
|
Args:
|
|
@@ -1244,10 +1261,13 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
|
|
|
1244
1261
|
else:
|
|
1245
1262
|
_MaybeAddDecoder(cls, field_des)
|
|
1246
1263
|
field_decoder = field_des._decoders[is_packed]
|
|
1247
|
-
pos = field_decoder(
|
|
1264
|
+
pos = field_decoder(
|
|
1265
|
+
buffer, new_pos, end, self, field_dict, current_depth
|
|
1266
|
+
)
|
|
1248
1267
|
if field_des.containing_oneof:
|
|
1249
1268
|
self._UpdateOneofState(field_des)
|
|
1250
1269
|
return pos
|
|
1270
|
+
|
|
1251
1271
|
cls._InternalParse = InternalParse
|
|
1252
1272
|
|
|
1253
1273
|
|
|
@@ -1256,7 +1276,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1256
1276
|
protocol message class."""
|
|
1257
1277
|
|
|
1258
1278
|
required_fields = [field for field in message_descriptor.fields
|
|
1259
|
-
if field.
|
|
1279
|
+
if field.is_required]
|
|
1260
1280
|
|
|
1261
1281
|
def IsInitialized(self, errors=None):
|
|
1262
1282
|
"""Checks if all required fields of a message are set.
|
|
@@ -1281,7 +1301,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1281
1301
|
|
|
1282
1302
|
for field, value in list(self._fields.items()): # dict can change size!
|
|
1283
1303
|
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
|
1284
|
-
if field.
|
|
1304
|
+
if field.is_repeated:
|
|
1285
1305
|
if (field.message_type._is_map_entry):
|
|
1286
1306
|
continue
|
|
1287
1307
|
for element in value:
|
|
@@ -1329,7 +1349,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
|
|
|
1329
1349
|
else:
|
|
1330
1350
|
# ScalarMaps can't have any initialization errors.
|
|
1331
1351
|
pass
|
|
1332
|
-
elif field.
|
|
1352
|
+
elif field.is_repeated:
|
|
1333
1353
|
for i in range(len(value)):
|
|
1334
1354
|
element = value[i]
|
|
1335
1355
|
prefix = '%s[%d].' % (name, i)
|
|
@@ -1354,7 +1374,6 @@ def _FullyQualifiedClassName(klass):
|
|
|
1354
1374
|
|
|
1355
1375
|
|
|
1356
1376
|
def _AddMergeFromMethod(cls):
|
|
1357
|
-
LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
|
|
1358
1377
|
CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
|
|
1359
1378
|
|
|
1360
1379
|
def MergeFrom(self, msg):
|
|
@@ -1370,7 +1389,7 @@ def _AddMergeFromMethod(cls):
|
|
|
1370
1389
|
fields = self._fields
|
|
1371
1390
|
|
|
1372
1391
|
for field, value in msg._fields.items():
|
|
1373
|
-
if field.
|
|
1392
|
+
if field.is_repeated:
|
|
1374
1393
|
field_value = fields.get(field)
|
|
1375
1394
|
if field_value is None:
|
|
1376
1395
|
# Construct a new object to represent this field.
|
|
@@ -1439,7 +1458,7 @@ def _DiscardUnknownFields(self):
|
|
|
1439
1458
|
if _IsMessageMapField(field):
|
|
1440
1459
|
for key in value:
|
|
1441
1460
|
value[key].DiscardUnknownFields()
|
|
1442
|
-
elif field.
|
|
1461
|
+
elif field.is_repeated:
|
|
1443
1462
|
for sub_message in value:
|
|
1444
1463
|
sub_message.DiscardUnknownFields()
|
|
1445
1464
|
else:
|
|
@@ -62,11 +62,13 @@ class ReferenceLeakCheckerMixin(object):
|
|
|
62
62
|
super(ReferenceLeakCheckerMixin, self).run(result=result)
|
|
63
63
|
super(ReferenceLeakCheckerMixin, self).run(result=result)
|
|
64
64
|
|
|
65
|
-
oldrefcount = 0 # pylint: disable=unused-variable but needed for refcounts.
|
|
66
65
|
local_result = LocalTestResult(result)
|
|
67
66
|
num_flakes = 0
|
|
68
|
-
|
|
69
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()
|
|
70
72
|
while len(refcount_deltas) < self.NB_RUNS:
|
|
71
73
|
oldrefcount = self._getRefcounts()
|
|
72
74
|
super(ReferenceLeakCheckerMixin, self).run(result=local_result)
|
|
@@ -90,6 +92,10 @@ class ReferenceLeakCheckerMixin(object):
|
|
|
90
92
|
result.addError(self, sys.exc_info())
|
|
91
93
|
|
|
92
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
|
|
93
99
|
copyreg.dispatch_table.clear()
|
|
94
100
|
copyreg.dispatch_table.update(self._saved_pickle_registry)
|
|
95
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,)))
|
|
@@ -20,9 +20,9 @@ __author__ = 'jieluo@google.com (Jie Luo)'
|
|
|
20
20
|
import calendar
|
|
21
21
|
import collections.abc
|
|
22
22
|
import datetime
|
|
23
|
+
from typing import Union
|
|
23
24
|
import warnings
|
|
24
25
|
from google.protobuf.internal import field_mask
|
|
25
|
-
from typing import Union
|
|
26
26
|
|
|
27
27
|
FieldMask = field_mask.FieldMask
|
|
28
28
|
|
|
@@ -48,8 +48,9 @@ class Any(object):
|
|
|
48
48
|
|
|
49
49
|
__slots__ = ()
|
|
50
50
|
|
|
51
|
-
def Pack(
|
|
52
|
-
|
|
51
|
+
def Pack(
|
|
52
|
+
self, msg, type_url_prefix='type.googleapis.com/', deterministic=None
|
|
53
|
+
):
|
|
53
54
|
"""Packs the specified message into current Any message."""
|
|
54
55
|
if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/':
|
|
55
56
|
self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
|
|
@@ -113,8 +114,8 @@ class Timestamp(object):
|
|
|
113
114
|
|
|
114
115
|
Args:
|
|
115
116
|
value: A date string. Any fractional digits (or none) and any offset are
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
accepted as long as they fit into nano-seconds precision. Example of
|
|
118
|
+
accepted format: '1972-01-01T10:00:20.021-05:00'
|
|
118
119
|
|
|
119
120
|
Raises:
|
|
120
121
|
ValueError: On parsing problems.
|
|
@@ -128,7 +129,8 @@ class Timestamp(object):
|
|
|
128
129
|
timezone_offset = value.rfind('-')
|
|
129
130
|
if timezone_offset == -1:
|
|
130
131
|
raise ValueError(
|
|
131
|
-
'Failed to parse timestamp: missing valid timezone offset.'
|
|
132
|
+
'Failed to parse timestamp: missing valid timezone offset.'
|
|
133
|
+
)
|
|
132
134
|
time_value = value[0:timezone_offset]
|
|
133
135
|
# Parse datetime and nanos.
|
|
134
136
|
point_position = time_value.find('.')
|
|
@@ -137,18 +139,20 @@ class Timestamp(object):
|
|
|
137
139
|
nano_value = ''
|
|
138
140
|
else:
|
|
139
141
|
second_value = time_value[:point_position]
|
|
140
|
-
nano_value = time_value[point_position + 1:]
|
|
142
|
+
nano_value = time_value[point_position + 1 :]
|
|
141
143
|
if 't' in second_value:
|
|
142
144
|
raise ValueError(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
"time data '{0}' does not match format '%Y-%m-%dT%H:%M:%S', "
|
|
146
|
+
"lowercase 't' is not accepted".format(second_value)
|
|
147
|
+
)
|
|
145
148
|
date_object = datetime.datetime.strptime(second_value, _TIMESTAMPFORMAT)
|
|
146
149
|
td = date_object - datetime.datetime(1970, 1, 1)
|
|
147
150
|
seconds = td.seconds + td.days * _SECONDS_PER_DAY
|
|
148
151
|
if len(nano_value) > 9:
|
|
149
152
|
raise ValueError(
|
|
150
153
|
'Failed to parse Timestamp: nanos {0} more than '
|
|
151
|
-
'9 fractional digits.'.format(nano_value)
|
|
154
|
+
'9 fractional digits.'.format(nano_value)
|
|
155
|
+
)
|
|
152
156
|
if nano_value:
|
|
153
157
|
nanos = round(float('0.' + nano_value) * 1e9)
|
|
154
158
|
else:
|
|
@@ -156,18 +160,20 @@ class Timestamp(object):
|
|
|
156
160
|
# Parse timezone offsets.
|
|
157
161
|
if value[timezone_offset] == 'Z':
|
|
158
162
|
if len(value) != timezone_offset + 1:
|
|
159
|
-
raise ValueError(
|
|
160
|
-
|
|
163
|
+
raise ValueError(
|
|
164
|
+
'Failed to parse timestamp: invalid trailing data {0}.'.format(
|
|
165
|
+
value
|
|
166
|
+
)
|
|
167
|
+
)
|
|
161
168
|
else:
|
|
162
169
|
timezone = value[timezone_offset:]
|
|
163
170
|
pos = timezone.find(':')
|
|
164
171
|
if pos == -1:
|
|
165
|
-
raise ValueError(
|
|
166
|
-
'Invalid timezone offset value: {0}.'.format(timezone))
|
|
172
|
+
raise ValueError('Invalid timezone offset value: {0}.'.format(timezone))
|
|
167
173
|
if timezone[0] == '+':
|
|
168
|
-
seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
|
|
174
|
+
seconds -= (int(timezone[1:pos]) * 60 + int(timezone[pos + 1 :])) * 60
|
|
169
175
|
else:
|
|
170
|
-
seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
|
|
176
|
+
seconds += (int(timezone[1:pos]) * 60 + int(timezone[pos + 1 :])) * 60
|
|
171
177
|
# Set seconds and nanos
|
|
172
178
|
_CheckTimestampValid(seconds, nanos)
|
|
173
179
|
self.seconds = int(seconds)
|
|
@@ -175,7 +181,7 @@ class Timestamp(object):
|
|
|
175
181
|
|
|
176
182
|
def GetCurrentTime(self):
|
|
177
183
|
"""Get the current UTC into Timestamp."""
|
|
178
|
-
self.FromDatetime(datetime.datetime.
|
|
184
|
+
self.FromDatetime(datetime.datetime.now(tz=datetime.timezone.utc))
|
|
179
185
|
|
|
180
186
|
def ToNanoseconds(self):
|
|
181
187
|
"""Converts Timestamp to nanoseconds since epoch."""
|
|
@@ -185,14 +191,16 @@ class Timestamp(object):
|
|
|
185
191
|
def ToMicroseconds(self):
|
|
186
192
|
"""Converts Timestamp to microseconds since epoch."""
|
|
187
193
|
_CheckTimestampValid(self.seconds, self.nanos)
|
|
188
|
-
return (
|
|
189
|
-
|
|
194
|
+
return (
|
|
195
|
+
self.seconds * _MICROS_PER_SECOND + self.nanos // _NANOS_PER_MICROSECOND
|
|
196
|
+
)
|
|
190
197
|
|
|
191
198
|
def ToMilliseconds(self):
|
|
192
199
|
"""Converts Timestamp to milliseconds since epoch."""
|
|
193
200
|
_CheckTimestampValid(self.seconds, self.nanos)
|
|
194
|
-
return (
|
|
195
|
-
|
|
201
|
+
return (
|
|
202
|
+
self.seconds * _MILLIS_PER_SECOND + self.nanos // _NANOS_PER_MILLISECOND
|
|
203
|
+
)
|
|
196
204
|
|
|
197
205
|
def ToSeconds(self):
|
|
198
206
|
"""Converts Timestamp to seconds since epoch."""
|
|
@@ -312,7 +320,8 @@ def _CheckTimestampValid(seconds, nanos):
|
|
|
312
320
|
if nanos < 0 or nanos >= _NANOS_PER_SECOND:
|
|
313
321
|
raise ValueError(
|
|
314
322
|
'Timestamp is not valid: Nanos {} must be in a range '
|
|
315
|
-
'[0, 999999].'.format(nanos)
|
|
323
|
+
'[0, 999999].'.format(nanos)
|
|
324
|
+
)
|
|
316
325
|
|
|
317
326
|
|
|
318
327
|
class Duration(object):
|
|
@@ -332,7 +341,7 @@ class Duration(object):
|
|
|
332
341
|
_CheckDurationValid(self.seconds, self.nanos)
|
|
333
342
|
if self.seconds < 0 or self.nanos < 0:
|
|
334
343
|
result = '-'
|
|
335
|
-
seconds = -
|
|
344
|
+
seconds = -self.seconds + int((0 - self.nanos) // 1e9)
|
|
336
345
|
nanos = (0 - self.nanos) % 1e9
|
|
337
346
|
else:
|
|
338
347
|
result = ''
|
|
@@ -357,8 +366,8 @@ class Duration(object):
|
|
|
357
366
|
|
|
358
367
|
Args:
|
|
359
368
|
value: A string to be converted. The string must end with 's'. Any
|
|
360
|
-
|
|
361
|
-
|
|
369
|
+
fractional digits (or none) are accepted as long as they fit into
|
|
370
|
+
precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s
|
|
362
371
|
|
|
363
372
|
Raises:
|
|
364
373
|
ValueError: On parsing problems.
|
|
@@ -366,8 +375,7 @@ class Duration(object):
|
|
|
366
375
|
if not isinstance(value, str):
|
|
367
376
|
raise ValueError('Duration JSON value not a string: {!r}'.format(value))
|
|
368
377
|
if len(value) < 1 or value[-1] != 's':
|
|
369
|
-
raise ValueError(
|
|
370
|
-
'Duration must end with letter "s": {0}.'.format(value))
|
|
378
|
+
raise ValueError('Duration must end with letter "s": {0}.'.format(value))
|
|
371
379
|
try:
|
|
372
380
|
pos = value.find('.')
|
|
373
381
|
if pos == -1:
|
|
@@ -376,15 +384,14 @@ class Duration(object):
|
|
|
376
384
|
else:
|
|
377
385
|
seconds = int(value[:pos])
|
|
378
386
|
if value[0] == '-':
|
|
379
|
-
nanos = int(round(float('-0{0}'.format(value[pos
|
|
387
|
+
nanos = int(round(float('-0{0}'.format(value[pos:-1])) * 1e9))
|
|
380
388
|
else:
|
|
381
|
-
nanos = int(round(float('0{0}'.format(value[pos
|
|
389
|
+
nanos = int(round(float('0{0}'.format(value[pos:-1])) * 1e9))
|
|
382
390
|
_CheckDurationValid(seconds, nanos)
|
|
383
391
|
self.seconds = seconds
|
|
384
392
|
self.nanos = nanos
|
|
385
393
|
except ValueError as e:
|
|
386
|
-
raise ValueError(
|
|
387
|
-
'Couldn\'t parse duration: {0} : {1}.'.format(value, e))
|
|
394
|
+
raise ValueError("Couldn't parse duration: {0} : {1}.".format(value, e))
|
|
388
395
|
|
|
389
396
|
def ToNanoseconds(self):
|
|
390
397
|
"""Converts a Duration to nanoseconds."""
|
|
@@ -406,20 +413,23 @@ class Duration(object):
|
|
|
406
413
|
|
|
407
414
|
def FromNanoseconds(self, nanos):
|
|
408
415
|
"""Converts nanoseconds to Duration."""
|
|
409
|
-
self._NormalizeDuration(
|
|
410
|
-
|
|
416
|
+
self._NormalizeDuration(
|
|
417
|
+
nanos // _NANOS_PER_SECOND, nanos % _NANOS_PER_SECOND
|
|
418
|
+
)
|
|
411
419
|
|
|
412
420
|
def FromMicroseconds(self, micros):
|
|
413
421
|
"""Converts microseconds to Duration."""
|
|
414
422
|
self._NormalizeDuration(
|
|
415
423
|
micros // _MICROS_PER_SECOND,
|
|
416
|
-
(micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND
|
|
424
|
+
(micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND,
|
|
425
|
+
)
|
|
417
426
|
|
|
418
427
|
def FromMilliseconds(self, millis):
|
|
419
428
|
"""Converts milliseconds to Duration."""
|
|
420
429
|
self._NormalizeDuration(
|
|
421
430
|
millis // _MILLIS_PER_SECOND,
|
|
422
|
-
(millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND
|
|
431
|
+
(millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND,
|
|
432
|
+
)
|
|
423
433
|
|
|
424
434
|
def FromSeconds(self, seconds):
|
|
425
435
|
"""Converts seconds to Duration."""
|
|
@@ -429,8 +439,9 @@ class Duration(object):
|
|
|
429
439
|
def ToTimedelta(self) -> datetime.timedelta:
|
|
430
440
|
"""Converts Duration to timedelta."""
|
|
431
441
|
return datetime.timedelta(
|
|
432
|
-
seconds=self.seconds,
|
|
433
|
-
|
|
442
|
+
seconds=self.seconds,
|
|
443
|
+
microseconds=_RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND),
|
|
444
|
+
)
|
|
434
445
|
|
|
435
446
|
def FromTimedelta(self, td):
|
|
436
447
|
"""Converts timedelta to Duration."""
|
|
@@ -464,22 +475,26 @@ class Duration(object):
|
|
|
464
475
|
|
|
465
476
|
__radd__ = __add__
|
|
466
477
|
|
|
467
|
-
def
|
|
468
|
-
return
|
|
478
|
+
def __sub__(self, value) -> datetime.timedelta:
|
|
479
|
+
return self.ToTimedelta() - value
|
|
480
|
+
|
|
481
|
+
def __rsub__(self, value) -> Union[datetime.datetime, datetime.timedelta]:
|
|
482
|
+
return value - self.ToTimedelta()
|
|
469
483
|
|
|
470
484
|
|
|
471
485
|
def _CheckDurationValid(seconds, nanos):
|
|
472
486
|
if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX:
|
|
473
487
|
raise ValueError(
|
|
474
488
|
'Duration is not valid: Seconds {0} must be in range '
|
|
475
|
-
'[-315576000000, 315576000000].'.format(seconds)
|
|
489
|
+
'[-315576000000, 315576000000].'.format(seconds)
|
|
490
|
+
)
|
|
476
491
|
if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND:
|
|
477
492
|
raise ValueError(
|
|
478
493
|
'Duration is not valid: Nanos {0} must be in range '
|
|
479
|
-
'[-999999999, 999999999].'.format(nanos)
|
|
494
|
+
'[-999999999, 999999999].'.format(nanos)
|
|
495
|
+
)
|
|
480
496
|
if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0):
|
|
481
|
-
raise ValueError(
|
|
482
|
-
'Duration is not valid: Sign mismatch.')
|
|
497
|
+
raise ValueError('Duration is not valid: Sign mismatch.')
|
|
483
498
|
|
|
484
499
|
|
|
485
500
|
def _RoundTowardZero(value, divider):
|
|
@@ -601,6 +616,7 @@ class Struct(object):
|
|
|
601
616
|
for key, value in dictionary.items():
|
|
602
617
|
_SetStructValue(self.fields[key], value)
|
|
603
618
|
|
|
619
|
+
|
|
604
620
|
collections.abc.MutableMapping.register(Struct)
|
|
605
621
|
|
|
606
622
|
|
|
@@ -663,6 +679,7 @@ class ListValue(object):
|
|
|
663
679
|
list_value.Clear()
|
|
664
680
|
return list_value
|
|
665
681
|
|
|
682
|
+
|
|
666
683
|
collections.abc.MutableSequence.register(ListValue)
|
|
667
684
|
|
|
668
685
|
|