crossplane-function-pythonic 0.0.11__py3-none-any.whl → 0.1.1__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.
@@ -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
- map = Values(None, None, None, Values.Type.MAP)
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
- list = Values(None, None, None, Values.Type.LIST)
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 Values(None, None, None, Values.Type.UNKNOWN)
36
+ return Value(None, None)
41
37
 
42
38
  def Yaml(string, readOnly=None):
43
- return _Object(yaml.safe_load(string), readOnly)
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
- return _Object(json.loads(string), readOnly)
47
-
48
- def _Object(object, readOnly=None):
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 = getattr(self._message, key)
78
+ if self._message is _Unknown:
79
+ value = _Unknown
82
80
  else:
83
- value = None
84
- if value is None and field.has_default_value:
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 == 'Struct':
93
- value = Values(self, key, value, Values.Type.MAP, self._readOnly)
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 != None
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 None:
125
- return other._message is None
126
- elif other._message is None:
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, type=None):
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 None:
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 None:
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
- if self._message is None:
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, Values):
192
- value = value._values
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 None:
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 None or key not in self._messages:
225
- value = None
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 == 'Struct':
232
- value = Values(self, key, value, Values.Type.MAP, self._readOnly)
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
- elif self._field.type == self._field.TYPE_BYTES and isinstance(value, bytes):
238
- value = value.decode('utf-8')
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 != None
244
+ return self._messages is not _Unknown
244
245
 
245
246
  def __len__(self):
246
- return 0 if self._messages is None else len(self._messages)
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 None and key in self._messages
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 None:
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 None:
270
- return other._messages is None
271
- elif other._messages is None:
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, type=None):
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 None:
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 None:
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 None:
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 None:
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 None or key >= len(self._messages):
362
- value = None
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 == 'Struct':
369
- value = Values(self, key, value, Values.Type.MAP, self._readOnly)
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
- elif self._field.type == self._field.TYPE_BYTES and isinstance(value, bytes):
375
- value = value.decode('utf-8')
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 != None
385
+ return self._messages is not _Unknown
381
386
 
382
387
  def __len__(self):
383
- return 0 if self._messages is None else len(self._messages)
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 None:
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 None:
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 None:
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 None:
411
- return other._messages is None
412
- elif other._messages is None:
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, type=None):
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 None:
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 None:
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 None:
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 None:
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=None):
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 None:
498
+ if self._messages is _Unknown:
488
499
  self._messages = self._parent._create_child(self._key)
489
- if message is None:
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 Values:
503
- class Type:
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__['_values'] = values
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
- if not self._isMap:
527
- if not self._isUnknown:
528
- raise ValueError(f"Invalid key, must be a int for lists: {key}")
529
- self.__dict__['_type'] = self.Type.MAP
530
- if self._values is None or key not in self._values:
531
- struct_value = None
532
- else:
533
- struct_value = self._values.fields[key]
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
- if not self._isList:
536
- if not self._isUnknown:
537
- raise ValueError(f"Invalid key, must be a str for maps: {key}")
538
- self.__dict__['_type'] = self.Type.LIST
539
- if self._values is None or key >= len(self._values):
540
- struct_value = None
541
- else:
542
- struct_value = self._values.values[key]
543
- else:
544
- raise ValueError('Unexpected key type')
545
- if struct_value is None:
546
- value = Values(self, key, None, self.Type.UNKNOWN, self._readOnly)
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
- kind = struct_value.WhichOneof('kind')
549
- if kind is None:
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._values != None
639
+ return not self._isUnknown
572
640
 
573
641
  def __len__(self):
574
- return 0 if self._values is None else len(self._values) + len(self._unknowns)
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
- if self._values is not None:
578
- if self._isMap:
579
- return item in self._values or item in self._unknowns
580
- if self._isList:
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
- if self._values is not None:
588
- if self._isMap:
589
- for key in sorted(set(self._values) | set(self._unknowns.keys())):
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
- elif self._isList:
592
- for ix in range(len(self._values)):
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._values):
683
+ if ix >= len(self._value.values):
596
684
  yield self[ix]
597
685
 
598
686
  def __hash__(self):
599
- if self._values is not None:
600
- if self._isMap:
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
- if self._isList:
690
+ case 'list_value' | 'ListValue':
603
691
  return hash(tuple(hash(item) for item in self))
604
- return self._type
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
- if not isinstance(other, Values):
608
- return False
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
- if len(self) != len(other):
616
- return False
617
- if self._isMap:
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 value != other[key]:
710
+ if len(self) != len(other):
622
711
  return False
623
- if self._isList:
624
- for ix, value in enumerate(self):
625
- if value != other[ix]:
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
- return True
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__['_values'] = None
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 not self._isMap:
726
- if not self._isUnknown:
727
- raise ValueError('Invalid key, must be a str for maps')
728
- self.__dict__['_type'] = self.Type.MAP
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 not self._isList:
737
- if not self._isUnknown:
738
- raise ValueError('Invalid key, must be an int for lists')
739
- self.__dict__['_type'] = self.Type.LIST
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, Values):
775
- if value._isMap:
776
- values[key].struct_value.Clear()
777
- for k, v in value:
778
- self[key][k] = v
779
- elif value._isList:
780
- values[key].list_value.Clear()
781
- for ix, v in enumerate(value):
782
- self[key][ix] = v
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
- self._unknowns[key] = value
785
- if self._isMap:
786
- if key in values:
787
- del values[key]
788
- elif self._isList:
789
- if key < len(values):
790
- values[key].Clear()
791
- for ix in reversed(range(len(values))):
792
- if ix not in self._unknowns:
793
- break
794
- del values[ix]
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
- if not self._isMap:
806
- if not self._isUnknown:
807
- raise ValueError('Invalid key, must be a str for maps')
808
- self.__dict__['_type'] = self.Type.MAP
809
- if self._values is not None:
810
- if key in self._values:
811
- del self._values[key]
812
- self._cache.pop(key, None)
813
- self._unknowns.pop(key, None)
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
- if not self._isList:
816
- if not self._isUnknown:
817
- raise ValueError('Invalid key, must be an int for lists')
818
- self.__dict__['_type'] = self.Type.LIST
819
- if self._values is not None:
820
- if key < len(self._values):
821
- del self._values[key]
822
- self._cache.pop(key, None)
823
- self._unknowns.pop(key, None)
824
- for ix in sorted(self._unknowns.keys()):
825
- if ix > key:
826
- self._cache.pop(ix, None)
827
- self._unknowns[ix - 1] = self._unknowns[ix]
828
- del self._unknowns[ix]
829
- for ix in reversed(range(len(self._values))):
830
- if ix not in self._unknowns:
831
- break
832
- del self._values[ix]
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._type == self.Type.UNKNOWN
1093
+ return self._kind == 'Unknown'
839
1094
 
840
1095
  @property
841
1096
  def _isMap(self):
842
- return self._type == self.Type.MAP
1097
+ return self._kind in ('struct_value', 'Struct')
843
1098
 
844
1099
  @property
845
1100
  def _isList(self):
846
- return self._type == self.Type.LIST
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, Values):
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, Values):
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, Values) and len(value):
1140
+ if isinstance(value, Value) and len(value):
869
1141
  patch = patches[key]
870
- if isinstance(patch, Values) and patch._type == value._type and len(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, Values) and len(value):
1146
+ if isinstance(value, Value) and len(value):
875
1147
  patch = patches[ix]
876
- if isinstance(patch, Values) and patch._type == value._type and len(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, Values) and len(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, Values) and len(value):
1161
+ if isinstance(value, Value) and len(value):
889
1162
  value._renderUnknowns(trimFullName)
890
1163
 
891
1164
 
892
- def _formatObject(object, spec):
893
- if spec == 'json':
894
- return json.dumps(object, indent=2, cls=_JSONEncoder)
895
- if spec == 'jsonc':
896
- return json.dumps(object, separators=(',', ':'), cls=_JSONEncoder)
897
- if spec == 'protobuf':
898
- if isinstance(object, Message):
899
- return str(object._message)
900
- if isinstance(object, (MapMessage, RepeatedMessage)):
901
- return str(object._messages)
902
- if isinstance(object, Values):
903
- return str(object._values)
904
- return format(object)
905
- return yaml.dump(object, Dumper=_Dumper)
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, Values):
919
- if object._isMap:
920
- return {key: value for key, value in object}
921
- if object._isList:
922
- return [value for value in object]
923
- if object._isUnknown:
924
- return '<<UNKNOWN>>'
925
- return '<<UNEXPECTED>>'
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 represent_values(self, values):
943
- if values._isMap:
944
- return self.represent_dict({key: value for key, value in values})
945
- if values._isList:
946
- return self.represent_list([value for value in values])
947
- if values._isUnknown:
948
- return self.represent_scalar('tag:yaml.org,2002:str', '<<UNKNOWN>>')
949
- return self.represent_scalar('tag:yaml.org,2002:str', '<<UNEXPECTED>>')
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(Values, _Dumper.represent_values)
1277
+ _Dumper.add_representer(FieldMessage, _Dumper.represent_message_field)
1278
+ _Dumper.add_representer(Value, _Dumper.represent_value)