protobuf 5.29.4__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 +4 -4
- google/protobuf/api_pb2.py +14 -10
- google/protobuf/compiler/plugin_pb2.py +4 -4
- google/protobuf/descriptor.py +413 -248
- google/protobuf/descriptor_database.py +22 -4
- google/protobuf/descriptor_pb2.py +319 -119
- google/protobuf/descriptor_pool.py +31 -13
- google/protobuf/duration_pb2.py +4 -4
- google/protobuf/empty_pb2.py +4 -4
- google/protobuf/field_mask_pb2.py +4 -4
- 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 +8 -28
- google/protobuf/source_context_pb2.py +4 -4
- google/protobuf/struct_pb2.py +4 -4
- google/protobuf/symbol_database.py +0 -18
- google/protobuf/text_format.py +49 -29
- google/protobuf/timestamp_pb2.py +4 -4
- google/protobuf/type_pb2.py +4 -4
- google/protobuf/unknown_fields.py +3 -4
- google/protobuf/wrappers_pb2.py +4 -4
- {protobuf-5.29.4.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.4.dist-info/RECORD +0 -59
- {protobuf-5.29.4.dist-info → protobuf-6.33.3.dist-info}/LICENSE +0 -0
- {protobuf-5.29.4.dist-info → protobuf-6.33.3.dist-info}/WHEEL +0 -0
|
@@ -20,13 +20,13 @@ __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
|
|
|
29
|
-
|
|
29
|
+
_TIMESTAMPFORMAT = '%Y-%m-%dT%H:%M:%S'
|
|
30
30
|
_NANOS_PER_SECOND = 1000000000
|
|
31
31
|
_NANOS_PER_MILLISECOND = 1000000
|
|
32
32
|
_NANOS_PER_MICROSECOND = 1000
|
|
@@ -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)
|
|
@@ -68,7 +69,7 @@ class Any(object):
|
|
|
68
69
|
def TypeName(self):
|
|
69
70
|
"""Returns the protobuf type name of the inner message."""
|
|
70
71
|
# Only last part is to be used: b/25630112
|
|
71
|
-
return self.type_url.
|
|
72
|
+
return self.type_url.rpartition('/')[2]
|
|
72
73
|
|
|
73
74
|
def Is(self, descriptor):
|
|
74
75
|
"""Checks if this Any represents the given protobuf type."""
|
|
@@ -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
|
-
|
|
145
|
+
"time data '{0}' does not match format '%Y-%m-%dT%H:%M:%S', "
|
|
146
|
+
"lowercase 't' is not accepted".format(second_value)
|
|
147
|
+
)
|
|
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
|
|
google/protobuf/json_format.py
CHANGED
|
@@ -26,6 +26,7 @@ import json
|
|
|
26
26
|
import math
|
|
27
27
|
from operator import methodcaller
|
|
28
28
|
import re
|
|
29
|
+
import warnings
|
|
29
30
|
|
|
30
31
|
from google.protobuf import descriptor
|
|
31
32
|
from google.protobuf import message_factory
|
|
@@ -72,6 +73,7 @@ class ParseError(Error):
|
|
|
72
73
|
|
|
73
74
|
class EnumStringValueParseError(ParseError):
|
|
74
75
|
"""Thrown if unknown string enum value is encountered.
|
|
76
|
+
|
|
75
77
|
This exception is suppressed if ignore_unknown_fields is set.
|
|
76
78
|
"""
|
|
77
79
|
|
|
@@ -91,10 +93,10 @@ def MessageToJson(
|
|
|
91
93
|
|
|
92
94
|
Args:
|
|
93
95
|
message: The protocol buffers message instance to serialize.
|
|
94
|
-
always_print_fields_with_no_presence: If True, fields without
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
always_print_fields_with_no_presence: If True, fields without presence
|
|
97
|
+
(implicit presence scalars, repeated fields, and map fields) will always
|
|
98
|
+
be serialized. Any field that supports presence is not affected by this
|
|
99
|
+
option (including singular message fields and oneof fields).
|
|
98
100
|
preserving_proto_field_name: If True, use the original proto field names as
|
|
99
101
|
defined in the .proto file. If False, convert the field names to
|
|
100
102
|
lowerCamelCase.
|
|
@@ -105,7 +107,8 @@ def MessageToJson(
|
|
|
105
107
|
use_integers_for_enums: If true, print integers instead of enum names.
|
|
106
108
|
descriptor_pool: A Descriptor Pool for resolving types. If None use the
|
|
107
109
|
default.
|
|
108
|
-
float_precision: If set, use this to specify float field valid
|
|
110
|
+
float_precision: Deprecated. If set, use this to specify float field valid
|
|
111
|
+
digits.
|
|
109
112
|
ensure_ascii: If True, strings with non-ASCII characters are escaped. If
|
|
110
113
|
False, Unicode strings are returned unchanged.
|
|
111
114
|
|
|
@@ -117,7 +120,7 @@ def MessageToJson(
|
|
|
117
120
|
use_integers_for_enums,
|
|
118
121
|
descriptor_pool,
|
|
119
122
|
float_precision,
|
|
120
|
-
always_print_fields_with_no_presence
|
|
123
|
+
always_print_fields_with_no_presence,
|
|
121
124
|
)
|
|
122
125
|
return printer.ToJsonString(message, indent, sort_keys, ensure_ascii)
|
|
123
126
|
|
|
@@ -136,17 +139,18 @@ def MessageToDict(
|
|
|
136
139
|
|
|
137
140
|
Args:
|
|
138
141
|
message: The protocol buffers message instance to serialize.
|
|
139
|
-
always_print_fields_with_no_presence: If True, fields without
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
always_print_fields_with_no_presence: If True, fields without presence
|
|
143
|
+
(implicit presence scalars, repeated fields, and map fields) will always
|
|
144
|
+
be serialized. Any field that supports presence is not affected by this
|
|
145
|
+
option (including singular message fields and oneof fields).
|
|
143
146
|
preserving_proto_field_name: If True, use the original proto field names as
|
|
144
147
|
defined in the .proto file. If False, convert the field names to
|
|
145
148
|
lowerCamelCase.
|
|
146
149
|
use_integers_for_enums: If true, print integers instead of enum names.
|
|
147
150
|
descriptor_pool: A Descriptor Pool for resolving types. If None use the
|
|
148
151
|
default.
|
|
149
|
-
float_precision: If set, use this to specify float field valid
|
|
152
|
+
float_precision: Deprecated. If set, use this to specify float field valid
|
|
153
|
+
digits.
|
|
150
154
|
|
|
151
155
|
Returns:
|
|
152
156
|
A dict representation of the protocol buffer message.
|
|
@@ -188,6 +192,11 @@ class _Printer(object):
|
|
|
188
192
|
self.use_integers_for_enums = use_integers_for_enums
|
|
189
193
|
self.descriptor_pool = descriptor_pool
|
|
190
194
|
if float_precision:
|
|
195
|
+
warnings.warn(
|
|
196
|
+
'float_precision option is deprecated for json_format. '
|
|
197
|
+
'This will turn into error in 7.34.0, please remove it '
|
|
198
|
+
'before that.'
|
|
199
|
+
)
|
|
191
200
|
self.float_format = '.{}g'.format(float_precision)
|
|
192
201
|
else:
|
|
193
202
|
self.float_format = None
|
|
@@ -215,10 +224,13 @@ class _Printer(object):
|
|
|
215
224
|
|
|
216
225
|
try:
|
|
217
226
|
for field, value in fields:
|
|
218
|
-
if
|
|
227
|
+
if field.is_extension:
|
|
228
|
+
name = '[%s]' % field.full_name
|
|
229
|
+
elif self.preserving_proto_field_name:
|
|
219
230
|
name = field.name
|
|
220
231
|
else:
|
|
221
232
|
name = field.json_name
|
|
233
|
+
|
|
222
234
|
if _IsMapEntry(field):
|
|
223
235
|
# Convert a map field.
|
|
224
236
|
v_field = field.message_type.fields_by_name['value']
|
|
@@ -233,12 +245,9 @@ class _Printer(object):
|
|
|
233
245
|
recorded_key = str(key)
|
|
234
246
|
js_map[recorded_key] = self._FieldToJsonObject(v_field, value[key])
|
|
235
247
|
js[name] = js_map
|
|
236
|
-
elif field.
|
|
248
|
+
elif field.is_repeated:
|
|
237
249
|
# Convert a repeated field.
|
|
238
250
|
js[name] = [self._FieldToJsonObject(field, k) for k in value]
|
|
239
|
-
elif field.is_extension:
|
|
240
|
-
name = '[%s]' % field.full_name
|
|
241
|
-
js[name] = self._FieldToJsonObject(field, value)
|
|
242
251
|
else:
|
|
243
252
|
js[name] = self._FieldToJsonObject(field, value)
|
|
244
253
|
|
|
@@ -251,10 +260,7 @@ class _Printer(object):
|
|
|
251
260
|
|
|
252
261
|
# always_print_fields_with_no_presence doesn't apply to
|
|
253
262
|
# any field which supports presence.
|
|
254
|
-
if
|
|
255
|
-
self.always_print_fields_with_no_presence
|
|
256
|
-
and field.has_presence
|
|
257
|
-
):
|
|
263
|
+
if self.always_print_fields_with_no_presence and field.has_presence:
|
|
258
264
|
continue
|
|
259
265
|
|
|
260
266
|
if self.preserving_proto_field_name:
|
|
@@ -266,7 +272,7 @@ class _Printer(object):
|
|
|
266
272
|
continue
|
|
267
273
|
if _IsMapEntry(field):
|
|
268
274
|
js[name] = {}
|
|
269
|
-
elif field.
|
|
275
|
+
elif field.is_repeated:
|
|
270
276
|
js[name] = []
|
|
271
277
|
else:
|
|
272
278
|
js[name] = self._FieldToJsonObject(field, field.default_value)
|
|
@@ -316,11 +322,10 @@ class _Printer(object):
|
|
|
316
322
|
return _INFINITY
|
|
317
323
|
if math.isnan(value):
|
|
318
324
|
return _NAN
|
|
319
|
-
if
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return type_checkers.ToShortestFloat(value)
|
|
325
|
+
if self.float_format:
|
|
326
|
+
return float(format(value, self.float_format))
|
|
327
|
+
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
|
|
328
|
+
return type_checkers.ToShortestFloat(value)
|
|
324
329
|
|
|
325
330
|
return value
|
|
326
331
|
|
|
@@ -497,6 +502,7 @@ def ParseDict(
|
|
|
497
502
|
|
|
498
503
|
|
|
499
504
|
_INT_OR_FLOAT = (int, float)
|
|
505
|
+
_LIST_LIKE = (list, tuple)
|
|
500
506
|
|
|
501
507
|
|
|
502
508
|
class _Parser(object):
|
|
@@ -556,6 +562,25 @@ class _Parser(object):
|
|
|
556
562
|
fields_by_json_name = dict(
|
|
557
563
|
(f.json_name, f) for f in message_descriptor.fields
|
|
558
564
|
)
|
|
565
|
+
|
|
566
|
+
def _ClearFieldOrExtension(message, field):
|
|
567
|
+
if field.is_extension:
|
|
568
|
+
message.ClearExtension(field)
|
|
569
|
+
else:
|
|
570
|
+
message.ClearField(field.name)
|
|
571
|
+
|
|
572
|
+
def _GetFieldOrExtension(message, field):
|
|
573
|
+
if field.is_extension:
|
|
574
|
+
return message.Extensions[field]
|
|
575
|
+
else:
|
|
576
|
+
return getattr(message, field.name)
|
|
577
|
+
|
|
578
|
+
def _SetFieldOrExtension(message, field, value):
|
|
579
|
+
if field.is_extension:
|
|
580
|
+
message.Extensions[field] = value
|
|
581
|
+
else:
|
|
582
|
+
setattr(message, field.name, value)
|
|
583
|
+
|
|
559
584
|
for name in js:
|
|
560
585
|
try:
|
|
561
586
|
field = fields_by_json_name.get(name, None)
|
|
@@ -619,26 +644,26 @@ class _Parser(object):
|
|
|
619
644
|
field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE
|
|
620
645
|
and field.message_type.full_name == 'google.protobuf.Value'
|
|
621
646
|
):
|
|
622
|
-
sub_message =
|
|
647
|
+
sub_message = _GetFieldOrExtension(message, field)
|
|
623
648
|
sub_message.null_value = 0
|
|
624
649
|
elif (
|
|
625
650
|
field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM
|
|
626
651
|
and field.enum_type.full_name == 'google.protobuf.NullValue'
|
|
627
652
|
):
|
|
628
|
-
|
|
653
|
+
_SetFieldOrExtension(message, field, 0)
|
|
629
654
|
else:
|
|
630
|
-
message
|
|
655
|
+
_ClearFieldOrExtension(message, field)
|
|
631
656
|
continue
|
|
632
657
|
|
|
633
658
|
# Parse field value.
|
|
634
659
|
if _IsMapEntry(field):
|
|
635
|
-
message
|
|
660
|
+
_ClearFieldOrExtension(message, field)
|
|
636
661
|
self._ConvertMapFieldValue(
|
|
637
662
|
value, message, field, '{0}.{1}'.format(path, name)
|
|
638
663
|
)
|
|
639
|
-
elif field.
|
|
640
|
-
message
|
|
641
|
-
if not isinstance(value,
|
|
664
|
+
elif field.is_repeated:
|
|
665
|
+
_ClearFieldOrExtension(message, field)
|
|
666
|
+
if not isinstance(value, _LIST_LIKE):
|
|
642
667
|
raise ParseError(
|
|
643
668
|
'repeated field {0} must be in [] which is {1} at {2}'.format(
|
|
644
669
|
name, value, path
|
|
@@ -647,7 +672,7 @@ class _Parser(object):
|
|
|
647
672
|
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
|
|
648
673
|
# Repeated message field.
|
|
649
674
|
for index, item in enumerate(value):
|
|
650
|
-
sub_message =
|
|
675
|
+
sub_message = _GetFieldOrExtension(message, field).add()
|
|
651
676
|
# None is a null_value in Value.
|
|
652
677
|
if (
|
|
653
678
|
item is None
|
|
@@ -674,19 +699,16 @@ class _Parser(object):
|
|
|
674
699
|
)
|
|
675
700
|
)
|
|
676
701
|
self._ConvertAndAppendScalar(
|
|
677
|
-
|
|
702
|
+
message, field, item, '{0}.{1}[{2}]'.format(path, name, index)
|
|
703
|
+
)
|
|
678
704
|
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
|
|
679
|
-
|
|
680
|
-
sub_message = message.Extensions[field]
|
|
681
|
-
else:
|
|
682
|
-
sub_message = getattr(message, field.name)
|
|
705
|
+
sub_message = _GetFieldOrExtension(message, field)
|
|
683
706
|
sub_message.SetInParent()
|
|
684
707
|
self.ConvertMessage(value, sub_message, '{0}.{1}'.format(path, name))
|
|
685
708
|
else:
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
self._ConvertAndSetScalar(message, field, value, '{0}.{1}'.format(path, name))
|
|
709
|
+
self._ConvertAndSetScalar(
|
|
710
|
+
message, field, value, '{0}.{1}'.format(path, name)
|
|
711
|
+
)
|
|
690
712
|
except ParseError as e:
|
|
691
713
|
if field and field.containing_oneof is None:
|
|
692
714
|
raise ParseError(
|
|
@@ -733,8 +755,10 @@ class _Parser(object):
|
|
|
733
755
|
)(self)
|
|
734
756
|
else:
|
|
735
757
|
del value['@type']
|
|
736
|
-
|
|
737
|
-
|
|
758
|
+
try:
|
|
759
|
+
self._ConvertFieldValuePair(value, sub_message, path)
|
|
760
|
+
finally:
|
|
761
|
+
value['@type'] = type_url
|
|
738
762
|
# Sets Any message
|
|
739
763
|
message.value = sub_message.SerializeToString()
|
|
740
764
|
message.type_url = type_url
|
|
@@ -752,8 +776,8 @@ class _Parser(object):
|
|
|
752
776
|
"""Convert a JSON representation into Value message."""
|
|
753
777
|
if isinstance(value, dict):
|
|
754
778
|
self._ConvertStructMessage(value, message.struct_value, path)
|
|
755
|
-
elif isinstance(value,
|
|
756
|
-
self.
|
|
779
|
+
elif isinstance(value, _LIST_LIKE):
|
|
780
|
+
self._ConvertListOrTupleValueMessage(value, message.list_value, path)
|
|
757
781
|
elif value is None:
|
|
758
782
|
message.null_value = 0
|
|
759
783
|
elif isinstance(value, bool):
|
|
@@ -769,9 +793,9 @@ class _Parser(object):
|
|
|
769
793
|
)
|
|
770
794
|
)
|
|
771
795
|
|
|
772
|
-
def
|
|
796
|
+
def _ConvertListOrTupleValueMessage(self, value, message, path):
|
|
773
797
|
"""Convert a JSON representation into ListValue message."""
|
|
774
|
-
if not isinstance(value,
|
|
798
|
+
if not isinstance(value, _LIST_LIKE):
|
|
775
799
|
raise ParseError(
|
|
776
800
|
'ListValue must be in [] which is {0} at {1}'.format(value, path)
|
|
777
801
|
)
|
|
@@ -799,7 +823,9 @@ class _Parser(object):
|
|
|
799
823
|
def _ConvertWrapperMessage(self, value, message, path):
|
|
800
824
|
"""Convert a JSON representation into Wrapper message."""
|
|
801
825
|
field = message.DESCRIPTOR.fields_by_name['value']
|
|
802
|
-
self._ConvertAndSetScalar(
|
|
826
|
+
self._ConvertAndSetScalar(
|
|
827
|
+
message, field, value, path='{0}.value'.format(path)
|
|
828
|
+
)
|
|
803
829
|
|
|
804
830
|
def _ConvertMapFieldValue(self, value, message, field, path):
|
|
805
831
|
"""Convert map field value for a message map field.
|
|
@@ -837,24 +863,17 @@ class _Parser(object):
|
|
|
837
863
|
field,
|
|
838
864
|
key_value,
|
|
839
865
|
value[key],
|
|
840
|
-
path='{0}[{1}]'.format(path, key_value)
|
|
841
|
-
|
|
842
|
-
def _ConvertAndSetScalarExtension(self, message, extension_field, js_value, path):
|
|
843
|
-
"""Convert scalar from js_value and assign it to message.Extensions[extension_field]."""
|
|
844
|
-
try:
|
|
845
|
-
message.Extensions[extension_field] = _ConvertScalarFieldValue(
|
|
846
|
-
js_value, extension_field, path)
|
|
847
|
-
except EnumStringValueParseError:
|
|
848
|
-
if not self.ignore_unknown_fields:
|
|
849
|
-
raise
|
|
866
|
+
path='{0}[{1}]'.format(path, key_value),
|
|
867
|
+
)
|
|
850
868
|
|
|
851
869
|
def _ConvertAndSetScalar(self, message, field, js_value, path):
|
|
852
870
|
"""Convert scalar from js_value and assign it to message.field."""
|
|
853
871
|
try:
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
872
|
+
value = _ConvertScalarFieldValue(js_value, field, path)
|
|
873
|
+
if field.is_extension:
|
|
874
|
+
message.Extensions[field] = value
|
|
875
|
+
else:
|
|
876
|
+
setattr(message, field.name, value)
|
|
858
877
|
except EnumStringValueParseError:
|
|
859
878
|
if not self.ignore_unknown_fields:
|
|
860
879
|
raise
|
|
@@ -862,17 +881,27 @@ class _Parser(object):
|
|
|
862
881
|
def _ConvertAndAppendScalar(self, message, repeated_field, js_value, path):
|
|
863
882
|
"""Convert scalar from js_value and append it to message.repeated_field."""
|
|
864
883
|
try:
|
|
865
|
-
|
|
866
|
-
|
|
884
|
+
if repeated_field.is_extension:
|
|
885
|
+
repeated = message.Extensions[repeated_field]
|
|
886
|
+
else:
|
|
887
|
+
repeated = getattr(message, repeated_field.name)
|
|
888
|
+
value = _ConvertScalarFieldValue(js_value, repeated_field, path)
|
|
889
|
+
repeated.append(value)
|
|
867
890
|
except EnumStringValueParseError:
|
|
868
891
|
if not self.ignore_unknown_fields:
|
|
869
892
|
raise
|
|
870
893
|
|
|
871
|
-
def _ConvertAndSetScalarToMapKey(
|
|
894
|
+
def _ConvertAndSetScalarToMapKey(
|
|
895
|
+
self, message, map_field, converted_key, js_value, path
|
|
896
|
+
):
|
|
872
897
|
"""Convert scalar from 'js_value' and add it to message.map_field[converted_key]."""
|
|
873
898
|
try:
|
|
874
|
-
getattr(message, map_field.name)[converted_key] =
|
|
875
|
-
|
|
899
|
+
getattr(message, map_field.name)[converted_key] = (
|
|
900
|
+
_ConvertScalarFieldValue(
|
|
901
|
+
js_value,
|
|
902
|
+
map_field.message_type.fields_by_name['value'],
|
|
903
|
+
path,
|
|
904
|
+
)
|
|
876
905
|
)
|
|
877
906
|
except EnumStringValueParseError:
|
|
878
907
|
if not self.ignore_unknown_fields:
|
|
@@ -971,7 +1000,20 @@ def _ConvertInteger(value):
|
|
|
971
1000
|
'Bool value {0} is not acceptable for integer field'.format(value)
|
|
972
1001
|
)
|
|
973
1002
|
|
|
974
|
-
|
|
1003
|
+
try:
|
|
1004
|
+
return int(value)
|
|
1005
|
+
except ValueError as e:
|
|
1006
|
+
# Attempt to parse as an integer-valued float.
|
|
1007
|
+
try:
|
|
1008
|
+
f = float(value)
|
|
1009
|
+
except ValueError:
|
|
1010
|
+
# Raise the original exception for the int parse.
|
|
1011
|
+
raise e # pylint: disable=raise-missing-from
|
|
1012
|
+
if not f.is_integer():
|
|
1013
|
+
raise ParseError(
|
|
1014
|
+
'Couldn\'t parse non-integer string: "{0}"'.format(value)
|
|
1015
|
+
) from e
|
|
1016
|
+
return int(f)
|
|
975
1017
|
|
|
976
1018
|
|
|
977
1019
|
def _ConvertFloat(value, field):
|
|
@@ -1052,7 +1094,7 @@ _WKTJSONMETHODS = {
|
|
|
1052
1094
|
],
|
|
1053
1095
|
'google.protobuf.ListValue': [
|
|
1054
1096
|
'_ListValueMessageToJsonObject',
|
|
1055
|
-
'
|
|
1097
|
+
'_ConvertListOrTupleValueMessage',
|
|
1056
1098
|
],
|
|
1057
1099
|
'google.protobuf.Struct': [
|
|
1058
1100
|
'_StructMessageToJsonObject',
|