Skip to content

Commit

Permalink
Added MultiDict support for client request params and data #114
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Jul 10, 2014
1 parent 0d414d4 commit b40e401
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGES
=======

0.9.1 (unreleased)
------------------

- Added MultiDict support for client request params and data #114.


0.9.0 (07-08-2014)
------------------

Expand Down
6 changes: 4 additions & 2 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ def update_path(self, params, data):

if isinstance(params, dict):
params = list(params.items())
elif isinstance(params, MultiDict):
params = list(params.items(getall=True))

# for GET request include data to query params
if data and self.method in self.GET_METHODS:
Expand Down Expand Up @@ -370,11 +372,11 @@ def update_body_from_data(self, data):
elif isinstance(data, (asyncio.StreamReader, streams.DataQueue)):
self.body = data

elif (hasattr(data, '__iter__') and not
isinstance(data, (tuple, list, dict, io.IOBase))):
elif inspect.isgenerator(data):
self.body = data
if 'CONTENT-LENGTH' not in self.headers and self.chunked is None:
self.chunked = True

else:
if not isinstance(data, helpers.FormData):
data = helpers.FormData(data)
Expand Down
11 changes: 10 additions & 1 deletion aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from collections import namedtuple
from wsgiref.handlers import format_date_time

from . import multidict


class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):
"""Http basic authentication helper."""
Expand Down Expand Up @@ -60,12 +62,19 @@ def add_field(self, name, value, contenttype=None, filename=None):
self._fields.append((name, value, contenttype, filename))

def add_fields(self, *fields):
for rec in fields:
to_add = list(fields)

while to_add:
rec = to_add.pop(0)

if isinstance(rec, io.IOBase):
k = guess_filename(rec, 'unknown')
self.add_field(k, rec)
self._has_io = True

elif isinstance(rec, multidict.MultiDict):
to_add.extend(rec.items(getall=True))

elif len(rec) == 1:
k = guess_filename(rec[0], 'unknown')
self.add_field(k, rec[0])
Expand Down
44 changes: 42 additions & 2 deletions tests/test_client_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import aiohttp
from aiohttp import client
from aiohttp import multidict
from aiohttp import test_utils
from aiohttp.multidict import MultiDict

Expand Down Expand Up @@ -228,6 +229,20 @@ def test_HTTP_200_GET_WITH_PARAMS(self):
self.assertEqual(r.status, 200)
r.close()

def test_HTTP_200_GET_MultiDict_PARAMS(self):
with test_utils.run_server(self.loop, router=Functional) as httpd:
r = self.loop.run_until_complete(
client.request('get', httpd.url('method', 'get'),
params=multidict.MultiDict(
[('q', 'test1'), ('q', 'test2')]),
loop=self.loop))
content = self.loop.run_until_complete(r.content.read())
content = content.decode()

self.assertIn('"query": "q=test1&q=test2"', content)
self.assertEqual(r.status, 200)
r.close()

def test_HTTP_200_GET_WITH_MIXED_PARAMS(self):
with test_utils.run_server(self.loop, router=Functional) as httpd:
@asyncio.coroutine
Expand Down Expand Up @@ -259,6 +274,20 @@ def test_POST_DATA(self):
self.assertEqual(r.status, 200)
r.close()

def test_POST_MultiDict(self):
with test_utils.run_server(self.loop, router=Functional) as httpd:
url = httpd.url('method', 'post')
r = self.loop.run_until_complete(
client.request('post', url, data=multidict.MultiDict(
[('q', 'test1'), ('q', 'test2')]),
loop=self.loop))
self.assertEqual(r.status, 200)

content = self.loop.run_until_complete(r.json())
self.assertEqual({'q': ['test1', 'test2']}, content['form'])
self.assertEqual(r.status, 200)
r.close()

def test_POST_DATA_DEFLATE(self):
with test_utils.run_server(self.loop, router=Functional) as httpd:
url = httpd.url('method', 'post')
Expand Down Expand Up @@ -486,12 +515,15 @@ def test_POST_FILES_IO_WITH_PARAMS(self):

r = self.loop.run_until_complete(
client.request('post', url,
data=(('test', 'true'), (data,)),
data=(('test', 'true'),
multidict.MultiDict(
[('q', 't1'), ('q', 't2')]),
(data,)),
loop=self.loop))

content = self.loop.run_until_complete(r.json())

self.assertEqual(2, len(content['multipart-data']))
self.assertEqual(4, len(content['multipart-data']))
self.assertEqual(
{'content-type': 'text/plain',
'data': 'true',
Expand All @@ -501,6 +533,14 @@ def test_POST_FILES_IO_WITH_PARAMS(self):
'data': 'data',
'filename': 'unknown',
'name': 'unknown'}, content['multipart-data'][1])
self.assertEqual(
{'content-type': 'text/plain',
'data': 't1',
'name': 'q'}, content['multipart-data'][2])
self.assertEqual(
{'content-type': 'text/plain',
'data': 't2',
'name': 'q'}, content['multipart-data'][3])
self.assertEqual(r.status, 200)
r.close()

Expand Down

0 comments on commit b40e401

Please sign in to comment.