Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error message for short/long file tuples #299

Merged
merged 10 commits into from Dec 28, 2020
1 change: 1 addition & 0 deletions changelog.d/299.feature.rst
@@ -0,0 +1 @@
treq produces a more helpful exception when passed a tuple of the wrong size in the *files* parameter.
12 changes: 12 additions & 0 deletions src/treq/client.py
Expand Up @@ -394,6 +394,17 @@ def _convert_files(files):
file_name, fobj = val
elif len(val) == 3:
file_name, content_type, fobj = val
else:
# NB: This is TypeError for backward compatibility. This case
# used to fall through to `IBodyProducer`, below, which raised
# TypeError about being unable to coerce None.
raise TypeError(
(
"Files must given as tuples of the form (file_name, file_obj)"
" or (file_name, content_type, file_obj), but the {!r} tuple"
" has length {}: {!r}"
twm marked this conversation as resolved.
Show resolved Hide resolved
).format(param, len(val), val),
)
else:
fobj = val
if hasattr(fobj, "name"):
Expand All @@ -402,6 +413,7 @@ def _convert_files(files):
if not content_type:
content_type = _guess_content_type(file_name)

# XXX: Shouldn't this call self._data_to_body_producer?
yield (param, (file_name, content_type, IBodyProducer(fobj)))


Expand Down
30 changes: 30 additions & 0 deletions src/treq/test/test_client.py
Expand Up @@ -398,6 +398,36 @@ def test_request_named_attachment_and_ctype(self):
boundary=b'heyDavid'),
self.MultiPartProducer.call_args)

def test_request_files_tuple_too_short(self):
"""
The `HTTPClient.request()` *files* argument requires tuples of length
2 or 3. It raises `TypeError` when the tuple is too short.
"""
with self.assertRaises(TypeError) as c:
self.client.request(
"POST",
b"http://example.com/",
files=[("t1", ("foo.txt",))],
)

self.assertIn("'t1' tuple has length 1", str(c.exception))

def test_request_files_tuple_too_long(self):
"""
The `HTTPClient.request()` *files* argument requires tuples of length
2 or 3. It raises `TypeError` when the tuple is too long.
"""
with self.assertRaises(TypeError) as c:
self.client.request(
"POST",
b"http://example.com/",
files=[
("t4", ("foo.txt", "text/plain", BytesIO(b"...\n"), "extra!")),
],
)

self.assertIn("'t4' tuple has length 4", str(c.exception))

@mock.patch('treq.client.uuid.uuid4', mock.Mock(return_value="heyDavid"))
def test_request_mixed_params(self):

Expand Down