fix: resolve ruff formatting issues
This commit is contained in:
parent
da3da4b709
commit
2eef94deeb
@ -370,10 +370,12 @@ class BaseClient:
|
||||
if data and all(
|
||||
isinstance(item, (dict, str, int, float, bool)) for item in data
|
||||
):
|
||||
raise TypeError(
|
||||
"Invalid value for 'data'. To send a JSON array, use the 'json' parameter. "
|
||||
"For form data, use a dictionary or a list of 2-item tuples."
|
||||
message = (
|
||||
"Invalid value for 'data'. To send a JSON array, use the 'json' "
|
||||
"parameter. For form data, use a dictionary or a list of 2-item "
|
||||
"tuples."
|
||||
)
|
||||
raise TypeError(message)
|
||||
|
||||
url = self._merge_url(url)
|
||||
headers = self._merge_headers(headers)
|
||||
|
||||
@ -137,11 +137,21 @@ def encode_urlencoded_data(
|
||||
data: RequestData,
|
||||
) -> tuple[dict[str, str], ByteStream]:
|
||||
plain_data = []
|
||||
for key, value in data.items():
|
||||
if isinstance(value, (list, tuple)):
|
||||
plain_data.extend([(key, primitive_value_to_str(item)) for item in value])
|
||||
else:
|
||||
|
||||
if isinstance(data, list):
|
||||
# Handle list of tuples case
|
||||
for key, value in data:
|
||||
plain_data.append((key, primitive_value_to_str(value)))
|
||||
else:
|
||||
# Handle dictionary case
|
||||
for key, value in data.items():
|
||||
if isinstance(value, (list, tuple)):
|
||||
plain_data.extend(
|
||||
[(key, primitive_value_to_str(item)) for item in value]
|
||||
)
|
||||
else:
|
||||
plain_data.append((key, primitive_value_to_str(value)))
|
||||
|
||||
body = urlencode(plain_data, doseq=True).encode("utf-8")
|
||||
content_length = str(len(body))
|
||||
content_type = "application/x-www-form-urlencoded"
|
||||
@ -195,16 +205,30 @@ def encode_request(
|
||||
returning a two-tuple of (<headers>, <stream>).
|
||||
"""
|
||||
if data is not None and not isinstance(data, Mapping):
|
||||
# We prefer to separate `content=<bytes|str|byte iterator|bytes aiterator>`
|
||||
# for raw request content, and `data=<form data>` for url encoded or
|
||||
# multipart form content.
|
||||
#
|
||||
# However for compat with requests, we *do* still support
|
||||
# `data=<bytes...>` usages. We deal with that case here, treating it
|
||||
# as if `content=<...>` had been supplied instead.
|
||||
message = "Use 'content=<...>' to upload raw bytes/text content."
|
||||
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
||||
return encode_content(data)
|
||||
# Check if this is a list of tuples (valid form data)
|
||||
if (
|
||||
isinstance(data, list)
|
||||
and data
|
||||
and all(isinstance(item, tuple) and len(item) == 2 for item in data)
|
||||
):
|
||||
# This is valid form data as a list of tuples
|
||||
pass
|
||||
else:
|
||||
# We prefer to separate `content=<bytes|str|byte iterator|bytes aiterator>`
|
||||
# for raw request content, and `data=<form data>` for url encoded or
|
||||
# multipart form content.
|
||||
#
|
||||
# However for compat with requests, we *do* still support
|
||||
# `data=<bytes...>` usages. We deal with that case here, treating it
|
||||
# as if `content=<...>` had been supplied instead.
|
||||
message = "Use 'content=<...>' to upload raw bytes/text content."
|
||||
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
||||
# At this point, data is not a list of tuples, so it's safe to pass to
|
||||
# encode_content
|
||||
from typing import cast
|
||||
|
||||
content_data = cast("RequestContent", data)
|
||||
return encode_content(content_data)
|
||||
|
||||
if content is not None:
|
||||
return encode_content(content)
|
||||
|
||||
@ -244,12 +244,16 @@ class MultipartStream(SyncByteStream, AsyncByteStream):
|
||||
def _iter_fields(
|
||||
self, data: RequestData, files: RequestFiles
|
||||
) -> typing.Iterator[FileField | DataField]:
|
||||
for name, value in data.items():
|
||||
if isinstance(value, (tuple, list)):
|
||||
for item in value:
|
||||
yield DataField(name=name, value=item)
|
||||
else:
|
||||
if isinstance(data, list):
|
||||
for name, value in data:
|
||||
yield DataField(name=name, value=value)
|
||||
else:
|
||||
for name, value in data.items():
|
||||
if isinstance(value, (tuple, list)):
|
||||
for item in value:
|
||||
yield DataField(name=name, value=item)
|
||||
else:
|
||||
yield DataField(name=name, value=value)
|
||||
|
||||
file_items = files.items() if isinstance(files, typing.Mapping) else files
|
||||
for name, value in file_items:
|
||||
|
||||
@ -69,7 +69,7 @@ RequestContent = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]]
|
||||
ResponseContent = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]]
|
||||
ResponseExtensions = Mapping[str, Any]
|
||||
|
||||
RequestData = Mapping[str, Any]
|
||||
RequestData = Union[Mapping[str, Any], List[Tuple[str, Any]]]
|
||||
|
||||
FileContent = Union[IO[bytes], bytes, str]
|
||||
FileTypes = Union[
|
||||
|
||||
@ -386,7 +386,8 @@ INVALID_DATA_FORMATS_ASYNC = [
|
||||
@pytest.mark.parametrize("invalid_data", INVALID_DATA_FORMATS_ASYNC)
|
||||
async def test_async_build_request_with_invalid_data_list(invalid_data):
|
||||
"""
|
||||
Verify that AsyncClient.build_request raises a helpful TypeError for invalid list formats.
|
||||
Verify that AsyncClient.build_request raises a helpful TypeError for invalid list
|
||||
formats.
|
||||
"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
expected_message = (
|
||||
@ -400,7 +401,8 @@ async def test_async_build_request_with_invalid_data_list(invalid_data):
|
||||
@pytest.mark.anyio
|
||||
async def test_async_build_request_with_valid_data_formats():
|
||||
"""
|
||||
Verify that AsyncClient.build_request accepts valid data formats without raising our custom TypeError.
|
||||
Verify that AsyncClient.build_request accepts valid data formats without raising
|
||||
our custom TypeError.
|
||||
"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Test with a dictionary
|
||||
@ -409,9 +411,5 @@ async def test_async_build_request_with_valid_data_formats():
|
||||
|
||||
# Test with a list of 2-item tuples (for multipart)
|
||||
# This is a valid use case and should not raise our TypeError.
|
||||
# We explicitly catch and ignore the DeprecationWarning that httpx raises in this specific case.
|
||||
with pytest.warns(DeprecationWarning):
|
||||
request = client.build_request(
|
||||
"POST", "https://example.com", data=[("a", "b")]
|
||||
)
|
||||
request = client.build_request("POST", "https://example.com", data=[("a", "b")])
|
||||
assert isinstance(request, httpx.Request)
|
||||
|
||||
@ -472,7 +472,8 @@ INVALID_DATA_FORMATS_SYNC = [
|
||||
@pytest.mark.parametrize("invalid_data", INVALID_DATA_FORMATS_SYNC)
|
||||
def test_sync_build_request_with_invalid_data_list(invalid_data):
|
||||
"""
|
||||
Verify that Client.build_request raises a helpful TypeError for invalid list formats.
|
||||
Verify that Client.build_request raises a helpful TypeError for invalid list
|
||||
formats.
|
||||
"""
|
||||
client = httpx.Client()
|
||||
expected_message = (
|
||||
@ -485,7 +486,8 @@ def test_sync_build_request_with_invalid_data_list(invalid_data):
|
||||
|
||||
def test_sync_build_request_with_valid_data_formats():
|
||||
"""
|
||||
Verify that Client.build_request accepts valid data formats without raising our custom TypeError.
|
||||
Verify that Client.build_request accepts valid data formats without raising our
|
||||
custom TypeError.
|
||||
"""
|
||||
client = httpx.Client()
|
||||
|
||||
@ -495,7 +497,5 @@ def test_sync_build_request_with_valid_data_formats():
|
||||
|
||||
# Test with a list of 2-item tuples (for multipart)
|
||||
# This is a valid use case and should not raise our TypeError.
|
||||
# We explicitly catch and ignore the DeprecationWarning that httpx raises in this specific case.
|
||||
with pytest.warns(DeprecationWarning):
|
||||
request = client.build_request("POST", "https://example.com", data=[("a", "b")])
|
||||
request = client.build_request("POST", "https://example.com", data=[("a", "b")])
|
||||
assert isinstance(request, httpx.Request)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user