2
2
import json
3
3
from re import L
4
4
5
- from servicestack .utils import to_timespan
5
+ from requests .models import Response
6
+ from requests .exceptions import HTTPError
6
7
7
- from requests .models import HTTPError , Response
8
-
9
- from servicestack .client_dtos import IDelete , IGet , IPatch , IPost , IPut , IReturn , IReturnVoid , ResponseStatus , KeyValuePair
8
+ from servicestack .dtos import *
10
9
from servicestack .log import Log
11
10
from servicestack .utils import *
11
+ from servicestack .fields import *
12
12
13
13
from typing import Callable , TypeVar , Generic , Optional , Dict , List , Tuple , get_args , Any , Type
14
14
from dataclasses import dataclass , field , fields , asdict , is_dataclass , Field
19
19
import requests
20
20
import base64
21
21
import decimal
22
+ import inspect
22
23
23
24
JSON_MIME_TYPE = "application/json"
24
25
25
- class Bytes (mf .Field ):
26
- def _serialize (self , value , attr , obj , ** kwargs ):
27
- return to_bytearray (value )
28
-
29
- def _deserialize (self , value , attr , data , ** kwargs ):
30
- return from_bytearray (value )
31
-
32
- mm .TYPES [timedelta ] = mf .DateTime
33
- mm .TYPES [KeyValuePair ] = KeyValuePair [str ,str ]
34
- mm .TYPES [bytes ] = Bytes
35
- mm .TYPES [Bytes ] = Bytes
36
-
37
26
@dataclass
38
27
class A :
39
28
l : list
@@ -129,33 +118,20 @@ def _json_encoder(obj:Any):
129
118
return base64 .b64encode (obj ).decode ('ascii' )
130
119
raise TypeError (f"Unsupported Type in JSON encoding: { type (obj )} " )
131
120
132
- def json_encode (obj :Any ):
121
+ def to_json (obj :Any ):
133
122
if is_dataclass (obj ):
134
- # return obj.to_json()
135
123
return json .dumps (clean_any (obj .to_dict ()), default = _json_encoder )
136
124
return json .dumps (obj , default = _json_encoder )
137
125
138
- def _json_decoder (obj :Any ):
139
- # print('ZZZZZZZZZZZZZZZZZ')
140
- # print(type(obj))
141
- return obj
142
-
143
126
class TypeConverters :
144
127
converters : dict [Type , Callable [[Any ],Any ]]
145
128
146
129
def register (type :Type , converter :Callable [[Any ],Any ]):
147
130
TypeConverters .converters [type ] = converter
148
131
149
132
TypeConverters .converters = {
150
- mf .Integer : int ,
151
- mf .Float : float ,
152
- mf .Decimal : decimal .Decimal ,
153
- mf .String : str ,
154
- mf .Boolean : bool ,
155
133
mf .DateTime : from_datetime ,
156
134
mf .TimeDelta : from_timespan ,
157
- Bytes : from_bytearray ,
158
- bytes : from_bytearray ,
159
135
}
160
136
161
137
def is_optional (cls :Type ): return f"{ cls } " .startswith ("typing.Optional" )
@@ -212,16 +188,25 @@ def convert(into:Type, obj:Any):
212
188
try :
213
189
return converter (obj )
214
190
except Exception as e :
215
- Log .error (f"ERROR converter(obj) { into } ({ obj } )" , e )
191
+ Log .error (f"converter(obj) { into } ({ obj } )" , e )
192
+ raise e
193
+ elif inspect .isclass (into ) and issubclass (into , mf .Field ):
194
+ try :
195
+ return into ().deserialize (obj )
196
+ except Exception as e :
197
+ Log .error (f"into().deserialize(obj) { into } ({ obj } )" , e )
216
198
raise e
217
199
else :
218
- # print(f"TRY {obj} into {into}")
219
200
try :
220
201
return into (obj )
221
202
except Exception as e :
222
- Log .error (f"ERROR into(obj) { into } ({ obj } )" , e )
203
+ Log .error (f"into(obj) { into } ({ obj } )" , e )
223
204
raise e
224
205
206
+ def from_json (into :Type , json_str :str ):
207
+ json_obj = json .loads (json_str )
208
+ return convert (into , json_obj )
209
+
225
210
def ex_message (e :Exception ):
226
211
if hasattr (e ,'message' ):
227
212
return e .message
@@ -378,17 +363,14 @@ def _create_response(self, response:Response, info:SendContext):
378
363
json_str = response .text
379
364
if Log .debug_enabled : Log .debug (f"json_str: { json_str } " )
380
365
381
- if not into :
366
+ if into is None :
382
367
return json .loads (json_str )
383
368
384
369
if into is str :
385
370
return json_str
386
371
387
372
try :
388
- # res_dto = into.schema().loads(json_str, object_hook=_json_decoder)
389
-
390
- json_obj = json .loads (json_str )
391
- res_dto = convert (into , json_obj )
373
+ res_dto = from_json (into , json_str )
392
374
except Exception as e :
393
375
Log .error (f"Failed to deserialize into { into } : { e } " , e )
394
376
raise e
@@ -399,20 +381,32 @@ def _raise_error(self, e:Exception):
399
381
return e
400
382
401
383
def _handle_error (self , hold_res :Response , e :Exception ):
402
- if e is WebServiceException :
384
+ if type ( e ) == WebServiceException :
403
385
raise self ._raise_error (e )
404
386
405
387
web_ex = WebServiceException ()
406
388
web_ex .inner_exception = e
407
389
web_ex .status_code = 500
408
390
web_ex .status_description = ex_message (e )
409
391
410
- if e is HTTPError :
411
- web_ex . status_code = e .response . status_code
412
- if Log . debug_enabled : Log . debug ( f" { e } " )
392
+ res = hold_res
393
+ if type ( e ) == HTTPError and not e .response is None :
394
+ res = e . response
413
395
414
- if hold_res :
415
- pass
396
+ if not res is None :
397
+ if Log .debug_enabled (): Log .debug (f"error.text: { res .text } " )
398
+ web_ex .status_code = res .status_code
399
+ web_ex .status_description = res .reason
400
+
401
+ web_ex .response_status = ResponseStatus (
402
+ error_code = f"{ res .status_code } " ,
403
+ message = res .reason )
404
+
405
+ try :
406
+ error_response = from_json (EmptyResponse , res .text )
407
+ web_ex .response_status = error_response .response_status
408
+ except Exception as ex :
409
+ Log .error (f"Could not deserialize error response { res .text } " , ex )
416
410
417
411
raise web_ex
418
412
@@ -449,7 +443,7 @@ def send_request(self, info:SendContext):
449
443
if type (body ) is str :
450
444
info .body_string = body
451
445
else :
452
- info .body_string = json_encode (body )
446
+ info .body_string = to_json (body )
453
447
454
448
Log .debug (f"info method: { info .method } , url: { info .url } , body_string: { info .body_string } " )
455
449
response :Response = None
0 commit comments