keepalive: rewrite readinto() to not use read()
It turns out http.client on Python 3 sometimes uses readinto() in the
implementation of read(). Unfortunately, Python 2 doesn't have a
readinto() in httplib's client, so we have to support both codepaths.
Subclassing is bad, folks.
Differential Revision: https://phab.mercurial-scm.org/D3246
--- a/mercurial/keepalive.py Thu Apr 12 17:22:59 2018 +0530
+++ b/mercurial/keepalive.py Wed Apr 11 14:39:49 2018 -0400
@@ -384,6 +384,7 @@
self._connection = None # (same)
_raw_read = httplib.HTTPResponse.read
+ _raw_readinto = getattr(httplib.HTTPResponse, 'readinto', None)
def close(self):
if self.fp:
@@ -523,12 +524,24 @@
return list
def readinto(self, dest):
- res = self.read(len(dest))
- if not res:
- return 0
-
- dest[0:len(res)] = res
- return len(res)
+ if self._raw_readinto is None:
+ res = self.read(len(dest))
+ if not res:
+ return 0
+ dest[0:len(res)] = res
+ return len(res)
+ total = len(dest)
+ have = len(self._rbuf)
+ if have >= total:
+ dest[0:total] = self._rbuf[:total]
+ self._rbuf = self._rbuf[total:]
+ return total
+ mv = memoryview(dest)
+ got = self._raw_readinto(mv[have:total])
+ dest[0:have] = self._rbuf
+ got += len(self._rbuf)
+ self._rbuf = ''
+ return got
def safesend(self, str):
"""Send `str' to the server.