1010import inspect
1111import logging
1212import platform
13+ import warnings
1314import email .utils
1415from types import TracebackType
1516from random import random
5455 ResponseT ,
5556 AnyMapping ,
5657 PostParser ,
58+ BinaryTypes ,
5759 RequestFiles ,
5860 HttpxSendArgs ,
5961 RequestOptions ,
62+ AsyncBinaryTypes ,
6063 HttpxRequestFiles ,
6164 ModelBuilderProtocol ,
6265 not_given ,
@@ -490,8 +493,19 @@ def _build_request(
490493 retries_taken : int = 0 ,
491494 ) -> httpx .Request :
492495 if log .isEnabledFor (logging .DEBUG ):
493- log .debug ("Request options: %s" , model_dump (options , exclude_unset = True ))
494-
496+ log .debug (
497+ "Request options: %s" ,
498+ model_dump (
499+ options ,
500+ exclude_unset = True ,
501+ # Pydantic v1 can't dump every type we support in content, so we exclude it for now.
502+ exclude = {
503+ "content" ,
504+ }
505+ if PYDANTIC_V1
506+ else {},
507+ ),
508+ )
495509 kwargs : dict [str , Any ] = {}
496510
497511 json_data = options .json_data
@@ -545,7 +559,13 @@ def _build_request(
545559 is_body_allowed = options .method .lower () != "get"
546560
547561 if is_body_allowed :
548- if isinstance (json_data , bytes ):
562+ if options .content is not None and json_data is not None :
563+ raise TypeError ("Passing both `content` and `json_data` is not supported" )
564+ if options .content is not None and files is not None :
565+ raise TypeError ("Passing both `content` and `files` is not supported" )
566+ if options .content is not None :
567+ kwargs ["content" ] = options .content
568+ elif isinstance (json_data , bytes ):
549569 kwargs ["content" ] = json_data
550570 else :
551571 kwargs ["json" ] = json_data if is_given (json_data ) else None
@@ -1278,6 +1298,7 @@ def post(
12781298 * ,
12791299 cast_to : Type [ResponseT ],
12801300 body : Body | None = None ,
1301+ content : BinaryTypes | None = None ,
12811302 options : RequestOptions = {},
12821303 files : RequestFiles | None = None ,
12831304 stream : Literal [False ] = False ,
@@ -1290,6 +1311,7 @@ def post(
12901311 * ,
12911312 cast_to : Type [ResponseT ],
12921313 body : Body | None = None ,
1314+ content : BinaryTypes | None = None ,
12931315 options : RequestOptions = {},
12941316 files : RequestFiles | None = None ,
12951317 stream : Literal [True ],
@@ -1303,6 +1325,7 @@ def post(
13031325 * ,
13041326 cast_to : Type [ResponseT ],
13051327 body : Body | None = None ,
1328+ content : BinaryTypes | None = None ,
13061329 options : RequestOptions = {},
13071330 files : RequestFiles | None = None ,
13081331 stream : bool ,
@@ -1315,13 +1338,25 @@ def post(
13151338 * ,
13161339 cast_to : Type [ResponseT ],
13171340 body : Body | None = None ,
1341+ content : BinaryTypes | None = None ,
13181342 options : RequestOptions = {},
13191343 files : RequestFiles | None = None ,
13201344 stream : bool = False ,
13211345 stream_cls : type [_StreamT ] | None = None ,
13221346 ) -> ResponseT | _StreamT :
1347+ if body is not None and content is not None :
1348+ raise TypeError ("Passing both `body` and `content` is not supported" )
1349+ if files is not None and content is not None :
1350+ raise TypeError ("Passing both `files` and `content` is not supported" )
1351+ if isinstance (body , bytes ):
1352+ warnings .warn (
1353+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1354+ "Please pass raw bytes via the `content` parameter instead." ,
1355+ DeprecationWarning ,
1356+ stacklevel = 2 ,
1357+ )
13231358 opts = FinalRequestOptions .construct (
1324- method = "post" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1359+ method = "post" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
13251360 )
13261361 return cast (ResponseT , self .request (cast_to , opts , stream = stream , stream_cls = stream_cls ))
13271362
@@ -1331,11 +1366,23 @@ def patch(
13311366 * ,
13321367 cast_to : Type [ResponseT ],
13331368 body : Body | None = None ,
1369+ content : BinaryTypes | None = None ,
13341370 files : RequestFiles | None = None ,
13351371 options : RequestOptions = {},
13361372 ) -> ResponseT :
1373+ if body is not None and content is not None :
1374+ raise TypeError ("Passing both `body` and `content` is not supported" )
1375+ if files is not None and content is not None :
1376+ raise TypeError ("Passing both `files` and `content` is not supported" )
1377+ if isinstance (body , bytes ):
1378+ warnings .warn (
1379+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1380+ "Please pass raw bytes via the `content` parameter instead." ,
1381+ DeprecationWarning ,
1382+ stacklevel = 2 ,
1383+ )
13371384 opts = FinalRequestOptions .construct (
1338- method = "patch" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1385+ method = "patch" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
13391386 )
13401387 return self .request (cast_to , opts )
13411388
@@ -1345,11 +1392,23 @@ def put(
13451392 * ,
13461393 cast_to : Type [ResponseT ],
13471394 body : Body | None = None ,
1395+ content : BinaryTypes | None = None ,
13481396 files : RequestFiles | None = None ,
13491397 options : RequestOptions = {},
13501398 ) -> ResponseT :
1399+ if body is not None and content is not None :
1400+ raise TypeError ("Passing both `body` and `content` is not supported" )
1401+ if files is not None and content is not None :
1402+ raise TypeError ("Passing both `files` and `content` is not supported" )
1403+ if isinstance (body , bytes ):
1404+ warnings .warn (
1405+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1406+ "Please pass raw bytes via the `content` parameter instead." ,
1407+ DeprecationWarning ,
1408+ stacklevel = 2 ,
1409+ )
13511410 opts = FinalRequestOptions .construct (
1352- method = "put" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1411+ method = "put" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
13531412 )
13541413 return self .request (cast_to , opts )
13551414
@@ -1359,9 +1418,19 @@ def delete(
13591418 * ,
13601419 cast_to : Type [ResponseT ],
13611420 body : Body | None = None ,
1421+ content : BinaryTypes | None = None ,
13621422 options : RequestOptions = {},
13631423 ) -> ResponseT :
1364- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
1424+ if body is not None and content is not None :
1425+ raise TypeError ("Passing both `body` and `content` is not supported" )
1426+ if isinstance (body , bytes ):
1427+ warnings .warn (
1428+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1429+ "Please pass raw bytes via the `content` parameter instead." ,
1430+ DeprecationWarning ,
1431+ stacklevel = 2 ,
1432+ )
1433+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
13651434 return self .request (cast_to , opts )
13661435
13671436 def get_api_list (
@@ -1857,6 +1926,7 @@ async def post(
18571926 * ,
18581927 cast_to : Type [ResponseT ],
18591928 body : Body | None = None ,
1929+ content : AsyncBinaryTypes | None = None ,
18601930 files : RequestFiles | None = None ,
18611931 options : RequestOptions = {},
18621932 stream : Literal [False ] = False ,
@@ -1869,6 +1939,7 @@ async def post(
18691939 * ,
18701940 cast_to : Type [ResponseT ],
18711941 body : Body | None = None ,
1942+ content : AsyncBinaryTypes | None = None ,
18721943 files : RequestFiles | None = None ,
18731944 options : RequestOptions = {},
18741945 stream : Literal [True ],
@@ -1882,6 +1953,7 @@ async def post(
18821953 * ,
18831954 cast_to : Type [ResponseT ],
18841955 body : Body | None = None ,
1956+ content : AsyncBinaryTypes | None = None ,
18851957 files : RequestFiles | None = None ,
18861958 options : RequestOptions = {},
18871959 stream : bool ,
@@ -1894,13 +1966,25 @@ async def post(
18941966 * ,
18951967 cast_to : Type [ResponseT ],
18961968 body : Body | None = None ,
1969+ content : AsyncBinaryTypes | None = None ,
18971970 files : RequestFiles | None = None ,
18981971 options : RequestOptions = {},
18991972 stream : bool = False ,
19001973 stream_cls : type [_AsyncStreamT ] | None = None ,
19011974 ) -> ResponseT | _AsyncStreamT :
1975+ if body is not None and content is not None :
1976+ raise TypeError ("Passing both `body` and `content` is not supported" )
1977+ if files is not None and content is not None :
1978+ raise TypeError ("Passing both `files` and `content` is not supported" )
1979+ if isinstance (body , bytes ):
1980+ warnings .warn (
1981+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1982+ "Please pass raw bytes via the `content` parameter instead." ,
1983+ DeprecationWarning ,
1984+ stacklevel = 2 ,
1985+ )
19021986 opts = FinalRequestOptions .construct (
1903- method = "post" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1987+ method = "post" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
19041988 )
19051989 return await self .request (cast_to , opts , stream = stream , stream_cls = stream_cls )
19061990
@@ -1910,11 +1994,28 @@ async def patch(
19101994 * ,
19111995 cast_to : Type [ResponseT ],
19121996 body : Body | None = None ,
1997+ content : AsyncBinaryTypes | None = None ,
19131998 files : RequestFiles | None = None ,
19141999 options : RequestOptions = {},
19152000 ) -> ResponseT :
2001+ if body is not None and content is not None :
2002+ raise TypeError ("Passing both `body` and `content` is not supported" )
2003+ if files is not None and content is not None :
2004+ raise TypeError ("Passing both `files` and `content` is not supported" )
2005+ if isinstance (body , bytes ):
2006+ warnings .warn (
2007+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2008+ "Please pass raw bytes via the `content` parameter instead." ,
2009+ DeprecationWarning ,
2010+ stacklevel = 2 ,
2011+ )
19162012 opts = FinalRequestOptions .construct (
1917- method = "patch" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
2013+ method = "patch" ,
2014+ url = path ,
2015+ json_data = body ,
2016+ content = content ,
2017+ files = await async_to_httpx_files (files ),
2018+ ** options ,
19182019 )
19192020 return await self .request (cast_to , opts )
19202021
@@ -1924,11 +2025,23 @@ async def put(
19242025 * ,
19252026 cast_to : Type [ResponseT ],
19262027 body : Body | None = None ,
2028+ content : AsyncBinaryTypes | None = None ,
19272029 files : RequestFiles | None = None ,
19282030 options : RequestOptions = {},
19292031 ) -> ResponseT :
2032+ if body is not None and content is not None :
2033+ raise TypeError ("Passing both `body` and `content` is not supported" )
2034+ if files is not None and content is not None :
2035+ raise TypeError ("Passing both `files` and `content` is not supported" )
2036+ if isinstance (body , bytes ):
2037+ warnings .warn (
2038+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2039+ "Please pass raw bytes via the `content` parameter instead." ,
2040+ DeprecationWarning ,
2041+ stacklevel = 2 ,
2042+ )
19302043 opts = FinalRequestOptions .construct (
1931- method = "put" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
2044+ method = "put" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
19322045 )
19332046 return await self .request (cast_to , opts )
19342047
@@ -1938,9 +2051,19 @@ async def delete(
19382051 * ,
19392052 cast_to : Type [ResponseT ],
19402053 body : Body | None = None ,
2054+ content : AsyncBinaryTypes | None = None ,
19412055 options : RequestOptions = {},
19422056 ) -> ResponseT :
1943- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
2057+ if body is not None and content is not None :
2058+ raise TypeError ("Passing both `body` and `content` is not supported" )
2059+ if isinstance (body , bytes ):
2060+ warnings .warn (
2061+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2062+ "Please pass raw bytes via the `content` parameter instead." ,
2063+ DeprecationWarning ,
2064+ stacklevel = 2 ,
2065+ )
2066+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
19442067 return await self .request (cast_to , opts )
19452068
19462069 def get_api_list (
0 commit comments