From 47d043e1dd051294d85f41b18f8e3c1f8434fd5c 2023-04-21 08:32:38 From: Matthias Bussonnier Date: 2023-04-21 08:32:38 Subject: [PATCH] %%bash: read from stream until separator found or buffer is full (#14019) Original issue: https://github.com/ipython/ipython/issues/14005 TLDR before we would read line by line however this is not necessary and we should just continue reading until we reach EOF. The case we patch here is if we read a line larger than the allowed buffer size, we will return that chunk (aka the entire buffer) to be written out and still continue reading. --- diff --git a/IPython/core/magics/script.py b/IPython/core/magics/script.py index e0615c0..a858c64 100644 --- a/IPython/core/magics/script.py +++ b/IPython/core/magics/script.py @@ -4,6 +4,7 @@ # Distributed under the terms of the Modified BSD License. import asyncio +import asyncio.exceptions import atexit import errno import os @@ -208,15 +209,23 @@ class ScriptMagics(Magics): """Call a coroutine on the asyncio thread""" return asyncio.run_coroutine_threadsafe(coro, event_loop).result() + async def _readchunk(stream): + try: + return await stream.readuntil(b"\n") + except asyncio.exceptions.IncompleteReadError as e: + return e.partial + except asyncio.exceptions.LimitOverrunError as e: + return await stream.read(e.consumed) + async def _handle_stream(stream, stream_arg, file_object): while True: - line = (await stream.readline()).decode("utf8", errors="replace") - if not line: + chunk = (await _readchunk(stream)).decode("utf8", errors="replace") + if not chunk: break if stream_arg: - self.shell.user_ns[stream_arg] = line + self.shell.user_ns[stream_arg] = chunk else: - file_object.write(line) + file_object.write(chunk) file_object.flush() async def _stream_communicate(process, cell):