streams.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. import asyncio
  2. import collections
  3. import warnings
  4. from typing import (
  5. Awaitable,
  6. Callable,
  7. Deque,
  8. Final,
  9. Generic,
  10. List,
  11. Optional,
  12. Tuple,
  13. TypeVar,
  14. )
  15. from .base_protocol import BaseProtocol
  16. from .helpers import (
  17. _EXC_SENTINEL,
  18. BaseTimerContext,
  19. TimerNoop,
  20. set_exception,
  21. set_result,
  22. )
  23. from .http_exceptions import LineTooLong
  24. from .log import internal_logger
  25. __all__ = (
  26. "EMPTY_PAYLOAD",
  27. "EofStream",
  28. "StreamReader",
  29. "DataQueue",
  30. )
  31. _T = TypeVar("_T")
  32. class EofStream(Exception):
  33. """eof stream indication."""
  34. class AsyncStreamIterator(Generic[_T]):
  35. __slots__ = ("read_func",)
  36. def __init__(self, read_func: Callable[[], Awaitable[_T]]) -> None:
  37. self.read_func = read_func
  38. def __aiter__(self) -> "AsyncStreamIterator[_T]":
  39. return self
  40. async def __anext__(self) -> _T:
  41. try:
  42. rv = await self.read_func()
  43. except EofStream:
  44. raise StopAsyncIteration
  45. if rv == b"":
  46. raise StopAsyncIteration
  47. return rv
  48. class ChunkTupleAsyncStreamIterator:
  49. __slots__ = ("_stream",)
  50. def __init__(self, stream: "StreamReader") -> None:
  51. self._stream = stream
  52. def __aiter__(self) -> "ChunkTupleAsyncStreamIterator":
  53. return self
  54. async def __anext__(self) -> Tuple[bytes, bool]:
  55. rv = await self._stream.readchunk()
  56. if rv == (b"", False):
  57. raise StopAsyncIteration
  58. return rv
  59. class AsyncStreamReaderMixin:
  60. __slots__ = ()
  61. def __aiter__(self) -> AsyncStreamIterator[bytes]:
  62. return AsyncStreamIterator(self.readline) # type: ignore[attr-defined]
  63. def iter_chunked(self, n: int) -> AsyncStreamIterator[bytes]:
  64. """Returns an asynchronous iterator that yields chunks of size n."""
  65. return AsyncStreamIterator(lambda: self.read(n)) # type: ignore[attr-defined]
  66. def iter_any(self) -> AsyncStreamIterator[bytes]:
  67. """Yield all available data as soon as it is received."""
  68. return AsyncStreamIterator(self.readany) # type: ignore[attr-defined]
  69. def iter_chunks(self) -> ChunkTupleAsyncStreamIterator:
  70. """Yield chunks of data as they are received by the server.
  71. The yielded objects are tuples
  72. of (bytes, bool) as returned by the StreamReader.readchunk method.
  73. """
  74. return ChunkTupleAsyncStreamIterator(self) # type: ignore[arg-type]
  75. class StreamReader(AsyncStreamReaderMixin):
  76. """An enhancement of asyncio.StreamReader.
  77. Supports asynchronous iteration by line, chunk or as available::
  78. async for line in reader:
  79. ...
  80. async for chunk in reader.iter_chunked(1024):
  81. ...
  82. async for slice in reader.iter_any():
  83. ...
  84. """
  85. __slots__ = (
  86. "_protocol",
  87. "_low_water",
  88. "_high_water",
  89. "_low_water_chunks",
  90. "_high_water_chunks",
  91. "_loop",
  92. "_size",
  93. "_cursor",
  94. "_http_chunk_splits",
  95. "_buffer",
  96. "_buffer_offset",
  97. "_eof",
  98. "_waiter",
  99. "_eof_waiter",
  100. "_exception",
  101. "_timer",
  102. "_eof_callbacks",
  103. "_eof_counter",
  104. "total_bytes",
  105. "total_compressed_bytes",
  106. )
  107. def __init__(
  108. self,
  109. protocol: BaseProtocol,
  110. limit: int,
  111. *,
  112. timer: Optional[BaseTimerContext] = None,
  113. loop: Optional[asyncio.AbstractEventLoop] = None,
  114. ) -> None:
  115. self._protocol = protocol
  116. self._low_water = limit
  117. self._high_water = limit * 2
  118. if loop is None:
  119. loop = asyncio.get_event_loop()
  120. # Ensure high_water_chunks >= 3 so it's always > low_water_chunks.
  121. self._high_water_chunks = max(3, limit // 4)
  122. # Use max(2, ...) because there's always at least 1 chunk split remaining
  123. # (the current position), so we need low_water >= 2 to allow resume.
  124. self._low_water_chunks = max(2, self._high_water_chunks // 2)
  125. self._loop = loop
  126. self._size = 0
  127. self._cursor = 0
  128. self._http_chunk_splits: Optional[Deque[int]] = None
  129. self._buffer: Deque[bytes] = collections.deque()
  130. self._buffer_offset = 0
  131. self._eof = False
  132. self._waiter: Optional[asyncio.Future[None]] = None
  133. self._eof_waiter: Optional[asyncio.Future[None]] = None
  134. self._exception: Optional[BaseException] = None
  135. self._timer = TimerNoop() if timer is None else timer
  136. self._eof_callbacks: List[Callable[[], None]] = []
  137. self._eof_counter = 0
  138. self.total_bytes = 0
  139. self.total_compressed_bytes: Optional[int] = None
  140. def __repr__(self) -> str:
  141. info = [self.__class__.__name__]
  142. if self._size:
  143. info.append("%d bytes" % self._size)
  144. if self._eof:
  145. info.append("eof")
  146. if self._low_water != 2**16: # default limit
  147. info.append("low=%d high=%d" % (self._low_water, self._high_water))
  148. if self._waiter:
  149. info.append("w=%r" % self._waiter)
  150. if self._exception:
  151. info.append("e=%r" % self._exception)
  152. return "<%s>" % " ".join(info)
  153. def get_read_buffer_limits(self) -> Tuple[int, int]:
  154. return (self._low_water, self._high_water)
  155. def exception(self) -> Optional[BaseException]:
  156. return self._exception
  157. def set_exception(
  158. self,
  159. exc: BaseException,
  160. exc_cause: BaseException = _EXC_SENTINEL,
  161. ) -> None:
  162. self._exception = exc
  163. self._eof_callbacks.clear()
  164. waiter = self._waiter
  165. if waiter is not None:
  166. self._waiter = None
  167. set_exception(waiter, exc, exc_cause)
  168. waiter = self._eof_waiter
  169. if waiter is not None:
  170. self._eof_waiter = None
  171. set_exception(waiter, exc, exc_cause)
  172. def on_eof(self, callback: Callable[[], None]) -> None:
  173. if self._eof:
  174. try:
  175. callback()
  176. except Exception:
  177. internal_logger.exception("Exception in eof callback")
  178. else:
  179. self._eof_callbacks.append(callback)
  180. def feed_eof(self) -> None:
  181. self._eof = True
  182. waiter = self._waiter
  183. if waiter is not None:
  184. self._waiter = None
  185. set_result(waiter, None)
  186. waiter = self._eof_waiter
  187. if waiter is not None:
  188. self._eof_waiter = None
  189. set_result(waiter, None)
  190. if self._protocol._reading_paused:
  191. self._protocol.resume_reading()
  192. for cb in self._eof_callbacks:
  193. try:
  194. cb()
  195. except Exception:
  196. internal_logger.exception("Exception in eof callback")
  197. self._eof_callbacks.clear()
  198. def is_eof(self) -> bool:
  199. """Return True if 'feed_eof' was called."""
  200. return self._eof
  201. def at_eof(self) -> bool:
  202. """Return True if the buffer is empty and 'feed_eof' was called."""
  203. return self._eof and not self._buffer
  204. async def wait_eof(self) -> None:
  205. if self._eof:
  206. return
  207. assert self._eof_waiter is None
  208. self._eof_waiter = self._loop.create_future()
  209. try:
  210. await self._eof_waiter
  211. finally:
  212. self._eof_waiter = None
  213. @property
  214. def total_raw_bytes(self) -> int:
  215. if self.total_compressed_bytes is None:
  216. return self.total_bytes
  217. return self.total_compressed_bytes
  218. def unread_data(self, data: bytes) -> None:
  219. """rollback reading some data from stream, inserting it to buffer head."""
  220. warnings.warn(
  221. "unread_data() is deprecated "
  222. "and will be removed in future releases (#3260)",
  223. DeprecationWarning,
  224. stacklevel=2,
  225. )
  226. if not data:
  227. return
  228. if self._buffer_offset:
  229. self._buffer[0] = self._buffer[0][self._buffer_offset :]
  230. self._buffer_offset = 0
  231. self._size += len(data)
  232. self._cursor -= len(data)
  233. self._buffer.appendleft(data)
  234. self._eof_counter = 0
  235. # TODO: size is ignored, remove the param later
  236. def feed_data(self, data: bytes, size: int = 0) -> None:
  237. assert not self._eof, "feed_data after feed_eof"
  238. if not data:
  239. return
  240. data_len = len(data)
  241. self._size += data_len
  242. self._buffer.append(data)
  243. self.total_bytes += data_len
  244. waiter = self._waiter
  245. if waiter is not None:
  246. self._waiter = None
  247. set_result(waiter, None)
  248. if self._size > self._high_water and not self._protocol._reading_paused:
  249. self._protocol.pause_reading()
  250. def begin_http_chunk_receiving(self) -> None:
  251. if self._http_chunk_splits is None:
  252. if self.total_bytes:
  253. raise RuntimeError(
  254. "Called begin_http_chunk_receiving when some data was already fed"
  255. )
  256. self._http_chunk_splits = collections.deque()
  257. def end_http_chunk_receiving(self) -> None:
  258. if self._http_chunk_splits is None:
  259. raise RuntimeError(
  260. "Called end_chunk_receiving without calling "
  261. "begin_chunk_receiving first"
  262. )
  263. # self._http_chunk_splits contains logical byte offsets from start of
  264. # the body transfer. Each offset is the offset of the end of a chunk.
  265. # "Logical" means bytes, accessible for a user.
  266. # If no chunks containing logical data were received, current position
  267. # is difinitely zero.
  268. pos = self._http_chunk_splits[-1] if self._http_chunk_splits else 0
  269. if self.total_bytes == pos:
  270. # We should not add empty chunks here. So we check for that.
  271. # Note, when chunked + gzip is used, we can receive a chunk
  272. # of compressed data, but that data may not be enough for gzip FSM
  273. # to yield any uncompressed data. That's why current position may
  274. # not change after receiving a chunk.
  275. return
  276. self._http_chunk_splits.append(self.total_bytes)
  277. # If we get too many small chunks before self._high_water is reached, then any
  278. # .read() call becomes computationally expensive, and could block the event loop
  279. # for too long, hence an additional self._high_water_chunks here.
  280. if (
  281. len(self._http_chunk_splits) > self._high_water_chunks
  282. and not self._protocol._reading_paused
  283. ):
  284. self._protocol.pause_reading()
  285. # wake up readchunk when end of http chunk received
  286. waiter = self._waiter
  287. if waiter is not None:
  288. self._waiter = None
  289. set_result(waiter, None)
  290. async def _wait(self, func_name: str) -> None:
  291. if not self._protocol.connected:
  292. raise RuntimeError("Connection closed.")
  293. # StreamReader uses a future to link the protocol feed_data() method
  294. # to a read coroutine. Running two read coroutines at the same time
  295. # would have an unexpected behaviour. It would not possible to know
  296. # which coroutine would get the next data.
  297. if self._waiter is not None:
  298. raise RuntimeError(
  299. "%s() called while another coroutine is "
  300. "already waiting for incoming data" % func_name
  301. )
  302. waiter = self._waiter = self._loop.create_future()
  303. try:
  304. with self._timer:
  305. await waiter
  306. finally:
  307. self._waiter = None
  308. async def readline(self, *, max_line_length: Optional[int] = None) -> bytes:
  309. return await self.readuntil(max_size=max_line_length)
  310. async def readuntil(
  311. self, separator: bytes = b"\n", *, max_size: Optional[int] = None
  312. ) -> bytes:
  313. seplen = len(separator)
  314. if seplen == 0:
  315. raise ValueError("Separator should be at least one-byte string")
  316. if self._exception is not None:
  317. raise self._exception
  318. chunk = b""
  319. chunk_size = 0
  320. not_enough = True
  321. max_size = max_size or self._high_water
  322. while not_enough:
  323. while self._buffer and not_enough:
  324. offset = self._buffer_offset
  325. ichar = self._buffer[0].find(separator, offset) + 1
  326. # Read from current offset to found separator or to the end.
  327. data = self._read_nowait_chunk(
  328. ichar - offset + seplen - 1 if ichar else -1
  329. )
  330. chunk += data
  331. chunk_size += len(data)
  332. if ichar:
  333. not_enough = False
  334. if chunk_size > max_size:
  335. raise LineTooLong(chunk[:100] + b"...", max_size)
  336. if self._eof:
  337. break
  338. if not_enough:
  339. await self._wait("readuntil")
  340. return chunk
  341. async def read(self, n: int = -1) -> bytes:
  342. if self._exception is not None:
  343. raise self._exception
  344. # migration problem; with DataQueue you have to catch
  345. # EofStream exception, so common way is to run payload.read() inside
  346. # infinite loop. what can cause real infinite loop with StreamReader
  347. # lets keep this code one major release.
  348. if __debug__:
  349. if self._eof and not self._buffer:
  350. self._eof_counter = getattr(self, "_eof_counter", 0) + 1
  351. if self._eof_counter > 5:
  352. internal_logger.warning(
  353. "Multiple access to StreamReader in eof state, "
  354. "might be infinite loop.",
  355. stack_info=True,
  356. )
  357. if not n:
  358. return b""
  359. if n < 0:
  360. # This used to just loop creating a new waiter hoping to
  361. # collect everything in self._buffer, but that would
  362. # deadlock if the subprocess sends more than self.limit
  363. # bytes. So just call self.readany() until EOF.
  364. blocks = []
  365. while True:
  366. block = await self.readany()
  367. if not block:
  368. break
  369. blocks.append(block)
  370. return b"".join(blocks)
  371. # TODO: should be `if` instead of `while`
  372. # because waiter maybe triggered on chunk end,
  373. # without feeding any data
  374. while not self._buffer and not self._eof:
  375. await self._wait("read")
  376. return self._read_nowait(n)
  377. async def readany(self) -> bytes:
  378. if self._exception is not None:
  379. raise self._exception
  380. # TODO: should be `if` instead of `while`
  381. # because waiter maybe triggered on chunk end,
  382. # without feeding any data
  383. while not self._buffer and not self._eof:
  384. await self._wait("readany")
  385. return self._read_nowait(-1)
  386. async def readchunk(self) -> Tuple[bytes, bool]:
  387. """Returns a tuple of (data, end_of_http_chunk).
  388. When chunked transfer
  389. encoding is used, end_of_http_chunk is a boolean indicating if the end
  390. of the data corresponds to the end of a HTTP chunk , otherwise it is
  391. always False.
  392. """
  393. while True:
  394. if self._exception is not None:
  395. raise self._exception
  396. while self._http_chunk_splits:
  397. pos = self._http_chunk_splits.popleft()
  398. if pos == self._cursor:
  399. return (b"", True)
  400. if pos > self._cursor:
  401. return (self._read_nowait(pos - self._cursor), True)
  402. internal_logger.warning(
  403. "Skipping HTTP chunk end due to data "
  404. "consumption beyond chunk boundary"
  405. )
  406. if self._buffer:
  407. return (self._read_nowait_chunk(-1), False)
  408. # return (self._read_nowait(-1), False)
  409. if self._eof:
  410. # Special case for signifying EOF.
  411. # (b'', True) is not a final return value actually.
  412. return (b"", False)
  413. await self._wait("readchunk")
  414. async def readexactly(self, n: int) -> bytes:
  415. if self._exception is not None:
  416. raise self._exception
  417. blocks: List[bytes] = []
  418. while n > 0:
  419. block = await self.read(n)
  420. if not block:
  421. partial = b"".join(blocks)
  422. raise asyncio.IncompleteReadError(partial, len(partial) + n)
  423. blocks.append(block)
  424. n -= len(block)
  425. return b"".join(blocks)
  426. def read_nowait(self, n: int = -1) -> bytes:
  427. # default was changed to be consistent with .read(-1)
  428. #
  429. # I believe the most users don't know about the method and
  430. # they are not affected.
  431. if self._exception is not None:
  432. raise self._exception
  433. if self._waiter and not self._waiter.done():
  434. raise RuntimeError(
  435. "Called while some coroutine is waiting for incoming data."
  436. )
  437. return self._read_nowait(n)
  438. def _read_nowait_chunk(self, n: int) -> bytes:
  439. first_buffer = self._buffer[0]
  440. offset = self._buffer_offset
  441. if n != -1 and len(first_buffer) - offset > n:
  442. data = first_buffer[offset : offset + n]
  443. self._buffer_offset += n
  444. elif offset:
  445. self._buffer.popleft()
  446. data = first_buffer[offset:]
  447. self._buffer_offset = 0
  448. else:
  449. data = self._buffer.popleft()
  450. data_len = len(data)
  451. self._size -= data_len
  452. self._cursor += data_len
  453. chunk_splits = self._http_chunk_splits
  454. # Prevent memory leak: drop useless chunk splits
  455. while chunk_splits and chunk_splits[0] < self._cursor:
  456. chunk_splits.popleft()
  457. if (
  458. self._protocol._reading_paused
  459. and self._size < self._low_water
  460. and (
  461. self._http_chunk_splits is None
  462. or len(self._http_chunk_splits) < self._low_water_chunks
  463. )
  464. ):
  465. self._protocol.resume_reading()
  466. return data
  467. def _read_nowait(self, n: int) -> bytes:
  468. """Read not more than n bytes, or whole buffer if n == -1"""
  469. self._timer.assert_timeout()
  470. chunks = []
  471. while self._buffer:
  472. chunk = self._read_nowait_chunk(n)
  473. chunks.append(chunk)
  474. if n != -1:
  475. n -= len(chunk)
  476. if n == 0:
  477. break
  478. return b"".join(chunks) if chunks else b""
  479. class EmptyStreamReader(StreamReader): # lgtm [py/missing-call-to-init]
  480. __slots__ = ("_read_eof_chunk",)
  481. def __init__(self) -> None:
  482. self._read_eof_chunk = False
  483. self.total_bytes = 0
  484. def __repr__(self) -> str:
  485. return "<%s>" % self.__class__.__name__
  486. def exception(self) -> Optional[BaseException]:
  487. return None
  488. def set_exception(
  489. self,
  490. exc: BaseException,
  491. exc_cause: BaseException = _EXC_SENTINEL,
  492. ) -> None:
  493. pass
  494. def on_eof(self, callback: Callable[[], None]) -> None:
  495. try:
  496. callback()
  497. except Exception:
  498. internal_logger.exception("Exception in eof callback")
  499. def feed_eof(self) -> None:
  500. pass
  501. def is_eof(self) -> bool:
  502. return True
  503. def at_eof(self) -> bool:
  504. return True
  505. async def wait_eof(self) -> None:
  506. return
  507. def feed_data(self, data: bytes, n: int = 0) -> None:
  508. pass
  509. async def readline(self, *, max_line_length: Optional[int] = None) -> bytes:
  510. return b""
  511. async def read(self, n: int = -1) -> bytes:
  512. return b""
  513. # TODO add async def readuntil
  514. async def readany(self) -> bytes:
  515. return b""
  516. async def readchunk(self) -> Tuple[bytes, bool]:
  517. if not self._read_eof_chunk:
  518. self._read_eof_chunk = True
  519. return (b"", False)
  520. return (b"", True)
  521. async def readexactly(self, n: int) -> bytes:
  522. raise asyncio.IncompleteReadError(b"", n)
  523. def read_nowait(self, n: int = -1) -> bytes:
  524. return b""
  525. EMPTY_PAYLOAD: Final[StreamReader] = EmptyStreamReader()
  526. class DataQueue(Generic[_T]):
  527. """DataQueue is a general-purpose blocking queue with one reader."""
  528. def __init__(self, loop: asyncio.AbstractEventLoop) -> None:
  529. self._loop = loop
  530. self._eof = False
  531. self._waiter: Optional[asyncio.Future[None]] = None
  532. self._exception: Optional[BaseException] = None
  533. self._buffer: Deque[Tuple[_T, int]] = collections.deque()
  534. def __len__(self) -> int:
  535. return len(self._buffer)
  536. def is_eof(self) -> bool:
  537. return self._eof
  538. def at_eof(self) -> bool:
  539. return self._eof and not self._buffer
  540. def exception(self) -> Optional[BaseException]:
  541. return self._exception
  542. def set_exception(
  543. self,
  544. exc: BaseException,
  545. exc_cause: BaseException = _EXC_SENTINEL,
  546. ) -> None:
  547. self._eof = True
  548. self._exception = exc
  549. if (waiter := self._waiter) is not None:
  550. self._waiter = None
  551. set_exception(waiter, exc, exc_cause)
  552. def feed_data(self, data: _T, size: int = 0) -> None:
  553. self._buffer.append((data, size))
  554. if (waiter := self._waiter) is not None:
  555. self._waiter = None
  556. set_result(waiter, None)
  557. def feed_eof(self) -> None:
  558. self._eof = True
  559. if (waiter := self._waiter) is not None:
  560. self._waiter = None
  561. set_result(waiter, None)
  562. async def read(self) -> _T:
  563. if not self._buffer and not self._eof:
  564. assert not self._waiter
  565. self._waiter = self._loop.create_future()
  566. try:
  567. await self._waiter
  568. except (asyncio.CancelledError, asyncio.TimeoutError):
  569. self._waiter = None
  570. raise
  571. if self._buffer:
  572. data, _ = self._buffer.popleft()
  573. return data
  574. if self._exception is not None:
  575. raise self._exception
  576. raise EofStream
  577. def __aiter__(self) -> AsyncStreamIterator[_T]:
  578. return AsyncStreamIterator(self.read)
  579. class FlowControlDataQueue(DataQueue[_T]):
  580. """FlowControlDataQueue resumes and pauses an underlying stream.
  581. It is a destination for parsed data.
  582. This class is deprecated and will be removed in version 4.0.
  583. """
  584. def __init__(
  585. self, protocol: BaseProtocol, limit: int, *, loop: asyncio.AbstractEventLoop
  586. ) -> None:
  587. super().__init__(loop=loop)
  588. self._size = 0
  589. self._protocol = protocol
  590. self._limit = limit * 2
  591. def feed_data(self, data: _T, size: int = 0) -> None:
  592. super().feed_data(data, size)
  593. self._size += size
  594. if self._size > self._limit and not self._protocol._reading_paused:
  595. self._protocol.pause_reading()
  596. async def read(self) -> _T:
  597. if not self._buffer and not self._eof:
  598. assert not self._waiter
  599. self._waiter = self._loop.create_future()
  600. try:
  601. await self._waiter
  602. except (asyncio.CancelledError, asyncio.TimeoutError):
  603. self._waiter = None
  604. raise
  605. if self._buffer:
  606. data, size = self._buffer.popleft()
  607. self._size -= size
  608. if self._size < self._limit and self._protocol._reading_paused:
  609. self._protocol.resume_reading()
  610. return data
  611. if self._exception is not None:
  612. raise self._exception
  613. raise EofStream