@@ -448,6 +448,7 @@ def _wait_for_data(self, func_name):
448448 assert not self ._eof , '_wait_for_data after EOF'
449449
450450 # Waiting for data while paused will make deadlock, so prevent it.
451+ # This is essential for readexactly(n) for case when n > self._limit.
451452 if self ._paused :
452453 self ._paused = False
453454 self ._transport .resume_reading ()
@@ -658,25 +659,22 @@ def readexactly(self, n):
658659 if n == 0 :
659660 return b''
660661
661- # There used to be "optimized" code here. It created its own
662- # Future and waited until self._buffer had at least the n
663- # bytes, then called read(n). Unfortunately, this could pause
664- # the transport if the argument was larger than the pause
665- # limit (which is twice self._limit). So now we just read()
666- # into a local buffer.
667-
668- blocks = []
669- while n > 0 :
670- block = yield from self .read (n )
671- if not block :
672- partial = b'' .join (blocks )
673- raise IncompleteReadError (partial , len (partial ) + n )
674- blocks .append (block )
675- n -= len (block )
676-
677- assert n == 0
678-
679- return b'' .join (blocks )
662+ while len (self ._buffer ) < n :
663+ if self ._eof :
664+ incomplete = bytes (self ._buffer )
665+ self ._buffer .clear ()
666+ raise IncompleteReadError (incomplete , n )
667+
668+ yield from self ._wait_for_data ('readexactly' )
669+
670+ if len (self ._buffer ) == n :
671+ data = bytes (self ._buffer )
672+ self ._buffer .clear ()
673+ else :
674+ data = bytes (self ._buffer [:n ])
675+ del self ._buffer [:n ]
676+ self ._maybe_resume_transport ()
677+ return data
680678
681679 if compat .PY35 :
682680 @coroutine
0 commit comments