crossplane-function-pythonic 0.0.10__py3-none-any.whl → 0.1.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/__init__.py +1 -4
- crossplane/pythonic/composite.py +68 -18
- crossplane/pythonic/function.py +176 -88
- crossplane/pythonic/main.py +6 -1
- crossplane/pythonic/packages.py +61 -70
- crossplane/pythonic/protobuf.py +701 -354
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/METADATA +24 -2
- crossplane_function_pythonic-0.1.0.dist-info/RECORD +11 -0
- crossplane_function_pythonic-0.0.10.dist-info/RECORD +0 -11
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/WHEEL +0 -0
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/entry_points.txt +0 -0
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/licenses/LICENSE +0 -0
crossplane/pythonic/protobuf.py
CHANGED
@@ -15,52 +15,50 @@
|
|
15
15
|
#
|
16
16
|
##################################################################################
|
17
17
|
|
18
|
+
import base64
|
18
19
|
import datetime
|
19
20
|
import google.protobuf.struct_pb2
|
20
21
|
import json
|
21
22
|
import sys
|
22
23
|
import yaml
|
23
24
|
|
25
|
+
_Unknown = object()
|
24
26
|
append = sys.maxsize
|
25
27
|
|
26
28
|
|
27
29
|
def Map(**kwargs):
|
28
|
-
|
29
|
-
for name, value in kwargs.items():
|
30
|
-
map[name] = value
|
31
|
-
return map
|
30
|
+
return Value(None, None, kwargs)
|
32
31
|
|
33
32
|
def List(*args):
|
34
|
-
|
35
|
-
for ix, value in enumerate(args):
|
36
|
-
list[ix] = value
|
37
|
-
return list
|
33
|
+
return Value(None, None, args)
|
38
34
|
|
39
35
|
def Unknown():
|
40
|
-
return
|
36
|
+
return Value(None, None)
|
41
37
|
|
42
38
|
def Yaml(string, readOnly=None):
|
43
|
-
|
39
|
+
if isinstance(string, (FieldMessage, Value)):
|
40
|
+
string = str(string)
|
41
|
+
return Value(None, None, yaml.safe_load(string), readOnly)
|
44
42
|
|
45
43
|
def Json(string, readOnly=None):
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
if isinstance(object, dict):
|
50
|
-
values = google.protobuf.struct_pb2.Struct()
|
51
|
-
if len(object):
|
52
|
-
values.update(object)
|
53
|
-
return Values(None, None, values, Values.Type.MAP, readOnly)
|
54
|
-
if isinstance(object, (list, tuple)):
|
55
|
-
values = google.protobuf.struct_pb2.ListValue()
|
56
|
-
if len(object):
|
57
|
-
values.extend(object)
|
58
|
-
return Values(None, None, values, Values.Type.LIST, readOnly)
|
59
|
-
return object
|
44
|
+
if isinstance(string, (FieldMessage, Value)):
|
45
|
+
string = str(string)
|
46
|
+
return Value(None, None, json.loads(string), readOnly)
|
60
47
|
|
48
|
+
def B64Encode(string):
|
49
|
+
if isinstance(string, (FieldMessage, Value)):
|
50
|
+
string = str(string)
|
51
|
+
return base64.b64encode(string.encode('utf-8')).decode('utf-8')
|
52
|
+
|
53
|
+
def B64Decode(string):
|
54
|
+
if isinstance(string, (FieldMessage, Value)):
|
55
|
+
string = str(string)
|
56
|
+
return base64.b64decode(string.encode('utf-8')).decode('utf-8')
|
57
|
+
|
58
|
+
B64Decode = lambda s: base64.b64decode(s.encode('utf-8')).decode('utf-8')
|
61
59
|
|
62
60
|
class Message:
|
63
|
-
def __init__(self, parent, key, descriptor, message, readOnly=False):
|
61
|
+
def __init__(self, parent, key, descriptor, message=_Unknown, readOnly=False):
|
64
62
|
self.__dict__['_parent'] = parent
|
65
63
|
self.__dict__['_key'] = key
|
66
64
|
self.__dict__['_descriptor'] = descriptor
|
@@ -77,29 +75,29 @@ class Message:
|
|
77
75
|
field = self._descriptor.fields_by_name.get(key)
|
78
76
|
if not field:
|
79
77
|
raise AttributeError(obj=self, name=key)
|
80
|
-
if self._message:
|
81
|
-
value =
|
78
|
+
if self._message is _Unknown:
|
79
|
+
value = _Unknown
|
82
80
|
else:
|
83
|
-
value =
|
84
|
-
if value is
|
81
|
+
value = getattr(self._message, key)
|
82
|
+
if value is _Unknown and field.has_default_value:
|
85
83
|
value = field.default_value
|
86
|
-
if field.
|
87
|
-
if field.
|
88
|
-
value =
|
89
|
-
|
90
|
-
value =
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
else:
|
95
|
-
value = RepeatedMessage(self, key, field.message_type, value, self._readOnly)
|
84
|
+
if field.label == field.LABEL_REPEATED:
|
85
|
+
if field.type == field.TYPE_MESSAGE and field.message_type.GetOptions().map_entry:
|
86
|
+
value = MapMessage(self, key, field.message_type.fields_by_name['value'], value, self._readOnly)
|
87
|
+
else:
|
88
|
+
value = RepeatedMessage(self, key, field, value, self._readOnly)
|
89
|
+
elif field.type == field.TYPE_MESSAGE:
|
90
|
+
if field.message_type.name in ('Struct', 'ListValue'):
|
91
|
+
value = Value(self, key, value, self._readOnly)
|
96
92
|
else:
|
97
93
|
value = Message(self, key, field.message_type, value, self._readOnly)
|
94
|
+
else:
|
95
|
+
value = FieldMessage(self, key, field.type, value)
|
98
96
|
self._cache[key] = value
|
99
97
|
return value
|
100
98
|
|
101
99
|
def __bool__(self):
|
102
|
-
return self._message
|
100
|
+
return self._message is not _Unknown
|
103
101
|
|
104
102
|
def __len__(self):
|
105
103
|
return len(self._descriptor.fields)
|
@@ -112,7 +110,7 @@ class Message:
|
|
112
110
|
yield key, self[key]
|
113
111
|
|
114
112
|
def __hash__(self):
|
115
|
-
if self._message:
|
113
|
+
if self._message is not _Unknown:
|
116
114
|
return hash(tuple(hash(item) for item in sorted(iter(self), key=lambda item: item[0])))
|
117
115
|
return 0
|
118
116
|
|
@@ -121,9 +119,9 @@ class Message:
|
|
121
119
|
return False
|
122
120
|
if self._descriptor.full_name != other._descriptor.full_name:
|
123
121
|
return False
|
124
|
-
if self._message is
|
125
|
-
return other._message is
|
126
|
-
elif other._message is
|
122
|
+
if self._message is _Unknown:
|
123
|
+
return other._message is _Unknown
|
124
|
+
elif other._message is _Unknown:
|
127
125
|
return False
|
128
126
|
if len(self) != len(other):
|
129
127
|
return False
|
@@ -147,26 +145,26 @@ class Message:
|
|
147
145
|
else:
|
148
146
|
name = str(self._key)
|
149
147
|
if key is not None:
|
150
|
-
if key
|
151
|
-
name += f"
|
148
|
+
if '.' in key:
|
149
|
+
name += f"[{key}]"
|
152
150
|
else:
|
153
|
-
name += f"
|
151
|
+
name += f".{key}"
|
154
152
|
return name
|
155
153
|
if key is not None:
|
156
154
|
return str(key)
|
157
155
|
return ''
|
158
156
|
|
159
|
-
def _create_child(self, key
|
157
|
+
def _create_child(self, key):
|
160
158
|
if self._readOnly:
|
161
159
|
raise ValueError(f"{self._readOnly} is read only")
|
162
|
-
if self._message is
|
160
|
+
if self._message is _Unknown:
|
163
161
|
self.__dict__['_message'] = self._parent._create_child(self._key)
|
164
162
|
return getattr(self._message, key)
|
165
163
|
|
166
164
|
def __call__(self, **kwargs):
|
167
165
|
if self._readOnly:
|
168
166
|
raise ValueError(f"{self._readOnly} is read only")
|
169
|
-
if self._message is
|
167
|
+
if self._message is _Unknown:
|
170
168
|
self.__dict__['_message'] = self._parent._create_child(self._key)
|
171
169
|
self._message.Clear()
|
172
170
|
self._cache.clear()
|
@@ -182,14 +180,19 @@ class Message:
|
|
182
180
|
raise ValueError(f"{self._readOnly} is read only")
|
183
181
|
if key not in self._descriptor.fields_by_name:
|
184
182
|
raise AttributeError(obj=self, name=key)
|
185
|
-
|
183
|
+
field = self._descriptor.fields_by_name[key]
|
184
|
+
if self._message is _Unknown:
|
186
185
|
self.__dict__['_message'] = self._parent._create_child(self._key)
|
187
186
|
if isinstance(value, Message):
|
188
187
|
value = value._message
|
189
188
|
elif isinstance(value, (MapMessage, RepeatedMessage)):
|
190
189
|
value = value._messages
|
191
|
-
elif isinstance(value,
|
192
|
-
value = value.
|
190
|
+
elif isinstance(value, FieldMessage):
|
191
|
+
value = value._value
|
192
|
+
elif isinstance(value, Value):
|
193
|
+
value = value._raw
|
194
|
+
if field.type == field.TYPE_BYTES and isinstance(value, str):
|
195
|
+
value = value.encode('utf-8')
|
193
196
|
setattr(self._message, key, value)
|
194
197
|
self._cache.pop(key, None)
|
195
198
|
|
@@ -201,16 +204,16 @@ class Message:
|
|
201
204
|
raise ValueError(f"{self._readOnly} is read only")
|
202
205
|
if key not in self._descriptor.fields_by_name:
|
203
206
|
raise AttributeError(obj=self, name=key)
|
204
|
-
if self._message is not
|
205
|
-
|
207
|
+
if self._message is not _Unknown:
|
208
|
+
self._message.ClearField(key)
|
206
209
|
self._cache.pop(key, None)
|
207
210
|
|
208
211
|
|
209
212
|
class MapMessage:
|
210
|
-
def __init__(self, parent, key,
|
213
|
+
def __init__(self, parent, key, field, messages=_Unknown, readOnly=False):
|
211
214
|
self.__dict__['_parent'] = parent
|
212
215
|
self.__dict__['_key'] = key
|
213
|
-
self.__dict__['_field'] =
|
216
|
+
self.__dict__['_field'] = field
|
214
217
|
self.__dict__['_messages'] = messages
|
215
218
|
self.__dict__['_readOnly'] = readOnly
|
216
219
|
self.__dict__['_cache'] = {}
|
@@ -221,40 +224,33 @@ class MapMessage:
|
|
221
224
|
def __getitem__(self, key):
|
222
225
|
if key in self._cache:
|
223
226
|
return self._cache[key]
|
224
|
-
if self._messages is
|
225
|
-
value =
|
227
|
+
if self._messages is _Unknown or key not in self._messages:
|
228
|
+
value = _Unknown
|
226
229
|
else:
|
227
230
|
value = self._messages[key]
|
228
231
|
if value is None and self._field.has_default_value:
|
229
232
|
value = self._field.default_value
|
230
233
|
if self._field.type == self._field.TYPE_MESSAGE:
|
231
|
-
if self._field.message_type.name
|
232
|
-
value =
|
233
|
-
elif self._field.message_type.name == 'ListValue':
|
234
|
-
value = Values(self, key, value, Values.Type.LIST, self._readOnly)
|
235
|
-
elif self._field.label == self._field.LABEL_REPEATED:
|
236
|
-
if self._field.message_type.GetOptions().map_entry:
|
237
|
-
value = MapMessage(self, key, self._field.message_type, value, self._readOnly)
|
238
|
-
else:
|
239
|
-
value = RepeatedMessage(self, key, self._field.message_type, value, self._readOnly)
|
234
|
+
if self._field.message_type.name in ('Struct', 'ListValue'):
|
235
|
+
value = Value(self, key, value, self._readOnly)
|
240
236
|
else:
|
241
237
|
value = Message(self, key, self._field.message_type, value, self._readOnly)
|
242
|
-
|
243
|
-
value = value
|
238
|
+
else:
|
239
|
+
value = FieldMessage(self, key, self._field.type, value)
|
244
240
|
self._cache[key] = value
|
245
241
|
return value
|
246
242
|
|
247
243
|
def __bool__(self):
|
248
|
-
return self._messages
|
244
|
+
return self._messages is not _Unknown
|
249
245
|
|
250
246
|
def __len__(self):
|
251
|
-
return 0 if self._messages is
|
247
|
+
return 0 if self._messages is _Unknown else len(self._messages)
|
252
248
|
|
253
249
|
def __contains__(self, key):
|
254
|
-
return self._messages is not
|
250
|
+
return self._messages is not _Unknown and key in self._messages
|
255
251
|
|
256
252
|
def __iter__(self):
|
257
|
-
if self._messages is not
|
253
|
+
if self._messages is not _Unknown:
|
258
254
|
for key in sorted(self._messages):
|
259
255
|
yield key, self[key]
|
260
256
|
|
@@ -266,11 +262,14 @@ class MapMessage:
|
|
266
262
|
def __eq__(self, other):
|
267
263
|
if not isinstance(other, MapMessage):
|
268
264
|
return False
|
269
|
-
if self.
|
265
|
+
if self._field.type != other._field.type:
|
270
266
|
return False
|
271
|
-
if self.
|
272
|
-
|
273
|
-
|
267
|
+
if self._field.type == self._field.TYPE_MESSAGE:
|
268
|
+
if self._field.message_type.full_name != other._field.message_type.full_name:
|
269
|
+
return False
|
270
|
+
if self._messages is _Unknown:
|
271
|
+
return other._messages is _Unknown
|
272
|
+
elif other._messages is _Unknown:
|
274
273
|
return False
|
275
274
|
if len(self) != len(other):
|
276
275
|
return False
|
@@ -294,26 +293,26 @@ class MapMessage:
|
|
294
293
|
else:
|
295
294
|
name = str(self._key)
|
296
295
|
if key is not None:
|
297
|
-
if key
|
298
|
-
name += f"
|
296
|
+
if '.' in key:
|
297
|
+
name += f"[{key}]"
|
299
298
|
else:
|
300
|
-
name += f"
|
299
|
+
name += f".{key}"
|
301
300
|
return name
|
302
301
|
if key is not None:
|
303
302
|
return str(key)
|
304
303
|
return ''
|
305
304
|
|
306
|
-
def _create_child(self, key
|
305
|
+
def _create_child(self, key):
|
307
306
|
if self._readOnly:
|
308
307
|
raise ValueError(f"{self._readOnly} is read only")
|
309
|
-
if self._messages is
|
308
|
+
if self._messages is _Unknown:
|
310
309
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
311
310
|
return self._messages[key]
|
312
311
|
|
313
312
|
def __call__(self, **kwargs):
|
314
313
|
if self._readOnly:
|
315
314
|
raise ValueError(f"{self._readOnly} is read only")
|
316
|
-
if self._messages is
|
315
|
+
if self._messages is _Unknown:
|
317
316
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
318
317
|
self._messages.clear()
|
319
318
|
self._cache.clear()
|
@@ -327,10 +326,16 @@ class MapMessage:
|
|
327
326
|
def __setitem__(self, key, message):
|
328
327
|
if self._readOnly:
|
329
328
|
raise ValueError(f"{self._readOnly} is read only")
|
330
|
-
if self._messages is
|
329
|
+
if self._messages is _Unknown:
|
331
330
|
self._messages = self._parent._create_child(self._key)
|
332
331
|
if isinstance(message, Message):
|
333
332
|
message = message._message
|
333
|
+
elif isinstance(message, (MapMessage, RepeatedMessage)):
|
334
|
+
message = message._messages
|
335
|
+
elif isinstance(message, FieldMessage):
|
336
|
+
message = message._value
|
337
|
+
elif isinstance(message, Value):
|
338
|
+
message = message._raw
|
334
339
|
if self._field.type == self._field.TYPE_BYTES and isinstance(message, str):
|
335
340
|
message = message.encode('utf-8')
|
336
341
|
self._messages[key] = message
|
@@ -342,17 +347,17 @@ class MapMessage:
|
|
342
347
|
def __delitem__(self, key):
|
343
348
|
if self._readOnly:
|
344
349
|
raise ValueError(f"{self._readOnly} is read only")
|
345
|
-
if self._messages is not
|
350
|
+
if self._messages is not _Unknown:
|
346
351
|
if key in self._messages:
|
347
352
|
del self._messages[key]
|
348
353
|
self._cache.pop(key, None)
|
349
354
|
|
350
355
|
|
351
356
|
class RepeatedMessage:
|
352
|
-
def __init__(self, parent, key,
|
357
|
+
def __init__(self, parent, key, field, messages=_Unknown, readOnly=False):
|
353
358
|
self._parent = parent
|
354
359
|
self._key = key
|
355
|
-
self.
|
360
|
+
self._field = field
|
356
361
|
self._messages = messages
|
357
362
|
self._readOnly = readOnly
|
358
363
|
self._cache = {}
|
@@ -360,45 +365,56 @@ class RepeatedMessage:
|
|
360
365
|
def __getitem__(self, key):
|
361
366
|
if key in self._cache:
|
362
367
|
return self._cache[key]
|
363
|
-
if self._messages is
|
364
|
-
|
368
|
+
if self._messages is _Unknown or key >= len(self._messages):
|
369
|
+
value = _Unknown
|
365
370
|
else:
|
366
|
-
|
367
|
-
value
|
371
|
+
value = self._messages[key]
|
372
|
+
if value is None and self._field.has_default_value:
|
373
|
+
value = self._field.default_value
|
374
|
+
if self._field.type == self._field.TYPE_MESSAGE:
|
375
|
+
if self._field.message_type.name in ('Struct', 'ListValue'):
|
376
|
+
value = Value(self, key, value, self._readOnly)
|
377
|
+
else:
|
378
|
+
value = Message(self, key, self._field.message_type, value, self._readOnly)
|
379
|
+
else:
|
380
|
+
value = FieldMessage(self, key, self._field.type, value)
|
368
381
|
self._cache[key] = value
|
369
382
|
return value
|
370
383
|
|
371
384
|
def __bool__(self):
|
372
|
-
return self._messages
|
385
|
+
return self._messages is not _Unknown
|
373
386
|
|
374
387
|
def __len__(self):
|
375
|
-
return 0 if self._messages is
|
388
|
+
return 0 if self._messages is _Unknown else len(self._messages)
|
376
389
|
|
377
390
|
def __contains__(self, value):
|
378
|
-
if self._messages is not
|
391
|
+
if self._messages is not _Unknown:
|
379
392
|
for message in self:
|
380
393
|
if value == message:
|
381
394
|
return True
|
382
395
|
return False
|
383
396
|
|
384
397
|
def __iter__(self):
|
385
|
-
if self._messages is not
|
398
|
+
if self._messages is not _Unknown:
|
386
399
|
for ix in range(len(self._messages)):
|
387
400
|
yield self[ix]
|
388
401
|
|
389
402
|
def __hash__(self):
|
390
|
-
if self._messages is not
|
403
|
+
if self._messages is not _Unknown:
|
391
404
|
return hash(tuple(hash(item) for item in self))
|
392
405
|
return 0
|
393
406
|
|
394
407
|
def __eq__(self, other):
|
395
408
|
if not isinstance(other, RepeatedMessage):
|
396
409
|
return False
|
397
|
-
if self.
|
410
|
+
if self._field.type != other._field.type:
|
398
411
|
return False
|
399
|
-
if self.
|
400
|
-
|
401
|
-
|
412
|
+
if self._field.type == self._field.TYPE_MESSAGE:
|
413
|
+
if self._field.message_type.full_name != other._field.message_type.full_name:
|
414
|
+
return False
|
415
|
+
if self._messages is _Unknown:
|
416
|
+
return other._messages is _Unknown
|
417
|
+
elif other._messages is _Unknown:
|
402
418
|
return False
|
403
419
|
if len(self) != len(other):
|
404
420
|
return False
|
@@ -426,10 +442,10 @@ class RepeatedMessage:
|
|
426
442
|
return str(key)
|
427
443
|
return ''
|
428
444
|
|
429
|
-
def _create_child(self, key
|
445
|
+
def _create_child(self, key):
|
430
446
|
if self._readOnly:
|
431
447
|
raise ValueError(f"{self._readOnly} is read only")
|
432
|
-
if self._messages is
|
448
|
+
if self._messages is _Unknown:
|
433
449
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
434
450
|
while key >= len(self._messages):
|
435
451
|
self._messages.add()
|
@@ -438,9 +454,9 @@ class RepeatedMessage:
|
|
438
454
|
def __call__(self, *args):
|
439
455
|
if self._readOnly:
|
440
456
|
raise ValueError(f"{self._readOnly} is read only")
|
441
|
-
if self._messages is
|
457
|
+
if self._messages is _Unknown:
|
442
458
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
443
|
-
self._messages.
|
459
|
+
self._messages.clear()
|
444
460
|
self._cache.clear()
|
445
461
|
for arg in args:
|
446
462
|
self.append(arg)
|
@@ -449,58 +465,135 @@ class RepeatedMessage:
|
|
449
465
|
def __setitem__(self, key, message):
|
450
466
|
if self._readOnly:
|
451
467
|
raise ValueError(f"{self._readOnly} is read only")
|
452
|
-
if self._messages is
|
468
|
+
if self._messages is _Unknown:
|
453
469
|
self._messages = self._parent._create_child(self._key)
|
454
|
-
if key
|
455
|
-
key = len(self._messages)
|
456
|
-
elif key < 0:
|
470
|
+
if key < 0:
|
457
471
|
key = len(self._messages) + key
|
458
|
-
while key >= len(self._messages):
|
459
|
-
self._messages.add()
|
460
472
|
if isinstance(message, Message):
|
461
473
|
message = message._message
|
462
|
-
|
474
|
+
elif isinstance(message, (MapMessage, RepeatedMessage)):
|
475
|
+
message = message._messages
|
476
|
+
elif isinstance(message, FieldMessage):
|
477
|
+
message = message._value
|
478
|
+
elif isinstance(message, Value):
|
479
|
+
message = message._raw
|
480
|
+
if self._field.type == self._field.TYPE_BYTES and isinstance(message, str):
|
481
|
+
message = message.encode('utf-8')
|
482
|
+
if key >= len(self._messages):
|
483
|
+
self._messages.append(message)
|
484
|
+
else:
|
485
|
+
self._messages[key] = message
|
463
486
|
self._cache.pop(key, None)
|
464
487
|
|
465
488
|
def __delitem__(self, key):
|
466
489
|
if self._readOnly:
|
467
490
|
raise ValueError(f"{self._readOnly} is read only")
|
468
|
-
if self.
|
469
|
-
del self.
|
491
|
+
if self._messages is not _Unknown:
|
492
|
+
del self._messages[key]
|
470
493
|
self._cache.pop(key, None)
|
471
494
|
|
472
|
-
def append(self, message=
|
495
|
+
def append(self, message=_Unknown):
|
473
496
|
if self._readOnly:
|
474
497
|
raise ValueError(f"{self._readOnly} is read only")
|
475
|
-
if self._messages is
|
498
|
+
if self._messages is _Unknown:
|
476
499
|
self._messages = self._parent._create_child(self._key)
|
477
|
-
if message is
|
500
|
+
if message is _Unknown:
|
478
501
|
message = self._messages.add()
|
479
502
|
else:
|
480
503
|
message = self._messages.append(message)
|
481
504
|
return self[len(self._messages) - 1]
|
482
505
|
|
483
506
|
|
507
|
+
class FieldMessage:
|
508
|
+
def __init__(self, parent, key, kind, value):
|
509
|
+
self.__dict__['_parent'] = parent
|
510
|
+
self.__dict__['_key'] = key
|
511
|
+
self.__dict__['_kind'] = kind
|
512
|
+
self.__dict__['_value'] = value
|
513
|
+
|
514
|
+
def __bool__(self):
|
515
|
+
return bool(self._value)
|
516
|
+
|
517
|
+
def __len__(self):
|
518
|
+
return len(self._value)
|
519
|
+
|
520
|
+
def __contains__(self, key):
|
521
|
+
return key in self._value
|
522
|
+
|
523
|
+
def __hash__(self):
|
524
|
+
return hash(self._value)
|
525
|
+
|
526
|
+
def __eq__(self, other):
|
527
|
+
if isinstance(other, FieldMessage):
|
528
|
+
return self._value == other._value
|
529
|
+
return self._value == other
|
530
|
+
|
531
|
+
def __str__(self):
|
532
|
+
return str(self._value)
|
533
|
+
|
534
|
+
def __format__(self, spec=''):
|
535
|
+
return format(self._value, spec)
|
536
|
+
|
537
|
+
def __int__(self):
|
538
|
+
return int(self._value)
|
539
|
+
|
540
|
+
def __float__(self):
|
541
|
+
return float(self._value)
|
542
|
+
|
543
|
+
def _fullName(self, key=None):
|
544
|
+
if self._key is not None:
|
545
|
+
if self._parent is not None:
|
546
|
+
name = self._parent._fullName(self._key)
|
547
|
+
else:
|
548
|
+
name = str(self._key)
|
549
|
+
if key is not None:
|
550
|
+
if '.' in key:
|
551
|
+
name += f"[{key}]"
|
552
|
+
else:
|
553
|
+
name += f".{key}"
|
554
|
+
return name
|
555
|
+
if key is not None:
|
556
|
+
return str(key)
|
557
|
+
return ''
|
558
|
+
|
559
|
+
|
484
560
|
class ProtobufValue:
|
485
561
|
@property
|
486
562
|
def _protobuf_value(self):
|
487
563
|
return None
|
488
564
|
|
489
565
|
|
490
|
-
class
|
491
|
-
|
492
|
-
UNKNOWN = 0
|
493
|
-
MAP = 1
|
494
|
-
LIST = 2
|
495
|
-
|
496
|
-
def __init__(self, parent, key, values, type, readOnly=None):
|
566
|
+
class Value:
|
567
|
+
def __init__(self, parent, key, value=_Unknown, readOnly=None):
|
497
568
|
self.__dict__['_parent'] = parent
|
498
569
|
self.__dict__['_key'] = key
|
499
|
-
self.__dict__['
|
500
|
-
self.__dict__['_type'] = type
|
501
|
-
self.__dict__['_readOnly'] = readOnly
|
570
|
+
self.__dict__['_dependencies'] = {}
|
502
571
|
self.__dict__['_unknowns'] = {}
|
503
572
|
self.__dict__['_cache'] = {}
|
573
|
+
self.__dict__['_readOnly'] = None
|
574
|
+
if isinstance(value, (google.protobuf.struct_pb2.Value, google.protobuf.struct_pb2.Struct, google.protobuf.struct_pb2.ListValue)) or value is _Unknown:
|
575
|
+
self.__dict__['_value'] = value
|
576
|
+
else:
|
577
|
+
self.__dict__['_value'] = google.protobuf.struct_pb2.Value()
|
578
|
+
if value is None:
|
579
|
+
self._value.null_value = 0
|
580
|
+
elif isinstance(value, dict):
|
581
|
+
self._value.struct_value.Clear()
|
582
|
+
for k, v in value.items():
|
583
|
+
self[k] = v
|
584
|
+
elif isinstance(value, (tuple, list)):
|
585
|
+
self._value.list_value.Clear()
|
586
|
+
for ix, v in enumerate(value):
|
587
|
+
self[ix] = v
|
588
|
+
elif isinstance(value, bool): # Must be before number check
|
589
|
+
self._value.bool_value = value
|
590
|
+
elif isinstance(value, (int, float)):
|
591
|
+
self._value.number_value = value
|
592
|
+
elif isinstance(value, str):
|
593
|
+
self._value.string_value = value
|
594
|
+
else:
|
595
|
+
raise ValueError(f"Unexpected Value type: {value.__class__}")
|
596
|
+
self.__dict__['_readOnly'] = readOnly
|
504
597
|
|
505
598
|
def __getattr__(self, key):
|
506
599
|
return self[key]
|
@@ -511,115 +604,201 @@ class Values:
|
|
511
604
|
if key in self._unknowns:
|
512
605
|
return self._unknowns[key]
|
513
606
|
if isinstance(key, str):
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
607
|
+
match self._kind:
|
608
|
+
case 'struct_value':
|
609
|
+
value = self._value.struct_value.fields.get(key, _Unknown)
|
610
|
+
case 'Struct':
|
611
|
+
value = self._value.fields.get(key, _Unknown)
|
612
|
+
case 'Unknown':
|
613
|
+
value = _Unknown
|
614
|
+
case _:
|
615
|
+
raise ValueError(f"Invalid key \"{key}\" for kind: {self._kind}")
|
522
616
|
elif isinstance(key, int):
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
617
|
+
match self._kind:
|
618
|
+
case 'list_value':
|
619
|
+
if key < len(self._value.list_value.values):
|
620
|
+
value = self._value.list_value.values[key]
|
621
|
+
else:
|
622
|
+
value = _Unknown
|
623
|
+
case 'ListValue':
|
624
|
+
if key < len(self._value.values):
|
625
|
+
value = self._value.values[key]
|
626
|
+
else:
|
627
|
+
value = _Unknown
|
628
|
+
case 'Unknown':
|
629
|
+
value = _Unknown
|
630
|
+
case _:
|
631
|
+
raise ValueError(f"Invalid key \"{key}\" for kind: {self._kind}")
|
535
632
|
else:
|
536
|
-
|
537
|
-
|
538
|
-
value = Values(self, key, None, self.Type.UNKNOWN, self._readOnly)
|
539
|
-
elif kind == 'struct_value':
|
540
|
-
value = Values(self, key, struct_value.struct_value, self.Type.MAP, self._readOnly)
|
541
|
-
elif kind == 'list_value':
|
542
|
-
value = Values(self, key, struct_value.list_value, self.Type.LIST, self._readOnly)
|
543
|
-
elif kind == 'string_value':
|
544
|
-
value = struct_value.string_value
|
545
|
-
elif kind == 'number_value':
|
546
|
-
value = struct_value.number_value
|
547
|
-
if value.is_integer():
|
548
|
-
value = int(value)
|
549
|
-
elif kind == 'bool_value':
|
550
|
-
value = struct_value.bool_value
|
551
|
-
elif kind == 'null_value':
|
552
|
-
value = None
|
553
|
-
else:
|
554
|
-
raise ValueError(f"Unexpected value kind: {kind}")
|
633
|
+
raise ValueError(f"Unexpected key type: {key.__class__}")
|
634
|
+
value = Value(self, key, value, self._readOnly)
|
555
635
|
self._cache[key] = value
|
556
636
|
return value
|
557
637
|
|
558
638
|
def __bool__(self):
|
559
|
-
return self.
|
639
|
+
return not self._isUnknown
|
560
640
|
|
561
641
|
def __len__(self):
|
562
|
-
|
642
|
+
match self._kind:
|
643
|
+
case 'struct_value':
|
644
|
+
return len(self._value.struct_value.fields) + len(self._unknowns)
|
645
|
+
case 'Struct':
|
646
|
+
return len(self._value.fields) + len(self._unknowns)
|
647
|
+
case 'list_value':
|
648
|
+
return len(self._value.list_value.values) + len(self._unknowns)
|
649
|
+
case 'ListValue':
|
650
|
+
return len(self._value.values) + len(self._unknowns)
|
651
|
+
return 0
|
563
652
|
|
564
653
|
def __contains__(self, item):
|
565
|
-
|
566
|
-
|
567
|
-
return item in self.
|
568
|
-
|
654
|
+
match self._kind:
|
655
|
+
case 'struct_value':
|
656
|
+
return item in self._value.struct_value.fields or item in self._unknowns
|
657
|
+
case 'Struct':
|
658
|
+
return item in self._value.fields or item in self._unknowns
|
659
|
+
case 'list_value' | 'ListValue':
|
569
660
|
for value in self:
|
570
661
|
if item == value:
|
571
662
|
return True
|
572
663
|
return False
|
573
664
|
|
574
665
|
def __iter__(self):
|
575
|
-
|
576
|
-
|
577
|
-
for key in sorted(set(self.
|
666
|
+
match self._kind:
|
667
|
+
case 'struct_value':
|
668
|
+
for key in sorted(set(self._value.struct_value.fields) | set(self._unknowns.keys())):
|
578
669
|
yield key, self[key]
|
579
|
-
|
580
|
-
for
|
670
|
+
case 'Struct':
|
671
|
+
for key in sorted(set(self._value.fields) | set(self._unknowns.keys())):
|
672
|
+
yield key, self[key]
|
673
|
+
case 'list_value':
|
674
|
+
for ix in range(len(self._value.list_value.values)):
|
581
675
|
yield self[ix]
|
582
676
|
for ix in sorted(self._unknowns.keys()):
|
583
|
-
if ix >= len(self.
|
677
|
+
if ix >= len(self._value.list_value.values):
|
678
|
+
yield self[ix]
|
679
|
+
case 'ListValue':
|
680
|
+
for ix in range(len(self._value.values)):
|
681
|
+
yield self[ix]
|
682
|
+
for ix in sorted(self._unknowns.keys()):
|
683
|
+
if ix >= len(self._value.values):
|
584
684
|
yield self[ix]
|
585
685
|
|
586
686
|
def __hash__(self):
|
587
|
-
|
588
|
-
|
687
|
+
match self._kind:
|
688
|
+
case 'struct_value' | 'Struct':
|
589
689
|
return hash(tuple(hash(item) for item in sorted(iter(self), key=lambda item: item[0])))
|
590
|
-
|
690
|
+
case 'list_value' | 'ListValue':
|
591
691
|
return hash(tuple(hash(item) for item in self))
|
592
|
-
|
692
|
+
case 'string_value':
|
693
|
+
return hash(self._value.string_value)
|
694
|
+
case 'null_value':
|
695
|
+
return hash(None)
|
696
|
+
case 'number_value':
|
697
|
+
return hash(self._value.number_value)
|
698
|
+
case 'bool_value':
|
699
|
+
return hash(self._value.bool_value)
|
700
|
+
return 0
|
593
701
|
|
594
702
|
def __eq__(self, other):
|
595
|
-
|
596
|
-
|
597
|
-
if self._type != other._type:
|
703
|
+
kind = self._kind
|
704
|
+
if isinstance(other, Value) and other._kind != kind:
|
598
705
|
return False
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
return False
|
603
|
-
if len(self) != len(other):
|
604
|
-
return False
|
605
|
-
if self._isMap:
|
606
|
-
for key, value in self:
|
607
|
-
if key not in other:
|
706
|
+
match kind:
|
707
|
+
case 'struct_value' | 'Struct':
|
708
|
+
if not isinstance(other, (Value, dict)):
|
608
709
|
return False
|
609
|
-
if
|
710
|
+
if len(self) != len(other):
|
610
711
|
return False
|
611
|
-
|
612
|
-
|
613
|
-
|
712
|
+
for key, value in self:
|
713
|
+
if key not in other:
|
714
|
+
return False
|
715
|
+
if value != other[key]:
|
716
|
+
return False
|
717
|
+
return True
|
718
|
+
case 'list_value' | 'ListValue':
|
719
|
+
if not isinstance(other, (Value, tuple, list)):
|
614
720
|
return False
|
615
|
-
|
721
|
+
if len(self) != len(other):
|
722
|
+
return False
|
723
|
+
for ix, value in enumerate(self):
|
724
|
+
if value != other[ix]:
|
725
|
+
return False
|
726
|
+
return True
|
727
|
+
case 'Unknown':
|
728
|
+
if isinstance(other, Value):
|
729
|
+
return other._isUnknown
|
730
|
+
return False
|
731
|
+
case 'string_value':
|
732
|
+
if isinstance(other, Value):
|
733
|
+
return self._value.string_value == other._value.string_value
|
734
|
+
if isinstance(other, str):
|
735
|
+
return self._value.string_value == other
|
736
|
+
return False
|
737
|
+
case 'null_value':
|
738
|
+
if isinstance(other, Value):
|
739
|
+
return True
|
740
|
+
return other is None
|
741
|
+
case 'number_value':
|
742
|
+
if isinstance(other, Value):
|
743
|
+
return self._value.number_value == other._value.number_value
|
744
|
+
if isinstance(other, (int, float)):
|
745
|
+
return self._value.number_value == other
|
746
|
+
return False
|
747
|
+
case 'bool_value':
|
748
|
+
if isinstance(other, Value):
|
749
|
+
return self._value.bool_value == other._value.bool_value
|
750
|
+
if isinstance(other, bool):
|
751
|
+
return self._value.bool_value == other
|
752
|
+
return False
|
753
|
+
return False
|
616
754
|
|
617
755
|
def __str__(self):
|
618
|
-
return format(self)
|
756
|
+
return format(self, '')
|
619
757
|
|
620
758
|
def __format__(self, spec='yaml'):
|
759
|
+
if not spec:
|
760
|
+
match self._kind:
|
761
|
+
case 'Unknown':
|
762
|
+
return '<<UNKNOWN>>'
|
763
|
+
case 'string_value':
|
764
|
+
return self._value.string_value
|
765
|
+
case 'null_value':
|
766
|
+
return 'null'
|
767
|
+
case 'number_value':
|
768
|
+
value = self._value.number_value
|
769
|
+
if value.is_integer():
|
770
|
+
value = int(value)
|
771
|
+
return str(value)
|
772
|
+
case 'bool_value':
|
773
|
+
return 'true' if self._value.bool_value else 'false'
|
621
774
|
return _formatObject(self, spec)
|
622
775
|
|
776
|
+
def __int__(self):
|
777
|
+
kind = self._kind
|
778
|
+
match kind:
|
779
|
+
case 'string_value':
|
780
|
+
return int(self._value.string_value)
|
781
|
+
case 'number_value':
|
782
|
+
return int(self._value.number_value)
|
783
|
+
case 'bool_value':
|
784
|
+
return int(self._value.bool_value)
|
785
|
+
case 'Unknown':
|
786
|
+
return 0
|
787
|
+
raise TypeError(f"Cannot convert kind to integer: {kind}")
|
788
|
+
|
789
|
+
def __float__(self):
|
790
|
+
kind = self._kind
|
791
|
+
match kind:
|
792
|
+
case 'string_value':
|
793
|
+
return float(self._value.string_value)
|
794
|
+
case 'number_value':
|
795
|
+
return float(self._value.number_value)
|
796
|
+
case 'bool_value':
|
797
|
+
return float(self._value.bool_value)
|
798
|
+
case 'Unknown':
|
799
|
+
return 0.0
|
800
|
+
raise TypeError(f"Cannot convert kind to float: {kind}")
|
801
|
+
|
623
802
|
def _fullName(self, key=None):
|
624
803
|
if self._key is not None:
|
625
804
|
if self._parent is not None:
|
@@ -638,60 +817,21 @@ class Values:
|
|
638
817
|
if isinstance(key, int):
|
639
818
|
name += f"[{key}]"
|
640
819
|
else:
|
641
|
-
if key
|
642
|
-
name += f"
|
820
|
+
if '.' in key:
|
821
|
+
name += f"[{key}]"
|
643
822
|
else:
|
644
|
-
name += f"
|
823
|
+
name += f".{key}"
|
645
824
|
return name
|
646
825
|
if key is not None:
|
647
826
|
return str(key)
|
648
827
|
return ''
|
649
828
|
|
650
|
-
def _create_child(self, key, type):
|
651
|
-
if self._readOnly:
|
652
|
-
raise ValueError(f"{self._readOnly} is read only")
|
653
|
-
if isinstance(key, str):
|
654
|
-
if not self._isMap:
|
655
|
-
if not self._isUnknown:
|
656
|
-
raise ValueError('Invalid key, must be a str for maps')
|
657
|
-
self.__dict__['_type'] = self.Type.MAP
|
658
|
-
if self._values is None:
|
659
|
-
if self._parent is None:
|
660
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.Struct()
|
661
|
-
else:
|
662
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
663
|
-
struct_value = self._values.fields[key]
|
664
|
-
elif isinstance(key, int):
|
665
|
-
if not self._isList:
|
666
|
-
if not self._isUnknown:
|
667
|
-
raise ValueError('Invalid key, must be an int for lists')
|
668
|
-
self.__dict__['_type'] = self.Type.LIST
|
669
|
-
if self._values is None:
|
670
|
-
if self._parent is None:
|
671
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.ListValue()
|
672
|
-
else:
|
673
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
674
|
-
while key >= len(self._values.values):
|
675
|
-
self._values.values.add()
|
676
|
-
struct_value = self._values.values[key]
|
677
|
-
else:
|
678
|
-
raise ValueError('Unexpected key type')
|
679
|
-
if type == self.Type.MAP:
|
680
|
-
if not struct_value.HasField('struct_value'):
|
681
|
-
struct_value.struct_value.Clear()
|
682
|
-
return struct_value.struct_value
|
683
|
-
if type == self.Type.LIST:
|
684
|
-
if not struct_value.HasField('list_value'):
|
685
|
-
struct_value.list_value.Clear()
|
686
|
-
return struct_value.list_value
|
687
|
-
raise ValueError(f"Unexpected type: {type}")
|
688
|
-
|
689
829
|
def __call__(self, *args, **kwargs):
|
690
830
|
if self._readOnly:
|
691
831
|
raise ValueError(f"{self._readOnly} is read only")
|
692
|
-
self.__dict__['
|
693
|
-
self.__dict__['_type'] = self.Type.UNKNOWN
|
832
|
+
self.__dict__['_value'] = google.protobuf.struct_pb2.Value()
|
694
833
|
self._cache.clear()
|
834
|
+
self._dependencies.clear()
|
695
835
|
self._unknowns.clear()
|
696
836
|
if len(kwargs):
|
697
837
|
if len(args):
|
@@ -710,27 +850,15 @@ class Values:
|
|
710
850
|
if self._readOnly:
|
711
851
|
raise ValueError(f"{self._readOnly} is read only")
|
712
852
|
if isinstance(key, str):
|
713
|
-
if
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
if self._values is None:
|
718
|
-
if self._parent is None:
|
719
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.Struct()
|
720
|
-
else:
|
721
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
722
|
-
values = self._values.fields
|
853
|
+
if self._ensure_map() == 'struct_value':
|
854
|
+
values = self._value.struct_value.fields
|
855
|
+
else:
|
856
|
+
values = self._value.fields
|
723
857
|
elif isinstance(key, int):
|
724
|
-
if
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
if self._values is None:
|
729
|
-
if self._parent is None:
|
730
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.ListValue()
|
731
|
-
else:
|
732
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
733
|
-
values = self._values.values
|
858
|
+
if self._ensure_list() == 'list_value':
|
859
|
+
values = self._value.list_value.values
|
860
|
+
else:
|
861
|
+
values = self._value.values
|
734
862
|
if key == append:
|
735
863
|
key = len(values)
|
736
864
|
elif key < 0:
|
@@ -740,6 +868,7 @@ class Values:
|
|
740
868
|
else:
|
741
869
|
raise ValueError('Unexpected key type')
|
742
870
|
self._cache.pop(key, None)
|
871
|
+
self._dependencies.pop(key, None)
|
743
872
|
self._unknowns.pop(key, None)
|
744
873
|
if isinstance(value, ProtobufValue):
|
745
874
|
value = value._protobuf_value
|
@@ -759,79 +888,217 @@ class Values:
|
|
759
888
|
values[key].list_value.Clear()
|
760
889
|
for ix, v in enumerate(value):
|
761
890
|
self[key][ix] = v
|
762
|
-
elif isinstance(value,
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
891
|
+
elif isinstance(value, FieldMessage):
|
892
|
+
self._dependencies[key] = value
|
893
|
+
if isinstance(value._value, str):
|
894
|
+
values[key].string_value = value._value
|
895
|
+
elif isinstance(value._value, bytes):
|
896
|
+
values[key].string_value = value._value.decode('utf-8')
|
897
|
+
elif value._value is None:
|
898
|
+
values[key].null_value = value._value.null_value
|
899
|
+
elif isinstance(value._value, (int, float)):
|
900
|
+
values[key].number_value = value._value
|
901
|
+
elif isinstance(value._value, bool):
|
902
|
+
values[key].bool_value = value._value
|
903
|
+
elif value._value is _Unknown:
|
904
|
+
self._setUnknown(key, value)
|
771
905
|
else:
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
906
|
+
raise ValueError(f"Unexpected field type: {value._value.__class__}")
|
907
|
+
elif isinstance(value, Value):
|
908
|
+
self._dependencies[key] = value
|
909
|
+
match value._kind:
|
910
|
+
case 'struct_value' | 'Struct':
|
911
|
+
values[key].struct_value.Clear()
|
912
|
+
for k, v in value:
|
913
|
+
self[key][k] = v
|
914
|
+
case 'list_value' | 'ListValue':
|
915
|
+
values[key].list_value.Clear()
|
916
|
+
for ix, v in enumerate(value):
|
917
|
+
self[key][ix] = v
|
918
|
+
case 'string_value':
|
919
|
+
values[key].string_value = value._value.string_value
|
920
|
+
case 'null_value':
|
921
|
+
values[key].null_value = value._value.null_value
|
922
|
+
case 'number_value':
|
923
|
+
values[key].number_value = value._value.number_value
|
924
|
+
case 'bool_value':
|
925
|
+
values[key].bool_value = value._value.bool_value
|
926
|
+
case 'Unknown':
|
927
|
+
self._setUnknown(key, value)
|
928
|
+
case _:
|
929
|
+
raise ValueError(f"Unexpected value kind: {value._kind}")
|
783
930
|
else:
|
784
931
|
raise ValueError(f"Unexpected type: {value.__class__}")
|
785
932
|
|
933
|
+
@property
|
934
|
+
def _raw(self):
|
935
|
+
match self._kind:
|
936
|
+
case 'struct_value':
|
937
|
+
return self._value.struct_value
|
938
|
+
case 'list_value':
|
939
|
+
return self._value.list_value
|
940
|
+
case 'string_value':
|
941
|
+
return self._value.string_value
|
942
|
+
case 'null_value':
|
943
|
+
return self._value.null_value
|
944
|
+
case 'number_value':
|
945
|
+
return self._value.number_value
|
946
|
+
case 'bool_value':
|
947
|
+
return self._value.bool_value
|
948
|
+
case 'Struct' | 'ListValue':
|
949
|
+
return self._value
|
950
|
+
case 'Unknown':
|
951
|
+
return _Unknown
|
952
|
+
|
953
|
+
def _setUnknown(self, key, value):
|
954
|
+
self._dependencies.pop(key, None)
|
955
|
+
self._unknowns[key] = value
|
956
|
+
match self._kind:
|
957
|
+
case 'struct_value':
|
958
|
+
if key in self._value.struct_value.fields:
|
959
|
+
del self._value.struct_value[key]
|
960
|
+
case 'Struct':
|
961
|
+
if key in self._value.fields:
|
962
|
+
del self._value[key]
|
963
|
+
case 'list_value':
|
964
|
+
if key < len(self._value.list_value.values):
|
965
|
+
self._value.list_value.values[key].Clear()
|
966
|
+
for ix in reversed(range(len(self._value.list_value.values))):
|
967
|
+
if ix not in self._unknowns:
|
968
|
+
break
|
969
|
+
del self._value.list_value[ix]
|
970
|
+
case 'ListValue':
|
971
|
+
if key < len(self._value.values):
|
972
|
+
self._value.values[key].Clear()
|
973
|
+
for ix in reversed(range(len(self._value.values))):
|
974
|
+
if ix not in self._unknowns:
|
975
|
+
break
|
976
|
+
del self._value[ix]
|
977
|
+
|
786
978
|
def __delattr__(self, key):
|
787
979
|
del self[key]
|
788
980
|
|
789
981
|
def __delitem__(self, key):
|
790
982
|
if self._readOnly:
|
791
983
|
raise ValueError(f"{self._readOnly} is read only")
|
984
|
+
kind = self._kind
|
985
|
+
if kind == 'Unknown':
|
986
|
+
return
|
792
987
|
if isinstance(key, str):
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
988
|
+
match kind:
|
989
|
+
case 'struct_value':
|
990
|
+
if key in self._value.struct_value.fields:
|
991
|
+
del self._value.struct_value[key]
|
992
|
+
case 'Struct':
|
993
|
+
if key in self._value.fields:
|
994
|
+
del self._value[key]
|
995
|
+
case _:
|
996
|
+
raise ValueError(f"Invalid key \"{key}\" for kind: {self._kind}")
|
997
|
+
self._cache.pop(key, None)
|
998
|
+
self._dependencies.pop(key, None)
|
999
|
+
self._unknowns.pop(key, None)
|
802
1000
|
elif isinstance(key, int):
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
1001
|
+
match kind:
|
1002
|
+
case 'list_value':
|
1003
|
+
values = self._value.list_value
|
1004
|
+
case 'ListValue':
|
1005
|
+
values = self._value
|
1006
|
+
case _:
|
1007
|
+
raise ValueError(f"Invalid key \"{key}\" for kind: {self._kind}")
|
1008
|
+
if key < len(values.values):
|
1009
|
+
del values[key]
|
1010
|
+
self._cache.pop(key, None)
|
1011
|
+
self._dependencies.pop(key, None)
|
1012
|
+
self._unknowns.pop(key, None)
|
1013
|
+
for ix in sorted(self._dependencies.keys()):
|
1014
|
+
if ix > key:
|
1015
|
+
self._cache.pop(ix, None)
|
1016
|
+
self._dependencies[ix - 1] = self._dependences[ix]
|
1017
|
+
del self._dependencies[ix]
|
1018
|
+
for ix in sorted(self._unknowns.keys()):
|
1019
|
+
if ix > key:
|
1020
|
+
self._cache.pop(ix, None)
|
1021
|
+
self._unknowns[ix - 1] = self._unknowns[ix]
|
1022
|
+
del self._unknowns[ix]
|
1023
|
+
for ix in reversed(range(len(values.values))):
|
1024
|
+
if ix not in self._unknowns:
|
1025
|
+
break
|
1026
|
+
del values[ix]
|
821
1027
|
else:
|
822
1028
|
raise ValueError('Unexpected key type')
|
823
1029
|
|
1030
|
+
def _create_child(self, key):
|
1031
|
+
if self._readOnly:
|
1032
|
+
raise ValueError(f"{self._readOnly} is read only")
|
1033
|
+
if isinstance(key, str):
|
1034
|
+
if self._ensure_map() == 'struct_value':
|
1035
|
+
fields = self._value.struct_value.fields
|
1036
|
+
else:
|
1037
|
+
fields = self._value.fields
|
1038
|
+
fields[key].Clear()
|
1039
|
+
return fields[key]
|
1040
|
+
if isinstance(key, int):
|
1041
|
+
if self._ensure_list() == 'list_value':
|
1042
|
+
values = self._value.list_value.values
|
1043
|
+
else:
|
1044
|
+
values = self._value.values
|
1045
|
+
while key >= len(values):
|
1046
|
+
values.add()
|
1047
|
+
values[key].Clear()
|
1048
|
+
return values[key]
|
1049
|
+
raise ValueError('Unexpected key type')
|
1050
|
+
|
1051
|
+
def _ensure_map(self):
|
1052
|
+
kind = self._kind
|
1053
|
+
if kind == 'Unknown':
|
1054
|
+
if self._parent is None:
|
1055
|
+
self.__dict__['_value'] = google.protobuf.struct_pb2.Value()
|
1056
|
+
else:
|
1057
|
+
self.__dict__['_value'] = self._parent._create_child(self._key)
|
1058
|
+
if isinstance(self._value, google.protobuf.struct_pb2.Value) and self._value.WhichOneof('kind') is None:
|
1059
|
+
self._value.struct_value.Clear()
|
1060
|
+
kind = self._kind
|
1061
|
+
if kind not in ('struct_value', 'Struct'):
|
1062
|
+
raise ValueError(f"Invalid map kind: {kind}")
|
1063
|
+
return kind
|
1064
|
+
|
1065
|
+
def _ensure_list(self):
|
1066
|
+
kind = self._kind
|
1067
|
+
if kind == 'Unknown':
|
1068
|
+
if self._parent is None:
|
1069
|
+
self.__dict__['_value'] = google.protobuf.struct_pb2.Value()
|
1070
|
+
else:
|
1071
|
+
self.__dict__['_value'] = self._parent._create_child(self._key)
|
1072
|
+
if isinstance(self._value, google.protobuf.struct_pb2.Value) and self._value.WhichOneof('kind') is None:
|
1073
|
+
self._value.list_value.Clear()
|
1074
|
+
kind = self._kind
|
1075
|
+
if kind not in ('list_value', 'ListValue'):
|
1076
|
+
raise ValueError(f"Invalid list kind: {kind}")
|
1077
|
+
return kind
|
1078
|
+
|
1079
|
+
@property
|
1080
|
+
def _kind(self):
|
1081
|
+
if isinstance(self._value, google.protobuf.struct_pb2.Value):
|
1082
|
+
return self._value.WhichOneof('kind') or 'Unknown'
|
1083
|
+
if isinstance(self._value, google.protobuf.struct_pb2.Struct):
|
1084
|
+
return 'Struct'
|
1085
|
+
if isinstance(self._value, google.protobuf.struct_pb2.ListValue):
|
1086
|
+
return 'ListValue'
|
1087
|
+
if self._value is _Unknown:
|
1088
|
+
return 'Unknown'
|
1089
|
+
raise ValueError(f"Unexpected value type: {self._value.__class__}")
|
1090
|
+
|
824
1091
|
@property
|
825
1092
|
def _isUnknown(self):
|
826
|
-
return self.
|
1093
|
+
return self._kind == 'Unknown'
|
827
1094
|
|
828
1095
|
@property
|
829
1096
|
def _isMap(self):
|
830
|
-
return self.
|
1097
|
+
return self._kind in ('struct_value', 'Struct')
|
831
1098
|
|
832
1099
|
@property
|
833
1100
|
def _isList(self):
|
834
|
-
return self.
|
1101
|
+
return self._kind in ('list_value', 'ListValue')
|
835
1102
|
|
836
1103
|
@property
|
837
1104
|
def _getUnknowns(self):
|
@@ -840,45 +1107,77 @@ class Values:
|
|
840
1107
|
unknowns[self._fullName(key)] = unknown._fullName()
|
841
1108
|
if self._isMap:
|
842
1109
|
for key, value in self:
|
843
|
-
if isinstance(value,
|
1110
|
+
if isinstance(value, Value):
|
844
1111
|
unknowns.update(value._getUnknowns)
|
845
1112
|
elif self._isList:
|
846
1113
|
for value in self:
|
847
|
-
if isinstance(value,
|
1114
|
+
if isinstance(value, Value):
|
848
1115
|
unknowns.update(value._getUnknowns)
|
849
1116
|
return unknowns
|
850
1117
|
|
1118
|
+
@property
|
1119
|
+
def _getDependencies(self):
|
1120
|
+
dependencies = {}
|
1121
|
+
for key, dependency in self._dependencies.items():
|
1122
|
+
dependencies[self._fullName(key)] = dependency._fullName()
|
1123
|
+
for key, unknown in self._unknowns.items():
|
1124
|
+
dependencies[self._fullName(key)] = unknown._fullName()
|
1125
|
+
if self._isMap:
|
1126
|
+
for key, value in self:
|
1127
|
+
if isinstance(value, Value):
|
1128
|
+
dependencies.update(value._getDependencies)
|
1129
|
+
elif self._isList:
|
1130
|
+
for value in self:
|
1131
|
+
if isinstance(value, Value):
|
1132
|
+
dependencies.update(value._getDependencies)
|
1133
|
+
return dependencies
|
1134
|
+
|
851
1135
|
def _patchUnknowns(self, patches):
|
852
|
-
for key in
|
1136
|
+
for key in list(self._unknowns.keys()):
|
853
1137
|
self[key] = patches[key]
|
854
1138
|
if self._isMap:
|
855
1139
|
for key, value in self:
|
856
|
-
if isinstance(value,
|
1140
|
+
if isinstance(value, Value) and len(value):
|
857
1141
|
patch = patches[key]
|
858
|
-
if isinstance(patch,
|
1142
|
+
if isinstance(patch, Value) and patch._type == value._type and len(patch):
|
859
1143
|
value._patchUnknowns(patch)
|
860
1144
|
elif self._isList:
|
861
1145
|
for ix, value in enumerate(self):
|
862
|
-
if isinstance(value,
|
1146
|
+
if isinstance(value, Value) and len(value):
|
863
1147
|
patch = patches[ix]
|
864
|
-
if isinstance(patch,
|
1148
|
+
if isinstance(patch, Value) and patch._type == value._type and len(patch):
|
865
1149
|
value._patchUnknowns(patch)
|
866
1150
|
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
1151
|
+
def _renderUnknowns(self, trimFullName):
|
1152
|
+
for key, unknown in list(self._unknowns.items()):
|
1153
|
+
self[key] = f"UNKNOWN:{trimFullName(unknown._fullName())}"
|
1154
|
+
self._dependencies[key] = unknown
|
1155
|
+
if self._isMap:
|
1156
|
+
for key, value in self:
|
1157
|
+
if isinstance(value, Value) and len(value):
|
1158
|
+
value._renderUnknowns(trimFullName)
|
1159
|
+
elif self._isList:
|
1160
|
+
for ix, value in enumerate(self):
|
1161
|
+
if isinstance(value, Value) and len(value):
|
1162
|
+
value._renderUnknowns(trimFullName)
|
1163
|
+
|
1164
|
+
|
1165
|
+
def _formatObject(object, spec='yaml'):
|
1166
|
+
match spec:
|
1167
|
+
case 'json':
|
1168
|
+
return json.dumps(object, indent=2, cls=_JSONEncoder)
|
1169
|
+
case 'jsonc':
|
1170
|
+
return json.dumps(object, separators=(',', ':'), cls=_JSONEncoder)
|
1171
|
+
case 'protobuf':
|
1172
|
+
if isinstance(object, Message):
|
1173
|
+
return str(object._message)
|
1174
|
+
if isinstance(object, (MapMessage, RepeatedMessage)):
|
1175
|
+
return str(object._messages)
|
1176
|
+
if isinstance(object, Value):
|
1177
|
+
return str(object._value)
|
1178
|
+
return format(object)
|
1179
|
+
case _:
|
1180
|
+
return yaml.dump(object, Dumper=_Dumper)
|
882
1181
|
|
883
1182
|
|
884
1183
|
class _JSONEncoder(json.JSONEncoder):
|
@@ -891,17 +1190,32 @@ class _JSONEncoder(json.JSONEncoder):
|
|
891
1190
|
if object:
|
892
1191
|
return [value for value in object]
|
893
1192
|
return None
|
894
|
-
if isinstance(object,
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
1193
|
+
if isinstance(object, FieldMessage):
|
1194
|
+
return object._value
|
1195
|
+
if isinstance(object, Value):
|
1196
|
+
match object._kind:
|
1197
|
+
case 'struct_value' | 'Struc':
|
1198
|
+
return {key: value for key, value in object}
|
1199
|
+
case 'list_value' | 'ListValue':
|
1200
|
+
return [value for value in object]
|
1201
|
+
case 'string_value':
|
1202
|
+
return object._value.string_value
|
1203
|
+
case 'null_value':
|
1204
|
+
return None
|
1205
|
+
case 'number_value':
|
1206
|
+
value = object._value.number_value
|
1207
|
+
if value.is_integer():
|
1208
|
+
value = int(value)
|
1209
|
+
return value
|
1210
|
+
case 'bool_value':
|
1211
|
+
return object._value.bool_value
|
1212
|
+
case 'Unknown':
|
1213
|
+
return '<<UNKNOWN>>'
|
1214
|
+
case _:
|
1215
|
+
return '<<UNEXPECTED>>'
|
902
1216
|
if isinstance(object, datetime.datetime):
|
903
1217
|
return object.isoformat()
|
904
|
-
return super(
|
1218
|
+
return super(_JSONEncoder, self).default(object)
|
905
1219
|
|
906
1220
|
|
907
1221
|
class _Dumper(yaml.SafeDumper):
|
@@ -915,17 +1229,50 @@ class _Dumper(yaml.SafeDumper):
|
|
915
1229
|
def represent_message_list(self, messages):
|
916
1230
|
return self.represent_list([value for value in messages])
|
917
1231
|
|
918
|
-
def
|
919
|
-
if
|
920
|
-
return self.
|
921
|
-
if
|
922
|
-
return self.
|
923
|
-
if
|
924
|
-
return self.
|
925
|
-
|
1232
|
+
def represent_message_field(self, field):
|
1233
|
+
if isinstance(field._value, str):
|
1234
|
+
return self.represent_str(field._value)
|
1235
|
+
if isinstance(field._value, bytes):
|
1236
|
+
return self.represent_binary(field._value)
|
1237
|
+
if field._value is None:
|
1238
|
+
return self.represent_none()
|
1239
|
+
if isinstance(field._value, int):
|
1240
|
+
return self.represent_int(field._value)
|
1241
|
+
if isinstance(field._value, float):
|
1242
|
+
if field._value.is_integer():
|
1243
|
+
return self.represent_int(int(field._value))
|
1244
|
+
return self.represent_float(field._value)
|
1245
|
+
if isinstance(field._value, bool):
|
1246
|
+
return self.represent_bool(field._value)
|
1247
|
+
if field._value is _Unknown:
|
1248
|
+
return self.represent_str('<<UNKNOWN>>')
|
1249
|
+
return self.represent_str('<<UNEXPECTED>>')
|
1250
|
+
|
1251
|
+
def represent_value(self, value):
|
1252
|
+
match value._kind:
|
1253
|
+
case 'struct_value' | 'Struct':
|
1254
|
+
return self.represent_dict({k:v for k,v in value})
|
1255
|
+
case 'list_value' | 'ListValue':
|
1256
|
+
return self.represent_list([v for v in value])
|
1257
|
+
case 'string_value':
|
1258
|
+
return self.represent_str(value._value.string_value)
|
1259
|
+
case 'null_value':
|
1260
|
+
return self.represent_none(None)
|
1261
|
+
case 'number_value':
|
1262
|
+
value = value._value.number_value
|
1263
|
+
if value.is_integer():
|
1264
|
+
return self.represent_int(int(value))
|
1265
|
+
return self.represent_float(value)
|
1266
|
+
case 'bool_value':
|
1267
|
+
return self.represent_bool(value._value.bool_value)
|
1268
|
+
case 'Unknown':
|
1269
|
+
return self.represent_str('<<UNKNOWN>>')
|
1270
|
+
case _:
|
1271
|
+
return self.represent_str('<<UNEXPECTED>>')
|
926
1272
|
|
927
1273
|
_Dumper.add_representer(str, _Dumper.represent_str)
|
928
1274
|
_Dumper.add_representer(Message, _Dumper.represent_message_dict)
|
929
1275
|
_Dumper.add_representer(MapMessage, _Dumper.represent_message_dict)
|
930
1276
|
_Dumper.add_representer(RepeatedMessage, _Dumper.represent_message_list)
|
931
|
-
_Dumper.add_representer(
|
1277
|
+
_Dumper.add_representer(FieldMessage, _Dumper.represent_message_field)
|
1278
|
+
_Dumper.add_representer(Value, _Dumper.represent_value)
|