Skip to content

Commit

Permalink
(#547) Support async for in multipart reader
Browse files Browse the repository at this point in the history
  • Loading branch information
kxepal committed Nov 23, 2015
1 parent 8d0cfc1 commit be9690b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
33 changes: 33 additions & 0 deletions aiohttp/multipart.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ def __init__(self, resp, stream):
self.resp = resp
self.stream = stream

@asyncio.coroutine
def __aiter__(self):
return self

@asyncio.coroutine
def __anext__(self):
part = yield from self.next()
if part is None:
raise StopAsyncIteration # NOQA
return part

def at_eof(self):
"""Returns ``True`` when all response data had been read.
Expand Down Expand Up @@ -202,6 +213,17 @@ def __init__(self, boundary, headers, content):
self._read_bytes = 0
self._unread = deque()

@asyncio.coroutine
def __aiter__(self):
return self

@asyncio.coroutine
def __anext__(self):
part = yield from self.next()
if part is None:
raise StopAsyncIteration # NOQA
return part

@asyncio.coroutine
def next(self):
item = yield from self.read()
Expand Down Expand Up @@ -430,6 +452,17 @@ def __init__(self, headers, content):
self._at_eof = False
self._unread = []

@asyncio.coroutine
def __aiter__(self):
return self

@asyncio.coroutine
def __anext__(self):
part = yield from self.next()
if part is None:
raise StopAsyncIteration # NOQA
return part

@classmethod
def from_response(cls, response):
"""Constructs reader instance from HTTP response.
Expand Down
68 changes: 68 additions & 0 deletions tests/test_py35/test_multipart_35.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import aiohttp
import aiohttp.hdrs as h
import io
import json
import pytest


class Stream(object):

def __init__(self, content):
self.content = io.BytesIO(content)

async def read(self, size=None):
return self.content.read(size)

async def readline(self):
return self.content.readline()


@pytest.mark.run_loop
async def test_async_for_reader(loop):
data = [{"test": "passed"}, 42, b'plain text', b'aiohttp\n']
reader = aiohttp.MultipartReader(
headers={h.CONTENT_TYPE: 'multipart/mixed; boundary=":"'},
content=Stream(b'\r\n'.join([
b'--:',
b'Content-Type: application/json',
b'',
json.dumps(data[0]).encode(),
b'--:',
b'Content-Type: application/json',
b'',
json.dumps(data[1]).encode(),
b'--:',
b'Content-Type: multipart/related; boundary="::"',
b'',
b'--::',
b'Content-Type: text/plain',
b'',
data[2],
b'--::',
b'Content-Disposition: attachment; filename="aiohttp"',
b'Content-Type: text/plain',
b'Content-Length: 28',
b'Content-Encoding: gzip',
b'',
b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03K\xcc\xcc\xcf())'
b'\xe0\x02\x00\xd6\x90\xe2O\x08\x00\x00\x00',
b'--::--',
b'--:--',
b''])))
idata = iter(data)
async for part in reader:
if isinstance(part, aiohttp.BodyPartReader):
assert next(idata) == (await part.json())
else:
async for subpart in part:
assert next(idata) == await subpart.read(decode=True)


@pytest.mark.run_loop
async def test_async_for_bodypart(loop):
part = aiohttp.BodyPartReader(
boundary=b'--:',
headers={},
content=Stream(b'foobarbaz\r\n--:--'))
async for data in part:
assert data == b'foobarbaz'

0 comments on commit be9690b

Please sign in to comment.