99import inspect
1010import logging
1111import platform
12+ import warnings
1213import email .utils
1314from types import TracebackType
1415from random import random
5152 ResponseT ,
5253 AnyMapping ,
5354 PostParser ,
55+ BinaryTypes ,
5456 RequestFiles ,
5557 HttpxSendArgs ,
5658 HttpxFileTypes ,
5759 RequestOptions ,
5860 MultipartSyntax ,
61+ AsyncBinaryTypes ,
5962 HttpxRequestFiles ,
6063 ModelBuilderProtocol ,
6164 not_given ,
@@ -484,8 +487,19 @@ def _build_request(
484487 retries_taken : int = 0 ,
485488 ) -> httpx .Request :
486489 if log .isEnabledFor (logging .DEBUG ):
487- log .debug ("Request options: %s" , model_dump (options , exclude_unset = True ))
488-
490+ log .debug (
491+ "Request options: %s" ,
492+ model_dump (
493+ options ,
494+ exclude_unset = True ,
495+ # Pydantic v1 can't dump every type we support in content, so we exclude it for now.
496+ exclude = {
497+ "content" ,
498+ }
499+ if PYDANTIC_V1
500+ else {},
501+ ),
502+ )
489503 kwargs : dict [str , Any ] = {}
490504
491505 json_data = options .json_data
@@ -556,7 +570,13 @@ def _build_request(
556570 is_body_allowed = options .method .lower () != "get"
557571
558572 if is_body_allowed :
559- if isinstance (json_data , bytes ):
573+ if options .content is not None and json_data is not None :
574+ raise TypeError ("Passing both `content` and `json_data` is not supported" )
575+ if options .content is not None and files is not None :
576+ raise TypeError ("Passing both `content` and `files` is not supported" )
577+ if options .content is not None :
578+ kwargs ["content" ] = options .content
579+ elif isinstance (json_data , bytes ):
560580 kwargs ["content" ] = json_data
561581 else :
562582 kwargs ["json" ] = json_data if is_given (json_data ) else None
@@ -1236,6 +1256,7 @@ def post(
12361256 * ,
12371257 cast_to : Type [ResponseT ],
12381258 body : Body | None = None ,
1259+ content : BinaryTypes | None = None ,
12391260 options : RequestOptions = {},
12401261 files : RequestFiles | None = None ,
12411262 stream : Literal [False ] = False ,
@@ -1248,6 +1269,7 @@ def post(
12481269 * ,
12491270 cast_to : Type [ResponseT ],
12501271 body : Body | None = None ,
1272+ content : BinaryTypes | None = None ,
12511273 options : RequestOptions = {},
12521274 files : RequestFiles | None = None ,
12531275 stream : Literal [True ],
@@ -1261,6 +1283,7 @@ def post(
12611283 * ,
12621284 cast_to : Type [ResponseT ],
12631285 body : Body | None = None ,
1286+ content : BinaryTypes | None = None ,
12641287 options : RequestOptions = {},
12651288 files : RequestFiles | None = None ,
12661289 stream : bool ,
@@ -1273,13 +1296,25 @@ def post(
12731296 * ,
12741297 cast_to : Type [ResponseT ],
12751298 body : Body | None = None ,
1299+ content : BinaryTypes | None = None ,
12761300 options : RequestOptions = {},
12771301 files : RequestFiles | None = None ,
12781302 stream : bool = False ,
12791303 stream_cls : type [_StreamT ] | None = None ,
12801304 ) -> ResponseT | _StreamT :
1305+ if body is not None and content is not None :
1306+ raise TypeError ("Passing both `body` and `content` is not supported" )
1307+ if files is not None and content is not None :
1308+ raise TypeError ("Passing both `files` and `content` is not supported" )
1309+ if isinstance (body , bytes ):
1310+ warnings .warn (
1311+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1312+ "Please pass raw bytes via the `content` parameter instead." ,
1313+ DeprecationWarning ,
1314+ stacklevel = 2 ,
1315+ )
12811316 opts = FinalRequestOptions .construct (
1282- method = "post" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1317+ method = "post" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
12831318 )
12841319 return cast (ResponseT , self .request (cast_to , opts , stream = stream , stream_cls = stream_cls ))
12851320
@@ -1289,9 +1324,24 @@ def patch(
12891324 * ,
12901325 cast_to : Type [ResponseT ],
12911326 body : Body | None = None ,
1327+ content : BinaryTypes | None = None ,
1328+ files : RequestFiles | None = None ,
12921329 options : RequestOptions = {},
12931330 ) -> ResponseT :
1294- opts = FinalRequestOptions .construct (method = "patch" , url = path , json_data = body , ** options )
1331+ if body is not None and content is not None :
1332+ raise TypeError ("Passing both `body` and `content` is not supported" )
1333+ if files is not None and content is not None :
1334+ raise TypeError ("Passing both `files` and `content` is not supported" )
1335+ if isinstance (body , bytes ):
1336+ warnings .warn (
1337+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1338+ "Please pass raw bytes via the `content` parameter instead." ,
1339+ DeprecationWarning ,
1340+ stacklevel = 2 ,
1341+ )
1342+ opts = FinalRequestOptions .construct (
1343+ method = "patch" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
1344+ )
12951345 return self .request (cast_to , opts )
12961346
12971347 def put (
@@ -1300,11 +1350,23 @@ def put(
13001350 * ,
13011351 cast_to : Type [ResponseT ],
13021352 body : Body | None = None ,
1353+ content : BinaryTypes | None = None ,
13031354 files : RequestFiles | None = None ,
13041355 options : RequestOptions = {},
13051356 ) -> ResponseT :
1357+ if body is not None and content is not None :
1358+ raise TypeError ("Passing both `body` and `content` is not supported" )
1359+ if files is not None and content is not None :
1360+ raise TypeError ("Passing both `files` and `content` is not supported" )
1361+ if isinstance (body , bytes ):
1362+ warnings .warn (
1363+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1364+ "Please pass raw bytes via the `content` parameter instead." ,
1365+ DeprecationWarning ,
1366+ stacklevel = 2 ,
1367+ )
13061368 opts = FinalRequestOptions .construct (
1307- method = "put" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1369+ method = "put" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
13081370 )
13091371 return self .request (cast_to , opts )
13101372
@@ -1314,9 +1376,19 @@ def delete(
13141376 * ,
13151377 cast_to : Type [ResponseT ],
13161378 body : Body | None = None ,
1379+ content : BinaryTypes | None = None ,
13171380 options : RequestOptions = {},
13181381 ) -> ResponseT :
1319- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
1382+ if body is not None and content is not None :
1383+ raise TypeError ("Passing both `body` and `content` is not supported" )
1384+ if isinstance (body , bytes ):
1385+ warnings .warn (
1386+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1387+ "Please pass raw bytes via the `content` parameter instead." ,
1388+ DeprecationWarning ,
1389+ stacklevel = 2 ,
1390+ )
1391+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
13201392 return self .request (cast_to , opts )
13211393
13221394 def get_api_list (
@@ -1758,6 +1830,7 @@ async def post(
17581830 * ,
17591831 cast_to : Type [ResponseT ],
17601832 body : Body | None = None ,
1833+ content : AsyncBinaryTypes | None = None ,
17611834 files : RequestFiles | None = None ,
17621835 options : RequestOptions = {},
17631836 stream : Literal [False ] = False ,
@@ -1770,6 +1843,7 @@ async def post(
17701843 * ,
17711844 cast_to : Type [ResponseT ],
17721845 body : Body | None = None ,
1846+ content : AsyncBinaryTypes | None = None ,
17731847 files : RequestFiles | None = None ,
17741848 options : RequestOptions = {},
17751849 stream : Literal [True ],
@@ -1783,6 +1857,7 @@ async def post(
17831857 * ,
17841858 cast_to : Type [ResponseT ],
17851859 body : Body | None = None ,
1860+ content : AsyncBinaryTypes | None = None ,
17861861 files : RequestFiles | None = None ,
17871862 options : RequestOptions = {},
17881863 stream : bool ,
@@ -1795,13 +1870,25 @@ async def post(
17951870 * ,
17961871 cast_to : Type [ResponseT ],
17971872 body : Body | None = None ,
1873+ content : AsyncBinaryTypes | None = None ,
17981874 files : RequestFiles | None = None ,
17991875 options : RequestOptions = {},
18001876 stream : bool = False ,
18011877 stream_cls : type [_AsyncStreamT ] | None = None ,
18021878 ) -> ResponseT | _AsyncStreamT :
1879+ if body is not None and content is not None :
1880+ raise TypeError ("Passing both `body` and `content` is not supported" )
1881+ if files is not None and content is not None :
1882+ raise TypeError ("Passing both `files` and `content` is not supported" )
1883+ if isinstance (body , bytes ):
1884+ warnings .warn (
1885+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1886+ "Please pass raw bytes via the `content` parameter instead." ,
1887+ DeprecationWarning ,
1888+ stacklevel = 2 ,
1889+ )
18031890 opts = FinalRequestOptions .construct (
1804- method = "post" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1891+ method = "post" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
18051892 )
18061893 return await self .request (cast_to , opts , stream = stream , stream_cls = stream_cls )
18071894
@@ -1811,9 +1898,29 @@ async def patch(
18111898 * ,
18121899 cast_to : Type [ResponseT ],
18131900 body : Body | None = None ,
1901+ content : AsyncBinaryTypes | None = None ,
1902+ files : RequestFiles | None = None ,
18141903 options : RequestOptions = {},
18151904 ) -> ResponseT :
1816- opts = FinalRequestOptions .construct (method = "patch" , url = path , json_data = body , ** options )
1905+ if body is not None and content is not None :
1906+ raise TypeError ("Passing both `body` and `content` is not supported" )
1907+ if files is not None and content is not None :
1908+ raise TypeError ("Passing both `files` and `content` is not supported" )
1909+ if isinstance (body , bytes ):
1910+ warnings .warn (
1911+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1912+ "Please pass raw bytes via the `content` parameter instead." ,
1913+ DeprecationWarning ,
1914+ stacklevel = 2 ,
1915+ )
1916+ opts = FinalRequestOptions .construct (
1917+ method = "patch" ,
1918+ url = path ,
1919+ json_data = body ,
1920+ content = content ,
1921+ files = await async_to_httpx_files (files ),
1922+ ** options ,
1923+ )
18171924 return await self .request (cast_to , opts )
18181925
18191926 async def put (
@@ -1822,11 +1929,23 @@ async def put(
18221929 * ,
18231930 cast_to : Type [ResponseT ],
18241931 body : Body | None = None ,
1932+ content : AsyncBinaryTypes | None = None ,
18251933 files : RequestFiles | None = None ,
18261934 options : RequestOptions = {},
18271935 ) -> ResponseT :
1936+ if body is not None and content is not None :
1937+ raise TypeError ("Passing both `body` and `content` is not supported" )
1938+ if files is not None and content is not None :
1939+ raise TypeError ("Passing both `files` and `content` is not supported" )
1940+ if isinstance (body , bytes ):
1941+ warnings .warn (
1942+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1943+ "Please pass raw bytes via the `content` parameter instead." ,
1944+ DeprecationWarning ,
1945+ stacklevel = 2 ,
1946+ )
18281947 opts = FinalRequestOptions .construct (
1829- method = "put" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1948+ method = "put" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
18301949 )
18311950 return await self .request (cast_to , opts )
18321951
@@ -1836,9 +1955,19 @@ async def delete(
18361955 * ,
18371956 cast_to : Type [ResponseT ],
18381957 body : Body | None = None ,
1958+ content : AsyncBinaryTypes | None = None ,
18391959 options : RequestOptions = {},
18401960 ) -> ResponseT :
1841- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
1961+ if body is not None and content is not None :
1962+ raise TypeError ("Passing both `body` and `content` is not supported" )
1963+ if isinstance (body , bytes ):
1964+ warnings .warn (
1965+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1966+ "Please pass raw bytes via the `content` parameter instead." ,
1967+ DeprecationWarning ,
1968+ stacklevel = 2 ,
1969+ )
1970+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
18421971 return await self .request (cast_to , opts )
18431972
18441973 def get_api_list (
0 commit comments