crossplane-function-pythonic 0.0.11__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 +16 -13
- crossplane/pythonic/function.py +121 -38
- crossplane/pythonic/protobuf.py +647 -324
- {crossplane_function_pythonic-0.0.11.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/METADATA +23 -1
- crossplane_function_pythonic-0.1.0.dist-info/RECORD +11 -0
- crossplane_function_pythonic-0.0.11.dist-info/RECORD +0 -11
- {crossplane_function_pythonic-0.0.11.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/WHEEL +0 -0
- {crossplane_function_pythonic-0.0.11.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/entry_points.txt +0 -0
- {crossplane_function_pythonic-0.0.11.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,11 +75,11 @@ 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
84
|
if field.label == field.LABEL_REPEATED:
|
87
85
|
if field.type == field.TYPE_MESSAGE and field.message_type.GetOptions().map_entry:
|
@@ -89,17 +87,17 @@ class Message:
|
|
89
87
|
else:
|
90
88
|
value = RepeatedMessage(self, key, field, value, self._readOnly)
|
91
89
|
elif field.type == field.TYPE_MESSAGE:
|
92
|
-
if field.message_type.name
|
93
|
-
value =
|
94
|
-
elif field.message_type.name == 'ListValue':
|
95
|
-
value = Values(self, key, value, Values.Type.LIST, self._readOnly)
|
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
|
@@ -156,17 +154,17 @@ class Message:
|
|
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,13 +204,13 @@ 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
|
207
|
+
if self._message is not _Unknown:
|
205
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, field, messages, readOnly=False):
|
213
|
+
def __init__(self, parent, key, field, messages=_Unknown, readOnly=False):
|
211
214
|
self.__dict__['_parent'] = parent
|
212
215
|
self.__dict__['_key'] = key
|
213
216
|
self.__dict__['_field'] = field
|
@@ -221,35 +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)
|
234
|
+
if self._field.message_type.name in ('Struct', 'ListValue'):
|
235
|
+
value = Value(self, key, value, self._readOnly)
|
235
236
|
else:
|
236
237
|
value = Message(self, key, self._field.message_type, value, self._readOnly)
|
237
|
-
|
238
|
-
value = value
|
238
|
+
else:
|
239
|
+
value = FieldMessage(self, key, self._field.type, value)
|
239
240
|
self._cache[key] = value
|
240
241
|
return value
|
241
242
|
|
242
243
|
def __bool__(self):
|
243
|
-
return self._messages
|
244
|
+
return self._messages is not _Unknown
|
244
245
|
|
245
246
|
def __len__(self):
|
246
|
-
return 0 if self._messages is
|
247
|
+
return 0 if self._messages is _Unknown else len(self._messages)
|
247
248
|
|
248
249
|
def __contains__(self, key):
|
249
|
-
return self._messages is not
|
250
|
+
return self._messages is not _Unknown and key in self._messages
|
250
251
|
|
251
252
|
def __iter__(self):
|
252
|
-
if self._messages is not
|
253
|
+
if self._messages is not _Unknown:
|
253
254
|
for key in sorted(self._messages):
|
254
255
|
yield key, self[key]
|
255
256
|
|
@@ -266,9 +267,9 @@ class MapMessage:
|
|
266
267
|
if self._field.type == self._field.TYPE_MESSAGE:
|
267
268
|
if self._field.message_type.full_name != other._field.message_type.full_name:
|
268
269
|
return False
|
269
|
-
if self._messages is
|
270
|
-
return other._messages is
|
271
|
-
elif other._messages is
|
270
|
+
if self._messages is _Unknown:
|
271
|
+
return other._messages is _Unknown
|
272
|
+
elif other._messages is _Unknown:
|
272
273
|
return False
|
273
274
|
if len(self) != len(other):
|
274
275
|
return False
|
@@ -301,17 +302,17 @@ class MapMessage:
|
|
301
302
|
return str(key)
|
302
303
|
return ''
|
303
304
|
|
304
|
-
def _create_child(self, key
|
305
|
+
def _create_child(self, key):
|
305
306
|
if self._readOnly:
|
306
307
|
raise ValueError(f"{self._readOnly} is read only")
|
307
|
-
if self._messages is
|
308
|
+
if self._messages is _Unknown:
|
308
309
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
309
310
|
return self._messages[key]
|
310
311
|
|
311
312
|
def __call__(self, **kwargs):
|
312
313
|
if self._readOnly:
|
313
314
|
raise ValueError(f"{self._readOnly} is read only")
|
314
|
-
if self._messages is
|
315
|
+
if self._messages is _Unknown:
|
315
316
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
316
317
|
self._messages.clear()
|
317
318
|
self._cache.clear()
|
@@ -325,10 +326,16 @@ class MapMessage:
|
|
325
326
|
def __setitem__(self, key, message):
|
326
327
|
if self._readOnly:
|
327
328
|
raise ValueError(f"{self._readOnly} is read only")
|
328
|
-
if self._messages is
|
329
|
+
if self._messages is _Unknown:
|
329
330
|
self._messages = self._parent._create_child(self._key)
|
330
331
|
if isinstance(message, Message):
|
331
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
|
332
339
|
if self._field.type == self._field.TYPE_BYTES and isinstance(message, str):
|
333
340
|
message = message.encode('utf-8')
|
334
341
|
self._messages[key] = message
|
@@ -340,14 +347,14 @@ class MapMessage:
|
|
340
347
|
def __delitem__(self, key):
|
341
348
|
if self._readOnly:
|
342
349
|
raise ValueError(f"{self._readOnly} is read only")
|
343
|
-
if self._messages is not
|
350
|
+
if self._messages is not _Unknown:
|
344
351
|
if key in self._messages:
|
345
352
|
del self._messages[key]
|
346
353
|
self._cache.pop(key, None)
|
347
354
|
|
348
355
|
|
349
356
|
class RepeatedMessage:
|
350
|
-
def __init__(self, parent, key, field, messages, readOnly=False):
|
357
|
+
def __init__(self, parent, key, field, messages=_Unknown, readOnly=False):
|
351
358
|
self._parent = parent
|
352
359
|
self._key = key
|
353
360
|
self._field = field
|
@@ -358,44 +365,42 @@ class RepeatedMessage:
|
|
358
365
|
def __getitem__(self, key):
|
359
366
|
if key in self._cache:
|
360
367
|
return self._cache[key]
|
361
|
-
if self._messages is
|
362
|
-
value =
|
368
|
+
if self._messages is _Unknown or key >= len(self._messages):
|
369
|
+
value = _Unknown
|
363
370
|
else:
|
364
371
|
value = self._messages[key]
|
365
372
|
if value is None and self._field.has_default_value:
|
366
373
|
value = self._field.default_value
|
367
374
|
if self._field.type == self._field.TYPE_MESSAGE:
|
368
|
-
if self._field.message_type.name
|
369
|
-
value =
|
370
|
-
elif self._field.message_type.name == 'ListValue':
|
371
|
-
value = Values(self, key, value, Values.Type.LIST, self._readOnly)
|
375
|
+
if self._field.message_type.name in ('Struct', 'ListValue'):
|
376
|
+
value = Value(self, key, value, self._readOnly)
|
372
377
|
else:
|
373
378
|
value = Message(self, key, self._field.message_type, value, self._readOnly)
|
374
|
-
|
375
|
-
value = value
|
379
|
+
else:
|
380
|
+
value = FieldMessage(self, key, self._field.type, value)
|
376
381
|
self._cache[key] = value
|
377
382
|
return value
|
378
383
|
|
379
384
|
def __bool__(self):
|
380
|
-
return self._messages
|
385
|
+
return self._messages is not _Unknown
|
381
386
|
|
382
387
|
def __len__(self):
|
383
|
-
return 0 if self._messages is
|
388
|
+
return 0 if self._messages is _Unknown else len(self._messages)
|
384
389
|
|
385
390
|
def __contains__(self, value):
|
386
|
-
if self._messages is not
|
391
|
+
if self._messages is not _Unknown:
|
387
392
|
for message in self:
|
388
393
|
if value == message:
|
389
394
|
return True
|
390
395
|
return False
|
391
396
|
|
392
397
|
def __iter__(self):
|
393
|
-
if self._messages is not
|
398
|
+
if self._messages is not _Unknown:
|
394
399
|
for ix in range(len(self._messages)):
|
395
400
|
yield self[ix]
|
396
401
|
|
397
402
|
def __hash__(self):
|
398
|
-
if self._messages is not
|
403
|
+
if self._messages is not _Unknown:
|
399
404
|
return hash(tuple(hash(item) for item in self))
|
400
405
|
return 0
|
401
406
|
|
@@ -407,9 +412,9 @@ class RepeatedMessage:
|
|
407
412
|
if self._field.type == self._field.TYPE_MESSAGE:
|
408
413
|
if self._field.message_type.full_name != other._field.message_type.full_name:
|
409
414
|
return False
|
410
|
-
if self._messages is
|
411
|
-
return other._messages is
|
412
|
-
elif other._messages is
|
415
|
+
if self._messages is _Unknown:
|
416
|
+
return other._messages is _Unknown
|
417
|
+
elif other._messages is _Unknown:
|
413
418
|
return False
|
414
419
|
if len(self) != len(other):
|
415
420
|
return False
|
@@ -437,10 +442,10 @@ class RepeatedMessage:
|
|
437
442
|
return str(key)
|
438
443
|
return ''
|
439
444
|
|
440
|
-
def _create_child(self, key
|
445
|
+
def _create_child(self, key):
|
441
446
|
if self._readOnly:
|
442
447
|
raise ValueError(f"{self._readOnly} is read only")
|
443
|
-
if self._messages is
|
448
|
+
if self._messages is _Unknown:
|
444
449
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
445
450
|
while key >= len(self._messages):
|
446
451
|
self._messages.add()
|
@@ -449,7 +454,7 @@ class RepeatedMessage:
|
|
449
454
|
def __call__(self, *args):
|
450
455
|
if self._readOnly:
|
451
456
|
raise ValueError(f"{self._readOnly} is read only")
|
452
|
-
if self._messages is
|
457
|
+
if self._messages is _Unknown:
|
453
458
|
self.__dict__['_messages'] = self._parent._create_child(self._key)
|
454
459
|
self._messages.clear()
|
455
460
|
self._cache.clear()
|
@@ -460,12 +465,18 @@ class RepeatedMessage:
|
|
460
465
|
def __setitem__(self, key, message):
|
461
466
|
if self._readOnly:
|
462
467
|
raise ValueError(f"{self._readOnly} is read only")
|
463
|
-
if self._messages is
|
468
|
+
if self._messages is _Unknown:
|
464
469
|
self._messages = self._parent._create_child(self._key)
|
465
470
|
if key < 0:
|
466
471
|
key = len(self._messages) + key
|
467
472
|
if isinstance(message, Message):
|
468
473
|
message = message._message
|
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
|
469
480
|
if self._field.type == self._field.TYPE_BYTES and isinstance(message, str):
|
470
481
|
message = message.encode('utf-8')
|
471
482
|
if key >= len(self._messages):
|
@@ -477,42 +488,112 @@ class RepeatedMessage:
|
|
477
488
|
def __delitem__(self, key):
|
478
489
|
if self._readOnly:
|
479
490
|
raise ValueError(f"{self._readOnly} is read only")
|
480
|
-
if self._messages is not
|
491
|
+
if self._messages is not _Unknown:
|
481
492
|
del self._messages[key]
|
482
493
|
self._cache.pop(key, None)
|
483
494
|
|
484
|
-
def append(self, message=
|
495
|
+
def append(self, message=_Unknown):
|
485
496
|
if self._readOnly:
|
486
497
|
raise ValueError(f"{self._readOnly} is read only")
|
487
|
-
if self._messages is
|
498
|
+
if self._messages is _Unknown:
|
488
499
|
self._messages = self._parent._create_child(self._key)
|
489
|
-
if message is
|
500
|
+
if message is _Unknown:
|
490
501
|
message = self._messages.add()
|
491
502
|
else:
|
492
503
|
message = self._messages.append(message)
|
493
504
|
return self[len(self._messages) - 1]
|
494
505
|
|
495
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
|
+
|
496
560
|
class ProtobufValue:
|
497
561
|
@property
|
498
562
|
def _protobuf_value(self):
|
499
563
|
return None
|
500
564
|
|
501
565
|
|
502
|
-
class
|
503
|
-
|
504
|
-
UNKNOWN = 0
|
505
|
-
MAP = 1
|
506
|
-
LIST = 2
|
507
|
-
|
508
|
-
def __init__(self, parent, key, values, type, readOnly=None):
|
566
|
+
class Value:
|
567
|
+
def __init__(self, parent, key, value=_Unknown, readOnly=None):
|
509
568
|
self.__dict__['_parent'] = parent
|
510
569
|
self.__dict__['_key'] = key
|
511
|
-
self.__dict__['
|
512
|
-
self.__dict__['_type'] = type
|
513
|
-
self.__dict__['_readOnly'] = readOnly
|
570
|
+
self.__dict__['_dependencies'] = {}
|
514
571
|
self.__dict__['_unknowns'] = {}
|
515
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
|
516
597
|
|
517
598
|
def __getattr__(self, key):
|
518
599
|
return self[key]
|
@@ -523,115 +604,201 @@ class Values:
|
|
523
604
|
if key in self._unknowns:
|
524
605
|
return self._unknowns[key]
|
525
606
|
if isinstance(key, str):
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
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}")
|
534
616
|
elif isinstance(key, int):
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
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}")
|
547
632
|
else:
|
548
|
-
|
549
|
-
|
550
|
-
value = Values(self, key, None, self.Type.UNKNOWN, self._readOnly)
|
551
|
-
elif kind == 'struct_value':
|
552
|
-
value = Values(self, key, struct_value.struct_value, self.Type.MAP, self._readOnly)
|
553
|
-
elif kind == 'list_value':
|
554
|
-
value = Values(self, key, struct_value.list_value, self.Type.LIST, self._readOnly)
|
555
|
-
elif kind == 'string_value':
|
556
|
-
value = struct_value.string_value
|
557
|
-
elif kind == 'number_value':
|
558
|
-
value = struct_value.number_value
|
559
|
-
if value.is_integer():
|
560
|
-
value = int(value)
|
561
|
-
elif kind == 'bool_value':
|
562
|
-
value = struct_value.bool_value
|
563
|
-
elif kind == 'null_value':
|
564
|
-
value = None
|
565
|
-
else:
|
566
|
-
raise ValueError(f"Unexpected value kind: {kind}")
|
633
|
+
raise ValueError(f"Unexpected key type: {key.__class__}")
|
634
|
+
value = Value(self, key, value, self._readOnly)
|
567
635
|
self._cache[key] = value
|
568
636
|
return value
|
569
637
|
|
570
638
|
def __bool__(self):
|
571
|
-
return self.
|
639
|
+
return not self._isUnknown
|
572
640
|
|
573
641
|
def __len__(self):
|
574
|
-
|
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
|
575
652
|
|
576
653
|
def __contains__(self, item):
|
577
|
-
|
578
|
-
|
579
|
-
return item in self.
|
580
|
-
|
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':
|
581
660
|
for value in self:
|
582
661
|
if item == value:
|
583
662
|
return True
|
584
663
|
return False
|
585
664
|
|
586
665
|
def __iter__(self):
|
587
|
-
|
588
|
-
|
589
|
-
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())):
|
669
|
+
yield key, self[key]
|
670
|
+
case 'Struct':
|
671
|
+
for key in sorted(set(self._value.fields) | set(self._unknowns.keys())):
|
590
672
|
yield key, self[key]
|
591
|
-
|
592
|
-
for ix in range(len(self.
|
673
|
+
case 'list_value':
|
674
|
+
for ix in range(len(self._value.list_value.values)):
|
675
|
+
yield self[ix]
|
676
|
+
for ix in sorted(self._unknowns.keys()):
|
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)):
|
593
681
|
yield self[ix]
|
594
682
|
for ix in sorted(self._unknowns.keys()):
|
595
|
-
if ix >= len(self.
|
683
|
+
if ix >= len(self._value.values):
|
596
684
|
yield self[ix]
|
597
685
|
|
598
686
|
def __hash__(self):
|
599
|
-
|
600
|
-
|
687
|
+
match self._kind:
|
688
|
+
case 'struct_value' | 'Struct':
|
601
689
|
return hash(tuple(hash(item) for item in sorted(iter(self), key=lambda item: item[0])))
|
602
|
-
|
690
|
+
case 'list_value' | 'ListValue':
|
603
691
|
return hash(tuple(hash(item) for item in self))
|
604
|
-
|
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
|
605
701
|
|
606
702
|
def __eq__(self, other):
|
607
|
-
|
608
|
-
|
609
|
-
if self._type != other._type:
|
610
|
-
return False
|
611
|
-
if self._values is None:
|
612
|
-
return other._values is None
|
613
|
-
elif other._values is None:
|
703
|
+
kind = self._kind
|
704
|
+
if isinstance(other, Value) and other._kind != kind:
|
614
705
|
return False
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
for key, value in self:
|
619
|
-
if key not in other:
|
706
|
+
match kind:
|
707
|
+
case 'struct_value' | 'Struct':
|
708
|
+
if not isinstance(other, (Value, dict)):
|
620
709
|
return False
|
621
|
-
if
|
710
|
+
if len(self) != len(other):
|
622
711
|
return False
|
623
|
-
|
624
|
-
|
625
|
-
|
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)):
|
626
720
|
return False
|
627
|
-
|
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
|
628
754
|
|
629
755
|
def __str__(self):
|
630
|
-
return format(self)
|
756
|
+
return format(self, '')
|
631
757
|
|
632
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'
|
633
774
|
return _formatObject(self, spec)
|
634
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
|
+
|
635
802
|
def _fullName(self, key=None):
|
636
803
|
if self._key is not None:
|
637
804
|
if self._parent is not None:
|
@@ -659,51 +826,12 @@ class Values:
|
|
659
826
|
return str(key)
|
660
827
|
return ''
|
661
828
|
|
662
|
-
def _create_child(self, key, type):
|
663
|
-
if self._readOnly:
|
664
|
-
raise ValueError(f"{self._readOnly} is read only")
|
665
|
-
if isinstance(key, str):
|
666
|
-
if not self._isMap:
|
667
|
-
if not self._isUnknown:
|
668
|
-
raise ValueError('Invalid key, must be a str for maps')
|
669
|
-
self.__dict__['_type'] = self.Type.MAP
|
670
|
-
if self._values is None:
|
671
|
-
if self._parent is None:
|
672
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.Struct()
|
673
|
-
else:
|
674
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
675
|
-
struct_value = self._values.fields[key]
|
676
|
-
elif isinstance(key, int):
|
677
|
-
if not self._isList:
|
678
|
-
if not self._isUnknown:
|
679
|
-
raise ValueError('Invalid key, must be an int for lists')
|
680
|
-
self.__dict__['_type'] = self.Type.LIST
|
681
|
-
if self._values is None:
|
682
|
-
if self._parent is None:
|
683
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.ListValue()
|
684
|
-
else:
|
685
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
686
|
-
while key >= len(self._values.values):
|
687
|
-
self._values.values.add()
|
688
|
-
struct_value = self._values.values[key]
|
689
|
-
else:
|
690
|
-
raise ValueError('Unexpected key type')
|
691
|
-
if type == self.Type.MAP:
|
692
|
-
if not struct_value.HasField('struct_value'):
|
693
|
-
struct_value.struct_value.Clear()
|
694
|
-
return struct_value.struct_value
|
695
|
-
if type == self.Type.LIST:
|
696
|
-
if not struct_value.HasField('list_value'):
|
697
|
-
struct_value.list_value.Clear()
|
698
|
-
return struct_value.list_value
|
699
|
-
raise ValueError(f"Unexpected type: {type}")
|
700
|
-
|
701
829
|
def __call__(self, *args, **kwargs):
|
702
830
|
if self._readOnly:
|
703
831
|
raise ValueError(f"{self._readOnly} is read only")
|
704
|
-
self.__dict__['
|
705
|
-
self.__dict__['_type'] = self.Type.UNKNOWN
|
832
|
+
self.__dict__['_value'] = google.protobuf.struct_pb2.Value()
|
706
833
|
self._cache.clear()
|
834
|
+
self._dependencies.clear()
|
707
835
|
self._unknowns.clear()
|
708
836
|
if len(kwargs):
|
709
837
|
if len(args):
|
@@ -722,27 +850,15 @@ class Values:
|
|
722
850
|
if self._readOnly:
|
723
851
|
raise ValueError(f"{self._readOnly} is read only")
|
724
852
|
if isinstance(key, str):
|
725
|
-
if
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
if self._values is None:
|
730
|
-
if self._parent is None:
|
731
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.Struct()
|
732
|
-
else:
|
733
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
734
|
-
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
|
735
857
|
elif isinstance(key, int):
|
736
|
-
if
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
if self._values is None:
|
741
|
-
if self._parent is None:
|
742
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.ListValue()
|
743
|
-
else:
|
744
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
745
|
-
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
|
746
862
|
if key == append:
|
747
863
|
key = len(values)
|
748
864
|
elif key < 0:
|
@@ -752,6 +868,7 @@ class Values:
|
|
752
868
|
else:
|
753
869
|
raise ValueError('Unexpected key type')
|
754
870
|
self._cache.pop(key, None)
|
871
|
+
self._dependencies.pop(key, None)
|
755
872
|
self._unknowns.pop(key, None)
|
756
873
|
if isinstance(value, ProtobufValue):
|
757
874
|
value = value._protobuf_value
|
@@ -771,79 +888,217 @@ class Values:
|
|
771
888
|
values[key].list_value.Clear()
|
772
889
|
for ix, v in enumerate(value):
|
773
890
|
self[key][ix] = v
|
774
|
-
elif isinstance(value,
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
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)
|
783
905
|
else:
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
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}")
|
795
930
|
else:
|
796
931
|
raise ValueError(f"Unexpected type: {value.__class__}")
|
797
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
|
+
|
798
978
|
def __delattr__(self, key):
|
799
979
|
del self[key]
|
800
980
|
|
801
981
|
def __delitem__(self, key):
|
802
982
|
if self._readOnly:
|
803
983
|
raise ValueError(f"{self._readOnly} is read only")
|
984
|
+
kind = self._kind
|
985
|
+
if kind == 'Unknown':
|
986
|
+
return
|
804
987
|
if isinstance(key, str):
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
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)
|
814
1000
|
elif isinstance(key, int):
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
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]
|
833
1027
|
else:
|
834
1028
|
raise ValueError('Unexpected key type')
|
835
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
|
+
|
836
1091
|
@property
|
837
1092
|
def _isUnknown(self):
|
838
|
-
return self.
|
1093
|
+
return self._kind == 'Unknown'
|
839
1094
|
|
840
1095
|
@property
|
841
1096
|
def _isMap(self):
|
842
|
-
return self.
|
1097
|
+
return self._kind in ('struct_value', 'Struct')
|
843
1098
|
|
844
1099
|
@property
|
845
1100
|
def _isList(self):
|
846
|
-
return self.
|
1101
|
+
return self._kind in ('list_value', 'ListValue')
|
847
1102
|
|
848
1103
|
@property
|
849
1104
|
def _getUnknowns(self):
|
@@ -852,57 +1107,77 @@ class Values:
|
|
852
1107
|
unknowns[self._fullName(key)] = unknown._fullName()
|
853
1108
|
if self._isMap:
|
854
1109
|
for key, value in self:
|
855
|
-
if isinstance(value,
|
1110
|
+
if isinstance(value, Value):
|
856
1111
|
unknowns.update(value._getUnknowns)
|
857
1112
|
elif self._isList:
|
858
1113
|
for value in self:
|
859
|
-
if isinstance(value,
|
1114
|
+
if isinstance(value, Value):
|
860
1115
|
unknowns.update(value._getUnknowns)
|
861
1116
|
return unknowns
|
862
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
|
+
|
863
1135
|
def _patchUnknowns(self, patches):
|
864
1136
|
for key in list(self._unknowns.keys()):
|
865
1137
|
self[key] = patches[key]
|
866
1138
|
if self._isMap:
|
867
1139
|
for key, value in self:
|
868
|
-
if isinstance(value,
|
1140
|
+
if isinstance(value, Value) and len(value):
|
869
1141
|
patch = patches[key]
|
870
|
-
if isinstance(patch,
|
1142
|
+
if isinstance(patch, Value) and patch._type == value._type and len(patch):
|
871
1143
|
value._patchUnknowns(patch)
|
872
1144
|
elif self._isList:
|
873
1145
|
for ix, value in enumerate(self):
|
874
|
-
if isinstance(value,
|
1146
|
+
if isinstance(value, Value) and len(value):
|
875
1147
|
patch = patches[ix]
|
876
|
-
if isinstance(patch,
|
1148
|
+
if isinstance(patch, Value) and patch._type == value._type and len(patch):
|
877
1149
|
value._patchUnknowns(patch)
|
878
1150
|
|
879
1151
|
def _renderUnknowns(self, trimFullName):
|
880
1152
|
for key, unknown in list(self._unknowns.items()):
|
881
1153
|
self[key] = f"UNKNOWN:{trimFullName(unknown._fullName())}"
|
1154
|
+
self._dependencies[key] = unknown
|
882
1155
|
if self._isMap:
|
883
1156
|
for key, value in self:
|
884
|
-
if isinstance(value,
|
1157
|
+
if isinstance(value, Value) and len(value):
|
885
1158
|
value._renderUnknowns(trimFullName)
|
886
1159
|
elif self._isList:
|
887
1160
|
for ix, value in enumerate(self):
|
888
|
-
if isinstance(value,
|
1161
|
+
if isinstance(value, Value) and len(value):
|
889
1162
|
value._renderUnknowns(trimFullName)
|
890
1163
|
|
891
1164
|
|
892
|
-
def _formatObject(object, spec):
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
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)
|
906
1181
|
|
907
1182
|
|
908
1183
|
class _JSONEncoder(json.JSONEncoder):
|
@@ -915,14 +1190,29 @@ class _JSONEncoder(json.JSONEncoder):
|
|
915
1190
|
if object:
|
916
1191
|
return [value for value in object]
|
917
1192
|
return None
|
918
|
-
if isinstance(object,
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
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>>'
|
926
1216
|
if isinstance(object, datetime.datetime):
|
927
1217
|
return object.isoformat()
|
928
1218
|
return super(_JSONEncoder, self).default(object)
|
@@ -939,17 +1229,50 @@ class _Dumper(yaml.SafeDumper):
|
|
939
1229
|
def represent_message_list(self, messages):
|
940
1230
|
return self.represent_list([value for value in messages])
|
941
1231
|
|
942
|
-
def
|
943
|
-
if
|
944
|
-
return self.
|
945
|
-
if
|
946
|
-
return self.
|
947
|
-
if
|
948
|
-
return self.
|
949
|
-
|
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>>')
|
950
1272
|
|
951
1273
|
_Dumper.add_representer(str, _Dumper.represent_str)
|
952
1274
|
_Dumper.add_representer(Message, _Dumper.represent_message_dict)
|
953
1275
|
_Dumper.add_representer(MapMessage, _Dumper.represent_message_dict)
|
954
1276
|
_Dumper.add_representer(RepeatedMessage, _Dumper.represent_message_list)
|
955
|
-
_Dumper.add_representer(
|
1277
|
+
_Dumper.add_representer(FieldMessage, _Dumper.represent_message_field)
|
1278
|
+
_Dumper.add_representer(Value, _Dumper.represent_value)
|