Skip to content

StreamReader.iter_chunks() raises IndexError #2112

Closed
@jlacoline

Description

Long story short

Any generator given by the iter_chunks() method on StreamReader will end raising an IndexError.
This comes from the readchunk() method which fails if the buffer is empty the end of file is reached.

Expected behaviour

stream.readchunk() should return b"" if the buffer is empty eof is reached
stream.iter_chunks() should return a generator that yields all the chunks and then raise StopAsyncIteration

Actual behaviour

stream.readchunk() raises IndexError if the buffer is empty eof is reached
stream.iter_chunks() returns a generator that yields all the chunks and then raises IndexError

Steps to reproduce

For stream.readchunk(): In the associated unit test in tests/test_streams.py, replace stream.read() with stream.readchunk()

    def test_readchunk(self):

        stream = self._make_one()

        def cb():
            stream.feed_data(b'chunk1')
            stream.feed_data(b'chunk2')
            stream.feed_eof()
        self.loop.call_soon(cb)

        data = self.loop.run_until_complete(stream.readchunk())
        self.assertEqual(b'chunk1', data)

        data = self.loop.run_until_complete(stream.readchunk())
        self.assertEqual(b'chunk2', data)

        data = self.loop.run_until_complete(stream.readchunk())
        self.assertEqual(b'', data)

Result:

――――――――――――――――――――――――――――――――――― TestStreamReader.test_readchunk ――――――――――――――――――――――――――――――――――――

self = <test_streams.TestStreamReader testMethod=test_readchunk>

    def test_readchunk(self):
    
        stream = self._make_one()
    
        def cb():
            stream.feed_data(b'chunk1')
            stream.feed_data(b'chunk2')
            stream.feed_eof()
        self.loop.call_soon(cb)
    
        data = self.loop.run_until_complete(stream.readchunk())
        self.assertEqual(b'chunk1', data)
    
        data = self.loop.run_until_complete(stream.readchunk())
        self.assertEqual(b'chunk2', data)
    
>       data = self.loop.run_until_complete(stream.readchunk())

tests/test_streams.py:565: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/loic/.pyenv/versions/3.5.3/lib/python3.5/asyncio/base_events.py:466: in run_until_complete
    return future.result()
/home/loic/.pyenv/versions/3.5.3/lib/python3.5/asyncio/futures.py:293: in result
    raise self._exception
/home/loic/.pyenv/versions/3.5.3/lib/python3.5/asyncio/tasks.py:239: in _step
    result = coro.send(None)
aiohttp/streams.py:329: in readchunk
    return self._read_nowait_chunk(-1)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <StreamReader eof>, n = -1

    def _read_nowait_chunk(self, n):
>       first_buffer = self._buffer[0]
E       IndexError: deque index out of range

aiohttp/streams.py:363: IndexError

Your environment

  • aiohttp master branch (identified on 2.2.3)
  • Python 3.5.3
  • Debian 8.8

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions