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 RequestOptions ,
59+ AsyncBinaryTypes ,
5760 HttpxRequestFiles ,
5861 ModelBuilderProtocol ,
5962 not_given ,
@@ -477,8 +480,19 @@ def _build_request(
477480 retries_taken : int = 0 ,
478481 ) -> httpx .Request :
479482 if log .isEnabledFor (logging .DEBUG ):
480- log .debug ("Request options: %s" , model_dump (options , exclude_unset = True ))
481-
483+ log .debug (
484+ "Request options: %s" ,
485+ model_dump (
486+ options ,
487+ exclude_unset = True ,
488+ # Pydantic v1 can't dump every type we support in content, so we exclude it for now.
489+ exclude = {
490+ "content" ,
491+ }
492+ if PYDANTIC_V1
493+ else {},
494+ ),
495+ )
482496 kwargs : dict [str , Any ] = {}
483497
484498 json_data = options .json_data
@@ -532,7 +546,13 @@ def _build_request(
532546 is_body_allowed = options .method .lower () != "get"
533547
534548 if is_body_allowed :
535- if isinstance (json_data , bytes ):
549+ if options .content is not None and json_data is not None :
550+ raise TypeError ("Passing both `content` and `json_data` is not supported" )
551+ if options .content is not None and files is not None :
552+ raise TypeError ("Passing both `content` and `files` is not supported" )
553+ if options .content is not None :
554+ kwargs ["content" ] = options .content
555+ elif isinstance (json_data , bytes ):
536556 kwargs ["content" ] = json_data
537557 else :
538558 kwargs ["json" ] = json_data if is_given (json_data ) else None
@@ -1194,6 +1214,7 @@ def post(
11941214 * ,
11951215 cast_to : Type [ResponseT ],
11961216 body : Body | None = None ,
1217+ content : BinaryTypes | None = None ,
11971218 options : RequestOptions = {},
11981219 files : RequestFiles | None = None ,
11991220 stream : Literal [False ] = False ,
@@ -1206,6 +1227,7 @@ def post(
12061227 * ,
12071228 cast_to : Type [ResponseT ],
12081229 body : Body | None = None ,
1230+ content : BinaryTypes | None = None ,
12091231 options : RequestOptions = {},
12101232 files : RequestFiles | None = None ,
12111233 stream : Literal [True ],
@@ -1219,6 +1241,7 @@ def post(
12191241 * ,
12201242 cast_to : Type [ResponseT ],
12211243 body : Body | None = None ,
1244+ content : BinaryTypes | None = None ,
12221245 options : RequestOptions = {},
12231246 files : RequestFiles | None = None ,
12241247 stream : bool ,
@@ -1231,13 +1254,25 @@ def post(
12311254 * ,
12321255 cast_to : Type [ResponseT ],
12331256 body : Body | None = None ,
1257+ content : BinaryTypes | None = None ,
12341258 options : RequestOptions = {},
12351259 files : RequestFiles | None = None ,
12361260 stream : bool = False ,
12371261 stream_cls : type [_StreamT ] | None = None ,
12381262 ) -> ResponseT | _StreamT :
1263+ if body is not None and content is not None :
1264+ raise TypeError ("Passing both `body` and `content` is not supported" )
1265+ if files is not None and content is not None :
1266+ raise TypeError ("Passing both `files` and `content` is not supported" )
1267+ if isinstance (body , bytes ):
1268+ warnings .warn (
1269+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1270+ "Please pass raw bytes via the `content` parameter instead." ,
1271+ DeprecationWarning ,
1272+ stacklevel = 2 ,
1273+ )
12391274 opts = FinalRequestOptions .construct (
1240- method = "post" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1275+ method = "post" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
12411276 )
12421277 return cast (ResponseT , self .request (cast_to , opts , stream = stream , stream_cls = stream_cls ))
12431278
@@ -1247,11 +1282,23 @@ def patch(
12471282 * ,
12481283 cast_to : Type [ResponseT ],
12491284 body : Body | None = None ,
1285+ content : BinaryTypes | None = None ,
12501286 files : RequestFiles | None = None ,
12511287 options : RequestOptions = {},
12521288 ) -> ResponseT :
1289+ if body is not None and content is not None :
1290+ raise TypeError ("Passing both `body` and `content` is not supported" )
1291+ if files is not None and content is not None :
1292+ raise TypeError ("Passing both `files` and `content` is not supported" )
1293+ if isinstance (body , bytes ):
1294+ warnings .warn (
1295+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1296+ "Please pass raw bytes via the `content` parameter instead." ,
1297+ DeprecationWarning ,
1298+ stacklevel = 2 ,
1299+ )
12531300 opts = FinalRequestOptions .construct (
1254- method = "patch" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1301+ method = "patch" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
12551302 )
12561303 return self .request (cast_to , opts )
12571304
@@ -1261,11 +1308,23 @@ def put(
12611308 * ,
12621309 cast_to : Type [ResponseT ],
12631310 body : Body | None = None ,
1311+ content : BinaryTypes | None = None ,
12641312 files : RequestFiles | None = None ,
12651313 options : RequestOptions = {},
12661314 ) -> ResponseT :
1315+ if body is not None and content is not None :
1316+ raise TypeError ("Passing both `body` and `content` is not supported" )
1317+ if files is not None and content is not None :
1318+ raise TypeError ("Passing both `files` and `content` is not supported" )
1319+ if isinstance (body , bytes ):
1320+ warnings .warn (
1321+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1322+ "Please pass raw bytes via the `content` parameter instead." ,
1323+ DeprecationWarning ,
1324+ stacklevel = 2 ,
1325+ )
12671326 opts = FinalRequestOptions .construct (
1268- method = "put" , url = path , json_data = body , files = to_httpx_files (files ), ** options
1327+ method = "put" , url = path , json_data = body , content = content , files = to_httpx_files (files ), ** options
12691328 )
12701329 return self .request (cast_to , opts )
12711330
@@ -1275,9 +1334,19 @@ def delete(
12751334 * ,
12761335 cast_to : Type [ResponseT ],
12771336 body : Body | None = None ,
1337+ content : BinaryTypes | None = None ,
12781338 options : RequestOptions = {},
12791339 ) -> ResponseT :
1280- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
1340+ if body is not None and content is not None :
1341+ raise TypeError ("Passing both `body` and `content` is not supported" )
1342+ if isinstance (body , bytes ):
1343+ warnings .warn (
1344+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1345+ "Please pass raw bytes via the `content` parameter instead." ,
1346+ DeprecationWarning ,
1347+ stacklevel = 2 ,
1348+ )
1349+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
12811350 return self .request (cast_to , opts )
12821351
12831352 def get_api_list (
@@ -1717,6 +1786,7 @@ async def post(
17171786 * ,
17181787 cast_to : Type [ResponseT ],
17191788 body : Body | None = None ,
1789+ content : AsyncBinaryTypes | None = None ,
17201790 files : RequestFiles | None = None ,
17211791 options : RequestOptions = {},
17221792 stream : Literal [False ] = False ,
@@ -1729,6 +1799,7 @@ async def post(
17291799 * ,
17301800 cast_to : Type [ResponseT ],
17311801 body : Body | None = None ,
1802+ content : AsyncBinaryTypes | None = None ,
17321803 files : RequestFiles | None = None ,
17331804 options : RequestOptions = {},
17341805 stream : Literal [True ],
@@ -1742,6 +1813,7 @@ async def post(
17421813 * ,
17431814 cast_to : Type [ResponseT ],
17441815 body : Body | None = None ,
1816+ content : AsyncBinaryTypes | None = None ,
17451817 files : RequestFiles | None = None ,
17461818 options : RequestOptions = {},
17471819 stream : bool ,
@@ -1754,13 +1826,25 @@ async def post(
17541826 * ,
17551827 cast_to : Type [ResponseT ],
17561828 body : Body | None = None ,
1829+ content : AsyncBinaryTypes | None = None ,
17571830 files : RequestFiles | None = None ,
17581831 options : RequestOptions = {},
17591832 stream : bool = False ,
17601833 stream_cls : type [_AsyncStreamT ] | None = None ,
17611834 ) -> ResponseT | _AsyncStreamT :
1835+ if body is not None and content is not None :
1836+ raise TypeError ("Passing both `body` and `content` is not supported" )
1837+ if files is not None and content is not None :
1838+ raise TypeError ("Passing both `files` and `content` is not supported" )
1839+ if isinstance (body , bytes ):
1840+ warnings .warn (
1841+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1842+ "Please pass raw bytes via the `content` parameter instead." ,
1843+ DeprecationWarning ,
1844+ stacklevel = 2 ,
1845+ )
17621846 opts = FinalRequestOptions .construct (
1763- method = "post" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1847+ method = "post" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
17641848 )
17651849 return await self .request (cast_to , opts , stream = stream , stream_cls = stream_cls )
17661850
@@ -1770,11 +1854,28 @@ async def patch(
17701854 * ,
17711855 cast_to : Type [ResponseT ],
17721856 body : Body | None = None ,
1857+ content : AsyncBinaryTypes | None = None ,
17731858 files : RequestFiles | None = None ,
17741859 options : RequestOptions = {},
17751860 ) -> ResponseT :
1861+ if body is not None and content is not None :
1862+ raise TypeError ("Passing both `body` and `content` is not supported" )
1863+ if files is not None and content is not None :
1864+ raise TypeError ("Passing both `files` and `content` is not supported" )
1865+ if isinstance (body , bytes ):
1866+ warnings .warn (
1867+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1868+ "Please pass raw bytes via the `content` parameter instead." ,
1869+ DeprecationWarning ,
1870+ stacklevel = 2 ,
1871+ )
17761872 opts = FinalRequestOptions .construct (
1777- method = "patch" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1873+ method = "patch" ,
1874+ url = path ,
1875+ json_data = body ,
1876+ content = content ,
1877+ files = await async_to_httpx_files (files ),
1878+ ** options ,
17781879 )
17791880 return await self .request (cast_to , opts )
17801881
@@ -1784,11 +1885,23 @@ async def put(
17841885 * ,
17851886 cast_to : Type [ResponseT ],
17861887 body : Body | None = None ,
1888+ content : AsyncBinaryTypes | None = None ,
17871889 files : RequestFiles | None = None ,
17881890 options : RequestOptions = {},
17891891 ) -> ResponseT :
1892+ if body is not None and content is not None :
1893+ raise TypeError ("Passing both `body` and `content` is not supported" )
1894+ if files is not None and content is not None :
1895+ raise TypeError ("Passing both `files` and `content` is not supported" )
1896+ if isinstance (body , bytes ):
1897+ warnings .warn (
1898+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1899+ "Please pass raw bytes via the `content` parameter instead." ,
1900+ DeprecationWarning ,
1901+ stacklevel = 2 ,
1902+ )
17901903 opts = FinalRequestOptions .construct (
1791- method = "put" , url = path , json_data = body , files = await async_to_httpx_files (files ), ** options
1904+ method = "put" , url = path , json_data = body , content = content , files = await async_to_httpx_files (files ), ** options
17921905 )
17931906 return await self .request (cast_to , opts )
17941907
@@ -1798,9 +1911,19 @@ async def delete(
17981911 * ,
17991912 cast_to : Type [ResponseT ],
18001913 body : Body | None = None ,
1914+ content : AsyncBinaryTypes | None = None ,
18011915 options : RequestOptions = {},
18021916 ) -> ResponseT :
1803- opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , ** options )
1917+ if body is not None and content is not None :
1918+ raise TypeError ("Passing both `body` and `content` is not supported" )
1919+ if isinstance (body , bytes ):
1920+ warnings .warn (
1921+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1922+ "Please pass raw bytes via the `content` parameter instead." ,
1923+ DeprecationWarning ,
1924+ stacklevel = 2 ,
1925+ )
1926+ opts = FinalRequestOptions .construct (method = "delete" , url = path , json_data = body , content = content , ** options )
18041927 return await self .request (cast_to , opts )
18051928
18061929 def get_api_list (
0 commit comments