58
58
HttpxSendArgs ,
59
59
AsyncTransport ,
60
60
RequestOptions ,
61
+ HttpxRequestFiles ,
61
62
ModelBuilderProtocol ,
62
63
)
63
64
from ._utils import is_dict , is_list , asyncify , is_given , lru_cache , is_mapping
@@ -460,6 +461,7 @@ def _build_request(
460
461
headers = self ._build_headers (options )
461
462
params = _merge_mappings (self .default_query , options .params )
462
463
content_type = headers .get ("Content-Type" )
464
+ files = options .files
463
465
464
466
# If the given Content-Type header is multipart/form-data then it
465
467
# has to be removed so that httpx can generate the header with
@@ -473,14 +475,23 @@ def _build_request(
473
475
headers .pop ("Content-Type" )
474
476
475
477
# As we are now sending multipart/form-data instead of application/json
476
- # we need to tell httpx to use it, https://www.python-httpx.org/advanced/#multipart-file-encoding
478
+ # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/ #multipart-file-encoding
477
479
if json_data :
478
480
if not is_dict (json_data ):
479
481
raise TypeError (
480
482
f"Expected query input to be a dictionary for multipart requests but got { type (json_data )} instead."
481
483
)
482
484
kwargs ["data" ] = self ._serialize_multipartform (json_data )
483
485
486
+ # httpx determines whether or not to send a "multipart/form-data"
487
+ # request based on the truthiness of the "files" argument.
488
+ # This gets around that issue by generating a dict value that
489
+ # evaluates to true.
490
+ #
491
+ # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186
492
+ if not files :
493
+ files = cast (HttpxRequestFiles , ForceMultipartDict ())
494
+
484
495
# TODO: report this error to httpx
485
496
return self ._client .build_request ( # pyright: ignore[reportUnknownMemberType]
486
497
headers = headers ,
@@ -493,7 +504,7 @@ def _build_request(
493
504
# https://github.com/microsoft/pyright/issues/3526#event-6715453066
494
505
params = self .qs .stringify (cast (Mapping [str , Any ], params )) if params else None ,
495
506
json = json_data ,
496
- files = options . files ,
507
+ files = files ,
497
508
** kwargs ,
498
509
)
499
510
@@ -1890,6 +1901,11 @@ def make_request_options(
1890
1901
return options
1891
1902
1892
1903
1904
+ class ForceMultipartDict (Dict [str , None ]):
1905
+ def __bool__ (self ) -> bool :
1906
+ return True
1907
+
1908
+
1893
1909
class OtherPlatform :
1894
1910
def __init__ (self , name : str ) -> None :
1895
1911
self .name = name
0 commit comments