@@ -78,7 +78,7 @@ def hmac_hashing(api_secret: str, payload: str) -> str:
7878 return m .hexdigest ()
7979
8080
81- def cleanNoneValue (d : dict ) -> dict :
81+ def clean_none_value (d : dict ) -> dict :
8282 """Removes any `None` values from the input dictionary `d` and returns a new
8383 dictionary with only non-`None` values.
8484
@@ -89,11 +89,24 @@ def cleanNoneValue(d: dict) -> dict:
8989 dict: A new dictionary with only non-`None` values from the input dictionary.
9090 """
9191
92- out = {}
93- for k in d .keys ():
94- if d [k ] is not None :
95- out [k ] = d [k ]
96- return out
92+ if isinstance (d , dict ):
93+ out = {}
94+ for k , v in d .items ():
95+ cleaned = clean_none_value (v )
96+ if cleaned not in (None , {}, []):
97+ out [k ] = cleaned
98+ return out
99+ elif isinstance (d , list ):
100+ out_list = []
101+ for item in d :
102+ cleaned_item = clean_none_value (item )
103+ if cleaned_item not in (None , {}, []):
104+ out_list .append (cleaned_item )
105+ return out_list
106+ elif hasattr (d , "__dict__" ):
107+ return clean_none_value (d .__dict__ )
108+ else :
109+ return d
97110
98111
99112def get_timestamp () -> int :
@@ -128,11 +141,35 @@ def make_serializable(val) -> Union[dict, list, str, int, float, bool]:
128141 return [v .__dict__ if hasattr (v , "__dict__" ) else v for v in val ]
129142 if isinstance (val , bool ):
130143 return str (val ).lower ()
131- if isinstance (val , Enum ):
144+ if isinstance (val , float ):
145+ return str (val )
146+ if isinstance (val , Enum ):
132147 return val .value
148+ if hasattr (val , "__dict__" ):
149+ return transform_query (val .__dict__ )
133150 return val
134151
135152
153+ def transform_query (data : Union [dict , list , str , int , float , bool ]) -> Union [dict , list , str , int , float , bool ]:
154+ """Recursively transform keys to camelCase and values to serializable.
155+
156+ Args:
157+ data (Union[dict, list, str, int, float, bool]): The data to transform.
158+ Returns:
159+ Union[dict, list, str, int, float, bool]: The transformed data.
160+ """
161+
162+ if isinstance (data , dict ):
163+ return {
164+ snake_to_camel (k ): transform_query (v )
165+ for k , v in data .items ()
166+ }
167+ elif isinstance (data , list ):
168+ return [transform_query (v ) for v in data ]
169+ else :
170+ return make_serializable (data )
171+
172+
136173def encoded_string (query : str ) -> str :
137174 """Encodes the given query string.
138175
@@ -143,10 +180,9 @@ def encoded_string(query: str) -> str:
143180 str: The encoded query string.
144181 """
145182
183+ query = transform_query (query )
146184 query = {
147- snake_to_camel (k ): json .dumps (make_serializable (v ), separators = ("," , ":" ))
148- if isinstance (v , (list , dict ))
149- else make_serializable (v )
185+ k : json .dumps (v , separators = ("," , ":" )) if isinstance (v , (dict , list )) else v
150186 for k , v in query .items ()
151187 }
152188 return urlencode (query , True )
@@ -263,7 +299,7 @@ def send_request(
263299 payload = {}
264300
265301 if is_signed :
266- cleaned_payload = cleanNoneValue (payload )
302+ cleaned_payload = clean_none_value (payload )
267303 cleaned_payload ["timestamp" ] = get_timestamp ()
268304 query_string = encoded_string (cleaned_payload )
269305 cleaned_payload ["signature" ] = get_signature (configuration , query_string , signer )
@@ -305,7 +341,7 @@ def send_request(
305341 response = session .request (
306342 method = method ,
307343 url = url ,
308- params = encoded_string (cleanNoneValue (payload )),
344+ params = encoded_string (clean_none_value (payload )),
309345 headers = headers ,
310346 timeout = timeout ,
311347 proxies = proxies ,
0 commit comments