1+ import json
12import logging
23from collections .abc import Callable , Mapping
34from typing import Any , Literal , TypeVar
@@ -45,6 +46,10 @@ class BlueskyRemoteControlError(Exception):
4546 pass
4647
4748
49+ class NonJsonResponseError (Exception ):
50+ pass
51+
52+
4853class BlueskyRequestError (Exception ):
4954 def __init__ (self , code : int , message : str ) -> None :
5055 super ().__init__ (message , code )
@@ -109,7 +114,7 @@ def _exception(response: requests.Response) -> Exception | None:
109114 if code < 400 :
110115 return None
111116 elif code == 404 :
112- return KeyError (str (response . json ( )))
117+ return KeyError (str (_response_json ( response )))
113118 else :
114119 return BlueskyRemoteControlError (code , str (response ))
115120
@@ -124,7 +129,7 @@ def _create_task_exceptions(response: requests.Response) -> Exception | None:
124129 return UnknownPlanError ()
125130 elif code == 422 :
126131 try :
127- content = response . json ( )
132+ content = _response_json ( response )
128133 return InvalidParametersError (
129134 TypeAdapter (list [ParameterError ]).validate_python (
130135 content .get ("detail" , [])
@@ -138,6 +143,18 @@ def _create_task_exceptions(response: requests.Response) -> Exception | None:
138143 return BlueskyRequestError (code , response .text )
139144
140145
146+ def _response_json (response : requests .Response ) -> Any :
147+ try :
148+ return response .json ()
149+ except json .decoder .JSONDecodeError as exc :
150+ LOGGER .debug (
151+ f"Invalid json response from <{ response .request .url } >: <{ response .content } >"
152+ )
153+ raise NonJsonResponseError (
154+ "Response does not contain a valid JSON object"
155+ ) from exc
156+
157+
141158class BlueapiRestClient :
142159 _config : RestConfig
143160 _session_manager : SessionManager | None
@@ -286,7 +303,9 @@ def _request_and_deserialize(
286303 f"but client version is { client_version } . "
287304 f"Some features may not work as expected."
288305 )
289- deserialized = TypeAdapter (target_type ).validate_python (response .json ())
306+ deserialized = TypeAdapter (target_type ).validate_python (
307+ _response_json (response )
308+ )
290309 return deserialized
291310
292311
0 commit comments