crossplane-function-pythonic 0.6.2__py3-none-any.whl → 0.7.0__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.
- crossplane/pythonic/__about__.py +6 -2
- crossplane/pythonic/__init__.py +21 -13
- crossplane/pythonic/__main__.py +1 -0
- crossplane/pythonic/auto_ready.py +118 -61
- crossplane/pythonic/command.py +69 -58
- crossplane/pythonic/composite.py +656 -428
- crossplane/pythonic/function.py +233 -130
- crossplane/pythonic/grpc.py +89 -65
- crossplane/pythonic/main.py +18 -5
- crossplane/pythonic/packages.py +82 -51
- crossplane/pythonic/proto/v1/run_function_pb2.py +3 -3
- crossplane/pythonic/proto/v1/run_function_pb2.pyi +1121 -255
- crossplane/pythonic/proto/v1/run_function_pb2_grpc.py +4 -4
- crossplane/pythonic/proto/v1/run_function_pb2_grpc.pyi +64 -0
- crossplane/pythonic/protobuf.py +589 -372
- crossplane/pythonic/render.py +568 -235
- crossplane/pythonic/version.py +3 -4
- {crossplane_function_pythonic-0.6.2.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/METADATA +23 -26
- crossplane_function_pythonic-0.7.0.dist-info/RECORD +22 -0
- {crossplane_function_pythonic-0.6.2.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/WHEEL +1 -1
- {crossplane_function_pythonic-0.6.2.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/entry_points.txt +1 -0
- crossplane_function_pythonic-0.6.2.dist-info/RECORD +0 -22
- crossplane_function_pythonic-0.6.2.dist-info/licenses/LICENSE +0 -201
crossplane/pythonic/protobuf.py
CHANGED
|
@@ -17,81 +17,158 @@
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
19
|
import datetime
|
|
20
|
-
import google.protobuf.struct_pb2
|
|
21
20
|
import json
|
|
22
21
|
import sys
|
|
23
|
-
import
|
|
22
|
+
import typing
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
import google.protobuf.descriptor
|
|
25
|
+
import google.protobuf.message
|
|
26
|
+
import google.protobuf.struct_pb2
|
|
27
|
+
import yaml
|
|
28
|
+
from google.protobuf.internal.containers import (
|
|
29
|
+
MessageMap,
|
|
30
|
+
RepeatedCompositeFieldContainer,
|
|
31
|
+
RepeatedScalarFieldContainer,
|
|
32
|
+
ScalarMap,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
type TypeString = str | Value | FieldMessage
|
|
36
|
+
_Unknown = sentinel("_Unknown")
|
|
26
37
|
append = sys.maxsize
|
|
27
38
|
|
|
28
39
|
|
|
29
|
-
def Map(**kwargs):
|
|
40
|
+
def Map(**kwargs) -> Value:
|
|
30
41
|
return Value(None, None, kwargs)
|
|
31
42
|
|
|
32
|
-
|
|
43
|
+
|
|
44
|
+
def List(*args) -> Value:
|
|
33
45
|
return Value(None, None, args)
|
|
34
46
|
|
|
35
|
-
|
|
47
|
+
|
|
48
|
+
def Unknown() -> Value:
|
|
36
49
|
return Value(None, None)
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
|
|
52
|
+
def Yaml(string: TypeString, readOnly: str | bool = False) -> Value | FieldMessage:
|
|
39
53
|
if isinstance(string, (FieldMessage, Value)):
|
|
40
54
|
if not string:
|
|
41
55
|
return string
|
|
42
56
|
string = str(string)
|
|
43
57
|
return Value(None, None, yaml.safe_load(string), readOnly)
|
|
44
58
|
|
|
45
|
-
|
|
59
|
+
|
|
60
|
+
def YamlAll(string: TypeString, readOnly: str | bool = False) -> Value | FieldMessage:
|
|
46
61
|
if isinstance(string, (FieldMessage, Value)):
|
|
47
62
|
if not string:
|
|
48
63
|
return string
|
|
49
64
|
string = str(string)
|
|
50
|
-
return Value(
|
|
65
|
+
return Value(
|
|
66
|
+
None, None, [document for document in yaml.safe_load_all(string)], readOnly
|
|
67
|
+
)
|
|
51
68
|
|
|
52
|
-
|
|
69
|
+
|
|
70
|
+
def Json(string: TypeString, readOnly: str | bool = False) -> Value | FieldMessage:
|
|
53
71
|
if isinstance(string, (FieldMessage, Value)):
|
|
54
72
|
if not string:
|
|
55
73
|
return string
|
|
56
74
|
string = str(string)
|
|
57
75
|
return Value(None, None, json.loads(string), readOnly)
|
|
58
76
|
|
|
59
|
-
|
|
77
|
+
|
|
78
|
+
def B64Encode(string: TypeString) -> TypeString:
|
|
60
79
|
if isinstance(string, (FieldMessage, Value)):
|
|
61
80
|
if not string:
|
|
62
81
|
return string
|
|
63
82
|
string = str(string)
|
|
64
|
-
return base64.b64encode(string.encode(
|
|
83
|
+
return base64.b64encode(string.encode("utf-8")).decode("utf-8")
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
|
|
86
|
+
def B64Decode(string: TypeString) -> TypeString:
|
|
67
87
|
if isinstance(string, (FieldMessage, Value)):
|
|
68
88
|
if not string:
|
|
69
89
|
return string
|
|
70
90
|
string = str(string)
|
|
71
|
-
return base64.b64decode(string.encode(
|
|
91
|
+
return base64.b64decode(string.encode("utf-8")).decode("utf-8")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class TypeProtobuf:
|
|
95
|
+
def __getattr__(self, key):
|
|
96
|
+
if key not in self.__dict__:
|
|
97
|
+
raise AttributeError(
|
|
98
|
+
f"{self.__class__.__name__} attribute does not exist: {key}"
|
|
99
|
+
)
|
|
100
|
+
return self.__dict__[key]
|
|
101
|
+
|
|
102
|
+
def __getitem__(self, key):
|
|
103
|
+
raise ValueError(f"{self.__class__.__name__} does not have dynamic items")
|
|
104
|
+
|
|
105
|
+
def __iter__(self):
|
|
106
|
+
raise ValueError(f"{self.__class__.__name__} is not iterable")
|
|
107
|
+
|
|
108
|
+
def __int__(self):
|
|
109
|
+
raise ValueError(f"{self.__class__.__name__} is not an integer")
|
|
72
110
|
|
|
111
|
+
def __float__(self):
|
|
112
|
+
raise ValueError(f"{self.__class__.__name__} is not a float")
|
|
73
113
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
self._set_attribute('_parent', parent)
|
|
77
|
-
self._set_attribute('_key', key)
|
|
78
|
-
self._set_attribute('_descriptor', descriptor)
|
|
79
|
-
self._set_attribute('_message', message)
|
|
80
|
-
self._set_attribute('_readOnly', readOnly)
|
|
81
|
-
self._set_attribute('_cache', {})
|
|
114
|
+
def __call__(self, *args, **kwargs):
|
|
115
|
+
raise ValueError(f"{self.__class__.__name__} is not callable")
|
|
82
116
|
|
|
83
|
-
def
|
|
117
|
+
def __setattr__(self, key, value):
|
|
84
118
|
self.__dict__[key] = value
|
|
85
119
|
|
|
86
|
-
def
|
|
120
|
+
def __setitem__(self, key, value):
|
|
121
|
+
raise ValueError(f"{self.__class__.__name__} does not have dynamic items")
|
|
122
|
+
|
|
123
|
+
def __delattr__(self, key):
|
|
124
|
+
raise ValueError(f"{self.__class__.__name__} does not have dynamic attributes")
|
|
125
|
+
|
|
126
|
+
def __delitem__(self, key):
|
|
127
|
+
raise ValueError(f"{self.__class__.__name__} does not have dynamic items")
|
|
128
|
+
|
|
129
|
+
def append(self, value):
|
|
130
|
+
raise ValueError(f"{self.__class__.__name__} does not have dynamic items")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class Message(TypeProtobuf):
|
|
134
|
+
def __init__(
|
|
135
|
+
self,
|
|
136
|
+
parent: Message | MapMessage | RepeatedMessage | None,
|
|
137
|
+
key: str | int | Value | FieldMessage | None,
|
|
138
|
+
descriptor: google.protobuf.descriptor.Descriptor,
|
|
139
|
+
message: google.protobuf.message.Message | _Unknown = _Unknown,
|
|
140
|
+
readOnly: str | bool = False,
|
|
141
|
+
):
|
|
142
|
+
self._parent: Message | MapMessage | RepeatedMessage | None = parent
|
|
143
|
+
self._key = key
|
|
144
|
+
self._descriptor: google.protobuf.descriptor.Descriptor = descriptor
|
|
145
|
+
self._message: google.protobuf.message.Message | _Unknown = message
|
|
146
|
+
self._readOnly: str | bool = readOnly
|
|
147
|
+
self._cache: dict[str, typing.Any] = {}
|
|
148
|
+
|
|
149
|
+
def _ensure_message(self):
|
|
150
|
+
if self._message is _Unknown:
|
|
151
|
+
if self._parent is None:
|
|
152
|
+
raise ValueError(
|
|
153
|
+
"Messages does not have parent to create internal message"
|
|
154
|
+
)
|
|
155
|
+
self._message: google.protobuf.message.Message = self._parent._create_child(
|
|
156
|
+
self._key
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def __getattr__(
|
|
160
|
+
self, key
|
|
161
|
+
) -> Message | MapMessage | RepeatedMessage | FieldMessage | Value:
|
|
87
162
|
return self[key]
|
|
88
163
|
|
|
89
|
-
def __getitem__(
|
|
164
|
+
def __getitem__(
|
|
165
|
+
self, key
|
|
166
|
+
) -> Message | MapMessage | RepeatedMessage | FieldMessage | Value:
|
|
90
167
|
key = self._validate_key(key)
|
|
91
168
|
if key in self._cache:
|
|
92
169
|
return self._cache[key]
|
|
93
170
|
field = self._descriptor.fields_by_name.get(key)
|
|
94
|
-
if
|
|
171
|
+
if field is None:
|
|
95
172
|
raise AttributeError(obj=self, name=key)
|
|
96
173
|
if self._message is _Unknown:
|
|
97
174
|
value = _Unknown
|
|
@@ -100,12 +177,22 @@ class Message:
|
|
|
100
177
|
if value is _Unknown and field.has_default_value:
|
|
101
178
|
value = field.default_value
|
|
102
179
|
if field.is_repeated:
|
|
103
|
-
if
|
|
104
|
-
|
|
180
|
+
if (
|
|
181
|
+
field.type == field.TYPE_MESSAGE
|
|
182
|
+
and field.message_type
|
|
183
|
+
and field.message_type.GetOptions().map_entry
|
|
184
|
+
):
|
|
185
|
+
value = MapMessage(
|
|
186
|
+
self,
|
|
187
|
+
key,
|
|
188
|
+
field.message_type.fields_by_name["value"],
|
|
189
|
+
value,
|
|
190
|
+
self._readOnly,
|
|
191
|
+
)
|
|
105
192
|
else:
|
|
106
193
|
value = RepeatedMessage(self, key, field, value, self._readOnly)
|
|
107
|
-
elif field.type == field.TYPE_MESSAGE:
|
|
108
|
-
if field.message_type.name in (
|
|
194
|
+
elif field.type == field.TYPE_MESSAGE and field.message_type:
|
|
195
|
+
if field.message_type.name in ("Struct", "ListValue"):
|
|
109
196
|
value = Value(self, key, value, self._readOnly)
|
|
110
197
|
else:
|
|
111
198
|
value = Message(self, key, field.message_type, value, self._readOnly)
|
|
@@ -129,7 +216,11 @@ class Message:
|
|
|
129
216
|
|
|
130
217
|
def __hash__(self):
|
|
131
218
|
if self._message is not _Unknown:
|
|
132
|
-
return hash(
|
|
219
|
+
return hash(
|
|
220
|
+
tuple(
|
|
221
|
+
hash(item) for item in sorted(iter(self), key=lambda item: item[0])
|
|
222
|
+
)
|
|
223
|
+
)
|
|
133
224
|
return 0
|
|
134
225
|
|
|
135
226
|
def __eq__(self, other):
|
|
@@ -153,7 +244,7 @@ class Message:
|
|
|
153
244
|
def __str__(self):
|
|
154
245
|
return format(self)
|
|
155
246
|
|
|
156
|
-
def __format__(self, spec=
|
|
247
|
+
def __format__(self, spec="yaml"):
|
|
157
248
|
return _formatObject(self, spec)
|
|
158
249
|
|
|
159
250
|
def _fullName(self, key=None):
|
|
@@ -163,36 +254,37 @@ class Message:
|
|
|
163
254
|
else:
|
|
164
255
|
name = str(self._key)
|
|
165
256
|
if key is not None:
|
|
166
|
-
if
|
|
257
|
+
if "." in key:
|
|
167
258
|
name += f"[{key}]"
|
|
168
259
|
else:
|
|
169
260
|
name += f".{key}"
|
|
170
261
|
return name
|
|
171
262
|
if key is not None:
|
|
172
263
|
return str(key)
|
|
173
|
-
return
|
|
264
|
+
return ""
|
|
174
265
|
|
|
175
266
|
def _create_child(self, key):
|
|
176
267
|
if self._readOnly:
|
|
177
268
|
raise ValueError(f"{self._readOnly} is read only")
|
|
178
269
|
key = self._validate_key(key)
|
|
179
|
-
|
|
180
|
-
self.__dict__['_message'] = self._parent._create_child(self._key)
|
|
270
|
+
self._ensure_message()
|
|
181
271
|
return getattr(self._message, key)
|
|
182
272
|
|
|
183
273
|
def __call__(self, **kwargs):
|
|
184
274
|
if self._readOnly:
|
|
185
275
|
raise ValueError(f"{self._readOnly} is read only")
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
self._message.Clear()
|
|
276
|
+
self._ensure_message()
|
|
277
|
+
typing.cast(google.protobuf.message.Message, self._message).Clear()
|
|
189
278
|
self._cache.clear()
|
|
190
279
|
for key, value in kwargs.items():
|
|
191
280
|
self[key] = value
|
|
192
281
|
return self
|
|
193
282
|
|
|
194
283
|
def __setattr__(self, key, value):
|
|
195
|
-
|
|
284
|
+
if key in ("_parent", "_key", "_descriptor", "_message", "_readOnly", "_cache"):
|
|
285
|
+
self.__dict__[key] = value
|
|
286
|
+
else:
|
|
287
|
+
self[key] = value
|
|
196
288
|
|
|
197
289
|
def __setitem__(self, key, value):
|
|
198
290
|
if self._readOnly:
|
|
@@ -200,19 +292,34 @@ class Message:
|
|
|
200
292
|
key = self._validate_key(key)
|
|
201
293
|
if key not in self._descriptor.fields_by_name:
|
|
202
294
|
raise AttributeError(obj=self, name=key)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
295
|
+
if isinstance(value, (Message, MapMessage)):
|
|
296
|
+
for k, v in value:
|
|
297
|
+
self[key][k] = v
|
|
298
|
+
return
|
|
299
|
+
if isinstance(value, dict):
|
|
300
|
+
for k, v in value.items():
|
|
301
|
+
self[key][k] = v
|
|
302
|
+
return
|
|
303
|
+
if isinstance(value, (RepeatedMessage, list, tuple)):
|
|
304
|
+
for ix, v in enumerate(value):
|
|
305
|
+
self[key][ix] = v
|
|
306
|
+
return
|
|
307
|
+
if isinstance(value, FieldMessage):
|
|
211
308
|
value = value._value
|
|
212
309
|
elif isinstance(value, Value):
|
|
310
|
+
if value._isMap:
|
|
311
|
+
for k, v in value:
|
|
312
|
+
self[key][k] = v
|
|
313
|
+
return
|
|
314
|
+
if value._isList:
|
|
315
|
+
for ix, v in enumerate(value):
|
|
316
|
+
self[key][ix] = v
|
|
317
|
+
return
|
|
213
318
|
value = value._raw
|
|
319
|
+
field = self._descriptor.fields_by_name[key]
|
|
214
320
|
if field.type == field.TYPE_BYTES and isinstance(value, str):
|
|
215
|
-
value = value.encode(
|
|
321
|
+
value = value.encode("utf-8")
|
|
322
|
+
self._ensure_message()
|
|
216
323
|
setattr(self._message, key, value)
|
|
217
324
|
self._cache.pop(key, None)
|
|
218
325
|
|
|
@@ -239,17 +346,21 @@ class Message:
|
|
|
239
346
|
return key
|
|
240
347
|
|
|
241
348
|
|
|
242
|
-
class MapMessage:
|
|
243
|
-
def __init__(
|
|
244
|
-
self
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
self.
|
|
349
|
+
class MapMessage(TypeProtobuf):
|
|
350
|
+
def __init__(
|
|
351
|
+
self,
|
|
352
|
+
parent: Message,
|
|
353
|
+
key: str,
|
|
354
|
+
field: google.protobuf.descriptor.FieldDescriptor,
|
|
355
|
+
messages: ScalarMap | MessageMap | _Unknown = _Unknown,
|
|
356
|
+
readOnly: str | bool = False,
|
|
357
|
+
):
|
|
358
|
+
self._parent: Message = parent
|
|
359
|
+
self._key: str = key
|
|
360
|
+
self._field: google.protobuf.descriptor.FieldDescriptor = field
|
|
361
|
+
self._messages: ScalarMap | MessageMap | _Unknown = messages
|
|
362
|
+
self._readOnly = readOnly
|
|
363
|
+
self._cache: dict[str, typing.Any] = {}
|
|
253
364
|
|
|
254
365
|
def __getattr__(self, key):
|
|
255
366
|
return self[key]
|
|
@@ -264,11 +375,13 @@ class MapMessage:
|
|
|
264
375
|
value = self._messages[key]
|
|
265
376
|
if value is None and self._field.has_default_value:
|
|
266
377
|
value = self._field.default_value
|
|
267
|
-
if self._field.type == self._field.TYPE_MESSAGE:
|
|
268
|
-
if self._field.message_type.name in (
|
|
378
|
+
if self._field.type == self._field.TYPE_MESSAGE and self._field.message_type:
|
|
379
|
+
if str(self._field.message_type.name) in ("Struct", "ListValue"):
|
|
269
380
|
value = Value(self, key, value, self._readOnly)
|
|
270
381
|
else:
|
|
271
|
-
value = Message(
|
|
382
|
+
value = Message(
|
|
383
|
+
self, key, self._field.message_type, value, self._readOnly
|
|
384
|
+
)
|
|
272
385
|
else:
|
|
273
386
|
value = FieldMessage(self, key, self._field.type, value)
|
|
274
387
|
self._cache[key] = value
|
|
@@ -281,7 +394,9 @@ class MapMessage:
|
|
|
281
394
|
return 0 if self._messages is _Unknown else len(self._messages)
|
|
282
395
|
|
|
283
396
|
def __contains__(self, key):
|
|
284
|
-
return
|
|
397
|
+
return (
|
|
398
|
+
self._messages is not _Unknown and self._validate_key(key) in self._messages
|
|
399
|
+
)
|
|
285
400
|
|
|
286
401
|
def __iter__(self):
|
|
287
402
|
if self._messages is not _Unknown:
|
|
@@ -289,8 +404,12 @@ class MapMessage:
|
|
|
289
404
|
yield key, self[key]
|
|
290
405
|
|
|
291
406
|
def __hash__(self):
|
|
292
|
-
if self.
|
|
293
|
-
return hash(
|
|
407
|
+
if self._messages is not _Unknown:
|
|
408
|
+
return hash(
|
|
409
|
+
tuple(
|
|
410
|
+
hash(item) for item in sorted(iter(self), key=lambda item: item[0])
|
|
411
|
+
)
|
|
412
|
+
)
|
|
294
413
|
return 0
|
|
295
414
|
|
|
296
415
|
def __eq__(self, other):
|
|
@@ -298,9 +417,13 @@ class MapMessage:
|
|
|
298
417
|
return False
|
|
299
418
|
if self._field.type != other._field.type:
|
|
300
419
|
return False
|
|
301
|
-
if
|
|
302
|
-
|
|
303
|
-
|
|
420
|
+
if (
|
|
421
|
+
self._field.type == self._field.TYPE_MESSAGE
|
|
422
|
+
and self._field.message_type
|
|
423
|
+
and self._field.message_type.full_name
|
|
424
|
+
!= other._field.message_type.full_name
|
|
425
|
+
):
|
|
426
|
+
return False
|
|
304
427
|
if self._messages is _Unknown:
|
|
305
428
|
return other._messages is _Unknown
|
|
306
429
|
elif other._messages is _Unknown:
|
|
@@ -317,67 +440,67 @@ class MapMessage:
|
|
|
317
440
|
def __str__(self):
|
|
318
441
|
return format(self)
|
|
319
442
|
|
|
320
|
-
def __format__(self, spec=
|
|
443
|
+
def __format__(self, spec="yaml"):
|
|
321
444
|
return _formatObject(self, spec)
|
|
322
445
|
|
|
323
446
|
def _fullName(self, key=None):
|
|
324
|
-
|
|
325
|
-
if self._parent is not None:
|
|
326
|
-
name = self._parent._fullName(self._key)
|
|
327
|
-
else:
|
|
328
|
-
name = str(self._key)
|
|
329
|
-
if key is not None:
|
|
330
|
-
if '.' in key:
|
|
331
|
-
name += f"[{key}]"
|
|
332
|
-
else:
|
|
333
|
-
name += f".{key}"
|
|
334
|
-
return name
|
|
447
|
+
name = self._parent._fullName(self._key)
|
|
335
448
|
if key is not None:
|
|
336
|
-
|
|
337
|
-
|
|
449
|
+
if "." in key:
|
|
450
|
+
name += f"[{key}]"
|
|
451
|
+
else:
|
|
452
|
+
name += f".{key}"
|
|
453
|
+
return name
|
|
338
454
|
|
|
339
455
|
def _create_child(self, key):
|
|
340
456
|
if self._readOnly:
|
|
341
457
|
raise ValueError(f"{self._readOnly} is read only")
|
|
342
458
|
key = self._validate_key(key)
|
|
343
459
|
if self._messages is _Unknown:
|
|
344
|
-
self.
|
|
460
|
+
self._messages = self._parent._create_child(self._key)
|
|
345
461
|
return self._messages[key]
|
|
346
462
|
|
|
347
463
|
def __call__(self, **kwargs):
|
|
348
464
|
if self._readOnly:
|
|
349
465
|
raise ValueError(f"{self._readOnly} is read only")
|
|
350
466
|
if self._messages is _Unknown:
|
|
351
|
-
self.
|
|
467
|
+
self._messages: ScalarMap | MessageMap = self._parent._create_child(
|
|
468
|
+
self._key
|
|
469
|
+
)
|
|
352
470
|
self._messages.clear()
|
|
353
471
|
self._cache.clear()
|
|
354
472
|
for key, value in kwargs.items():
|
|
355
473
|
self[key] = value
|
|
356
474
|
return self
|
|
357
475
|
|
|
358
|
-
def __setattr__(self, key,
|
|
359
|
-
|
|
476
|
+
def __setattr__(self, key, value):
|
|
477
|
+
if key in ("_parent", "_key", "_field", "_messages", "_readOnly", "_cache"):
|
|
478
|
+
self.__dict__[key] = value
|
|
479
|
+
else:
|
|
480
|
+
self[key] = value
|
|
360
481
|
|
|
361
|
-
def __setitem__(self, key,
|
|
482
|
+
def __setitem__(self, key, value):
|
|
362
483
|
if self._readOnly:
|
|
363
484
|
raise ValueError(f"{self._readOnly} is read only")
|
|
364
485
|
key = self._validate_key(key)
|
|
365
486
|
if self._messages is _Unknown:
|
|
366
|
-
self._messages = self._parent._create_child(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
elif isinstance(
|
|
372
|
-
|
|
373
|
-
elif isinstance(
|
|
374
|
-
|
|
375
|
-
|
|
487
|
+
self._messages: ScalarMap | MessageMap = self._parent._create_child(
|
|
488
|
+
self._key
|
|
489
|
+
)
|
|
490
|
+
if isinstance(value, Message):
|
|
491
|
+
value = value._message
|
|
492
|
+
elif isinstance(value, (MapMessage, RepeatedMessage)):
|
|
493
|
+
value = value._messages
|
|
494
|
+
elif isinstance(value, FieldMessage):
|
|
495
|
+
value = value._value
|
|
496
|
+
elif isinstance(value, Value):
|
|
497
|
+
value = value._raw
|
|
498
|
+
if value is _Unknown:
|
|
376
499
|
self._messages.pop(key, None)
|
|
377
500
|
else:
|
|
378
|
-
if self._field.type == self._field.TYPE_BYTES and isinstance(
|
|
379
|
-
|
|
380
|
-
self._messages[key] =
|
|
501
|
+
if self._field.type == self._field.TYPE_BYTES and isinstance(value, str):
|
|
502
|
+
value = value.encode("utf-8")
|
|
503
|
+
self._messages[key] = value
|
|
381
504
|
self._cache.pop(key, None)
|
|
382
505
|
|
|
383
506
|
def __delattr__(self, key):
|
|
@@ -402,14 +525,25 @@ class MapMessage:
|
|
|
402
525
|
return key
|
|
403
526
|
|
|
404
527
|
|
|
405
|
-
class RepeatedMessage:
|
|
406
|
-
def __init__(
|
|
407
|
-
self
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
528
|
+
class RepeatedMessage(TypeProtobuf):
|
|
529
|
+
def __init__(
|
|
530
|
+
self,
|
|
531
|
+
parent: Message,
|
|
532
|
+
key: str,
|
|
533
|
+
field: google.protobuf.descriptor.FieldDescriptor,
|
|
534
|
+
messages: RepeatedCompositeFieldContainer
|
|
535
|
+
| RepeatedScalarFieldContainer
|
|
536
|
+
| _Unknown = _Unknown,
|
|
537
|
+
readOnly: str | bool = False,
|
|
538
|
+
):
|
|
539
|
+
self._parent: Message = parent
|
|
540
|
+
self._key: str = key
|
|
541
|
+
self._field: google.protobuf.descriptor.FieldDescriptor = field
|
|
542
|
+
self._messages: (
|
|
543
|
+
RepeatedCompositeFieldContainer | RepeatedScalarFieldContainer | _Unknown
|
|
544
|
+
) = messages
|
|
545
|
+
self._readOnly: str | bool = readOnly
|
|
546
|
+
self._cache: dict[int, typing.Any] = {}
|
|
413
547
|
|
|
414
548
|
def __getitem__(self, key):
|
|
415
549
|
key = self._validate_key(key)
|
|
@@ -425,8 +559,7 @@ class RepeatedMessage:
|
|
|
425
559
|
key = 0
|
|
426
560
|
else:
|
|
427
561
|
key = len(self._messages) + key
|
|
428
|
-
|
|
429
|
-
key = 0
|
|
562
|
+
key = max(key, 0)
|
|
430
563
|
if key in self._cache:
|
|
431
564
|
return self._cache[key]
|
|
432
565
|
if self._messages is _Unknown or key >= len(self._messages):
|
|
@@ -435,11 +568,13 @@ class RepeatedMessage:
|
|
|
435
568
|
value = self._messages[key]
|
|
436
569
|
if value is None and self._field.has_default_value:
|
|
437
570
|
value = self._field.default_value
|
|
438
|
-
if self._field.type == self._field.TYPE_MESSAGE:
|
|
439
|
-
if self._field.message_type.name in (
|
|
571
|
+
if self._field.type == self._field.TYPE_MESSAGE and self._field.message_type:
|
|
572
|
+
if self._field.message_type.name in ("Struct", "ListValue"):
|
|
440
573
|
value = Value(self, key, value, self._readOnly)
|
|
441
574
|
else:
|
|
442
|
-
value = Message(
|
|
575
|
+
value = Message(
|
|
576
|
+
self, key, self._field.message_type, value, self._readOnly
|
|
577
|
+
)
|
|
443
578
|
else:
|
|
444
579
|
value = FieldMessage(self, key, self._field.type, value)
|
|
445
580
|
self._cache[key] = value
|
|
@@ -473,9 +608,13 @@ class RepeatedMessage:
|
|
|
473
608
|
return False
|
|
474
609
|
if self._field.type != other._field.type:
|
|
475
610
|
return False
|
|
476
|
-
if
|
|
477
|
-
|
|
478
|
-
|
|
611
|
+
if (
|
|
612
|
+
self._field.type == self._field.TYPE_MESSAGE
|
|
613
|
+
and self._field.message_type
|
|
614
|
+
and self._field.message_type.full_name
|
|
615
|
+
!= other._field.message_type.full_name
|
|
616
|
+
):
|
|
617
|
+
return False
|
|
479
618
|
if self._messages is _Unknown:
|
|
480
619
|
return other._messages is _Unknown
|
|
481
620
|
elif other._messages is _Unknown:
|
|
@@ -490,7 +629,7 @@ class RepeatedMessage:
|
|
|
490
629
|
def __str__(self):
|
|
491
630
|
return format(self)
|
|
492
631
|
|
|
493
|
-
def __format__(self, spec=
|
|
632
|
+
def __format__(self, spec="yaml"):
|
|
494
633
|
return _formatObject(self, spec)
|
|
495
634
|
|
|
496
635
|
def _fullName(self, key=None):
|
|
@@ -504,34 +643,38 @@ class RepeatedMessage:
|
|
|
504
643
|
return name
|
|
505
644
|
if key is not None:
|
|
506
645
|
return str(key)
|
|
507
|
-
return
|
|
646
|
+
return ""
|
|
508
647
|
|
|
509
648
|
def _create_child(self, key):
|
|
510
649
|
if self._readOnly:
|
|
511
650
|
raise ValueError(f"{self._readOnly} is read only")
|
|
512
651
|
key = self._validate_key(key)
|
|
513
652
|
if self._messages is _Unknown:
|
|
514
|
-
self.
|
|
653
|
+
self._messages: (
|
|
654
|
+
RepeatedCompositeFieldContainer | RepeatedScalarFieldContainer
|
|
655
|
+
) = self._parent._create_child(self._key)
|
|
515
656
|
if key == append:
|
|
516
657
|
key = len(self._messages)
|
|
517
658
|
elif key < 0:
|
|
518
659
|
key = len(self._messages) + key
|
|
519
660
|
while key >= len(self._messages):
|
|
520
|
-
self._messages.add()
|
|
661
|
+
typing.cast(RepeatedCompositeFieldContainer, self._messages).add()
|
|
521
662
|
return self._messages[key]
|
|
522
663
|
|
|
523
664
|
def __call__(self, *args):
|
|
524
665
|
if self._readOnly:
|
|
525
666
|
raise ValueError(f"{self._readOnly} is read only")
|
|
526
667
|
if self._messages is _Unknown:
|
|
527
|
-
self.
|
|
668
|
+
self._messages: (
|
|
669
|
+
RepeatedCompositeFieldContainer | RepeatedScalarFieldContainer
|
|
670
|
+
) = self._parent._create_child(self._key)
|
|
528
671
|
self._messages.clear()
|
|
529
672
|
self._cache.clear()
|
|
530
673
|
for arg in args:
|
|
531
674
|
self.append(arg)
|
|
532
675
|
return self
|
|
533
676
|
|
|
534
|
-
def __setitem__(self, key,
|
|
677
|
+
def __setitem__(self, key, value):
|
|
535
678
|
if self._readOnly:
|
|
536
679
|
raise ValueError(f"{self._readOnly} is read only")
|
|
537
680
|
key = self._validate_key(key)
|
|
@@ -539,25 +682,25 @@ class RepeatedMessage:
|
|
|
539
682
|
self._messages = self._parent._create_child(self._key)
|
|
540
683
|
if key < 0:
|
|
541
684
|
key = len(self._messages) + key
|
|
542
|
-
if isinstance(
|
|
543
|
-
|
|
544
|
-
elif isinstance(
|
|
545
|
-
|
|
546
|
-
elif isinstance(
|
|
547
|
-
|
|
548
|
-
elif isinstance(
|
|
549
|
-
|
|
550
|
-
if
|
|
685
|
+
if isinstance(value, Message):
|
|
686
|
+
value = value._message
|
|
687
|
+
elif isinstance(value, (MapMessage, RepeatedMessage)):
|
|
688
|
+
value = value._messages
|
|
689
|
+
elif isinstance(value, FieldMessage):
|
|
690
|
+
value = value._value
|
|
691
|
+
elif isinstance(value, Value):
|
|
692
|
+
value = value._raw
|
|
693
|
+
if value is _Unknown:
|
|
551
694
|
if key < len(self._messages):
|
|
552
695
|
self._messages.pop(key)
|
|
553
696
|
self._cache.clear()
|
|
554
697
|
else:
|
|
555
|
-
if self._field.type == self._field.TYPE_BYTES and isinstance(
|
|
556
|
-
|
|
698
|
+
if self._field.type == self._field.TYPE_BYTES and isinstance(value, str):
|
|
699
|
+
value = value.encode("utf-8")
|
|
557
700
|
if key >= len(self._messages):
|
|
558
|
-
self._messages.append(
|
|
701
|
+
self._messages.append(value)
|
|
559
702
|
else:
|
|
560
|
-
self._messages[key] =
|
|
703
|
+
self._messages[key] = value
|
|
561
704
|
self._cache.pop(key, None)
|
|
562
705
|
|
|
563
706
|
def __delitem__(self, key):
|
|
@@ -568,15 +711,27 @@ class RepeatedMessage:
|
|
|
568
711
|
del self._messages[key]
|
|
569
712
|
self._cache.pop(key, None)
|
|
570
713
|
|
|
571
|
-
def append(self,
|
|
714
|
+
def append(self, value=_Unknown) -> TypeProtobuf:
|
|
572
715
|
if self._readOnly:
|
|
573
716
|
raise ValueError(f"{self._readOnly} is read only")
|
|
574
717
|
if self._messages is _Unknown:
|
|
575
|
-
self._messages =
|
|
576
|
-
|
|
577
|
-
|
|
718
|
+
self._messages: RepeatedCompositeFieldContainer = (
|
|
719
|
+
self._parent._create_child(self._key)
|
|
720
|
+
)
|
|
721
|
+
if isinstance(value, Message):
|
|
722
|
+
value = value._message
|
|
723
|
+
elif isinstance(value, (MapMessage, RepeatedMessage)):
|
|
724
|
+
value = value._messages
|
|
725
|
+
elif isinstance(value, FieldMessage):
|
|
726
|
+
value = value._value
|
|
727
|
+
elif isinstance(value, Value):
|
|
728
|
+
value = value._raw
|
|
729
|
+
if value is _Unknown:
|
|
730
|
+
typing.cast(RepeatedCompositeFieldContainer, self._messages).add()
|
|
578
731
|
else:
|
|
579
|
-
|
|
732
|
+
if self._field.type == self._field.TYPE_BYTES and isinstance(value, str):
|
|
733
|
+
value = value.encode("utf-8")
|
|
734
|
+
self._messages.append(value)
|
|
580
735
|
return self[len(self._messages) - 1]
|
|
581
736
|
|
|
582
737
|
def _validate_key(self, key):
|
|
@@ -589,23 +744,29 @@ class RepeatedMessage:
|
|
|
589
744
|
return key
|
|
590
745
|
|
|
591
746
|
|
|
592
|
-
class FieldMessage:
|
|
593
|
-
def __init__(
|
|
594
|
-
self
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
747
|
+
class FieldMessage(TypeProtobuf):
|
|
748
|
+
def __init__(
|
|
749
|
+
self,
|
|
750
|
+
parent: Message | MapMessage | RepeatedMessage,
|
|
751
|
+
key: str | int,
|
|
752
|
+
kind: int,
|
|
753
|
+
value: typing.Any,
|
|
754
|
+
):
|
|
755
|
+
self._parent: Message | MapMessage | RepeatedMessage = parent
|
|
756
|
+
self._key: str | int = key
|
|
757
|
+
self._kind: int = kind
|
|
758
|
+
self._value: typing.Any = value
|
|
598
759
|
|
|
599
760
|
def __bool__(self):
|
|
600
761
|
return self._value is not _Unknown
|
|
601
762
|
|
|
602
763
|
def __len__(self):
|
|
603
|
-
if self._value is _Unknown:
|
|
764
|
+
if self._value is _Unknown or not isinstance(self._value, (bytes, str)):
|
|
604
765
|
return 0
|
|
605
766
|
return len(self._value)
|
|
606
767
|
|
|
607
768
|
def __contains__(self, key):
|
|
608
|
-
if self._value is _Unknown:
|
|
769
|
+
if self._value is _Unknown or not isinstance(self._value, (bytes, str)):
|
|
609
770
|
return False
|
|
610
771
|
return key in self._value
|
|
611
772
|
|
|
@@ -618,24 +779,29 @@ class FieldMessage:
|
|
|
618
779
|
if self._value is _Unknown:
|
|
619
780
|
return False
|
|
620
781
|
if isinstance(other, FieldMessage):
|
|
621
|
-
|
|
782
|
+
other = other._value
|
|
783
|
+
if isinstance(self._value, str):
|
|
784
|
+
if isinstance(other, bytes):
|
|
785
|
+
other = other.decode("utf-8")
|
|
786
|
+
elif isinstance(self._value, bytes) and isinstance(other, str):
|
|
787
|
+
other = other.encode("utf-8")
|
|
622
788
|
return self._value == other
|
|
623
789
|
|
|
624
790
|
def __bytes__(self):
|
|
625
|
-
if self._value is _Unknown:
|
|
626
|
-
return None
|
|
791
|
+
if self._value is _Unknown or not isinstance(self._value, (bytes, str)):
|
|
792
|
+
return None # noqa: PLE0308
|
|
627
793
|
if isinstance(self._value, str):
|
|
628
|
-
return self._value.encode(
|
|
794
|
+
return self._value.encode("utf-8")
|
|
629
795
|
return bytes(self._value)
|
|
630
796
|
|
|
631
797
|
def __str__(self):
|
|
632
798
|
if self._value is _Unknown:
|
|
633
|
-
return None
|
|
799
|
+
return None # noqa: PLE0307
|
|
634
800
|
if isinstance(self._value, bytes):
|
|
635
|
-
return self._value.decode(
|
|
801
|
+
return self._value.decode("utf-8")
|
|
636
802
|
return str(self._value)
|
|
637
803
|
|
|
638
|
-
def __format__(self, spec=
|
|
804
|
+
def __format__(self, spec=""):
|
|
639
805
|
if self._value is _Unknown:
|
|
640
806
|
return None
|
|
641
807
|
return format(self._value, spec)
|
|
@@ -651,20 +817,13 @@ class FieldMessage:
|
|
|
651
817
|
return float(self._value)
|
|
652
818
|
|
|
653
819
|
def _fullName(self, key=None):
|
|
654
|
-
|
|
655
|
-
if self._parent is not None:
|
|
656
|
-
name = self._parent._fullName(self._key)
|
|
657
|
-
else:
|
|
658
|
-
name = str(self._key)
|
|
659
|
-
if key is not None:
|
|
660
|
-
if '.' in key:
|
|
661
|
-
name += f"[{key}]"
|
|
662
|
-
else:
|
|
663
|
-
name += f".{key}"
|
|
664
|
-
return name
|
|
820
|
+
name = self._parent._fullName(self._key)
|
|
665
821
|
if key is not None:
|
|
666
|
-
|
|
667
|
-
|
|
822
|
+
if "." in key:
|
|
823
|
+
name += f"[{key}]"
|
|
824
|
+
else:
|
|
825
|
+
name += f".{key}"
|
|
826
|
+
return name
|
|
668
827
|
|
|
669
828
|
|
|
670
829
|
class ProtobufValue:
|
|
@@ -673,20 +832,38 @@ class ProtobufValue:
|
|
|
673
832
|
return None
|
|
674
833
|
|
|
675
834
|
|
|
676
|
-
class Value:
|
|
677
|
-
def __init__(
|
|
678
|
-
self
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
835
|
+
class Value(TypeProtobuf):
|
|
836
|
+
def __init__(
|
|
837
|
+
self,
|
|
838
|
+
parent: Message | MapMessage | RepeatedMessage | Value | None,
|
|
839
|
+
key: str | int | None,
|
|
840
|
+
value: typing.Any | _Unknown = _Unknown,
|
|
841
|
+
readOnly: str | bool = False,
|
|
842
|
+
):
|
|
843
|
+
self._parent: Message | MapMessage | RepeatedMessage | Value | None = parent
|
|
844
|
+
self._key: str | int | None = key
|
|
845
|
+
self._dependencies: dict[str | int, FieldMessage | Value] = {}
|
|
846
|
+
self._unknowns: dict[str | int, FieldMessage | Value] = {}
|
|
847
|
+
self._cache: dict[str | int, Value] = {}
|
|
848
|
+
self._readOnly: str | bool = False
|
|
849
|
+
if (
|
|
850
|
+
isinstance(
|
|
851
|
+
value,
|
|
852
|
+
(
|
|
853
|
+
google.protobuf.struct_pb2.Value,
|
|
854
|
+
google.protobuf.struct_pb2.Struct,
|
|
855
|
+
google.protobuf.struct_pb2.ListValue,
|
|
856
|
+
),
|
|
857
|
+
)
|
|
858
|
+
or value is _Unknown
|
|
859
|
+
):
|
|
860
|
+
self._value: typing.Any = value
|
|
686
861
|
else:
|
|
687
|
-
self.
|
|
862
|
+
self._value: google.protobuf.struct_pb2.Value = (
|
|
863
|
+
google.protobuf.struct_pb2.Value()
|
|
864
|
+
)
|
|
688
865
|
if value is None:
|
|
689
|
-
self._value.null_value =
|
|
866
|
+
self._value.null_value = google.protobuf.struct_pb2.NULL_VALUE
|
|
690
867
|
elif isinstance(value, dict):
|
|
691
868
|
self._value.struct_value.Clear()
|
|
692
869
|
for k, v in value.items():
|
|
@@ -695,7 +872,7 @@ class Value:
|
|
|
695
872
|
self._value.list_value.Clear()
|
|
696
873
|
for ix, v in enumerate(value):
|
|
697
874
|
self[ix] = v
|
|
698
|
-
elif isinstance(value, bool):
|
|
875
|
+
elif isinstance(value, bool): # Must be before number check
|
|
699
876
|
self._value.bool_value = value
|
|
700
877
|
elif isinstance(value, (int, float)):
|
|
701
878
|
self._value.number_value = value
|
|
@@ -703,10 +880,7 @@ class Value:
|
|
|
703
880
|
self._value.string_value = value
|
|
704
881
|
else:
|
|
705
882
|
raise ValueError(f"Unexpected Value type: {value.__class__}")
|
|
706
|
-
self.
|
|
707
|
-
|
|
708
|
-
def _set_attribute(self, key, value):
|
|
709
|
-
self.__dict__[key] = value
|
|
883
|
+
self._setReadOnly(readOnly)
|
|
710
884
|
|
|
711
885
|
def __enter__(self):
|
|
712
886
|
return self
|
|
@@ -714,12 +888,6 @@ class Value:
|
|
|
714
888
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
715
889
|
pass
|
|
716
890
|
|
|
717
|
-
def __aenter__(self):
|
|
718
|
-
return self
|
|
719
|
-
|
|
720
|
-
def __aexit__(self, exc_type, exc_value, traceback):
|
|
721
|
-
pass
|
|
722
|
-
|
|
723
891
|
def __getattr__(self, key):
|
|
724
892
|
return self[key]
|
|
725
893
|
|
|
@@ -732,42 +900,40 @@ class Value:
|
|
|
732
900
|
return self._unknowns[key]
|
|
733
901
|
if isinstance(key, str):
|
|
734
902
|
match self._kind:
|
|
735
|
-
case
|
|
903
|
+
case "struct_value":
|
|
736
904
|
value = self._value.struct_value.fields.get(key, _Unknown)
|
|
737
|
-
case
|
|
905
|
+
case "Struct":
|
|
738
906
|
value = self._value.fields.get(key, _Unknown)
|
|
739
|
-
case
|
|
907
|
+
case "Unknown":
|
|
740
908
|
value = _Unknown
|
|
741
909
|
case _:
|
|
742
|
-
raise ValueError(f
|
|
910
|
+
raise ValueError(f'Invalid key "{key}" for kind: {self._kind}')
|
|
743
911
|
elif isinstance(key, int):
|
|
744
912
|
match self._kind:
|
|
745
|
-
case
|
|
913
|
+
case "list_value":
|
|
746
914
|
if key < 0:
|
|
747
915
|
key = len(self._value.list_value.values) + key
|
|
748
|
-
|
|
749
|
-
key = 0
|
|
916
|
+
key = max(key, 0)
|
|
750
917
|
if key < len(self._value.list_value.values):
|
|
751
918
|
value = self._value.list_value.values[key]
|
|
752
919
|
else:
|
|
753
920
|
if key == append:
|
|
754
921
|
key = len(self._value.list_value.values)
|
|
755
922
|
value = _Unknown
|
|
756
|
-
case
|
|
923
|
+
case "ListValue":
|
|
757
924
|
if key < 0:
|
|
758
925
|
key = len(self._value.values) + key
|
|
759
|
-
|
|
760
|
-
key = 0
|
|
926
|
+
key = max(key, 0)
|
|
761
927
|
if key < len(self._value.values):
|
|
762
928
|
value = self._value.values[key]
|
|
763
929
|
else:
|
|
764
930
|
if key == append:
|
|
765
931
|
key = len(self._value.values)
|
|
766
932
|
value = _Unknown
|
|
767
|
-
case
|
|
933
|
+
case "Unknown":
|
|
768
934
|
value = _Unknown
|
|
769
935
|
case _:
|
|
770
|
-
raise ValueError(f
|
|
936
|
+
raise ValueError(f'Invalid key "{key}" for kind: {self._kind}')
|
|
771
937
|
else:
|
|
772
938
|
raise NotImplementedError()
|
|
773
939
|
value = Value(self, key, value, self._readOnly)
|
|
@@ -779,29 +945,29 @@ class Value:
|
|
|
779
945
|
|
|
780
946
|
def __len__(self):
|
|
781
947
|
match self._kind:
|
|
782
|
-
case
|
|
948
|
+
case "struct_value":
|
|
783
949
|
return len(self._value.struct_value.fields) + len(self._unknowns)
|
|
784
|
-
case
|
|
950
|
+
case "Struct":
|
|
785
951
|
return len(self._value.fields) + len(self._unknowns)
|
|
786
|
-
case
|
|
952
|
+
case "list_value":
|
|
787
953
|
return len(self._value.list_value.values) + len(self._unknowns)
|
|
788
|
-
case
|
|
954
|
+
case "ListValue":
|
|
789
955
|
return len(self._value.values) + len(self._unknowns)
|
|
790
|
-
case
|
|
956
|
+
case "string_value":
|
|
791
957
|
return len(self._value.string_value)
|
|
792
|
-
case
|
|
958
|
+
case "bool_value":
|
|
793
959
|
return 1 if self._value.bool_value else 0
|
|
794
960
|
return 0
|
|
795
961
|
|
|
796
962
|
def __contains__(self, item):
|
|
797
963
|
match self._kind:
|
|
798
|
-
case
|
|
964
|
+
case "struct_value":
|
|
799
965
|
item = self._validate_key(item)
|
|
800
966
|
return item in self._value.struct_value.fields or item in self._unknowns
|
|
801
|
-
case
|
|
967
|
+
case "Struct":
|
|
802
968
|
item = self._validate_key(item)
|
|
803
969
|
return item in self._value.fields or item in self._unknowns
|
|
804
|
-
case
|
|
970
|
+
case "list_value" | "ListValue":
|
|
805
971
|
for value in self:
|
|
806
972
|
if item == value:
|
|
807
973
|
return True
|
|
@@ -809,38 +975,45 @@ class Value:
|
|
|
809
975
|
|
|
810
976
|
def __iter__(self):
|
|
811
977
|
match self._kind:
|
|
812
|
-
case
|
|
813
|
-
for key in sorted(
|
|
978
|
+
case "struct_value":
|
|
979
|
+
for key in sorted(
|
|
980
|
+
set(self._value.struct_value.fields) | set(self._unknowns.keys())
|
|
981
|
+
):
|
|
814
982
|
yield key, self[key]
|
|
815
|
-
case
|
|
983
|
+
case "Struct":
|
|
816
984
|
for key in sorted(set(self._value.fields) | set(self._unknowns.keys())):
|
|
817
985
|
yield key, self[key]
|
|
818
|
-
case
|
|
986
|
+
case "list_value":
|
|
819
987
|
for ix in range(len(self._value.list_value.values)):
|
|
820
988
|
yield self[ix]
|
|
821
989
|
for ix in sorted(self._unknowns.keys()):
|
|
822
|
-
if ix >= len(self._value.list_value.values):
|
|
990
|
+
if typing.cast(int, ix) >= len(self._value.list_value.values):
|
|
823
991
|
yield self[ix]
|
|
824
|
-
case
|
|
992
|
+
case "ListValue":
|
|
825
993
|
for ix in range(len(self._value.values)):
|
|
826
994
|
yield self[ix]
|
|
827
995
|
for ix in sorted(self._unknowns.keys()):
|
|
828
|
-
if ix >= len(self._value.values):
|
|
996
|
+
if typing.cast(int, ix) >= len(self._value.values):
|
|
829
997
|
yield self[ix]
|
|
830
998
|
|
|
831
999
|
def __hash__(self):
|
|
832
1000
|
match self._kind:
|
|
833
|
-
case
|
|
834
|
-
return hash(
|
|
835
|
-
|
|
1001
|
+
case "struct_value" | "Struct":
|
|
1002
|
+
return hash(
|
|
1003
|
+
tuple(
|
|
1004
|
+
hash(item)
|
|
1005
|
+
for item in sorted(iter(self), key=lambda item: item[0])
|
|
1006
|
+
)
|
|
1007
|
+
)
|
|
1008
|
+
case "list_value" | "ListValue":
|
|
836
1009
|
return hash(tuple(hash(item) for item in self))
|
|
837
|
-
case
|
|
1010
|
+
case "string_value":
|
|
838
1011
|
return hash(self._value.string_value)
|
|
839
|
-
case
|
|
1012
|
+
case "null_value":
|
|
840
1013
|
return hash(None)
|
|
841
|
-
case
|
|
1014
|
+
case "number_value":
|
|
842
1015
|
return hash(self._value.number_value)
|
|
843
|
-
case
|
|
1016
|
+
case "bool_value":
|
|
844
1017
|
return hash(self._value.bool_value)
|
|
845
1018
|
return 0
|
|
846
1019
|
|
|
@@ -849,7 +1022,7 @@ class Value:
|
|
|
849
1022
|
if isinstance(other, Value) and other._kind != kind:
|
|
850
1023
|
return False
|
|
851
1024
|
match kind:
|
|
852
|
-
case
|
|
1025
|
+
case "struct_value" | "Struct":
|
|
853
1026
|
if not isinstance(other, (Value, dict)):
|
|
854
1027
|
return False
|
|
855
1028
|
if len(self) != len(other):
|
|
@@ -860,7 +1033,7 @@ class Value:
|
|
|
860
1033
|
if value != other[key]:
|
|
861
1034
|
return False
|
|
862
1035
|
return True
|
|
863
|
-
case
|
|
1036
|
+
case "list_value" | "ListValue":
|
|
864
1037
|
if not isinstance(other, (Value, tuple, list)):
|
|
865
1038
|
return False
|
|
866
1039
|
if len(self) != len(other):
|
|
@@ -869,27 +1042,27 @@ class Value:
|
|
|
869
1042
|
if value != other[ix]:
|
|
870
1043
|
return False
|
|
871
1044
|
return True
|
|
872
|
-
case
|
|
1045
|
+
case "Unknown":
|
|
873
1046
|
if isinstance(other, Value):
|
|
874
1047
|
return other._isUnknown
|
|
875
1048
|
return False
|
|
876
|
-
case
|
|
1049
|
+
case "string_value":
|
|
877
1050
|
if isinstance(other, Value):
|
|
878
1051
|
return self._value.string_value == other._value.string_value
|
|
879
1052
|
if isinstance(other, str):
|
|
880
1053
|
return self._value.string_value == other
|
|
881
1054
|
return False
|
|
882
|
-
case
|
|
1055
|
+
case "null_value":
|
|
883
1056
|
if isinstance(other, Value):
|
|
884
1057
|
return True
|
|
885
1058
|
return other is None
|
|
886
|
-
case
|
|
1059
|
+
case "number_value":
|
|
887
1060
|
if isinstance(other, Value):
|
|
888
1061
|
return self._value.number_value == other._value.number_value
|
|
889
1062
|
if isinstance(other, (int, float)):
|
|
890
1063
|
return self._value.number_value == other
|
|
891
1064
|
return False
|
|
892
|
-
case
|
|
1065
|
+
case "bool_value":
|
|
893
1066
|
if isinstance(other, Value):
|
|
894
1067
|
return self._value.bool_value == other._value.bool_value
|
|
895
1068
|
if isinstance(other, bool):
|
|
@@ -899,7 +1072,7 @@ class Value:
|
|
|
899
1072
|
|
|
900
1073
|
def __or__(self, other):
|
|
901
1074
|
kind = self._kind
|
|
902
|
-
if kind not in (
|
|
1075
|
+
if kind not in ("struct_value", "Struct"):
|
|
903
1076
|
return NotImplemented
|
|
904
1077
|
if not isinstance(other, (Value, dict)):
|
|
905
1078
|
return NotImplemented
|
|
@@ -917,56 +1090,56 @@ class Value:
|
|
|
917
1090
|
result = Map()
|
|
918
1091
|
for key, value in other.items():
|
|
919
1092
|
result[key] = value
|
|
920
|
-
if self._kind not in (
|
|
1093
|
+
if self._kind not in ("struct_value", "Struct"):
|
|
921
1094
|
return NotImplemented
|
|
922
1095
|
for key, value in self:
|
|
923
1096
|
result[key] = value
|
|
924
1097
|
return result
|
|
925
1098
|
|
|
926
1099
|
def __str__(self):
|
|
927
|
-
return format(self,
|
|
1100
|
+
return format(self, "")
|
|
928
1101
|
|
|
929
|
-
def __format__(self, spec=
|
|
1102
|
+
def __format__(self, spec="yaml"):
|
|
930
1103
|
if not spec:
|
|
931
1104
|
match self._kind:
|
|
932
|
-
case
|
|
933
|
-
return
|
|
934
|
-
case
|
|
1105
|
+
case "Unknown":
|
|
1106
|
+
return "<<UNKNOWN>>"
|
|
1107
|
+
case "string_value":
|
|
935
1108
|
return self._value.string_value
|
|
936
|
-
case
|
|
937
|
-
return
|
|
938
|
-
case
|
|
1109
|
+
case "null_value":
|
|
1110
|
+
return "null"
|
|
1111
|
+
case "number_value":
|
|
939
1112
|
value = self._value.number_value
|
|
940
1113
|
if value.is_integer():
|
|
941
1114
|
value = int(value)
|
|
942
1115
|
return str(value)
|
|
943
|
-
case
|
|
944
|
-
return
|
|
1116
|
+
case "bool_value":
|
|
1117
|
+
return "true" if self._value.bool_value else "false"
|
|
945
1118
|
return _formatObject(self, spec)
|
|
946
1119
|
|
|
947
1120
|
def __int__(self):
|
|
948
1121
|
kind = self._kind
|
|
949
1122
|
match kind:
|
|
950
|
-
case
|
|
1123
|
+
case "string_value":
|
|
951
1124
|
return int(self._value.string_value)
|
|
952
|
-
case
|
|
1125
|
+
case "number_value":
|
|
953
1126
|
return int(self._value.number_value)
|
|
954
|
-
case
|
|
1127
|
+
case "bool_value":
|
|
955
1128
|
return int(self._value.bool_value)
|
|
956
|
-
case
|
|
1129
|
+
case "Unknown":
|
|
957
1130
|
return 0
|
|
958
1131
|
raise TypeError(f"Cannot convert kind to integer: {kind}")
|
|
959
1132
|
|
|
960
1133
|
def __float__(self):
|
|
961
1134
|
kind = self._kind
|
|
962
1135
|
match kind:
|
|
963
|
-
case
|
|
1136
|
+
case "string_value":
|
|
964
1137
|
return float(self._value.string_value)
|
|
965
|
-
case
|
|
1138
|
+
case "number_value":
|
|
966
1139
|
return float(self._value.number_value)
|
|
967
|
-
case
|
|
1140
|
+
case "bool_value":
|
|
968
1141
|
return float(self._value.bool_value)
|
|
969
|
-
case
|
|
1142
|
+
case "Unknown":
|
|
970
1143
|
return 0.0
|
|
971
1144
|
raise TypeError(f"Cannot convert kind to float: {kind}")
|
|
972
1145
|
|
|
@@ -988,25 +1161,25 @@ class Value:
|
|
|
988
1161
|
if isinstance(key, int):
|
|
989
1162
|
name += f"[{key}]"
|
|
990
1163
|
else:
|
|
991
|
-
if
|
|
1164
|
+
if "." in key:
|
|
992
1165
|
name += f"[{key}]"
|
|
993
1166
|
else:
|
|
994
1167
|
name += f".{key}"
|
|
995
1168
|
return name
|
|
996
1169
|
if key is not None:
|
|
997
1170
|
return str(key)
|
|
998
|
-
return
|
|
1171
|
+
return ""
|
|
999
1172
|
|
|
1000
1173
|
def __call__(self, *args, **kwargs):
|
|
1001
1174
|
if self._readOnly:
|
|
1002
1175
|
raise ValueError(f"{self._readOnly} is read only")
|
|
1003
|
-
self.__dict__[
|
|
1176
|
+
self.__dict__["_value"] = google.protobuf.struct_pb2.Value()
|
|
1004
1177
|
self._cache.clear()
|
|
1005
1178
|
self._dependencies.clear()
|
|
1006
1179
|
self._unknowns.clear()
|
|
1007
1180
|
if len(kwargs):
|
|
1008
1181
|
if len(args):
|
|
1009
|
-
raise ValueError(
|
|
1182
|
+
raise ValueError("Connect specify both kwargs and args")
|
|
1010
1183
|
for key, value in kwargs.items():
|
|
1011
1184
|
self[key] = value
|
|
1012
1185
|
elif len(args):
|
|
@@ -1017,19 +1190,30 @@ class Value:
|
|
|
1017
1190
|
return self
|
|
1018
1191
|
|
|
1019
1192
|
def __setattr__(self, key, value):
|
|
1020
|
-
|
|
1193
|
+
if key in (
|
|
1194
|
+
"_parent",
|
|
1195
|
+
"_key",
|
|
1196
|
+
"_value",
|
|
1197
|
+
"_dependencies",
|
|
1198
|
+
"_unknowns",
|
|
1199
|
+
"_cache",
|
|
1200
|
+
"_readOnly",
|
|
1201
|
+
):
|
|
1202
|
+
self.__dict__[key] = value
|
|
1203
|
+
else:
|
|
1204
|
+
self[key] = value
|
|
1021
1205
|
|
|
1022
1206
|
def __setitem__(self, key, value):
|
|
1023
1207
|
if self._readOnly:
|
|
1024
1208
|
raise ValueError(f"{self._readOnly} is read only")
|
|
1025
1209
|
key = self._validate_key(key)
|
|
1026
1210
|
if isinstance(key, str):
|
|
1027
|
-
if self._ensure_map() ==
|
|
1211
|
+
if self._ensure_map() == "struct_value":
|
|
1028
1212
|
values = self._value.struct_value.fields
|
|
1029
1213
|
else:
|
|
1030
1214
|
values = self._value.fields
|
|
1031
1215
|
elif isinstance(key, int):
|
|
1032
|
-
if self._ensure_list() ==
|
|
1216
|
+
if self._ensure_list() == "list_value":
|
|
1033
1217
|
values = self._value.list_value.values
|
|
1034
1218
|
else:
|
|
1035
1219
|
values = self._value.values
|
|
@@ -1048,10 +1232,10 @@ class Value:
|
|
|
1048
1232
|
value = value._protobuf_value
|
|
1049
1233
|
if value is None:
|
|
1050
1234
|
values[key].null_value = 0
|
|
1051
|
-
elif isinstance(value, bool):
|
|
1235
|
+
elif isinstance(value, bool): # Must be before int check
|
|
1052
1236
|
values[key].bool_value = value
|
|
1053
1237
|
elif isinstance(value, bytes):
|
|
1054
|
-
values[key].string_value = value.
|
|
1238
|
+
values[key].string_value = value.decode("utf-8")
|
|
1055
1239
|
elif isinstance(value, str):
|
|
1056
1240
|
values[key].string_value = value
|
|
1057
1241
|
elif isinstance(value, (int, float)):
|
|
@@ -1069,13 +1253,13 @@ class Value:
|
|
|
1069
1253
|
if isinstance(value._value, str):
|
|
1070
1254
|
values[key].string_value = value._value
|
|
1071
1255
|
elif isinstance(value._value, bytes):
|
|
1072
|
-
values[key].string_value = value._value.decode(
|
|
1256
|
+
values[key].string_value = value._value.decode("utf-8")
|
|
1073
1257
|
elif value._value is None:
|
|
1074
1258
|
values[key].null_value = value._value.null_value
|
|
1259
|
+
elif isinstance(value._value, bool): # Must be before number check
|
|
1260
|
+
values[key].bool_value = value._value
|
|
1075
1261
|
elif isinstance(value._value, (int, float)):
|
|
1076
1262
|
values[key].number_value = value._value
|
|
1077
|
-
elif isinstance(value._value, bool):
|
|
1078
|
-
values[key].bool_value = value._value
|
|
1079
1263
|
elif value._value is _Unknown:
|
|
1080
1264
|
self._setUnknown(key, value)
|
|
1081
1265
|
else:
|
|
@@ -1083,23 +1267,23 @@ class Value:
|
|
|
1083
1267
|
elif isinstance(value, Value):
|
|
1084
1268
|
self._dependencies[key] = value
|
|
1085
1269
|
match value._kind:
|
|
1086
|
-
case
|
|
1270
|
+
case "struct_value" | "Struct":
|
|
1087
1271
|
values[key].struct_value.Clear()
|
|
1088
1272
|
for k, v in value:
|
|
1089
1273
|
self[key][k] = v
|
|
1090
|
-
case
|
|
1274
|
+
case "list_value" | "ListValue":
|
|
1091
1275
|
values[key].list_value.Clear()
|
|
1092
1276
|
for ix, v in enumerate(value):
|
|
1093
1277
|
self[key][ix] = v
|
|
1094
|
-
case
|
|
1278
|
+
case "string_value":
|
|
1095
1279
|
values[key].string_value = value._value.string_value
|
|
1096
|
-
case
|
|
1280
|
+
case "null_value":
|
|
1097
1281
|
values[key].null_value = value._value.null_value
|
|
1098
|
-
case
|
|
1282
|
+
case "number_value":
|
|
1099
1283
|
values[key].number_value = value._value.number_value
|
|
1100
|
-
case
|
|
1284
|
+
case "bool_value":
|
|
1101
1285
|
values[key].bool_value = value._value.bool_value
|
|
1102
|
-
case
|
|
1286
|
+
case "Unknown":
|
|
1103
1287
|
self._setUnknown(key, value)
|
|
1104
1288
|
case _:
|
|
1105
1289
|
raise ValueError(f"Unexpected value kind: {value._kind}")
|
|
@@ -1109,41 +1293,43 @@ class Value:
|
|
|
1109
1293
|
@property
|
|
1110
1294
|
def _raw(self):
|
|
1111
1295
|
match self._kind:
|
|
1112
|
-
case
|
|
1296
|
+
case "struct_value":
|
|
1113
1297
|
return self._value.struct_value
|
|
1114
|
-
case
|
|
1298
|
+
case "list_value":
|
|
1115
1299
|
return self._value.list_value
|
|
1116
|
-
case
|
|
1300
|
+
case "string_value":
|
|
1117
1301
|
return self._value.string_value
|
|
1118
|
-
case
|
|
1302
|
+
case "null_value":
|
|
1119
1303
|
return self._value.null_value
|
|
1120
|
-
case
|
|
1304
|
+
case "number_value":
|
|
1305
|
+
if self._value.number_value.is_integer():
|
|
1306
|
+
return int(self._value.number_value)
|
|
1121
1307
|
return self._value.number_value
|
|
1122
|
-
case
|
|
1308
|
+
case "bool_value":
|
|
1123
1309
|
return self._value.bool_value
|
|
1124
|
-
case
|
|
1310
|
+
case "Struct" | "ListValue":
|
|
1125
1311
|
return self._value
|
|
1126
|
-
case
|
|
1312
|
+
case "Unknown":
|
|
1127
1313
|
return _Unknown
|
|
1128
1314
|
|
|
1129
1315
|
def _setUnknown(self, key, value):
|
|
1130
1316
|
self._dependencies.pop(key, None)
|
|
1131
1317
|
self._unknowns[key] = value
|
|
1132
1318
|
match self._kind:
|
|
1133
|
-
case
|
|
1319
|
+
case "struct_value":
|
|
1134
1320
|
if key in self._value.struct_value.fields:
|
|
1135
1321
|
del self._value.struct_value[key]
|
|
1136
|
-
case
|
|
1322
|
+
case "Struct":
|
|
1137
1323
|
if key in self._value.fields:
|
|
1138
1324
|
del self._value[key]
|
|
1139
|
-
case
|
|
1325
|
+
case "list_value":
|
|
1140
1326
|
if key < len(self._value.list_value.values):
|
|
1141
1327
|
self._value.list_value.values[key].Clear()
|
|
1142
1328
|
for ix in reversed(range(len(self._value.list_value.values))):
|
|
1143
1329
|
if ix not in self._unknowns:
|
|
1144
1330
|
break
|
|
1145
1331
|
del self._value.list_value[ix]
|
|
1146
|
-
case
|
|
1332
|
+
case "ListValue":
|
|
1147
1333
|
if key < len(self._value.values):
|
|
1148
1334
|
self._value.values[key].Clear()
|
|
1149
1335
|
for ix in reversed(range(len(self._value.values))):
|
|
@@ -1158,30 +1344,30 @@ class Value:
|
|
|
1158
1344
|
if self._readOnly:
|
|
1159
1345
|
raise ValueError(f"{self._readOnly} is read only")
|
|
1160
1346
|
kind = self._kind
|
|
1161
|
-
if kind ==
|
|
1347
|
+
if kind == "Unknown":
|
|
1162
1348
|
return
|
|
1163
1349
|
key = self._validate_key(key)
|
|
1164
1350
|
if isinstance(key, str):
|
|
1165
1351
|
match kind:
|
|
1166
|
-
case
|
|
1352
|
+
case "struct_value":
|
|
1167
1353
|
if key in self._value.struct_value.fields:
|
|
1168
1354
|
del self._value.struct_value[key]
|
|
1169
|
-
case
|
|
1355
|
+
case "Struct":
|
|
1170
1356
|
if key in self._value.fields:
|
|
1171
1357
|
del self._value[key]
|
|
1172
1358
|
case _:
|
|
1173
|
-
raise ValueError(f
|
|
1359
|
+
raise ValueError(f'Invalid key "{key}" for kind: {self._kind}')
|
|
1174
1360
|
self._cache.pop(key, None)
|
|
1175
1361
|
self._dependencies.pop(key, None)
|
|
1176
1362
|
self._unknowns.pop(key, None)
|
|
1177
1363
|
elif isinstance(key, int):
|
|
1178
1364
|
match kind:
|
|
1179
|
-
case
|
|
1365
|
+
case "list_value":
|
|
1180
1366
|
values = self._value.list_value
|
|
1181
|
-
case
|
|
1367
|
+
case "ListValue":
|
|
1182
1368
|
values = self._value
|
|
1183
1369
|
case _:
|
|
1184
|
-
raise ValueError(f
|
|
1370
|
+
raise ValueError(f'Invalid key "{key}" for kind: {self._kind}')
|
|
1185
1371
|
if key < len(values.values):
|
|
1186
1372
|
del values[key]
|
|
1187
1373
|
self._cache.pop(key, None)
|
|
@@ -1190,12 +1376,14 @@ class Value:
|
|
|
1190
1376
|
for ix in sorted(self._dependencies.keys()):
|
|
1191
1377
|
if ix > key:
|
|
1192
1378
|
self._cache.pop(ix, None)
|
|
1193
|
-
self._dependencies[ix - 1] = self.
|
|
1379
|
+
self._dependencies[typing.cast(int, ix) - 1] = self._dependencies[
|
|
1380
|
+
ix
|
|
1381
|
+
]
|
|
1194
1382
|
del self._dependencies[ix]
|
|
1195
1383
|
for ix in sorted(self._unknowns.keys()):
|
|
1196
1384
|
if ix > key:
|
|
1197
1385
|
self._cache.pop(ix, None)
|
|
1198
|
-
self._unknowns[ix - 1] = self._unknowns[ix]
|
|
1386
|
+
self._unknowns[typing.cast(int, ix) - 1] = self._unknowns[ix]
|
|
1199
1387
|
del self._unknowns[ix]
|
|
1200
1388
|
for ix in reversed(range(len(values.values))):
|
|
1201
1389
|
if ix not in self._unknowns:
|
|
@@ -1209,14 +1397,14 @@ class Value:
|
|
|
1209
1397
|
raise ValueError(f"{self._readOnly} is read only")
|
|
1210
1398
|
key = self._validate_key(key)
|
|
1211
1399
|
if isinstance(key, str):
|
|
1212
|
-
if self._ensure_map() ==
|
|
1400
|
+
if self._ensure_map() == "struct_value":
|
|
1213
1401
|
fields = self._value.struct_value.fields
|
|
1214
1402
|
else:
|
|
1215
1403
|
fields = self._value.fields
|
|
1216
1404
|
fields[key].Clear()
|
|
1217
1405
|
return fields[key]
|
|
1218
1406
|
if isinstance(key, int):
|
|
1219
|
-
if self._ensure_list() ==
|
|
1407
|
+
if self._ensure_list() == "list_value":
|
|
1220
1408
|
values = self._value.list_value.values
|
|
1221
1409
|
else:
|
|
1222
1410
|
values = self._value.values
|
|
@@ -1241,55 +1429,61 @@ class Value:
|
|
|
1241
1429
|
|
|
1242
1430
|
def _ensure_map(self):
|
|
1243
1431
|
kind = self._kind
|
|
1244
|
-
if kind ==
|
|
1432
|
+
if kind == "Unknown":
|
|
1245
1433
|
if self._parent is None:
|
|
1246
|
-
self.__dict__[
|
|
1434
|
+
self.__dict__["_value"] = google.protobuf.struct_pb2.Value()
|
|
1247
1435
|
else:
|
|
1248
|
-
self.__dict__[
|
|
1249
|
-
if
|
|
1436
|
+
self.__dict__["_value"] = self._parent._create_child(self._key)
|
|
1437
|
+
if (
|
|
1438
|
+
isinstance(self._value, google.protobuf.struct_pb2.Value)
|
|
1439
|
+
and self._value.WhichOneof("kind") is None
|
|
1440
|
+
):
|
|
1250
1441
|
self._value.struct_value.Clear()
|
|
1251
1442
|
kind = self._kind
|
|
1252
|
-
if kind not in (
|
|
1443
|
+
if kind not in ("struct_value", "Struct"):
|
|
1253
1444
|
raise ValueError(f"Invalid map kind: {kind}")
|
|
1254
1445
|
return kind
|
|
1255
1446
|
|
|
1256
1447
|
def _ensure_list(self):
|
|
1257
1448
|
kind = self._kind
|
|
1258
|
-
if kind ==
|
|
1449
|
+
if kind == "Unknown":
|
|
1259
1450
|
if self._parent is None:
|
|
1260
|
-
self.__dict__[
|
|
1451
|
+
self.__dict__["_value"] = google.protobuf.struct_pb2.Value()
|
|
1261
1452
|
else:
|
|
1262
|
-
self.__dict__[
|
|
1263
|
-
if
|
|
1453
|
+
self.__dict__["_value"] = self._parent._create_child(self._key)
|
|
1454
|
+
if (
|
|
1455
|
+
isinstance(self._value, google.protobuf.struct_pb2.Value)
|
|
1456
|
+
and self._value.WhichOneof("kind") is None
|
|
1457
|
+
):
|
|
1264
1458
|
self._value.list_value.Clear()
|
|
1265
1459
|
kind = self._kind
|
|
1266
|
-
if kind not in (
|
|
1460
|
+
if kind not in ("list_value", "ListValue"):
|
|
1267
1461
|
raise ValueError(f"Invalid list kind: {kind}")
|
|
1268
1462
|
return kind
|
|
1269
1463
|
|
|
1270
1464
|
@property
|
|
1271
1465
|
def _kind(self):
|
|
1272
1466
|
if isinstance(self._value, google.protobuf.struct_pb2.Value):
|
|
1273
|
-
return self._value.WhichOneof(
|
|
1467
|
+
return self._value.WhichOneof("kind") or "Unknown"
|
|
1274
1468
|
if isinstance(self._value, google.protobuf.struct_pb2.Struct):
|
|
1275
|
-
return
|
|
1469
|
+
return "Struct"
|
|
1276
1470
|
if isinstance(self._value, google.protobuf.struct_pb2.ListValue):
|
|
1277
|
-
return
|
|
1471
|
+
return "ListValue"
|
|
1278
1472
|
if self._value is _Unknown:
|
|
1279
|
-
return
|
|
1473
|
+
return "Unknown"
|
|
1280
1474
|
raise ValueError(f"Unexpected value type: {self._value.__class__}")
|
|
1281
1475
|
|
|
1282
1476
|
@property
|
|
1283
1477
|
def _isUnknown(self):
|
|
1284
|
-
return self._kind ==
|
|
1478
|
+
return self._kind == "Unknown"
|
|
1285
1479
|
|
|
1286
1480
|
@property
|
|
1287
1481
|
def _isMap(self):
|
|
1288
|
-
return self._kind in (
|
|
1482
|
+
return self._kind in ("struct_value", "Struct")
|
|
1289
1483
|
|
|
1290
1484
|
@property
|
|
1291
1485
|
def _isList(self):
|
|
1292
|
-
return self._kind in (
|
|
1486
|
+
return self._kind in ("list_value", "ListValue")
|
|
1293
1487
|
|
|
1294
1488
|
@property
|
|
1295
1489
|
def _getUnknowns(self):
|
|
@@ -1307,8 +1501,8 @@ class Value:
|
|
|
1307
1501
|
return unknowns
|
|
1308
1502
|
|
|
1309
1503
|
@property
|
|
1310
|
-
def _getDependencies(self):
|
|
1311
|
-
dependencies = {}
|
|
1504
|
+
def _getDependencies(self) -> dict[str, str]:
|
|
1505
|
+
dependencies: dict[str, str] = {}
|
|
1312
1506
|
for key, dependency in self._dependencies.items():
|
|
1313
1507
|
dependencies[self._fullName(key)] = dependency._fullName()
|
|
1314
1508
|
for key, unknown in self._unknowns.items():
|
|
@@ -1323,6 +1517,17 @@ class Value:
|
|
|
1323
1517
|
dependencies.update(value._getDependencies)
|
|
1324
1518
|
return dependencies
|
|
1325
1519
|
|
|
1520
|
+
def _setReadOnly(self, readOnly: bool | str):
|
|
1521
|
+
self._readOnly = readOnly
|
|
1522
|
+
if self._isMap:
|
|
1523
|
+
for key, value in self:
|
|
1524
|
+
if isinstance(value, Value):
|
|
1525
|
+
value._setReadOnly(readOnly)
|
|
1526
|
+
elif self._isList:
|
|
1527
|
+
for value in enumerate(self):
|
|
1528
|
+
if isinstance(value, Value):
|
|
1529
|
+
value._setReadOnly(readOnly)
|
|
1530
|
+
|
|
1326
1531
|
def _patchUnknowns(self, patches):
|
|
1327
1532
|
for key in list(self._unknowns.keys()):
|
|
1328
1533
|
self[key] = patches[key]
|
|
@@ -1330,13 +1535,21 @@ class Value:
|
|
|
1330
1535
|
for key, value in self:
|
|
1331
1536
|
if isinstance(value, Value) and len(value):
|
|
1332
1537
|
patch = patches[key]
|
|
1333
|
-
if
|
|
1538
|
+
if (
|
|
1539
|
+
isinstance(patch, Value)
|
|
1540
|
+
and patch._kind == value._kind
|
|
1541
|
+
and len(patch)
|
|
1542
|
+
):
|
|
1334
1543
|
value._patchUnknowns(patch)
|
|
1335
1544
|
elif self._isList:
|
|
1336
1545
|
for ix, value in enumerate(self):
|
|
1337
1546
|
if isinstance(value, Value) and len(value):
|
|
1338
1547
|
patch = patches[ix]
|
|
1339
|
-
if
|
|
1548
|
+
if (
|
|
1549
|
+
isinstance(patch, Value)
|
|
1550
|
+
and patch._kind == value._kind
|
|
1551
|
+
and len(patch)
|
|
1552
|
+
):
|
|
1340
1553
|
value._patchUnknowns(patch)
|
|
1341
1554
|
|
|
1342
1555
|
def _renderUnknowns(self, trimFullName):
|
|
@@ -1353,13 +1566,13 @@ class Value:
|
|
|
1353
1566
|
value._renderUnknowns(trimFullName)
|
|
1354
1567
|
|
|
1355
1568
|
|
|
1356
|
-
def _formatObject(object, spec=
|
|
1569
|
+
def _formatObject(object, spec="yaml"):
|
|
1357
1570
|
match spec:
|
|
1358
|
-
case
|
|
1571
|
+
case "json":
|
|
1359
1572
|
return json.dumps(object, indent=2, cls=_JSONEncoder)
|
|
1360
|
-
case
|
|
1361
|
-
return json.dumps(object, separators=(
|
|
1362
|
-
case
|
|
1573
|
+
case "jsonc":
|
|
1574
|
+
return json.dumps(object, separators=(",", ":"), cls=_JSONEncoder)
|
|
1575
|
+
case "protobuf":
|
|
1363
1576
|
if isinstance(object, Message):
|
|
1364
1577
|
return str(object._message)
|
|
1365
1578
|
if isinstance(object, (MapMessage, RepeatedMessage)):
|
|
@@ -1372,94 +1585,98 @@ def _formatObject(object, spec='yaml'):
|
|
|
1372
1585
|
|
|
1373
1586
|
|
|
1374
1587
|
class _JSONEncoder(json.JSONEncoder):
|
|
1375
|
-
def default(self,
|
|
1376
|
-
if isinstance(
|
|
1377
|
-
if
|
|
1378
|
-
return {key: value for key, value in
|
|
1588
|
+
def default(self, o):
|
|
1589
|
+
if isinstance(o, (Message, MapMessage)):
|
|
1590
|
+
if o:
|
|
1591
|
+
return {key: value for key, value in o}
|
|
1379
1592
|
return None
|
|
1380
|
-
if isinstance(
|
|
1381
|
-
if
|
|
1382
|
-
return [value for value in
|
|
1593
|
+
if isinstance(o, RepeatedMessage):
|
|
1594
|
+
if o:
|
|
1595
|
+
return [value for value in o]
|
|
1383
1596
|
return None
|
|
1384
|
-
if isinstance(
|
|
1385
|
-
return
|
|
1386
|
-
if isinstance(
|
|
1387
|
-
match
|
|
1388
|
-
case
|
|
1389
|
-
return {key: value for key, value in
|
|
1390
|
-
case
|
|
1391
|
-
return [value for value in
|
|
1392
|
-
case
|
|
1393
|
-
return
|
|
1394
|
-
case
|
|
1597
|
+
if isinstance(o, FieldMessage):
|
|
1598
|
+
return o._value
|
|
1599
|
+
if isinstance(o, Value):
|
|
1600
|
+
match o._kind:
|
|
1601
|
+
case "struct_value" | "Struct":
|
|
1602
|
+
return {key: value for key, value in o}
|
|
1603
|
+
case "list_value" | "ListValue":
|
|
1604
|
+
return [value for value in o]
|
|
1605
|
+
case "string_value":
|
|
1606
|
+
return o._value.string_value
|
|
1607
|
+
case "null_value":
|
|
1395
1608
|
return None
|
|
1396
|
-
case
|
|
1397
|
-
value =
|
|
1609
|
+
case "number_value":
|
|
1610
|
+
value = o._value.number_value
|
|
1398
1611
|
if value.is_integer():
|
|
1399
1612
|
value = int(value)
|
|
1400
1613
|
return value
|
|
1401
|
-
case
|
|
1402
|
-
return
|
|
1403
|
-
case
|
|
1404
|
-
return
|
|
1614
|
+
case "bool_value":
|
|
1615
|
+
return o._value.bool_value
|
|
1616
|
+
case "Unknown":
|
|
1617
|
+
return "<<UNKNOWN>>"
|
|
1405
1618
|
case _:
|
|
1406
|
-
return
|
|
1407
|
-
if isinstance(
|
|
1408
|
-
return
|
|
1409
|
-
|
|
1619
|
+
return "<<UNEXPECTED>>"
|
|
1620
|
+
if isinstance(o, datetime.datetime):
|
|
1621
|
+
return o.isoformat()
|
|
1622
|
+
if isinstance(o, bytes):
|
|
1623
|
+
return o.decode("utf-8")
|
|
1624
|
+
return super().default(o)
|
|
1410
1625
|
|
|
1411
1626
|
|
|
1412
1627
|
class _Dumper(yaml.SafeDumper):
|
|
1413
|
-
|
|
1414
1628
|
def represent_str(self, data):
|
|
1415
|
-
return self.represent_scalar(
|
|
1629
|
+
return self.represent_scalar(
|
|
1630
|
+
"tag:yaml.org,2002:str", data, "|" if "\n" in data else None
|
|
1631
|
+
)
|
|
1416
1632
|
|
|
1417
|
-
def represent_message_dict(self, message):
|
|
1633
|
+
def represent_message_dict(self, message: Message | MapMessage):
|
|
1418
1634
|
return self.represent_dict({key: value for key, value in message})
|
|
1419
1635
|
|
|
1420
|
-
def represent_message_list(self, messages):
|
|
1636
|
+
def represent_message_list(self, messages: RepeatedMessage):
|
|
1421
1637
|
return self.represent_list([value for value in messages])
|
|
1422
1638
|
|
|
1423
|
-
def represent_message_field(self, field):
|
|
1639
|
+
def represent_message_field(self, field: FieldMessage):
|
|
1424
1640
|
if isinstance(field._value, str):
|
|
1425
1641
|
return self.represent_str(field._value)
|
|
1426
1642
|
if isinstance(field._value, bytes):
|
|
1427
1643
|
return self.represent_binary(field._value)
|
|
1428
1644
|
if field._value is None:
|
|
1429
|
-
return self.represent_none()
|
|
1645
|
+
return self.represent_none(field._value)
|
|
1646
|
+
if isinstance(field._value, bool): # Must be before number check
|
|
1647
|
+
return self.represent_bool(bool(field._value))
|
|
1430
1648
|
if isinstance(field._value, int):
|
|
1431
1649
|
return self.represent_int(field._value)
|
|
1432
1650
|
if isinstance(field._value, float):
|
|
1433
1651
|
if field._value.is_integer():
|
|
1434
1652
|
return self.represent_int(int(field._value))
|
|
1435
1653
|
return self.represent_float(field._value)
|
|
1436
|
-
if isinstance(field._value, bool):
|
|
1437
|
-
return self.represent_bool(field._value)
|
|
1438
1654
|
if field._value is _Unknown:
|
|
1439
|
-
return self.represent_str(
|
|
1440
|
-
return self.represent_str(
|
|
1655
|
+
return self.represent_str("<<UNKNOWN>>")
|
|
1656
|
+
return self.represent_str("<<UNEXPECTED>>")
|
|
1441
1657
|
|
|
1442
|
-
def represent_value(self, value):
|
|
1658
|
+
def represent_value(self, value: Value):
|
|
1443
1659
|
match value._kind:
|
|
1444
|
-
case
|
|
1445
|
-
return self.represent_dict({k:v for k,v in value})
|
|
1446
|
-
case
|
|
1660
|
+
case "struct_value" | "Struct":
|
|
1661
|
+
return self.represent_dict({k: v for k, v in value})
|
|
1662
|
+
case "list_value" | "ListValue":
|
|
1447
1663
|
return self.represent_list([v for v in value])
|
|
1448
|
-
case
|
|
1664
|
+
case "string_value":
|
|
1449
1665
|
return self.represent_str(value._value.string_value)
|
|
1450
|
-
case
|
|
1666
|
+
case "null_value":
|
|
1451
1667
|
return self.represent_none(None)
|
|
1452
|
-
case
|
|
1668
|
+
case "number_value":
|
|
1453
1669
|
value = value._value.number_value
|
|
1454
1670
|
if value.is_integer():
|
|
1455
1671
|
return self.represent_int(int(value))
|
|
1456
1672
|
return self.represent_float(value)
|
|
1457
|
-
case
|
|
1458
|
-
return self.represent_bool(value._value.bool_value)
|
|
1459
|
-
case
|
|
1460
|
-
return self.represent_str(
|
|
1673
|
+
case "bool_value":
|
|
1674
|
+
return self.represent_bool(bool(value._value.bool_value))
|
|
1675
|
+
case "Unknown":
|
|
1676
|
+
return self.represent_str("<<UNKNOWN>>")
|
|
1461
1677
|
case _:
|
|
1462
|
-
return self.represent_str(
|
|
1678
|
+
return self.represent_str("<<UNEXPECTED>>")
|
|
1679
|
+
|
|
1463
1680
|
|
|
1464
1681
|
_Dumper.add_representer(str, _Dumper.represent_str)
|
|
1465
1682
|
_Dumper.add_representer(Message, _Dumper.represent_message_dict)
|