11"""Frigidaire 2.0 API client"""
2+ import traceback
23from enum import Enum
34from requests import Response
45from typing import Optional , Dict , Union , List
@@ -428,7 +429,12 @@ def get_appliances_inner():
428429
429430 try :
430431 return get_appliances_inner ()
431- except FrigidaireException :
432+ except FrigidaireException as e :
433+ # Re-authenticating on a 429 makes things worse
434+ if "cas_3403" in traceback .format_exc ():
435+ logging .debug ("Rate limited - try again later" )
436+ raise e
437+
432438 logging .debug ('Listing appliances failed - attempting to re-authenticate' )
433439 self .re_authenticate ()
434440 return get_appliances_inner ()
@@ -446,7 +452,12 @@ def get_appliance_details(self, appliance: Appliance) -> Dict:
446452 appliances = self .get_request (self .regional_base_url ,
447453 '/appliance/api/v2/appliances?includeMetadata=true' ,
448454 self .get_headers_frigidaire ("GET" , include_bearer_token = True ))
449- except FrigidaireException :
455+ except FrigidaireException as e :
456+ # Re-authenticating on a 429 makes things worse
457+ if "cas_3403" in traceback .format_exc ():
458+ logging .debug ("Rate limited - try again later" )
459+ raise e
460+
450461 self .re_authenticate ()
451462 appliances = self .get_request (self .regional_base_url ,
452463 '/appliance/api/v2/appliances?includeMetadata=true' ,
@@ -475,7 +486,12 @@ def execute_action(self, appliance: Appliance, action: List[Component]) -> None:
475486 self .put_request (self .regional_base_url ,
476487 f'/appliance/api/v2/appliances/{ appliance .appliance_id } /command' ,
477488 self .get_headers_frigidaire ("PUT" , include_bearer_token = True ), data )
478- except FrigidaireException :
489+ except FrigidaireException as e :
490+ # Re-authenticating on a 429 makes things worse
491+ if "cas_3403" in traceback .format_exc ():
492+ logging .debug ("Rate limited - try again later" )
493+ raise e
494+
479495 self .re_authenticate ()
480496 self .put_request (self .regional_base_url ,
481497 f'/appliance/api/v2/appliances/{ appliance .appliance_id } /command' ,
@@ -493,28 +509,29 @@ def parse_response(response: Response) -> Dict:
493509
494510 try :
495511 if response .headers .get ('Content-Encoding' ) == 'gzip' :
496- # Hack: Sometimes the server indicates "Content-Encoding: gzip" but does not send gzipped data
512+ # Hack: Often, the server indicates "Content-Encoding: gzip" but does not send gzipped data
497513 try :
498514 data = gzip .decompress (response .content )
499515 response_dict = json .loads (data .decode ("utf-8" ))
500516 except gzip .BadGzipFile :
501- logging .debug ("Bad gzipped payload-- attempting to parse as plaintext" )
502517 response_dict = response .json ()
518+ elif response .content == b'' :
519+ # The server says it was JSON, but it was not
520+ response_dict = {}
503521 else :
504522 response_dict = response .json ()
505523 except Exception as e :
506524 logging .error (e )
507- raise FrigidaireException (f'Received an unexpected response:\n { response .content } ' )
525+ raise FrigidaireException (f'Received an unexpected response:\n { response .content } ' ) from e
508526
509527 return response_dict
510528
511529 @staticmethod
512530 def handle_request_exception (e : Exception , method : str , fullpath : str , headers : Dict [str , str ], payload : str ):
513531 logging .warning (e )
514532 error_str = f'Error processing request:\n { method } { fullpath } \n headers={ headers } \n payload={ payload } \n '
515- 'This may be safely ignored when used to test for a good connection in the authentication flow'
516533 logging .warning (error_str )
517- raise FrigidaireException (error_str )
534+ raise FrigidaireException (error_str ) from e
518535
519536 def get_request (self , url : str , path : str , headers : Dict [str , str ]) -> Union [Dict , List ]:
520537 """
0 commit comments