@@ -156,8 +156,8 @@ def __gt__(self, other: Any) -> 'Comparison':
156
156
def __ge__ (self , other : Any ) -> 'Comparison' :
157
157
return Path (self ).__ge__ (other )
158
158
159
- def __getitem__ (self , idx : int ) -> Any :
160
- return Path (self ).__getitem__ (idx )
159
+ def __getitem__ (self , item : Union [ int , str ] ) -> Path :
160
+ return Path (self ).__getitem__ (item )
161
161
162
162
def between (self , lower : Any , upper : Any ) -> 'Between' :
163
163
return Path (self ).between (lower , upper )
@@ -838,12 +838,10 @@ def deserialize(self, values):
838
838
instance ._deserialize (values )
839
839
return instance
840
840
841
- deserialized_dict : Dict [str , Any ] = dict ()
842
- for k , v in values .items ():
843
- attr_type , attr_value = next (iter (v .items ()))
844
- attr_class = DESERIALIZE_CLASS_MAP [attr_type ]
845
- deserialized_dict [k ] = attr_class .deserialize (attr_value )
846
- return deserialized_dict
841
+ return {
842
+ k : DESERIALIZE_CLASS_MAP [attr_type ].deserialize (attr_value )
843
+ for k , v in values .items () for attr_type , attr_value in v .items ()
844
+ }
847
845
848
846
@classmethod
849
847
def is_raw (cls ):
@@ -900,7 +898,7 @@ def _fast_parse_utc_datestring(datestring):
900
898
901
899
class ListAttribute (Generic [_T ], Attribute [List [_T ]]):
902
900
attr_type = LIST
903
- element_type : Any = None
901
+ element_type : Optional [ Type [ Attribute ]] = None
904
902
905
903
def __init__ (
906
904
self ,
@@ -945,18 +943,41 @@ def deserialize(self, values):
945
943
"""
946
944
Decode from list of AttributeValue types.
947
945
"""
948
- deserialized_lst = []
949
- for v in values :
950
- attr_type , attr_value = next (iter (v .items ()))
951
- attr_class = self ._get_deserialize_class (attr_type )
952
- if attr_class .attr_type != attr_type :
953
- raise ValueError ("Cannot deserialize {} elements from type: {}" .format (
954
- attr_class .__class__ .__name__ , attr_type ))
955
- deserialized_lst .append (attr_class .deserialize (attr_value ))
956
- return deserialized_lst
957
-
958
- def __getitem__ (self , idx : int ) -> Path :
959
- # for typing only
946
+ if self .element_type :
947
+ element_attr = self .element_type ()
948
+ if isinstance (element_attr , MapAttribute ):
949
+ element_attr ._make_attribute () # ensure attr_name exists
950
+ deserialized_lst = []
951
+ for idx , attribute_value in enumerate (values ):
952
+ value = None
953
+ if NULL not in attribute_value :
954
+ # set attr_name in case `get_value` raises an exception
955
+ element_attr .attr_name = '{}[{}]' .format (self .attr_name , idx )
956
+ value = element_attr .deserialize (element_attr .get_value (attribute_value ))
957
+ deserialized_lst .append (value )
958
+ return deserialized_lst
959
+
960
+ return [
961
+ DESERIALIZE_CLASS_MAP [attr_type ].deserialize (attr_value )
962
+ for v in values for attr_type , attr_value in v .items ()
963
+ ]
964
+
965
+ def __getitem__ (self , idx : int ) -> Path : # type: ignore
966
+ if not isinstance (idx , int ):
967
+ raise TypeError ("list indices must be integers, not {}" .format (type (idx ).__name__ ))
968
+
969
+ if self .element_type :
970
+ # If this instance is typed, return a properly configured attribute on list element access.
971
+ element_attr = self .element_type ()
972
+ if isinstance (element_attr , MapAttribute ):
973
+ element_attr ._make_attribute ()
974
+ element_attr .attr_path = list (self .attr_path ) # copy the document path before indexing last element
975
+ element_attr .attr_name = '{}[{}]' .format (element_attr .attr_name , idx )
976
+ if isinstance (element_attr , MapAttribute ):
977
+ for path_segment in reversed (element_attr .attr_path ):
978
+ element_attr ._update_attribute_paths (path_segment )
979
+ return element_attr # type: ignore
980
+
960
981
return super ().__getitem__ (idx )
961
982
962
983
def _get_serialize_class (self , value ):
@@ -968,11 +989,6 @@ def _get_serialize_class(self, value):
968
989
return self .element_type ()
969
990
return SERIALIZE_CLASS_MAP [type (value )]
970
991
971
- def _get_deserialize_class (self , attr_type ):
972
- if self .element_type and attr_type != NULL :
973
- return self .element_type ()
974
- return DESERIALIZE_CLASS_MAP [attr_type ]
975
-
976
992
977
993
DESERIALIZE_CLASS_MAP : Dict [str , Attribute ] = {
978
994
BINARY : BinaryAttribute (),
0 commit comments