protobuf 6.33.0__cp39-abi3-manylinux2014_s390x.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/_upb/_message.abi3.so +0 -0
- google/protobuf/__init__.py +10 -0
- google/protobuf/any.py +53 -0
- google/protobuf/any_pb2.py +37 -0
- google/protobuf/api_pb2.py +47 -0
- google/protobuf/compiler/__init__.py +0 -0
- google/protobuf/compiler/plugin_pb2.py +46 -0
- google/protobuf/descriptor.py +1676 -0
- google/protobuf/descriptor_database.py +172 -0
- google/protobuf/descriptor_pb2.py +3363 -0
- google/protobuf/descriptor_pool.py +1370 -0
- google/protobuf/duration.py +100 -0
- google/protobuf/duration_pb2.py +37 -0
- google/protobuf/empty_pb2.py +37 -0
- google/protobuf/field_mask_pb2.py +37 -0
- google/protobuf/internal/__init__.py +7 -0
- google/protobuf/internal/api_implementation.py +136 -0
- google/protobuf/internal/builder.py +118 -0
- google/protobuf/internal/containers.py +690 -0
- google/protobuf/internal/decoder.py +1066 -0
- google/protobuf/internal/encoder.py +806 -0
- google/protobuf/internal/enum_type_wrapper.py +112 -0
- google/protobuf/internal/extension_dict.py +194 -0
- google/protobuf/internal/field_mask.py +312 -0
- google/protobuf/internal/message_listener.py +55 -0
- google/protobuf/internal/python_edition_defaults.py +5 -0
- google/protobuf/internal/python_message.py +1599 -0
- google/protobuf/internal/testing_refleaks.py +128 -0
- google/protobuf/internal/type_checkers.py +455 -0
- google/protobuf/internal/well_known_types.py +695 -0
- google/protobuf/internal/wire_format.py +245 -0
- google/protobuf/json_format.py +1111 -0
- google/protobuf/message.py +448 -0
- google/protobuf/message_factory.py +190 -0
- google/protobuf/proto.py +153 -0
- google/protobuf/proto_builder.py +111 -0
- google/protobuf/proto_json.py +83 -0
- google/protobuf/proto_text.py +129 -0
- google/protobuf/pyext/__init__.py +0 -0
- google/protobuf/pyext/cpp_message.py +49 -0
- google/protobuf/reflection.py +36 -0
- google/protobuf/runtime_version.py +104 -0
- google/protobuf/service_reflection.py +272 -0
- google/protobuf/source_context_pb2.py +37 -0
- google/protobuf/struct_pb2.py +47 -0
- google/protobuf/symbol_database.py +179 -0
- google/protobuf/testdata/__init__.py +0 -0
- google/protobuf/text_encoding.py +106 -0
- google/protobuf/text_format.py +1884 -0
- google/protobuf/timestamp.py +112 -0
- google/protobuf/timestamp_pb2.py +37 -0
- google/protobuf/type_pb2.py +53 -0
- google/protobuf/unknown_fields.py +96 -0
- google/protobuf/util/__init__.py +0 -0
- google/protobuf/wrappers_pb2.py +53 -0
- protobuf-6.33.0.dist-info/LICENSE +32 -0
- protobuf-6.33.0.dist-info/METADATA +17 -0
- protobuf-6.33.0.dist-info/RECORD +59 -0
- protobuf-6.33.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
# Protocol Buffers - Google's data interchange format
|
|
2
|
+
# Copyright 2008 Google Inc. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Use of this source code is governed by a BSD-style
|
|
5
|
+
# license that can be found in the LICENSE file or at
|
|
6
|
+
# https://developers.google.com/open-source/licenses/bsd
|
|
7
|
+
|
|
8
|
+
"""Contains well known classes.
|
|
9
|
+
|
|
10
|
+
This files defines well known classes which need extra maintenance including:
|
|
11
|
+
- Any
|
|
12
|
+
- Duration
|
|
13
|
+
- FieldMask
|
|
14
|
+
- Struct
|
|
15
|
+
- Timestamp
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__author__ = 'jieluo@google.com (Jie Luo)'
|
|
19
|
+
|
|
20
|
+
import calendar
|
|
21
|
+
import collections.abc
|
|
22
|
+
import datetime
|
|
23
|
+
from typing import Union
|
|
24
|
+
import warnings
|
|
25
|
+
from google.protobuf.internal import field_mask
|
|
26
|
+
|
|
27
|
+
FieldMask = field_mask.FieldMask
|
|
28
|
+
|
|
29
|
+
_TIMESTAMPFORMAT = '%Y-%m-%dT%H:%M:%S'
|
|
30
|
+
_NANOS_PER_SECOND = 1000000000
|
|
31
|
+
_NANOS_PER_MILLISECOND = 1000000
|
|
32
|
+
_NANOS_PER_MICROSECOND = 1000
|
|
33
|
+
_MILLIS_PER_SECOND = 1000
|
|
34
|
+
_MICROS_PER_SECOND = 1000000
|
|
35
|
+
_SECONDS_PER_DAY = 24 * 3600
|
|
36
|
+
_DURATION_SECONDS_MAX = 315576000000
|
|
37
|
+
_TIMESTAMP_SECONDS_MIN = -62135596800
|
|
38
|
+
_TIMESTAMP_SECONDS_MAX = 253402300799
|
|
39
|
+
|
|
40
|
+
_EPOCH_DATETIME_NAIVE = datetime.datetime(1970, 1, 1, tzinfo=None)
|
|
41
|
+
_EPOCH_DATETIME_AWARE = _EPOCH_DATETIME_NAIVE.replace(
|
|
42
|
+
tzinfo=datetime.timezone.utc
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Any(object):
|
|
47
|
+
"""Class for Any Message type."""
|
|
48
|
+
|
|
49
|
+
__slots__ = ()
|
|
50
|
+
|
|
51
|
+
def Pack(
|
|
52
|
+
self, msg, type_url_prefix='type.googleapis.com/', deterministic=None
|
|
53
|
+
):
|
|
54
|
+
"""Packs the specified message into current Any message."""
|
|
55
|
+
if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/':
|
|
56
|
+
self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
|
|
57
|
+
else:
|
|
58
|
+
self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
|
|
59
|
+
self.value = msg.SerializeToString(deterministic=deterministic)
|
|
60
|
+
|
|
61
|
+
def Unpack(self, msg):
|
|
62
|
+
"""Unpacks the current Any message into specified message."""
|
|
63
|
+
descriptor = msg.DESCRIPTOR
|
|
64
|
+
if not self.Is(descriptor):
|
|
65
|
+
return False
|
|
66
|
+
msg.ParseFromString(self.value)
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
def TypeName(self):
|
|
70
|
+
"""Returns the protobuf type name of the inner message."""
|
|
71
|
+
# Only last part is to be used: b/25630112
|
|
72
|
+
return self.type_url.rpartition('/')[2]
|
|
73
|
+
|
|
74
|
+
def Is(self, descriptor):
|
|
75
|
+
"""Checks if this Any represents the given protobuf type."""
|
|
76
|
+
return '/' in self.type_url and self.TypeName() == descriptor.full_name
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Timestamp(object):
|
|
80
|
+
"""Class for Timestamp message type."""
|
|
81
|
+
|
|
82
|
+
__slots__ = ()
|
|
83
|
+
|
|
84
|
+
def ToJsonString(self):
|
|
85
|
+
"""Converts Timestamp to RFC 3339 date string format.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
A string converted from timestamp. The string is always Z-normalized
|
|
89
|
+
and uses 3, 6 or 9 fractional digits as required to represent the
|
|
90
|
+
exact time. Example of the return format: '1972-01-01T10:00:20.021Z'
|
|
91
|
+
"""
|
|
92
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
93
|
+
nanos = self.nanos
|
|
94
|
+
seconds = self.seconds % _SECONDS_PER_DAY
|
|
95
|
+
days = (self.seconds - seconds) // _SECONDS_PER_DAY
|
|
96
|
+
dt = datetime.datetime(1970, 1, 1) + datetime.timedelta(days, seconds)
|
|
97
|
+
|
|
98
|
+
result = dt.isoformat()
|
|
99
|
+
if (nanos % 1e9) == 0:
|
|
100
|
+
# If there are 0 fractional digits, the fractional
|
|
101
|
+
# point '.' should be omitted when serializing.
|
|
102
|
+
return result + 'Z'
|
|
103
|
+
if (nanos % 1e6) == 0:
|
|
104
|
+
# Serialize 3 fractional digits.
|
|
105
|
+
return result + '.%03dZ' % (nanos / 1e6)
|
|
106
|
+
if (nanos % 1e3) == 0:
|
|
107
|
+
# Serialize 6 fractional digits.
|
|
108
|
+
return result + '.%06dZ' % (nanos / 1e3)
|
|
109
|
+
# Serialize 9 fractional digits.
|
|
110
|
+
return result + '.%09dZ' % nanos
|
|
111
|
+
|
|
112
|
+
def FromJsonString(self, value):
|
|
113
|
+
"""Parse a RFC 3339 date string format to Timestamp.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
value: A date string. Any fractional digits (or none) and any offset are
|
|
117
|
+
accepted as long as they fit into nano-seconds precision. Example of
|
|
118
|
+
accepted format: '1972-01-01T10:00:20.021-05:00'
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
ValueError: On parsing problems.
|
|
122
|
+
"""
|
|
123
|
+
if not isinstance(value, str):
|
|
124
|
+
raise ValueError('Timestamp JSON value not a string: {!r}'.format(value))
|
|
125
|
+
timezone_offset = value.find('Z')
|
|
126
|
+
if timezone_offset == -1:
|
|
127
|
+
timezone_offset = value.find('+')
|
|
128
|
+
if timezone_offset == -1:
|
|
129
|
+
timezone_offset = value.rfind('-')
|
|
130
|
+
if timezone_offset == -1:
|
|
131
|
+
raise ValueError(
|
|
132
|
+
'Failed to parse timestamp: missing valid timezone offset.'
|
|
133
|
+
)
|
|
134
|
+
time_value = value[0:timezone_offset]
|
|
135
|
+
# Parse datetime and nanos.
|
|
136
|
+
point_position = time_value.find('.')
|
|
137
|
+
if point_position == -1:
|
|
138
|
+
second_value = time_value
|
|
139
|
+
nano_value = ''
|
|
140
|
+
else:
|
|
141
|
+
second_value = time_value[:point_position]
|
|
142
|
+
nano_value = time_value[point_position + 1 :]
|
|
143
|
+
if 't' in second_value:
|
|
144
|
+
raise ValueError(
|
|
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)
|
|
149
|
+
td = date_object - datetime.datetime(1970, 1, 1)
|
|
150
|
+
seconds = td.seconds + td.days * _SECONDS_PER_DAY
|
|
151
|
+
if len(nano_value) > 9:
|
|
152
|
+
raise ValueError(
|
|
153
|
+
'Failed to parse Timestamp: nanos {0} more than '
|
|
154
|
+
'9 fractional digits.'.format(nano_value)
|
|
155
|
+
)
|
|
156
|
+
if nano_value:
|
|
157
|
+
nanos = round(float('0.' + nano_value) * 1e9)
|
|
158
|
+
else:
|
|
159
|
+
nanos = 0
|
|
160
|
+
# Parse timezone offsets.
|
|
161
|
+
if value[timezone_offset] == 'Z':
|
|
162
|
+
if len(value) != timezone_offset + 1:
|
|
163
|
+
raise ValueError(
|
|
164
|
+
'Failed to parse timestamp: invalid trailing data {0}.'.format(
|
|
165
|
+
value
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
timezone = value[timezone_offset:]
|
|
170
|
+
pos = timezone.find(':')
|
|
171
|
+
if pos == -1:
|
|
172
|
+
raise ValueError('Invalid timezone offset value: {0}.'.format(timezone))
|
|
173
|
+
if timezone[0] == '+':
|
|
174
|
+
seconds -= (int(timezone[1:pos]) * 60 + int(timezone[pos + 1 :])) * 60
|
|
175
|
+
else:
|
|
176
|
+
seconds += (int(timezone[1:pos]) * 60 + int(timezone[pos + 1 :])) * 60
|
|
177
|
+
# Set seconds and nanos
|
|
178
|
+
_CheckTimestampValid(seconds, nanos)
|
|
179
|
+
self.seconds = int(seconds)
|
|
180
|
+
self.nanos = int(nanos)
|
|
181
|
+
|
|
182
|
+
def GetCurrentTime(self):
|
|
183
|
+
"""Get the current UTC into Timestamp."""
|
|
184
|
+
self.FromDatetime(datetime.datetime.now(tz=datetime.timezone.utc))
|
|
185
|
+
|
|
186
|
+
def ToNanoseconds(self):
|
|
187
|
+
"""Converts Timestamp to nanoseconds since epoch."""
|
|
188
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
189
|
+
return self.seconds * _NANOS_PER_SECOND + self.nanos
|
|
190
|
+
|
|
191
|
+
def ToMicroseconds(self):
|
|
192
|
+
"""Converts Timestamp to microseconds since epoch."""
|
|
193
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
194
|
+
return (
|
|
195
|
+
self.seconds * _MICROS_PER_SECOND + self.nanos // _NANOS_PER_MICROSECOND
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def ToMilliseconds(self):
|
|
199
|
+
"""Converts Timestamp to milliseconds since epoch."""
|
|
200
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
201
|
+
return (
|
|
202
|
+
self.seconds * _MILLIS_PER_SECOND + self.nanos // _NANOS_PER_MILLISECOND
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def ToSeconds(self):
|
|
206
|
+
"""Converts Timestamp to seconds since epoch."""
|
|
207
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
208
|
+
return self.seconds
|
|
209
|
+
|
|
210
|
+
def FromNanoseconds(self, nanos):
|
|
211
|
+
"""Converts nanoseconds since epoch to Timestamp."""
|
|
212
|
+
seconds = nanos // _NANOS_PER_SECOND
|
|
213
|
+
nanos = nanos % _NANOS_PER_SECOND
|
|
214
|
+
_CheckTimestampValid(seconds, nanos)
|
|
215
|
+
self.seconds = seconds
|
|
216
|
+
self.nanos = nanos
|
|
217
|
+
|
|
218
|
+
def FromMicroseconds(self, micros):
|
|
219
|
+
"""Converts microseconds since epoch to Timestamp."""
|
|
220
|
+
seconds = micros // _MICROS_PER_SECOND
|
|
221
|
+
nanos = (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND
|
|
222
|
+
_CheckTimestampValid(seconds, nanos)
|
|
223
|
+
self.seconds = seconds
|
|
224
|
+
self.nanos = nanos
|
|
225
|
+
|
|
226
|
+
def FromMilliseconds(self, millis):
|
|
227
|
+
"""Converts milliseconds since epoch to Timestamp."""
|
|
228
|
+
seconds = millis // _MILLIS_PER_SECOND
|
|
229
|
+
nanos = (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND
|
|
230
|
+
_CheckTimestampValid(seconds, nanos)
|
|
231
|
+
self.seconds = seconds
|
|
232
|
+
self.nanos = nanos
|
|
233
|
+
|
|
234
|
+
def FromSeconds(self, seconds):
|
|
235
|
+
"""Converts seconds since epoch to Timestamp."""
|
|
236
|
+
_CheckTimestampValid(seconds, 0)
|
|
237
|
+
self.seconds = seconds
|
|
238
|
+
self.nanos = 0
|
|
239
|
+
|
|
240
|
+
def ToDatetime(self, tzinfo=None):
|
|
241
|
+
"""Converts Timestamp to a datetime.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
tzinfo: A datetime.tzinfo subclass; defaults to None.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
If tzinfo is None, returns a timezone-naive UTC datetime (with no timezone
|
|
248
|
+
information, i.e. not aware that it's UTC).
|
|
249
|
+
|
|
250
|
+
Otherwise, returns a timezone-aware datetime in the input timezone.
|
|
251
|
+
"""
|
|
252
|
+
# Using datetime.fromtimestamp for this would avoid constructing an extra
|
|
253
|
+
# timedelta object and possibly an extra datetime. Unfortunately, that has
|
|
254
|
+
# the disadvantage of not handling the full precision (on all platforms, see
|
|
255
|
+
# https://github.com/python/cpython/issues/109849) or full range (on some
|
|
256
|
+
# platforms, see https://github.com/python/cpython/issues/110042) of
|
|
257
|
+
# datetime.
|
|
258
|
+
_CheckTimestampValid(self.seconds, self.nanos)
|
|
259
|
+
delta = datetime.timedelta(
|
|
260
|
+
seconds=self.seconds,
|
|
261
|
+
microseconds=_RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND),
|
|
262
|
+
)
|
|
263
|
+
if tzinfo is None:
|
|
264
|
+
return _EPOCH_DATETIME_NAIVE + delta
|
|
265
|
+
else:
|
|
266
|
+
# Note the tz conversion has to come after the timedelta arithmetic.
|
|
267
|
+
return (_EPOCH_DATETIME_AWARE + delta).astimezone(tzinfo)
|
|
268
|
+
|
|
269
|
+
def FromDatetime(self, dt):
|
|
270
|
+
"""Converts datetime to Timestamp.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
dt: A datetime. If it's timezone-naive, it's assumed to be in UTC.
|
|
274
|
+
"""
|
|
275
|
+
# Using this guide: http://wiki.python.org/moin/WorkingWithTime
|
|
276
|
+
# And this conversion guide: http://docs.python.org/library/time.html
|
|
277
|
+
|
|
278
|
+
# Turn the date parameter into a tuple (struct_time) that can then be
|
|
279
|
+
# manipulated into a long value of seconds. During the conversion from
|
|
280
|
+
# struct_time to long, the source date in UTC, and so it follows that the
|
|
281
|
+
# correct transformation is calendar.timegm()
|
|
282
|
+
try:
|
|
283
|
+
seconds = calendar.timegm(dt.utctimetuple())
|
|
284
|
+
nanos = dt.microsecond * _NANOS_PER_MICROSECOND
|
|
285
|
+
except AttributeError as e:
|
|
286
|
+
raise AttributeError(
|
|
287
|
+
'Fail to convert to Timestamp. Expected a datetime like '
|
|
288
|
+
'object got {0} : {1}'.format(type(dt).__name__, e)
|
|
289
|
+
) from e
|
|
290
|
+
_CheckTimestampValid(seconds, nanos)
|
|
291
|
+
self.seconds = seconds
|
|
292
|
+
self.nanos = nanos
|
|
293
|
+
|
|
294
|
+
def _internal_assign(self, dt):
|
|
295
|
+
self.FromDatetime(dt)
|
|
296
|
+
|
|
297
|
+
def __add__(self, value) -> datetime.datetime:
|
|
298
|
+
if isinstance(value, Duration):
|
|
299
|
+
return self.ToDatetime() + value.ToTimedelta()
|
|
300
|
+
return self.ToDatetime() + value
|
|
301
|
+
|
|
302
|
+
__radd__ = __add__
|
|
303
|
+
|
|
304
|
+
def __sub__(self, value) -> Union[datetime.datetime, datetime.timedelta]:
|
|
305
|
+
if isinstance(value, Timestamp):
|
|
306
|
+
return self.ToDatetime() - value.ToDatetime()
|
|
307
|
+
elif isinstance(value, Duration):
|
|
308
|
+
return self.ToDatetime() - value.ToTimedelta()
|
|
309
|
+
return self.ToDatetime() - value
|
|
310
|
+
|
|
311
|
+
def __rsub__(self, dt) -> datetime.timedelta:
|
|
312
|
+
return dt - self.ToDatetime()
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _CheckTimestampValid(seconds, nanos):
|
|
316
|
+
if seconds < _TIMESTAMP_SECONDS_MIN or seconds > _TIMESTAMP_SECONDS_MAX:
|
|
317
|
+
raise ValueError(
|
|
318
|
+
'Timestamp is not valid: Seconds {0} must be in range '
|
|
319
|
+
'[-62135596800, 253402300799].'.format(seconds))
|
|
320
|
+
if nanos < 0 or nanos >= _NANOS_PER_SECOND:
|
|
321
|
+
raise ValueError(
|
|
322
|
+
'Timestamp is not valid: Nanos {} must be in a range '
|
|
323
|
+
'[0, 999999].'.format(nanos)
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class Duration(object):
|
|
328
|
+
"""Class for Duration message type."""
|
|
329
|
+
|
|
330
|
+
__slots__ = ()
|
|
331
|
+
|
|
332
|
+
def ToJsonString(self):
|
|
333
|
+
"""Converts Duration to string format.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
A string converted from self. The string format will contains
|
|
337
|
+
3, 6, or 9 fractional digits depending on the precision required to
|
|
338
|
+
represent the exact Duration value. For example: "1s", "1.010s",
|
|
339
|
+
"1.000000100s", "-3.100s"
|
|
340
|
+
"""
|
|
341
|
+
_CheckDurationValid(self.seconds, self.nanos)
|
|
342
|
+
if self.seconds < 0 or self.nanos < 0:
|
|
343
|
+
result = '-'
|
|
344
|
+
seconds = -self.seconds + int((0 - self.nanos) // 1e9)
|
|
345
|
+
nanos = (0 - self.nanos) % 1e9
|
|
346
|
+
else:
|
|
347
|
+
result = ''
|
|
348
|
+
seconds = self.seconds + int(self.nanos // 1e9)
|
|
349
|
+
nanos = self.nanos % 1e9
|
|
350
|
+
result += '%d' % seconds
|
|
351
|
+
if (nanos % 1e9) == 0:
|
|
352
|
+
# If there are 0 fractional digits, the fractional
|
|
353
|
+
# point '.' should be omitted when serializing.
|
|
354
|
+
return result + 's'
|
|
355
|
+
if (nanos % 1e6) == 0:
|
|
356
|
+
# Serialize 3 fractional digits.
|
|
357
|
+
return result + '.%03ds' % (nanos / 1e6)
|
|
358
|
+
if (nanos % 1e3) == 0:
|
|
359
|
+
# Serialize 6 fractional digits.
|
|
360
|
+
return result + '.%06ds' % (nanos / 1e3)
|
|
361
|
+
# Serialize 9 fractional digits.
|
|
362
|
+
return result + '.%09ds' % nanos
|
|
363
|
+
|
|
364
|
+
def FromJsonString(self, value):
|
|
365
|
+
"""Converts a string to Duration.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
value: A string to be converted. The string must end with 's'. Any
|
|
369
|
+
fractional digits (or none) are accepted as long as they fit into
|
|
370
|
+
precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s
|
|
371
|
+
|
|
372
|
+
Raises:
|
|
373
|
+
ValueError: On parsing problems.
|
|
374
|
+
"""
|
|
375
|
+
if not isinstance(value, str):
|
|
376
|
+
raise ValueError('Duration JSON value not a string: {!r}'.format(value))
|
|
377
|
+
if len(value) < 1 or value[-1] != 's':
|
|
378
|
+
raise ValueError('Duration must end with letter "s": {0}.'.format(value))
|
|
379
|
+
try:
|
|
380
|
+
pos = value.find('.')
|
|
381
|
+
if pos == -1:
|
|
382
|
+
seconds = int(value[:-1])
|
|
383
|
+
nanos = 0
|
|
384
|
+
else:
|
|
385
|
+
seconds = int(value[:pos])
|
|
386
|
+
if value[0] == '-':
|
|
387
|
+
nanos = int(round(float('-0{0}'.format(value[pos:-1])) * 1e9))
|
|
388
|
+
else:
|
|
389
|
+
nanos = int(round(float('0{0}'.format(value[pos:-1])) * 1e9))
|
|
390
|
+
_CheckDurationValid(seconds, nanos)
|
|
391
|
+
self.seconds = seconds
|
|
392
|
+
self.nanos = nanos
|
|
393
|
+
except ValueError as e:
|
|
394
|
+
raise ValueError("Couldn't parse duration: {0} : {1}.".format(value, e))
|
|
395
|
+
|
|
396
|
+
def ToNanoseconds(self):
|
|
397
|
+
"""Converts a Duration to nanoseconds."""
|
|
398
|
+
return self.seconds * _NANOS_PER_SECOND + self.nanos
|
|
399
|
+
|
|
400
|
+
def ToMicroseconds(self):
|
|
401
|
+
"""Converts a Duration to microseconds."""
|
|
402
|
+
micros = _RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND)
|
|
403
|
+
return self.seconds * _MICROS_PER_SECOND + micros
|
|
404
|
+
|
|
405
|
+
def ToMilliseconds(self):
|
|
406
|
+
"""Converts a Duration to milliseconds."""
|
|
407
|
+
millis = _RoundTowardZero(self.nanos, _NANOS_PER_MILLISECOND)
|
|
408
|
+
return self.seconds * _MILLIS_PER_SECOND + millis
|
|
409
|
+
|
|
410
|
+
def ToSeconds(self):
|
|
411
|
+
"""Converts a Duration to seconds."""
|
|
412
|
+
return self.seconds
|
|
413
|
+
|
|
414
|
+
def FromNanoseconds(self, nanos):
|
|
415
|
+
"""Converts nanoseconds to Duration."""
|
|
416
|
+
self._NormalizeDuration(
|
|
417
|
+
nanos // _NANOS_PER_SECOND, nanos % _NANOS_PER_SECOND
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
def FromMicroseconds(self, micros):
|
|
421
|
+
"""Converts microseconds to Duration."""
|
|
422
|
+
self._NormalizeDuration(
|
|
423
|
+
micros // _MICROS_PER_SECOND,
|
|
424
|
+
(micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
def FromMilliseconds(self, millis):
|
|
428
|
+
"""Converts milliseconds to Duration."""
|
|
429
|
+
self._NormalizeDuration(
|
|
430
|
+
millis // _MILLIS_PER_SECOND,
|
|
431
|
+
(millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND,
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
def FromSeconds(self, seconds):
|
|
435
|
+
"""Converts seconds to Duration."""
|
|
436
|
+
self.seconds = seconds
|
|
437
|
+
self.nanos = 0
|
|
438
|
+
|
|
439
|
+
def ToTimedelta(self) -> datetime.timedelta:
|
|
440
|
+
"""Converts Duration to timedelta."""
|
|
441
|
+
return datetime.timedelta(
|
|
442
|
+
seconds=self.seconds,
|
|
443
|
+
microseconds=_RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND),
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
def FromTimedelta(self, td):
|
|
447
|
+
"""Converts timedelta to Duration."""
|
|
448
|
+
try:
|
|
449
|
+
self._NormalizeDuration(
|
|
450
|
+
td.seconds + td.days * _SECONDS_PER_DAY,
|
|
451
|
+
td.microseconds * _NANOS_PER_MICROSECOND,
|
|
452
|
+
)
|
|
453
|
+
except AttributeError as e:
|
|
454
|
+
raise AttributeError(
|
|
455
|
+
'Fail to convert to Duration. Expected a timedelta like '
|
|
456
|
+
'object got {0}: {1}'.format(type(td).__name__, e)
|
|
457
|
+
) from e
|
|
458
|
+
|
|
459
|
+
def _internal_assign(self, td):
|
|
460
|
+
self.FromTimedelta(td)
|
|
461
|
+
|
|
462
|
+
def _NormalizeDuration(self, seconds, nanos):
|
|
463
|
+
"""Set Duration by seconds and nanos."""
|
|
464
|
+
# Force nanos to be negative if the duration is negative.
|
|
465
|
+
if seconds < 0 and nanos > 0:
|
|
466
|
+
seconds += 1
|
|
467
|
+
nanos -= _NANOS_PER_SECOND
|
|
468
|
+
self.seconds = seconds
|
|
469
|
+
self.nanos = nanos
|
|
470
|
+
|
|
471
|
+
def __add__(self, value) -> Union[datetime.datetime, datetime.timedelta]:
|
|
472
|
+
if isinstance(value, Timestamp):
|
|
473
|
+
return self.ToTimedelta() + value.ToDatetime()
|
|
474
|
+
return self.ToTimedelta() + value
|
|
475
|
+
|
|
476
|
+
__radd__ = __add__
|
|
477
|
+
|
|
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()
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def _CheckDurationValid(seconds, nanos):
|
|
486
|
+
if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX:
|
|
487
|
+
raise ValueError(
|
|
488
|
+
'Duration is not valid: Seconds {0} must be in range '
|
|
489
|
+
'[-315576000000, 315576000000].'.format(seconds)
|
|
490
|
+
)
|
|
491
|
+
if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND:
|
|
492
|
+
raise ValueError(
|
|
493
|
+
'Duration is not valid: Nanos {0} must be in range '
|
|
494
|
+
'[-999999999, 999999999].'.format(nanos)
|
|
495
|
+
)
|
|
496
|
+
if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0):
|
|
497
|
+
raise ValueError('Duration is not valid: Sign mismatch.')
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _RoundTowardZero(value, divider):
|
|
501
|
+
"""Truncates the remainder part after division."""
|
|
502
|
+
# For some languages, the sign of the remainder is implementation
|
|
503
|
+
# dependent if any of the operands is negative. Here we enforce
|
|
504
|
+
# "rounded toward zero" semantics. For example, for (-5) / 2 an
|
|
505
|
+
# implementation may give -3 as the result with the remainder being
|
|
506
|
+
# 1. This function ensures we always return -2 (closer to zero).
|
|
507
|
+
result = value // divider
|
|
508
|
+
remainder = value % divider
|
|
509
|
+
if result < 0 and remainder > 0:
|
|
510
|
+
return result + 1
|
|
511
|
+
else:
|
|
512
|
+
return result
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def _SetStructValue(struct_value, value):
|
|
516
|
+
if value is None:
|
|
517
|
+
struct_value.null_value = 0
|
|
518
|
+
elif isinstance(value, bool):
|
|
519
|
+
# Note: this check must come before the number check because in Python
|
|
520
|
+
# True and False are also considered numbers.
|
|
521
|
+
struct_value.bool_value = value
|
|
522
|
+
elif isinstance(value, str):
|
|
523
|
+
struct_value.string_value = value
|
|
524
|
+
elif isinstance(value, (int, float)):
|
|
525
|
+
struct_value.number_value = value
|
|
526
|
+
elif isinstance(value, (dict, Struct)):
|
|
527
|
+
struct_value.struct_value.Clear()
|
|
528
|
+
struct_value.struct_value.update(value)
|
|
529
|
+
elif isinstance(value, (list, tuple, ListValue)):
|
|
530
|
+
struct_value.list_value.Clear()
|
|
531
|
+
struct_value.list_value.extend(value)
|
|
532
|
+
else:
|
|
533
|
+
raise ValueError('Unexpected type')
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def _GetStructValue(struct_value):
|
|
537
|
+
which = struct_value.WhichOneof('kind')
|
|
538
|
+
if which == 'struct_value':
|
|
539
|
+
return struct_value.struct_value
|
|
540
|
+
elif which == 'null_value':
|
|
541
|
+
return None
|
|
542
|
+
elif which == 'number_value':
|
|
543
|
+
return struct_value.number_value
|
|
544
|
+
elif which == 'string_value':
|
|
545
|
+
return struct_value.string_value
|
|
546
|
+
elif which == 'bool_value':
|
|
547
|
+
return struct_value.bool_value
|
|
548
|
+
elif which == 'list_value':
|
|
549
|
+
return struct_value.list_value
|
|
550
|
+
elif which is None:
|
|
551
|
+
raise ValueError('Value not set')
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
class Struct(object):
|
|
555
|
+
"""Class for Struct message type."""
|
|
556
|
+
|
|
557
|
+
__slots__ = ()
|
|
558
|
+
|
|
559
|
+
def __getitem__(self, key):
|
|
560
|
+
return _GetStructValue(self.fields[key])
|
|
561
|
+
|
|
562
|
+
def __setitem__(self, key, value):
|
|
563
|
+
_SetStructValue(self.fields[key], value)
|
|
564
|
+
|
|
565
|
+
def __delitem__(self, key):
|
|
566
|
+
del self.fields[key]
|
|
567
|
+
|
|
568
|
+
def __len__(self):
|
|
569
|
+
return len(self.fields)
|
|
570
|
+
|
|
571
|
+
def __iter__(self):
|
|
572
|
+
return iter(self.fields)
|
|
573
|
+
|
|
574
|
+
def _internal_assign(self, dictionary):
|
|
575
|
+
self.Clear()
|
|
576
|
+
self.update(dictionary)
|
|
577
|
+
|
|
578
|
+
def _internal_compare(self, other):
|
|
579
|
+
size = len(self)
|
|
580
|
+
if size != len(other):
|
|
581
|
+
return False
|
|
582
|
+
for key, value in self.items():
|
|
583
|
+
if key not in other:
|
|
584
|
+
return False
|
|
585
|
+
if isinstance(other[key], (dict, list)):
|
|
586
|
+
if not value._internal_compare(other[key]):
|
|
587
|
+
return False
|
|
588
|
+
elif value != other[key]:
|
|
589
|
+
return False
|
|
590
|
+
return True
|
|
591
|
+
|
|
592
|
+
def keys(self): # pylint: disable=invalid-name
|
|
593
|
+
return self.fields.keys()
|
|
594
|
+
|
|
595
|
+
def values(self): # pylint: disable=invalid-name
|
|
596
|
+
return [self[key] for key in self]
|
|
597
|
+
|
|
598
|
+
def items(self): # pylint: disable=invalid-name
|
|
599
|
+
return [(key, self[key]) for key in self]
|
|
600
|
+
|
|
601
|
+
def get_or_create_list(self, key):
|
|
602
|
+
"""Returns a list for this key, creating if it didn't exist already."""
|
|
603
|
+
if not self.fields[key].HasField('list_value'):
|
|
604
|
+
# Clear will mark list_value modified which will indeed create a list.
|
|
605
|
+
self.fields[key].list_value.Clear()
|
|
606
|
+
return self.fields[key].list_value
|
|
607
|
+
|
|
608
|
+
def get_or_create_struct(self, key):
|
|
609
|
+
"""Returns a struct for this key, creating if it didn't exist already."""
|
|
610
|
+
if not self.fields[key].HasField('struct_value'):
|
|
611
|
+
# Clear will mark struct_value modified which will indeed create a struct.
|
|
612
|
+
self.fields[key].struct_value.Clear()
|
|
613
|
+
return self.fields[key].struct_value
|
|
614
|
+
|
|
615
|
+
def update(self, dictionary): # pylint: disable=invalid-name
|
|
616
|
+
for key, value in dictionary.items():
|
|
617
|
+
_SetStructValue(self.fields[key], value)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
collections.abc.MutableMapping.register(Struct)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
class ListValue(object):
|
|
624
|
+
"""Class for ListValue message type."""
|
|
625
|
+
|
|
626
|
+
__slots__ = ()
|
|
627
|
+
|
|
628
|
+
def __len__(self):
|
|
629
|
+
return len(self.values)
|
|
630
|
+
|
|
631
|
+
def append(self, value):
|
|
632
|
+
_SetStructValue(self.values.add(), value)
|
|
633
|
+
|
|
634
|
+
def extend(self, elem_seq):
|
|
635
|
+
for value in elem_seq:
|
|
636
|
+
self.append(value)
|
|
637
|
+
|
|
638
|
+
def __getitem__(self, index):
|
|
639
|
+
"""Retrieves item by the specified index."""
|
|
640
|
+
return _GetStructValue(self.values.__getitem__(index))
|
|
641
|
+
|
|
642
|
+
def __setitem__(self, index, value):
|
|
643
|
+
_SetStructValue(self.values.__getitem__(index), value)
|
|
644
|
+
|
|
645
|
+
def __delitem__(self, key):
|
|
646
|
+
del self.values[key]
|
|
647
|
+
|
|
648
|
+
def _internal_assign(self, elem_seq):
|
|
649
|
+
self.Clear()
|
|
650
|
+
self.extend(elem_seq)
|
|
651
|
+
|
|
652
|
+
def _internal_compare(self, other):
|
|
653
|
+
size = len(self)
|
|
654
|
+
if size != len(other):
|
|
655
|
+
return False
|
|
656
|
+
for i in range(size):
|
|
657
|
+
if isinstance(other[i], (dict, list)):
|
|
658
|
+
if not self[i]._internal_compare(other[i]):
|
|
659
|
+
return False
|
|
660
|
+
elif self[i] != other[i]:
|
|
661
|
+
return False
|
|
662
|
+
return True
|
|
663
|
+
|
|
664
|
+
def items(self):
|
|
665
|
+
for i in range(len(self)):
|
|
666
|
+
yield self[i]
|
|
667
|
+
|
|
668
|
+
def add_struct(self):
|
|
669
|
+
"""Appends and returns a struct value as the next value in the list."""
|
|
670
|
+
struct_value = self.values.add().struct_value
|
|
671
|
+
# Clear will mark struct_value modified which will indeed create a struct.
|
|
672
|
+
struct_value.Clear()
|
|
673
|
+
return struct_value
|
|
674
|
+
|
|
675
|
+
def add_list(self):
|
|
676
|
+
"""Appends and returns a list value as the next value in the list."""
|
|
677
|
+
list_value = self.values.add().list_value
|
|
678
|
+
# Clear will mark list_value modified which will indeed create a list.
|
|
679
|
+
list_value.Clear()
|
|
680
|
+
return list_value
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
collections.abc.MutableSequence.register(ListValue)
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
# LINT.IfChange(wktbases)
|
|
687
|
+
WKTBASES = {
|
|
688
|
+
'google.protobuf.Any': Any,
|
|
689
|
+
'google.protobuf.Duration': Duration,
|
|
690
|
+
'google.protobuf.FieldMask': FieldMask,
|
|
691
|
+
'google.protobuf.ListValue': ListValue,
|
|
692
|
+
'google.protobuf.Struct': Struct,
|
|
693
|
+
'google.protobuf.Timestamp': Timestamp,
|
|
694
|
+
}
|
|
695
|
+
# LINT.ThenChange(//depot/google.protobuf/compiler/python/pyi_generator.cc:wktbases)
|