1+ import json
12import sys
3+ import warnings
24from io import BufferedIOBase
35from json .decoder import JSONDecodeError
4- from typing import Any , List , Optional , Tuple
6+ from typing import Any , List , Optional , Tuple , Union
57
68import aiohttp
79import requests
8- from aiohttp import ClientResponse , ContentTypeError
9- from databento .common .error import BentoClientError , BentoServerError
10- from databento .version import __version__
10+ from aiohttp import ClientResponse
11+ from aiohttp import ContentTypeError
1112from requests import Response
1213from requests .auth import HTTPBasicAuth
1314
15+ from databento .common .error import BentoClientError
16+ from databento .common .error import BentoDeprecationWarning
17+ from databento .common .error import BentoServerError
18+ from databento .common .error import BentoWarning
19+ from databento .version import __version__
20+
1421
1522_32KB = 1024 * 32 # 32_768
23+ WARNING_HEADER_FIELD : str = "X-Warning"
1624
1725
1826class BentoHttpAPI :
@@ -51,6 +59,7 @@ def _get(
5159 auth = HTTPBasicAuth (username = self ._key , password = "" ) if basic_auth else None ,
5260 timeout = (self .TIMEOUT , self .TIMEOUT ),
5361 ) as response :
62+ check_backend_warnings (response )
5463 check_http_error (response )
5564 return response
5665
@@ -71,6 +80,7 @@ async def _get_json_async(
7180 else None ,
7281 timeout = self .TIMEOUT ,
7382 ) as response :
83+ check_backend_warnings (response )
7484 await check_http_error_async (response )
7585 return await response .json ()
7686
@@ -89,6 +99,7 @@ def _post(
8999 auth = HTTPBasicAuth (username = self ._key , password = "" ) if basic_auth else None ,
90100 timeout = (self .TIMEOUT , self .TIMEOUT ),
91101 ) as response :
102+ check_backend_warnings (response )
92103 check_http_error (response )
93104 return response
94105
@@ -109,6 +120,7 @@ def _stream(
109120 timeout = (self .TIMEOUT , self .TIMEOUT ),
110121 stream = True ,
111122 ) as response :
123+ check_backend_warnings (response )
112124 check_http_error (response )
113125
114126 for chunk in response .iter_content (chunk_size = _32KB ):
@@ -133,6 +145,7 @@ async def _stream_async(
133145 else None ,
134146 timeout = self .TIMEOUT ,
135147 ) as response :
148+ check_backend_warnings (response )
136149 await check_http_error_async (response )
137150
138151 async for chunk in response .content .iter_chunks ():
@@ -147,6 +160,24 @@ def is_500_series_error(status: int) -> bool:
147160 return status // 100 == 5
148161
149162
163+ def check_backend_warnings (response : Union [Response , ClientResponse ]) -> None :
164+ if WARNING_HEADER_FIELD not in response .headers : # type: ignore [arg-type]
165+ return
166+
167+ backend_warnings = json .loads (
168+ response .headers [WARNING_HEADER_FIELD ], # type: ignore [arg-type]
169+ )
170+
171+ for bw in backend_warnings :
172+ type_ , _ , message = bw .partition (": " )
173+ if type_ == "DeprecationWarning" :
174+ category = BentoDeprecationWarning
175+ else :
176+ category = BentoWarning # type: ignore [assignment]
177+
178+ warnings .warn (message , category = category , stacklevel = 4 )
179+
180+
150181def check_http_error (response : Response ) -> None :
151182 if is_500_series_error (response .status_code ):
152183 try :
0 commit comments