fix: resolve ruff formatting issues

This commit is contained in:
Mahdi 2025-08-13 01:19:52 +03:30
parent da3da4b709
commit 2eef94deeb
6 changed files with 63 additions and 35 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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[

View File

@ -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)

View File

@ -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)