--- a/mercurial/httpclient/__init__.py Wed May 08 20:55:56 2013 +0200
+++ b/mercurial/httpclient/__init__.py Sat May 11 20:25:15 2013 -0500
@@ -37,6 +37,9 @@
* implements ssl inline instead of in a different class
"""
+# Many functions in this file have too many arguments.
+# pylint: disable=R0913
+
import cStringIO
import errno
import httplib
@@ -117,6 +120,8 @@
def _close(self):
if self._reader is not None:
+ # We're a friend of the reader class here.
+ # pylint: disable=W0212
self._reader._close()
def readline(self):
@@ -137,6 +142,7 @@
return ''.join(blocks)
def read(self, length=None):
+ """Read data from the response body."""
# if length is None, unbounded read
while (not self.complete() # never select on a finished read
and (not length # unbounded, so we wait for complete()
@@ -150,7 +156,8 @@
return r
def _select(self):
- r, _, _ = select.select([self.sock], [], [], self._timeout)
+ r, unused_write, unused_err = select.select(
+ [self.sock], [], [], self._timeout)
if not r:
# socket was not readable. If the response is not
# complete, raise a timeout.
@@ -170,13 +177,16 @@
# raise an exception if this is an invalid situation.
if not data:
if self._reader:
+ # We're a friend of the reader class here.
+ # pylint: disable=W0212
self._reader._close()
return False
else:
self._load_response(data)
return True
- def _load_response(self, data):
+ # This method gets replaced by _load later, which confuses pylint.
+ def _load_response(self, data): # pylint: disable=E0202
# Being here implies we're not at the end of the headers yet,
# since at the end of this method if headers were completely
# loaded we replace this method with the load() method of the
@@ -201,7 +211,7 @@
# handle 100-continue response
hdrs, body = self.raw_response.split(self._end_headers, 1)
- http_ver, status = hdrs.split(' ', 1)
+ unused_http_ver, status = hdrs.split(' ', 1)
if status.startswith('100'):
self.raw_response = body
self.continued = True
@@ -260,9 +270,13 @@
self.will_close = True
if body:
+ # We're a friend of the reader class here.
+ # pylint: disable=W0212
self._reader._load(body)
logger.debug('headers complete')
self.headers = headers
+ # We're a friend of the reader class here.
+ # pylint: disable=W0212
self._load_response = self._reader._load
@@ -335,9 +349,9 @@
self._proxy_port))
if self.ssl:
# TODO proxy header support
- data = self.buildheaders('CONNECT', '%s:%d' % (self.host,
- self.port),
- {}, HTTP_VER_1_0)
+ data = self._buildheaders('CONNECT', '%s:%d' % (self.host,
+ self.port),
+ {}, HTTP_VER_1_0)
sock.send(data)
sock.setblocking(0)
r = self.response_class(sock, self.timeout, 'CONNECT')
@@ -345,6 +359,9 @@
'Timed out waiting for CONNECT response from proxy')
while not r.complete():
try:
+ # We're a friend of the response class, so let
+ # us use the private attribute.
+ # pylint: disable=W0212
if not r._select():
if not r.complete():
raise timeout_exc
@@ -376,7 +393,7 @@
sock.setblocking(0)
self.sock = sock
- def buildheaders(self, method, path, headers, http_ver):
+ def _buildheaders(self, method, path, headers, http_ver):
if self.ssl and self.port == 443 or self.port == 80:
# default port for protocol, so leave it out
hdrhost = self.host
@@ -437,6 +454,11 @@
return True
return False
+ def _reconnect(self, where):
+ logger.info('reconnecting during %s', where)
+ self.close()
+ self._connect()
+
def request(self, method, path, body=None, headers={},
expect_continue=False):
"""Send a request to the server.
@@ -474,16 +496,11 @@
raise BadRequestData('body has no __len__() nor read()')
self._connect()
- outgoing_headers = self.buildheaders(
+ outgoing_headers = self._buildheaders(
method, path, hdrs, self.http_version)
response = None
first = True
- def reconnect(where):
- logger.info('reconnecting during %s', where)
- self.close()
- self._connect()
-
while ((outgoing_headers or body)
and not (response and response.complete())):
select_timeout = self.timeout
@@ -523,14 +540,17 @@
except socket.sslerror, e:
if e.args[0] != socket.SSL_ERROR_WANT_READ:
raise
- logger.debug(
- 'SSL_ERROR_WANT_READ while sending data, retrying...')
+ logger.debug('SSL_ERROR_WANT_READ while sending '
+ 'data, retrying...')
continue
if not data:
logger.info('socket appears closed in read')
self.sock = None
self._current_response = None
if response is not None:
+ # We're a friend of the response class, so let
+ # us use the private attribute.
+ # pylint: disable=W0212
response._close()
# This if/elif ladder is a bit subtle,
# comments in each branch should help.
@@ -550,7 +570,7 @@
logger.info(
'Connection appeared closed in read on first'
' request loop iteration, will retry.')
- reconnect('read')
+ self._reconnect('read')
continue
else:
# We didn't just send the first data hunk,
@@ -563,7 +583,11 @@
'response was missing or incomplete!')
logger.debug('read %d bytes in request()', len(data))
if response is None:
- response = self.response_class(r[0], self.timeout, method)
+ response = self.response_class(
+ r[0], self.timeout, method)
+ # We're a friend of the response class, so let us
+ # use the private attribute.
+ # pylint: disable=W0212
response._load_response(data)
# Jump to the next select() call so we load more
# data if the server is still sending us content.
@@ -576,6 +600,8 @@
if w and out:
try:
if getattr(out, 'read', False):
+ # pylint guesses the type of out incorrectly here
+ # pylint: disable=E1103
data = out.read(OUTGOING_BUFFER_SIZE)
if not data:
continue
@@ -599,14 +625,10 @@
elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
and not first):
raise
- reconnect('write')
+ self._reconnect('write')
amt = self.sock.send(out)
logger.debug('sent %d', amt)
first = False
- # stash data we think we sent in case the socket breaks
- # when we read from it
- if was_first:
- sent_data = out[:amt]
if out is body:
body = out[amt:]
else:
@@ -616,7 +638,6 @@
# the whole request
if response is None:
response = self.response_class(self.sock, self.timeout, method)
- complete = response.complete()
data_left = bool(outgoing_headers or body)
if data_left:
logger.info('stopped sending request early, '
@@ -629,10 +650,14 @@
self._current_response = response
def getresponse(self):
+ """Returns the response to the most recent request."""
if self._current_response is None:
raise httplib.ResponseNotReady()
r = self._current_response
while r.headers is None:
+ # We're a friend of the response class, so let us use the
+ # private attribute.
+ # pylint: disable=W0212
if not r._select() and not r.complete():
raise _readers.HTTPRemoteClosedError()
if r.will_close:
--- a/mercurial/httpclient/_readers.py Wed May 08 20:55:56 2013 +0200
+++ b/mercurial/httpclient/_readers.py Sat May 11 20:25:15 2013 -0500
@@ -33,7 +33,6 @@
"""
import httplib
-import itertools
import logging
logger = logging.getLogger(__name__)
@@ -59,33 +58,35 @@
self._done_chunks = []
self.available_data = 0
- def addchunk(self, data):
+ def _addchunk(self, data):
self._done_chunks.append(data)
self.available_data += len(data)
- def pushchunk(self, data):
+ def _pushchunk(self, data):
self._done_chunks.insert(0, data)
self.available_data += len(data)
- def popchunk(self):
+ def _popchunk(self):
b = self._done_chunks.pop(0)
self.available_data -= len(b)
return b
def done(self):
+ """Returns true if the response body is entirely read."""
return self._finished
def read(self, amt):
+ """Read amt bytes from the response body."""
if self.available_data < amt and not self._finished:
raise ReadNotReady()
blocks = []
need = amt
while self._done_chunks:
- b = self.popchunk()
+ b = self._popchunk()
if len(b) > need:
nb = b[:need]
- self.pushchunk(b[need:])
+ self._pushchunk(b[need:])
b = nb
blocks.append(b)
need -= len(b)
@@ -107,11 +108,11 @@
blocks = []
while self._done_chunks:
- b = self.popchunk()
+ b = self._popchunk()
i = b.find(delimstr) + len(delimstr)
if i:
if i < len(b):
- self.pushchunk(b[i:])
+ self._pushchunk(b[i:])
blocks.append(b[:i])
break
else:
@@ -154,8 +155,9 @@
if data:
assert not self._finished, (
'tried to add data (%r) to a closed reader!' % data)
- logger.debug('%s read an additional %d data', self.name, len(data))
- self.addchunk(data)
+ logger.debug('%s read an additional %d data',
+ self.name, len(data)) # pylint: disable=E1101
+ self._addchunk(data)
class CloseIsEndReader(AbstractSimpleReader):
@@ -172,7 +174,7 @@
name = 'content-length'
def __init__(self, amount):
- AbstractReader.__init__(self)
+ AbstractSimpleReader.__init__(self)
self._amount = amount
if amount == 0:
self._finished = True
@@ -199,7 +201,8 @@
logger.debug('chunked read an additional %d data', len(data))
position = 0
if self._leftover_data:
- logger.debug('chunked reader trying to finish block from leftover data')
+ logger.debug(
+ 'chunked reader trying to finish block from leftover data')
# TODO: avoid this string concatenation if possible
data = self._leftover_data + data
position = self._leftover_skip_amt
@@ -224,6 +227,6 @@
self._finished = True
logger.debug('closing chunked reader due to chunk of length 0')
return
- self.addchunk(data[block_start:block_start + amt])
+ self._addchunk(data[block_start:block_start + amt])
position = block_start + amt + len(self._eol)
# no-check-code
--- a/mercurial/httpclient/socketutil.py Wed May 08 20:55:56 2013 +0200
+++ b/mercurial/httpclient/socketutil.py Sat May 11 20:25:15 2013 -0500
@@ -39,7 +39,8 @@
try:
import ssl
- ssl.wrap_socket # make demandimporters load the module
+ # make demandimporters load the module
+ ssl.wrap_socket # pylint: disable=W0104
have_ssl = True
except ImportError:
import httplib
@@ -52,12 +53,13 @@
create_connection = socket.create_connection
except AttributeError:
def create_connection(address):
+ """Backport of socket.create_connection from Python 2.6."""
host, port = address
msg = "getaddrinfo returns an empty list"
sock = None
for res in socket.getaddrinfo(host, port, 0,
socket.SOCK_STREAM):
- af, socktype, proto, _canonname, sa = res
+ af, socktype, proto, unused_canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
logger.info("connect: (%s, %s)", host, port)
@@ -80,8 +82,11 @@
CERT_REQUIRED = ssl.CERT_REQUIRED
else:
class FakeSocket(httplib.FakeSocket):
- """Socket wrapper that supports SSL.
- """
+ """Socket wrapper that supports SSL."""
+
+ # Silence lint about this goofy backport class
+ # pylint: disable=W0232,E1101,R0903,R0913,C0111
+
# backport the behavior from Python 2.6, which is to busy wait
# on the socket instead of anything nice. Sigh.
# See http://bugs.python.org/issue3890 for more info.
@@ -107,11 +112,16 @@
CERT_OPTIONAL = 1
CERT_REQUIRED = 2
+ # Disable unused-argument because we're making a dumb wrapper
+ # that's like an upstream method.
+ #
+ # pylint: disable=W0613,R0913
def wrap_socket(sock, keyfile=None, certfile=None,
server_side=False, cert_reqs=CERT_NONE,
ssl_version=_PROTOCOL_SSLv23, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True):
+ """Backport of ssl.wrap_socket from Python 2.6."""
if cert_reqs != CERT_NONE and ca_certs:
raise CertificateValidationUnsupported(
'SSL certificate validation requires the ssl module'
@@ -120,6 +130,7 @@
# borrow httplib's workaround for no ssl.wrap_socket
sock = FakeSocket(sock, sslob)
return sock
+ # pylint: enable=W0613,R0913
class CertificateValidationUnsupported(Exception):