uplink
uplink copied to clipboard
async vs sync and list as query parameter
Hi folks,
first of all thanks for this great python library, awesome work! I think I found a glitch between sync and async support in regards of query parameter handling.
Describe the bug
So far as I understand I can use lists as query params too and it'll generate urls like /?a=1&a=2 but it looks like there is a difference between sync (requests) and async (aiohttp).
To Reproduce
import asyncio
import os
import sys
from uplink import AiohttpClient, Consumer, Query, get
BASE_URL = "http://httpbin.org/"
class HttpBin(Consumer):
"""Just a stub."""
@get("get")
def get(self, names: Query("vm.names")):
pass
def test_sync():
httpbin = HttpBin(base_url=BASE_URL)
resp = httpbin.get(names=["foo", "bar"])
print(resp.json()["args"])
async def test_async():
httpbin = HttpBin(base_url=BASE_URL, client=AiohttpClient())
resp = await httpbin.get(names=["foo", "bar"])
print((await resp.json())["args"])
if __name__ == "__main__":
test_sync()
loop = asyncio.get_event_loop()
loop.run_until_complete(test_async())
sys.exit(0)
Expected behavior
test_sync prints {'vm.names': ['foo', 'bar']}
but test_async
Traceback (most recent call last):
File "uplink-debug.py", line 39, in <module>
loop.run_until_complete(test_async())
File "/home/user/.env/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete
return future.result()
File "uplink-debug.py", line 31, in test_async
resp = await httpbin.get(names=["foo", "bar"])
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/asyncio_strategy.py", line 38, in execute
response = yield from executable.execute()
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/asyncio_strategy.py", line 20, in invoke
response = yield from callback.on_failure(type(error), error, tb)
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/asyncio_strategy.py", line 20, in invoke
response = yield from callback.on_failure(type(error), error, tb)
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/execution.py", line 108, in on_failure
return self._io.fail(exc_type, exc_val, exc_tb)
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/interfaces.py", line 303, in fail
compat.reraise(exc_type, exc_val, exc_tb)
File "/home/user/.env/lib/python3.6/site-packages/six.py", line 693, in reraise
raise value
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/asyncio_strategy.py", line 17, in invoke
response = yield from func(*args, **kwargs)
File "/home/user/.env/lib/python3.6/site-packages/uplink/hooks.py", line 109, in handle_exception
compat.reraise(exc_type, exc_val, exc_tb)
File "/home/user/.env/lib/python3.6/site-packages/six.py", line 693, in reraise
raise value
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/io/asyncio_strategy.py", line 17, in invoke
response = yield from func(*args, **kwargs)
File "/home/user/.env/lib/python3.6/site-packages/uplink/clients/aiohttp_.py", line 137, in send
response = yield from session.request(method, url, **extras)
File "/home/user/.env/lib/python3.6/site-packages/aiohttp/client.py", line 473, in _request
ssl=ssl, proxy_headers=proxy_headers, traces=traces)
File "/home/user/.env/lib/python3.6/site-packages/aiohttp/client_reqrep.py", line 263, in __init__
url2 = url.with_query(params)
File "/home/user/.env/lib/python3.6/site-packages/yarl/__init__.py", line 885, in with_query
new_query = self._get_str_query(*args, **kwargs)
File "/home/user/.env/lib/python3.6/site-packages/yarl/__init__.py", line 849, in _get_str_query
quoter(k) + "=" + quoter(self._query_var(v)) for k, v in query.items()
File "/home/user/.env/lib/python3.6/site-packages/yarl/__init__.py", line 849, in <genexpr>
quoter(k) + "=" + quoter(self._query_var(v)) for k, v in query.items()
File "/home/user/.env/lib/python3.6/site-packages/yarl/__init__.py", line 827, in _query_var
"of type {}".format(v, type(v))
TypeError: Invalid variable type: value should be str or int, got ['foo', 'bar'] of type <class 'list'>
looks like yarl (aiohttp) doesn't support lists, aiohttp documentation mention you have to use MultiDict but uplink doesn't support MultiDict :(
cheers, chris