1212
1313from saic_ismart_client_ng .api .schema import LoginResp
1414from saic_ismart_client_ng .crypto_utils import sha1_hex_digest
15- from saic_ismart_client_ng .exceptions import SaicApiException , SaicApiRetryException , SaicLogoutException
15+ from saic_ismart_client_ng .exceptions import (
16+ SaicApiException ,
17+ SaicApiRetryException ,
18+ SaicLogoutException ,
19+ )
1620from saic_ismart_client_ng .listener import SaicApiListener
1721from saic_ismart_client_ng .model import SaicApiConfiguration
1822from saic_ismart_client_ng .net .client import SaicApiClient
1923
2024logger = logging .getLogger (__name__ )
2125
22- T = TypeVar ('T' )
26+ T = TypeVar ("T" )
2327
2428
2529class AbstractSaicApi (ABC ):
2630 def __init__ (
27- self ,
28- configuration : SaicApiConfiguration ,
29- listener : Optional [SaicApiListener ] = None ,
31+ self ,
32+ configuration : SaicApiConfiguration ,
33+ listener : Optional [SaicApiListener ] = None ,
3034 ):
3135 self .__configuration = configuration
3236 self .__api_client = SaicApiClient (configuration , listener = listener )
@@ -36,7 +40,7 @@ async def login(self) -> LoginResp:
3640 headers = {
3741 "Content-Type" : "application/x-www-form-urlencoded" ,
3842 "Accept" : "application/json" ,
39- "Authorization" : "Basic c3dvcmQ6c3dvcmRfc2VjcmV0"
43+ "Authorization" : "Basic c3dvcmQ6c3dvcmRfc2VjcmV0" ,
4044 }
4145 firebase_device_id = "cqSHOMG1SmK4k-fzAeK6hr:APA91bGtGihOG5SEQ9hPx3Dtr9o9mQguNiKZrQzboa-1C_UBlRZYdFcMmdfLvh9Q_xA8A0dGFIjkMhZbdIXOYnKfHCeWafAfLXOrxBS3N18T4Slr-x9qpV6FHLMhE9s7I6s89k9lU7DD"
4246 form_body = {
@@ -47,32 +51,36 @@ async def login(self) -> LoginResp:
4751 "deviceId" : f"{ firebase_device_id } ###europecar" ,
4852 "deviceType" : "1" , # 2 for huawei
4953 "loginType" : "2" if self .__configuration .username_is_email else "1" ,
50- "countryCode" : "" if self .__configuration .username_is_email else self .__configuration .phone_country_code ,
54+ "countryCode" : ""
55+ if self .__configuration .username_is_email
56+ else self .__configuration .phone_country_code ,
5157 }
5258
5359 result = await self .execute_api_call (
5460 "POST" ,
5561 "/oauth/token" ,
5662 form_body = form_body ,
5763 out_type = LoginResp ,
58- headers = headers
64+ headers = headers ,
5965 )
6066 # Update the user token
6167 self .__api_client .user_token = result .access_token
62- self .__token_expiration = datetime .datetime .now () + datetime .timedelta (seconds = result .expires_in )
68+ self .__token_expiration = datetime .datetime .now () + datetime .timedelta (
69+ seconds = result .expires_in
70+ )
6371 return result
6472
6573 async def execute_api_call (
66- self ,
67- method : str ,
68- path : str ,
69- * ,
70- body : Optional [Any ] = None ,
71- form_body : Optional [Any ] = None ,
72- out_type : Optional [Type [T ]] = None ,
73- params : Optional [QueryParamTypes ] = None ,
74- headers : Optional [HeaderTypes ] = None ,
75- allow_null_body : bool = False ,
74+ self ,
75+ method : str ,
76+ path : str ,
77+ * ,
78+ body : Optional [Any ] = None ,
79+ form_body : Optional [Any ] = None ,
80+ out_type : Optional [Type [T ]] = None ,
81+ params : Optional [QueryParamTypes ] = None ,
82+ headers : Optional [HeaderTypes ] = None ,
83+ allow_null_body : bool = False ,
7684 ) -> T :
7785 try :
7886 return await self .__execute_api_call (
@@ -83,41 +91,45 @@ async def execute_api_call(
8391 out_type = out_type ,
8492 params = params ,
8593 headers = headers ,
86- allow_null_body = allow_null_body
94+ allow_null_body = allow_null_body ,
8795 )
8896 except SaicApiException as e :
8997 raise e
9098 except Exception as e :
91- raise SaicApiException (f"API call { method } { path } failed unexpectedly" , return_code = 500 ) from e
99+ raise SaicApiException (
100+ f"API call { method } { path } failed unexpectedly" , return_code = 500
101+ ) from e
92102
93103 async def __execute_api_call (
94- self ,
95- method : str ,
96- path : str ,
97- * ,
98- body : Optional [Any ] = None ,
99- form_body : Optional [Any ] = None ,
100- out_type : Optional [Type [T ]] = None ,
101- params : Optional [QueryParamTypes ] = None ,
102- headers : Optional [HeaderTypes ] = None ,
103- allow_null_body : bool = False ,
104+ self ,
105+ method : str ,
106+ path : str ,
107+ * ,
108+ body : Optional [Any ] = None ,
109+ form_body : Optional [Any ] = None ,
110+ out_type : Optional [Type [T ]] = None ,
111+ params : Optional [QueryParamTypes ] = None ,
112+ headers : Optional [HeaderTypes ] = None ,
113+ allow_null_body : bool = False ,
104114 ) -> Optional [T ]:
105115 url = f"{ self .__configuration .base_uri } { path [1 :] if path .startswith ('/' ) else path } "
106116 json_body = asdict (body ) if body else None
107- req = httpx .Request (method , url , params = params , headers = headers , data = form_body , json = json_body )
117+ req = httpx .Request (
118+ method , url , params = params , headers = headers , data = form_body , json = json_body
119+ )
108120 response = await self .__api_client .send (req )
109121 return await self .__deserialize (req , response , out_type , allow_null_body )
110122
111123 async def execute_api_call_with_event_id (
112- self ,
113- method : str ,
114- path : str ,
115- * ,
116- body : Optional [Any ] = None ,
117- out_type : Optional [Type [T ]] = None ,
118- params : Optional [QueryParamTypes ] = None ,
119- headers : Optional [HeaderTypes ] = None ,
120- delay : Optional [tenacity .wait .WaitBaseT ] = None ,
124+ self ,
125+ method : str ,
126+ path : str ,
127+ * ,
128+ body : Optional [Any ] = None ,
129+ out_type : Optional [Type [T ]] = None ,
130+ params : Optional [QueryParamTypes ] = None ,
131+ headers : Optional [HeaderTypes ] = None ,
132+ delay : Optional [tenacity .wait .WaitBaseT ] = None ,
121133 ) -> Optional [T ]:
122134 @tenacity .retry (
123135 stop = tenacity .stop_after_delay (30 ),
@@ -128,55 +140,60 @@ async def execute_api_call_with_event_id(
128140 )
129141 async def execute_api_call_with_event_id_inner (* , event_id : str ):
130142 actual_headers = headers or dict ()
131- actual_headers .update ({' event-id' : event_id })
143+ actual_headers .update ({" event-id" : event_id })
132144 return await self .__execute_api_call (
133145 method ,
134146 path ,
135147 body = body ,
136148 out_type = out_type ,
137149 params = params ,
138- headers = actual_headers
150+ headers = actual_headers ,
139151 )
140152
141- return await execute_api_call_with_event_id_inner (event_id = '0' )
153+ return await execute_api_call_with_event_id_inner (event_id = "0" )
142154
143155 async def __deserialize (
144- self ,
145- request : httpx .Request ,
146- response : httpx .Response ,
147- data_class : Optional [Type [T ]],
148- allow_null_body : bool
156+ self ,
157+ request : httpx .Request ,
158+ response : httpx .Response ,
159+ data_class : Optional [Type [T ]],
160+ allow_null_body : bool ,
149161 ) -> Optional [T ]:
150-
151162 try :
152- request_event_id = request .headers .get (' event-id' )
163+ request_event_id = request .headers .get (" event-id" )
153164 json_data = response .json ()
154- return_code = json_data .get (' code' , - 1 )
155- error_message = json_data .get (' message' , ' Unknown error' )
165+ return_code = json_data .get (" code" , - 1 )
166+ error_message = json_data .get (" message" , " Unknown error" )
156167 logger .debug (f"Response code: { return_code } { response .text } " )
157168
158169 if return_code in (401 , 403 ) or response .status_code in (401 , 403 ):
159170 self .logout ()
160171 raise SaicLogoutException (response .text , return_code )
161172
162173 if return_code in (2 , 3 , 7 ):
163- logger .error (f"API call return code is not acceptable: { return_code } : { response .text } " )
174+ logger .error (
175+ f"API call return code is not acceptable: { return_code } : { response .text } "
176+ )
164177 raise SaicApiException (error_message , return_code = return_code )
165178
166- if 'event-id' in response .headers and 'data' not in json_data :
167- event_id = response .headers ['event-id' ]
168- logger .info (f"Retrying since we got event-id in headers: { event_id } , but no data" )
169- raise SaicApiRetryException (error_message , event_id = event_id , return_code = return_code )
179+ if "event-id" in response .headers and "data" not in json_data :
180+ event_id = response .headers ["event-id" ]
181+ logger .info (
182+ f"Retrying since we got event-id in headers: { event_id } , but no data"
183+ )
184+ raise SaicApiRetryException (
185+ error_message , event_id = event_id , return_code = return_code
186+ )
170187
171188 if return_code != 0 :
172- if request_event_id is not None and request_event_id != '0' :
189+ if request_event_id is not None and request_event_id != "0" :
173190 logger .info (
174191 f"API call asked us to retry: { return_code } : { response .text } . Event id was: { request_event_id } "
175192 )
176193 raise SaicApiRetryException (
177194 error_message ,
178195 event_id = request_event_id ,
179- return_code = return_code
196+ return_code = return_code ,
180197 )
181198 else :
182199 logger .error (
@@ -186,17 +203,19 @@ async def __deserialize(
186203
187204 if data_class is None :
188205 return None
189- elif ' data' in json_data :
206+ elif " data" in json_data :
190207 if data_class is str :
191- return json .dumps (json_data [' data' ])
208+ return json .dumps (json_data [" data" ])
192209 elif data_class is dict :
193- return json_data [' data' ]
210+ return json_data [" data" ]
194211 else :
195- return dacite .from_dict (data_class , json_data [' data' ])
212+ return dacite .from_dict (data_class , json_data [" data" ])
196213 elif allow_null_body :
197214 return None
198215 else :
199- raise SaicApiException (f"Failed to deserialize response, missing 'data' field: { response .text } " )
216+ raise SaicApiException (
217+ f"Failed to deserialize response, missing 'data' field: { response .text } "
218+ )
200219
201220 except SaicApiException as se :
202221 raise se
@@ -205,29 +224,33 @@ async def __deserialize(
205224 if response .status_code in (401 , 403 ):
206225 logger .error (
207226 f"API call failed due to an authentication failure: { response .status_code } { response .text } " ,
208- exc_info = e
227+ exc_info = e ,
209228 )
210229 self .logout ()
211- raise SaicLogoutException (response .text , response .status_code ) from e
230+ raise SaicLogoutException (
231+ response .text , response .status_code
232+ ) from e
212233 else :
213234 logger .error (
214235 f"API call failed: { response .status_code } { response .text } " ,
215- exc_info = e
236+ exc_info = e ,
216237 )
217238 raise SaicApiException (response .text , response .status_code ) from e
218239 else :
219- raise SaicApiException (f"Failed to deserialize response: { e } . Original json was { response .text } " ) from e
240+ raise SaicApiException (
241+ f"Failed to deserialize response: { e } . Original json was { response .text } "
242+ ) from e
220243
221244 def logout (self ):
222- self .__api_client .user_token = ''
245+ self .__api_client .user_token = ""
223246 self .__token_expiration = None
224247
225248 @property
226249 def is_logged_in (self ) -> bool :
227250 return (
228- self .__api_client .user_token is not None and
229- self .__token_expiration is not None and
230- self .__token_expiration > datetime .datetime .now ()
251+ self .__api_client .user_token is not None
252+ and self .__token_expiration is not None
253+ and self .__token_expiration > datetime .datetime .now ()
231254 )
232255
233256 @property
@@ -238,9 +261,11 @@ def token_expiration(self) -> Optional[datetime.datetime]:
238261def saic_api_after_retry (retry_state ):
239262 wrapped_exception = retry_state .outcome .exception ()
240263 if isinstance (wrapped_exception , SaicApiRetryException ):
241- if 'event_id' in retry_state .kwargs :
242- logger .debug (f"Updating event_id to the newly obtained value { wrapped_exception .event_id } " )
243- retry_state .kwargs ['event_id' ] = wrapped_exception .event_id
264+ if "event_id" in retry_state .kwargs :
265+ logger .debug (
266+ f"Updating event_id to the newly obtained value { wrapped_exception .event_id } "
267+ )
268+ retry_state .kwargs ["event_id" ] = wrapped_exception .event_id
244269 else :
245270 logger .debug ("Retrying without an event_id" )
246271
0 commit comments