@@ -58,17 +58,21 @@ def B64Decode(string):
5858
5959class Message :
6060 def __init__ (self , parent , key , descriptor , message = _Unknown , readOnly = False ):
61- self .__dict__ ['_parent' ] = parent
62- self .__dict__ ['_key' ] = key
63- self .__dict__ ['_descriptor' ] = descriptor
64- self .__dict__ ['_message' ] = message
65- self .__dict__ ['_readOnly' ] = readOnly
66- self .__dict__ ['_cache' ] = {}
61+ self ._set_attribute ('_parent' , parent )
62+ self ._set_attribute ('_key' , key )
63+ self ._set_attribute ('_descriptor' , descriptor )
64+ self ._set_attribute ('_message' , message )
65+ self ._set_attribute ('_readOnly' , readOnly )
66+ self ._set_attribute ('_cache' , {})
67+
68+ def _set_attribute (self , key , value ):
69+ self .__dict__ [key ] = value
6770
6871 def __getattr__ (self , key ):
6972 return self [key ]
7073
7174 def __getitem__ (self , key ):
75+ key = self ._validate_key (key )
7276 if key in self ._cache :
7377 return self ._cache [key ]
7478 field = self ._descriptor .fields_by_name .get (key )
@@ -156,6 +160,7 @@ def _fullName(self, key=None):
156160 def _create_child (self , key ):
157161 if self ._readOnly :
158162 raise ValueError (f"{ self ._readOnly } is read only" )
163+ key = self ._validate_key (key )
159164 if self ._message is _Unknown :
160165 self .__dict__ ['_message' ] = self ._parent ._create_child (self ._key )
161166 return getattr (self ._message , key )
@@ -177,6 +182,7 @@ def __setattr__(self, key, value):
177182 def __setitem__ (self , key , value ):
178183 if self ._readOnly :
179184 raise ValueError (f"{ self ._readOnly } is read only" )
185+ key = self ._validate_key (key )
180186 if key not in self ._descriptor .fields_by_name :
181187 raise AttributeError (obj = self , name = key )
182188 field = self ._descriptor .fields_by_name [key ]
@@ -201,26 +207,40 @@ def __delattr__(self, key):
201207 def __delitem__ (self , key ):
202208 if self ._readOnly :
203209 raise ValueError (f"{ self ._readOnly } is read only" )
210+ key = self ._validate_key (key )
204211 if key not in self ._descriptor .fields_by_name :
205212 raise AttributeError (obj = self , name = key )
206213 if self ._message is not _Unknown :
207214 self ._message .ClearField (key )
208215 self ._cache .pop (key , None )
209216
217+ def _validate_key (self , key ):
218+ if isinstance (key , FieldMessage ):
219+ key = key ._value
220+ elif isinstance (key , Value ):
221+ key = key ._raw
222+ if not isinstance (key , str ):
223+ raise TypeError (f"Unexpected key type: { key .__class__ } " )
224+ return key
225+
210226
211227class MapMessage :
212228 def __init__ (self , parent , key , field , messages = _Unknown , readOnly = False ):
213- self .__dict__ ['_parent' ] = parent
214- self .__dict__ ['_key' ] = key
215- self .__dict__ ['_field' ] = field
216- self .__dict__ ['_messages' ] = messages
217- self .__dict__ ['_readOnly' ] = readOnly
218- self .__dict__ ['_cache' ] = {}
229+ self ._set_attribute ('_parent' , parent )
230+ self ._set_attribute ('_key' , key )
231+ self ._set_attribute ('_field' , field )
232+ self ._set_attribute ('_messages' , messages )
233+ self ._set_attribute ('_readOnly' , readOnly )
234+ self ._set_attribute ('_cache' , {})
235+
236+ def _set_attribute (self , key , value ):
237+ self .__dict__ [key ] = value
219238
220239 def __getattr__ (self , key ):
221240 return self [key ]
222241
223242 def __getitem__ (self , key ):
243+ key = self ._validate_key (key )
224244 if key in self ._cache :
225245 return self ._cache [key ]
226246 if self ._messages is _Unknown or key not in self ._messages :
@@ -304,6 +324,7 @@ def _fullName(self, key=None):
304324 def _create_child (self , key ):
305325 if self ._readOnly :
306326 raise ValueError (f"{ self ._readOnly } is read only" )
327+ key = self ._validate_key (key )
307328 if self ._messages is _Unknown :
308329 self .__dict__ ['_messages' ] = self ._parent ._create_child (self ._key )
309330 return self ._messages [key ]
@@ -325,6 +346,7 @@ def __setattr__(self, key, message):
325346 def __setitem__ (self , key , message ):
326347 if self ._readOnly :
327348 raise ValueError (f"{ self ._readOnly } is read only" )
349+ key = self ._validate_key (key )
328350 if self ._messages is _Unknown :
329351 self ._messages = self ._parent ._create_child (self ._key )
330352 if isinstance (message , Message ):
@@ -349,11 +371,21 @@ def __delattr__(self, key):
349371 def __delitem__ (self , key ):
350372 if self ._readOnly :
351373 raise ValueError (f"{ self ._readOnly } is read only" )
374+ key = self ._validate_key (key )
352375 if self ._messages is not _Unknown :
353376 if key in self ._messages :
354377 del self ._messages [key ]
355378 self ._cache .pop (key , None )
356379
380+ def _validate_key (self , key ):
381+ if isinstance (key , FieldMessage ):
382+ key = key ._value
383+ elif isinstance (key , Value ):
384+ key = key ._raw
385+ if not isinstance (key , str ):
386+ raise TypeError (f"Unexpected key type: { key .__class__ } " )
387+ return key
388+
357389
358390class RepeatedMessage :
359391 def __init__ (self , parent , key , field , messages = _Unknown , readOnly = False ):
@@ -365,6 +397,7 @@ def __init__(self, parent, key, field, messages=_Unknown, readOnly=False):
365397 self ._cache = {}
366398
367399 def __getitem__ (self , key ):
400+ key = self ._validate_key (key )
368401 if key in self ._cache :
369402 return self ._cache [key ]
370403 if self ._messages is _Unknown or key >= len (self ._messages ):
@@ -447,6 +480,7 @@ def _fullName(self, key=None):
447480 def _create_child (self , key ):
448481 if self ._readOnly :
449482 raise ValueError (f"{ self ._readOnly } is read only" )
483+ key = self ._validate_key (key )
450484 if self ._messages is _Unknown :
451485 self .__dict__ ['_messages' ] = self ._parent ._create_child (self ._key )
452486 if key == append :
@@ -471,6 +505,7 @@ def __call__(self, *args):
471505 def __setitem__ (self , key , message ):
472506 if self ._readOnly :
473507 raise ValueError (f"{ self ._readOnly } is read only" )
508+ key = self ._validate_key (key )
474509 if self ._messages is _Unknown :
475510 self ._messages = self ._parent ._create_child (self ._key )
476511 if key < 0 :
@@ -499,6 +534,7 @@ def __setitem__(self, key, message):
499534 def __delitem__ (self , key ):
500535 if self ._readOnly :
501536 raise ValueError (f"{ self ._readOnly } is read only" )
537+ key = self ._validate_key (key )
502538 if self ._messages is not _Unknown :
503539 del self ._messages [key ]
504540 self ._cache .pop (key , None )
@@ -514,13 +550,22 @@ def append(self, message=_Unknown):
514550 message = self ._messages .append (message )
515551 return self [len (self ._messages ) - 1 ]
516552
553+ def _validate_key (self , key ):
554+ if isinstance (key , FieldMessage ):
555+ key = key ._value
556+ elif isinstance (key , Value ):
557+ key = key ._raw
558+ if not isinstance (key , int ):
559+ raise TypeError (f"Unexpected key type: { key .__class__ } " )
560+ return key
561+
517562
518563class FieldMessage :
519564 def __init__ (self , parent , key , kind , value ):
520- self .__dict__ [ ' _parent' ] = parent
521- self .__dict__ [ ' _key' ] = key
522- self .__dict__ [ ' _kind' ] = kind
523- self .__dict__ [ ' _value' ] = value
565+ self ._parent = parent
566+ self ._key = key
567+ self ._kind = kind
568+ self ._value = value
524569
525570 def __bool__ (self ):
526571 return bool (self ._value )
@@ -539,7 +584,14 @@ def __eq__(self, other):
539584 return self ._value == other ._value
540585 return self ._value == other
541586
587+ def __bytes__ (self ):
588+ if isinstance (self ._value , str ):
589+ return self ._value .encode ('utf-8' )
590+ return bytes (self ._value )
591+
542592 def __str__ (self ):
593+ if isinstance (self ._value , bytes ):
594+ return self ._value .decode ('utf-8' )
543595 return str (self ._value )
544596
545597 def __format__ (self , spec = '' ):
@@ -576,16 +628,16 @@ def _protobuf_value(self):
576628
577629class Value :
578630 def __init__ (self , parent , key , value = _Unknown , readOnly = None ):
579- self .__dict__ [ '_parent' ] = parent
580- self .__dict__ [ '_key' ] = key
581- self .__dict__ [ '_dependencies' ] = {}
582- self .__dict__ [ '_unknowns' ] = {}
583- self .__dict__ [ '_cache' ] = {}
584- self .__dict__ [ '_readOnly' ] = None
631+ self ._set_attribute ( '_parent' , parent )
632+ self ._set_attribute ( '_key' , key )
633+ self ._set_attribute ( '_dependencies' , {})
634+ self ._set_attribute ( '_unknowns' , {})
635+ self ._set_attribute ( '_cache' , {})
636+ self ._set_attribute ( '_readOnly' , None )
585637 if isinstance (value , (google .protobuf .struct_pb2 .Value , google .protobuf .struct_pb2 .Struct , google .protobuf .struct_pb2 .ListValue )) or value is _Unknown :
586- self .__dict__ [ '_value' ] = value
638+ self ._set_attribute ( '_value' , value )
587639 else :
588- self .__dict__ [ '_value' ] = google .protobuf .struct_pb2 .Value ()
640+ self ._set_attribute ( '_value' , google .protobuf .struct_pb2 .Value () )
589641 if value is None :
590642 self ._value .null_value = 0
591643 elif isinstance (value , dict ):
@@ -604,12 +656,16 @@ def __init__(self, parent, key, value=_Unknown, readOnly=None):
604656 self ._value .string_value = value
605657 else :
606658 raise ValueError (f"Unexpected Value type: { value .__class__ } " )
607- self .__dict__ ['_readOnly' ] = readOnly
659+ self ._set_attribute ('_readOnly' , readOnly )
660+
661+ def _set_attribute (self , key , value ):
662+ self .__dict__ [key ] = value
608663
609664 def __getattr__ (self , key ):
610665 return self [key ]
611666
612667 def __getitem__ (self , key ):
668+ key = self ._validate_key (key )
613669 if key in self ._cache :
614670 return self ._cache [key ]
615671 if key in self ._unknowns :
@@ -641,7 +697,7 @@ def __getitem__(self, key):
641697 case _:
642698 raise ValueError (f"Invalid key \" { key } \" for kind: { self ._kind } " )
643699 else :
644- raise ValueError ( f"Unexpected key type: { key . __class__ } " )
700+ raise NotImplementedError ( )
645701 value = Value (self , key , value , self ._readOnly )
646702 self ._cache [key ] = value
647703 return value
@@ -860,6 +916,7 @@ def __setattr__(self, key, value):
860916 def __setitem__ (self , key , value ):
861917 if self ._readOnly :
862918 raise ValueError (f"{ self ._readOnly } is read only" )
919+ key = self ._validate_key (key )
863920 if isinstance (key , str ):
864921 if self ._ensure_map () == 'struct_value' :
865922 values = self ._value .struct_value .fields
@@ -877,7 +934,7 @@ def __setitem__(self, key, value):
877934 while key >= len (values ):
878935 values .add ()
879936 else :
880- raise ValueError ( 'Unexpected key type' )
937+ raise NotImplementedError ( )
881938 self ._cache .pop (key , None )
882939 self ._dependencies .pop (key , None )
883940 self ._unknowns .pop (key , None )
@@ -887,6 +944,8 @@ def __setitem__(self, key, value):
887944 values [key ].null_value = 0
888945 elif isinstance (value , bool ): # Must be before int check
889946 values [key ].bool_value = value
947+ elif isinstance (value , bytes ):
948+ values [key ].string_value = value ._value .decode ('utf-8' )
890949 elif isinstance (value , str ):
891950 values [key ].string_value = value
892951 elif isinstance (value , (int , float )):
@@ -995,6 +1054,7 @@ def __delitem__(self, key):
9951054 kind = self ._kind
9961055 if kind == 'Unknown' :
9971056 return
1057+ key = self ._validate_key (key )
9981058 if isinstance (key , str ):
9991059 match kind :
10001060 case 'struct_value' :
@@ -1036,11 +1096,12 @@ def __delitem__(self, key):
10361096 break
10371097 del values [ix ]
10381098 else :
1039- raise ValueError ( 'Unexpected key type' )
1099+ raise NotImplementedError ( )
10401100
10411101 def _create_child (self , key ):
10421102 if self ._readOnly :
10431103 raise ValueError (f"{ self ._readOnly } is read only" )
1104+ key = self ._validate_key (key )
10441105 if isinstance (key , str ):
10451106 if self ._ensure_map () == 'struct_value' :
10461107 fields = self ._value .struct_value .fields
@@ -1061,7 +1122,16 @@ def _create_child(self, key):
10611122 values .add ()
10621123 values [key ].Clear ()
10631124 return values [key ]
1064- raise ValueError ('Unexpected key type' )
1125+ raise NotImplementedError ()
1126+
1127+ def _validate_key (self , key ):
1128+ if isinstance (key , FieldMessage ):
1129+ key = key ._value
1130+ elif isinstance (key , Value ):
1131+ key = key ._raw
1132+ if not isinstance (key , (str , int )):
1133+ raise TypeError (f"Unexpected key type: { key .__class__ } " )
1134+ return key
10651135
10661136 def _ensure_map (self ):
10671137 kind = self ._kind
0 commit comments