1313# limitations under the License.
1414
1515
16- from typing import Dict , Optional , Set , Any , Callable , Union , List , Sequence
17-
1816import json
17+ from typing import Any , Callable , Dict , Optional , Sequence , Set , Union
1918
2019Primitive = Union [bool , str , int , float ]
2120BoolList = list [bool ]
@@ -55,8 +54,8 @@ def _is_homogenous_primitive_list(v):
5554
5655
5756def _get_flatten_func (
58- flatten_functions : Dict [str , Callable ],
59- key_names : set [ str ] ):
57+ flatten_functions : Dict [str , Callable ], key_names : set [ str ]
58+ ):
6059 for key in key_names :
6160 flatten_func = flatten_functions .get (key )
6261 if flatten_func is not None :
@@ -70,81 +69,135 @@ def _flatten_value(
7069 exclude_keys : Set [str ],
7170 rename_keys : Dict [str , str ],
7271 flatten_functions : Dict [str , Callable ],
73- _from_json = False ) -> FlattenedDict :
74- if value is None :
75- return {}
76- key_names = set ([key ])
77- renamed_key = rename_keys .get (key )
78- if renamed_key is not None :
79- key_names .add (renamed_key )
80- key = renamed_key
81- if key_names & exclude_keys :
82- return {}
83- if _is_primitive (value ):
84- return {key : value }
85- flatten_func = _get_flatten_func (flatten_functions , key_names )
86- if flatten_func is not None :
87- func_output = flatten_func (key , value , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
88- if func_output is not None :
89- return {key : func_output }
90- if isinstance (value , dict ):
91- return _flatten_dict (value , key_prefix = key , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
92- if isinstance (value , list ):
93- if _is_homogenous_primitive_list (value ):
72+ _from_json = False ,
73+ ) -> FlattenedDict :
74+ if value is None :
75+ return {}
76+ key_names = set ([key ])
77+ renamed_key = rename_keys .get (key )
78+ if renamed_key is not None :
79+ key_names .add (renamed_key )
80+ key = renamed_key
81+ if key_names & exclude_keys :
82+ return {}
83+ if _is_primitive (value ):
9484 return {key : value }
95- return _flatten_list (value , key_prefix = key , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
96- if hasattr (value , "model_dump" ):
97- d = value .model_dump ()
98- return _flatten_dict (d , key_prefix = key , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
99- if _from_json :
100- raise ValueError (f"Cannot flatten value with key { key } ; value: { value } " )
101- json_value = json .loads (json .dumps (value ))
102- return _flatten_value (key , json_value , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions , _from_json = True )
85+ flatten_func = _get_flatten_func (flatten_functions , key_names )
86+ if flatten_func is not None :
87+ func_output = flatten_func (
88+ key ,
89+ value ,
90+ exclude_keys = exclude_keys ,
91+ rename_keys = rename_keys ,
92+ flatten_functions = flatten_functions ,
93+ )
94+ if func_output is not None :
95+ return {key : func_output }
96+ if isinstance (value , dict ):
97+ return _flatten_dict (
98+ value ,
99+ key_prefix = key ,
100+ exclude_keys = exclude_keys ,
101+ rename_keys = rename_keys ,
102+ flatten_functions = flatten_functions ,
103+ )
104+ if isinstance (value , list ):
105+ if _is_homogenous_primitive_list (value ):
106+ return {key : value }
107+ return _flatten_list (
108+ value ,
109+ key_prefix = key ,
110+ exclude_keys = exclude_keys ,
111+ rename_keys = rename_keys ,
112+ flatten_functions = flatten_functions ,
113+ )
114+ if hasattr (value , "model_dump" ):
115+ d = value .model_dump ()
116+ return _flatten_dict (
117+ d ,
118+ key_prefix = key ,
119+ exclude_keys = exclude_keys ,
120+ rename_keys = rename_keys ,
121+ flatten_functions = flatten_functions ,
122+ )
123+ if _from_json :
124+ raise ValueError (
125+ f"Cannot flatten value with key { key } ; value: { value } "
126+ )
127+ json_value = json .loads (json .dumps (value ))
128+ return _flatten_value (
129+ key ,
130+ json_value ,
131+ exclude_keys = exclude_keys ,
132+ rename_keys = rename_keys ,
133+ flatten_functions = flatten_functions ,
134+ _from_json = True ,
135+ )
103136
104137
105138def _flatten_dict (
106139 d : Dict [str , Any ],
107140 key_prefix : str ,
108141 exclude_keys : Set [str ],
109142 rename_keys : Dict [str , str ],
110- flatten_functions : Dict [str , Callable ]) -> FlattenedDict :
111- result = {}
112- for key , value in d .items ():
113- if key in exclude_keys :
114- continue
115- full_key = _concat_key (key_prefix , key )
116- flattened = _flatten_value (full_key , value , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
117- result .update (flattened )
118- return result
119-
143+ flatten_functions : Dict [str , Callable ],
144+ ) -> FlattenedDict :
145+ result = {}
146+ for key , value in d .items ():
147+ if key in exclude_keys :
148+ continue
149+ full_key = _concat_key (key_prefix , key )
150+ flattened = _flatten_value (
151+ full_key ,
152+ value ,
153+ exclude_keys = exclude_keys ,
154+ rename_keys = rename_keys ,
155+ flatten_functions = flatten_functions ,
156+ )
157+ result .update (flattened )
158+ return result
120159
121160
122161def _flatten_list (
123162 lst : list [Any ],
124163 key_prefix : str ,
125164 exclude_keys : Set [str ],
126165 rename_keys : Dict [str , str ],
127- flatten_functions : Dict [str , Callable ]) -> FlattenedDict :
128- result = {}
129- result [_concat_key (key_prefix , "length" )] = len (lst )
130- for index , value in enumerate (lst ):
131- full_key = f"{ key_prefix } [{ index } ]"
132- flattened = _flatten_value (full_key , value , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
133- result .update (flattened )
134- return result
166+ flatten_functions : Dict [str , Callable ],
167+ ) -> FlattenedDict :
168+ result = {}
169+ result [_concat_key (key_prefix , "length" )] = len (lst )
170+ for index , value in enumerate (lst ):
171+ full_key = f"{ key_prefix } [{ index } ]"
172+ flattened = _flatten_value (
173+ full_key ,
174+ value ,
175+ exclude_keys = exclude_keys ,
176+ rename_keys = rename_keys ,
177+ flatten_functions = flatten_functions ,
178+ )
179+ result .update (flattened )
180+ return result
135181
136182
137183def flatten_dict (
138184 d : Dict [str , Any ],
139185 key_prefix : Optional [str ] = None ,
140186 exclude_keys : Optional [Sequence [str ]] = None ,
141187 rename_keys : Optional [Dict [str , str ]] = None ,
142- flatten_functions : Optional [Dict [str , Callable ]] = None ):
143- key_prefix = key_prefix or ""
144- if exclude_keys is None :
145- exclude_keys = set ()
146- elif isinstance (exclude_keys , list ):
147- exclude_keys = set (exclude_keys )
148- rename_keys = rename_keys or {}
149- flatten_functions = flatten_functions or {}
150- return _flatten_dict (d , key_prefix = key_prefix , exclude_keys = exclude_keys , rename_keys = rename_keys , flatten_functions = flatten_functions )
188+ flatten_functions : Optional [Dict [str , Callable ]] = None ,
189+ ):
190+ key_prefix = key_prefix or ""
191+ if exclude_keys is None :
192+ exclude_keys = set ()
193+ elif isinstance (exclude_keys , list ):
194+ exclude_keys = set (exclude_keys )
195+ rename_keys = rename_keys or {}
196+ flatten_functions = flatten_functions or {}
197+ return _flatten_dict (
198+ d ,
199+ key_prefix = key_prefix ,
200+ exclude_keys = exclude_keys ,
201+ rename_keys = rename_keys ,
202+ flatten_functions = flatten_functions ,
203+ )
0 commit comments