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
@@ -459,6 +460,7 @@ def _build_request(
459
460
headers = self ._build_headers (options )
460
461
params = _merge_mappings (self .default_query , options .params )
461
462
content_type = headers .get ("Content-Type" )
463
+ files = options .files
462
464
463
465
# If the given Content-Type header is multipart/form-data then it
464
466
# has to be removed so that httpx can generate the header with
@@ -472,14 +474,23 @@ def _build_request(
472
474
headers .pop ("Content-Type" )
473
475
474
476
# As we are now sending multipart/form-data instead of application/json
475
- # we need to tell httpx to use it, https://www.python-httpx.org/advanced/#multipart-file-encoding
477
+ # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/ #multipart-file-encoding
476
478
if json_data :
477
479
if not is_dict (json_data ):
478
480
raise TypeError (
479
481
f"Expected query input to be a dictionary for multipart requests but got { type (json_data )} instead."
480
482
)
481
483
kwargs ["data" ] = self ._serialize_multipartform (json_data )
482
484
485
+ # httpx determines whether or not to send a "multipart/form-data"
486
+ # request based on the truthiness of the "files" argument.
487
+ # This gets around that issue by generating a dict value that
488
+ # evaluates to true.
489
+ #
490
+ # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186
491
+ if not files :
492
+ files = cast (HttpxRequestFiles , ForceMultipartDict ())
493
+
483
494
# TODO: report this error to httpx
484
495
return self ._client .build_request ( # pyright: ignore[reportUnknownMemberType]
485
496
headers = headers ,
@@ -492,7 +503,7 @@ def _build_request(
492
503
# https://github.com/microsoft/pyright/issues/3526#event-6715453066
493
504
params = self .qs .stringify (cast (Mapping [str , Any ], params )) if params else None ,
494
505
json = json_data ,
495
- files = options . files ,
506
+ files = files ,
496
507
** kwargs ,
497
508
)
498
509
@@ -1863,6 +1874,11 @@ def make_request_options(
1863
1874
return options
1864
1875
1865
1876
1877
+ class ForceMultipartDict (Dict [str , None ]):
1878
+ def __bool__ (self ) -> bool :
1879
+ return True
1880
+
1881
+
1866
1882
class OtherPlatform :
1867
1883
def __init__ (self , name : str ) -> None :
1868
1884
self .name = name
0 commit comments