from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Mapping, Union, \
IO, Sequence, ClassVar, cast
if TYPE_CHECKING:
from ..types import JSON_ro
from dataclasses import dataclass
from .types import RequestFiles, ExtendedRequestFiles
[docs]class Content(Payload):
CONTENT_TYPE_HEADER_NAME: ClassVar[str] = 'Content-Type'
MEDIA_TYPE_HINT: ClassVar[str] = 'application/octet-stream'
[docs] def get_media_type(self) -> str:
return self.MEDIA_TYPE_HINT
[docs]@dataclass(repr=False, eq=False)
class Bytes(Content):
MEDIA_TYPE_HINT: ClassVar[str] = 'application/octet-stream'
data: bytes
[docs]@dataclass(repr=False, eq=False)
class Text(Content):
MEDIA_TYPE_HINT: ClassVar[str] = 'text/plain'
text: str
[docs]@dataclass(repr=False, eq=False)
class JSON(Content):
MEDIA_TYPE_HINT: ClassVar[str] = 'application/json'
json: JSON_ro
[docs]def make_multipart_payload_from_extended_request_files(xfiles: ExtendedRequestFiles) -> MultipartFormData:
parts: list[MultipartFormData.Field] = []
for key, value in xfiles.items():
if isinstance(value, str):
parts.append(MultipartFormData.TextField(key, value))
elif isinstance(value, tuple):
length = len(value)
if length == 2:
file, filename = cast("tuple[IO[bytes], str]", value)
parts.append(MultipartFormData.FileField(key, file, filename))
elif length == 3:
file, filename, content_type = cast("tuple[IO[bytes], str, str]", value)
parts.append(MultipartFormData.FileField(key, file, filename, content_type))
else:
raise TypeError
else:
parts.append(MultipartFormData.FileField(key, value))
return MultipartFormData(parts)
[docs]def make_multipart(xfiles: ExtendedRequestFiles) -> MultipartFormData:
return make_multipart_payload_from_extended_request_files(xfiles)
[docs]def make_multipart_parts_from_request_files(files: RequestFiles) -> Sequence[MultipartFormData.Field]:
parts: list[MultipartFormData.Field] = []
for key, value in files.items():
field: MultipartFormData.Field
if isinstance(value, str):
field = MultipartFormData.TextField(key, value)
else:
field = MultipartFormData.FileField(key, value)
parts.append(field)
return parts
[docs]def make_multipart_payload_from_request_files(files: RequestFiles) -> MultipartFormData:
return MultipartFormData(make_multipart_parts_from_request_files(files))
[docs]def make_payload(
data: Optional[Union[Mapping[str, str], bytes]] = None,
json: JSON_ro = None,
files: Optional[RequestFiles] = None,
) -> Optional[Payload]:
if files is not None:
if json is not None:
raise TypeError("mutually exclusive parameters: `files`, `json`")
if data is not None:
if isinstance(data, bytes):
raise TypeError("`data` cannot be bytes when `files` is used")
files = {**data, **files}
return MultipartFormData(make_multipart_parts_from_request_files(files))
if data is not None:
if json is not None:
raise TypeError("mutually exclusive parameters: `data`, `json`")
if isinstance(data, bytes):
return Bytes(data)
return URLEncodedFormData(data)
if json is not None:
return JSON(json)
return None