| 496 | return SSEDecoder() |
| 497 | |
| 498 | def _build_request( |
| 499 | self, |
| 500 | options: FinalRequestOptions, |
| 501 | *, |
| 502 | retries_taken: int = 0, |
| 503 | ) -> httpx.Request: |
| 504 | if log.isEnabledFor(logging.DEBUG): |
| 505 | log.debug( |
| 506 | class="st">"Request options: %s", |
| 507 | model_dump( |
| 508 | options, |
| 509 | exclude_unset=True, |
| 510 | class="cm"># Pydantic v1 can't dump every type we support in content, so we exclude it for now. |
| 511 | exclude={ |
| 512 | class="st">"content", |
| 513 | } |
| 514 | if PYDANTIC_V1 |
| 515 | else {}, |
| 516 | ), |
| 517 | ) |
| 518 | kwargs: dict[str, Any] = {} |
| 519 | |
| 520 | json_data = options.json_data |
| 521 | if options.extra_json is not None: |
| 522 | if json_data is None: |
| 523 | json_data = cast(Body, options.extra_json) |
| 524 | elif is_mapping(json_data): |
| 525 | json_data = _merge_mappings(json_data, options.extra_json) |
| 526 | else: |
| 527 | raise RuntimeError(fclass="st">"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") |
| 528 | |
| 529 | headers = self._build_headers(options, retries_taken=retries_taken) |
| 530 | params = _merge_mappings({**self._auth_query(options.security), **self.default_query}, options.params) |
| 531 | content_type = headers.get(class="st">"Content-Type") |
| 532 | files = options.files |
| 533 | |
| 534 | class="cm"># If the given Content-Type header is multipart/form-data then it |
| 535 | class="cm"># has to be removed so that httpx can generate the header with |
| 536 | class="cm"># additional information for us as it has to be in this form |
| 537 | class="cm"># for the server to be able to correctly parse the request: |
| 538 | class="cm"># multipart/form-data; boundary=---abc-- |
| 539 | if content_type is not None and content_type.startswith(class="st">"multipart/form-data"): |
| 540 | if class="st">"boundary" not in content_type: |
| 541 | class="cm"># only remove the header if the boundary hasn't been explicitly set |
| 542 | class="cm"># as the caller doesn't want httpx to come up with their own boundary |
| 543 | headers.pop(class="st">"Content-Type") |
| 544 | |
| 545 | class="cm"># As we are now sending multipart/form-data instead of application/json |
| 546 | class="cm"># we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding |
| 547 | if json_data: |
| 548 | if not is_dict(json_data): |
| 549 | raise TypeError( |
| 550 | fclass="st">"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead." |
| 551 | ) |
| 552 | kwargs[class="st">"data"] = self._serialize_multipartform(json_data) |
| 553 | |
| 554 | class="cm"># httpx determines whether or not to send a class="st">"multipart/form-data" |
| 555 | class="cm"># request based on the truthiness of the class="st">"files" argument. |