Show More
@@ -37,6 +37,9 b' httplib, but has several additional feat' | |||||
37 | * implements ssl inline instead of in a different class |
|
37 | * implements ssl inline instead of in a different class | |
38 | """ |
|
38 | """ | |
39 |
|
39 | |||
|
40 | # Many functions in this file have too many arguments. | |||
|
41 | # pylint: disable=R0913 | |||
|
42 | ||||
40 | import cStringIO |
|
43 | import cStringIO | |
41 | import errno |
|
44 | import errno | |
42 | import httplib |
|
45 | import httplib | |
@@ -117,6 +120,8 b' class HTTPResponse(object):' | |||||
117 |
|
120 | |||
118 | def _close(self): |
|
121 | def _close(self): | |
119 | if self._reader is not None: |
|
122 | if self._reader is not None: | |
|
123 | # We're a friend of the reader class here. | |||
|
124 | # pylint: disable=W0212 | |||
120 | self._reader._close() |
|
125 | self._reader._close() | |
121 |
|
126 | |||
122 | def readline(self): |
|
127 | def readline(self): | |
@@ -137,6 +142,7 b' class HTTPResponse(object):' | |||||
137 | return ''.join(blocks) |
|
142 | return ''.join(blocks) | |
138 |
|
143 | |||
139 | def read(self, length=None): |
|
144 | def read(self, length=None): | |
|
145 | """Read data from the response body.""" | |||
140 | # if length is None, unbounded read |
|
146 | # if length is None, unbounded read | |
141 | while (not self.complete() # never select on a finished read |
|
147 | while (not self.complete() # never select on a finished read | |
142 | and (not length # unbounded, so we wait for complete() |
|
148 | and (not length # unbounded, so we wait for complete() | |
@@ -150,7 +156,8 b' class HTTPResponse(object):' | |||||
150 | return r |
|
156 | return r | |
151 |
|
157 | |||
152 | def _select(self): |
|
158 | def _select(self): | |
153 | r, _, _ = select.select([self.sock], [], [], self._timeout) |
|
159 | r, unused_write, unused_err = select.select( | |
|
160 | [self.sock], [], [], self._timeout) | |||
154 | if not r: |
|
161 | if not r: | |
155 | # socket was not readable. If the response is not |
|
162 | # socket was not readable. If the response is not | |
156 | # complete, raise a timeout. |
|
163 | # complete, raise a timeout. | |
@@ -170,13 +177,16 b' class HTTPResponse(object):' | |||||
170 | # raise an exception if this is an invalid situation. |
|
177 | # raise an exception if this is an invalid situation. | |
171 | if not data: |
|
178 | if not data: | |
172 | if self._reader: |
|
179 | if self._reader: | |
|
180 | # We're a friend of the reader class here. | |||
|
181 | # pylint: disable=W0212 | |||
173 | self._reader._close() |
|
182 | self._reader._close() | |
174 | return False |
|
183 | return False | |
175 | else: |
|
184 | else: | |
176 | self._load_response(data) |
|
185 | self._load_response(data) | |
177 | return True |
|
186 | return True | |
178 |
|
187 | |||
179 | def _load_response(self, data): |
|
188 | # This method gets replaced by _load later, which confuses pylint. | |
|
189 | def _load_response(self, data): # pylint: disable=E0202 | |||
180 | # Being here implies we're not at the end of the headers yet, |
|
190 | # Being here implies we're not at the end of the headers yet, | |
181 | # since at the end of this method if headers were completely |
|
191 | # since at the end of this method if headers were completely | |
182 | # loaded we replace this method with the load() method of the |
|
192 | # loaded we replace this method with the load() method of the | |
@@ -201,7 +211,7 b' class HTTPResponse(object):' | |||||
201 |
|
211 | |||
202 | # handle 100-continue response |
|
212 | # handle 100-continue response | |
203 | hdrs, body = self.raw_response.split(self._end_headers, 1) |
|
213 | hdrs, body = self.raw_response.split(self._end_headers, 1) | |
204 | http_ver, status = hdrs.split(' ', 1) |
|
214 | unused_http_ver, status = hdrs.split(' ', 1) | |
205 | if status.startswith('100'): |
|
215 | if status.startswith('100'): | |
206 | self.raw_response = body |
|
216 | self.raw_response = body | |
207 | self.continued = True |
|
217 | self.continued = True | |
@@ -260,9 +270,13 b' class HTTPResponse(object):' | |||||
260 | self.will_close = True |
|
270 | self.will_close = True | |
261 |
|
271 | |||
262 | if body: |
|
272 | if body: | |
|
273 | # We're a friend of the reader class here. | |||
|
274 | # pylint: disable=W0212 | |||
263 | self._reader._load(body) |
|
275 | self._reader._load(body) | |
264 | logger.debug('headers complete') |
|
276 | logger.debug('headers complete') | |
265 | self.headers = headers |
|
277 | self.headers = headers | |
|
278 | # We're a friend of the reader class here. | |||
|
279 | # pylint: disable=W0212 | |||
266 | self._load_response = self._reader._load |
|
280 | self._load_response = self._reader._load | |
267 |
|
281 | |||
268 |
|
282 | |||
@@ -335,9 +349,9 b' class HTTPConnection(object):' | |||||
335 | self._proxy_port)) |
|
349 | self._proxy_port)) | |
336 | if self.ssl: |
|
350 | if self.ssl: | |
337 | # TODO proxy header support |
|
351 | # TODO proxy header support | |
338 | data = self.buildheaders('CONNECT', '%s:%d' % (self.host, |
|
352 | data = self._buildheaders('CONNECT', '%s:%d' % (self.host, | |
339 | self.port), |
|
353 | self.port), | |
340 | {}, HTTP_VER_1_0) |
|
354 | {}, HTTP_VER_1_0) | |
341 | sock.send(data) |
|
355 | sock.send(data) | |
342 | sock.setblocking(0) |
|
356 | sock.setblocking(0) | |
343 | r = self.response_class(sock, self.timeout, 'CONNECT') |
|
357 | r = self.response_class(sock, self.timeout, 'CONNECT') | |
@@ -345,6 +359,9 b' class HTTPConnection(object):' | |||||
345 | 'Timed out waiting for CONNECT response from proxy') |
|
359 | 'Timed out waiting for CONNECT response from proxy') | |
346 | while not r.complete(): |
|
360 | while not r.complete(): | |
347 | try: |
|
361 | try: | |
|
362 | # We're a friend of the response class, so let | |||
|
363 | # us use the private attribute. | |||
|
364 | # pylint: disable=W0212 | |||
348 | if not r._select(): |
|
365 | if not r._select(): | |
349 | if not r.complete(): |
|
366 | if not r.complete(): | |
350 | raise timeout_exc |
|
367 | raise timeout_exc | |
@@ -376,7 +393,7 b' class HTTPConnection(object):' | |||||
376 | sock.setblocking(0) |
|
393 | sock.setblocking(0) | |
377 | self.sock = sock |
|
394 | self.sock = sock | |
378 |
|
395 | |||
379 | def buildheaders(self, method, path, headers, http_ver): |
|
396 | def _buildheaders(self, method, path, headers, http_ver): | |
380 | if self.ssl and self.port == 443 or self.port == 80: |
|
397 | if self.ssl and self.port == 443 or self.port == 80: | |
381 | # default port for protocol, so leave it out |
|
398 | # default port for protocol, so leave it out | |
382 | hdrhost = self.host |
|
399 | hdrhost = self.host | |
@@ -437,6 +454,11 b' class HTTPConnection(object):' | |||||
437 | return True |
|
454 | return True | |
438 | return False |
|
455 | return False | |
439 |
|
456 | |||
|
457 | def _reconnect(self, where): | |||
|
458 | logger.info('reconnecting during %s', where) | |||
|
459 | self.close() | |||
|
460 | self._connect() | |||
|
461 | ||||
440 | def request(self, method, path, body=None, headers={}, |
|
462 | def request(self, method, path, body=None, headers={}, | |
441 | expect_continue=False): |
|
463 | expect_continue=False): | |
442 | """Send a request to the server. |
|
464 | """Send a request to the server. | |
@@ -474,16 +496,11 b' class HTTPConnection(object):' | |||||
474 | raise BadRequestData('body has no __len__() nor read()') |
|
496 | raise BadRequestData('body has no __len__() nor read()') | |
475 |
|
497 | |||
476 | self._connect() |
|
498 | self._connect() | |
477 | outgoing_headers = self.buildheaders( |
|
499 | outgoing_headers = self._buildheaders( | |
478 | method, path, hdrs, self.http_version) |
|
500 | method, path, hdrs, self.http_version) | |
479 | response = None |
|
501 | response = None | |
480 | first = True |
|
502 | first = True | |
481 |
|
503 | |||
482 | def reconnect(where): |
|
|||
483 | logger.info('reconnecting during %s', where) |
|
|||
484 | self.close() |
|
|||
485 | self._connect() |
|
|||
486 |
|
||||
487 | while ((outgoing_headers or body) |
|
504 | while ((outgoing_headers or body) | |
488 | and not (response and response.complete())): |
|
505 | and not (response and response.complete())): | |
489 | select_timeout = self.timeout |
|
506 | select_timeout = self.timeout | |
@@ -523,14 +540,17 b' class HTTPConnection(object):' | |||||
523 | except socket.sslerror, e: |
|
540 | except socket.sslerror, e: | |
524 | if e.args[0] != socket.SSL_ERROR_WANT_READ: |
|
541 | if e.args[0] != socket.SSL_ERROR_WANT_READ: | |
525 | raise |
|
542 | raise | |
526 | logger.debug( |
|
543 | logger.debug('SSL_ERROR_WANT_READ while sending ' | |
527 |
' |
|
544 | 'data, retrying...') | |
528 | continue |
|
545 | continue | |
529 | if not data: |
|
546 | if not data: | |
530 | logger.info('socket appears closed in read') |
|
547 | logger.info('socket appears closed in read') | |
531 | self.sock = None |
|
548 | self.sock = None | |
532 | self._current_response = None |
|
549 | self._current_response = None | |
533 | if response is not None: |
|
550 | if response is not None: | |
|
551 | # We're a friend of the response class, so let | |||
|
552 | # us use the private attribute. | |||
|
553 | # pylint: disable=W0212 | |||
534 | response._close() |
|
554 | response._close() | |
535 | # This if/elif ladder is a bit subtle, |
|
555 | # This if/elif ladder is a bit subtle, | |
536 | # comments in each branch should help. |
|
556 | # comments in each branch should help. | |
@@ -550,7 +570,7 b' class HTTPConnection(object):' | |||||
550 | logger.info( |
|
570 | logger.info( | |
551 | 'Connection appeared closed in read on first' |
|
571 | 'Connection appeared closed in read on first' | |
552 | ' request loop iteration, will retry.') |
|
572 | ' request loop iteration, will retry.') | |
553 | reconnect('read') |
|
573 | self._reconnect('read') | |
554 | continue |
|
574 | continue | |
555 | else: |
|
575 | else: | |
556 | # We didn't just send the first data hunk, |
|
576 | # We didn't just send the first data hunk, | |
@@ -563,7 +583,11 b' class HTTPConnection(object):' | |||||
563 | 'response was missing or incomplete!') |
|
583 | 'response was missing or incomplete!') | |
564 | logger.debug('read %d bytes in request()', len(data)) |
|
584 | logger.debug('read %d bytes in request()', len(data)) | |
565 | if response is None: |
|
585 | if response is None: | |
566 |
response = self.response_class( |
|
586 | response = self.response_class( | |
|
587 | r[0], self.timeout, method) | |||
|
588 | # We're a friend of the response class, so let us | |||
|
589 | # use the private attribute. | |||
|
590 | # pylint: disable=W0212 | |||
567 | response._load_response(data) |
|
591 | response._load_response(data) | |
568 | # Jump to the next select() call so we load more |
|
592 | # Jump to the next select() call so we load more | |
569 | # data if the server is still sending us content. |
|
593 | # data if the server is still sending us content. | |
@@ -576,6 +600,8 b' class HTTPConnection(object):' | |||||
576 | if w and out: |
|
600 | if w and out: | |
577 | try: |
|
601 | try: | |
578 | if getattr(out, 'read', False): |
|
602 | if getattr(out, 'read', False): | |
|
603 | # pylint guesses the type of out incorrectly here | |||
|
604 | # pylint: disable=E1103 | |||
579 | data = out.read(OUTGOING_BUFFER_SIZE) |
|
605 | data = out.read(OUTGOING_BUFFER_SIZE) | |
580 | if not data: |
|
606 | if not data: | |
581 | continue |
|
607 | continue | |
@@ -599,14 +625,10 b' class HTTPConnection(object):' | |||||
599 | elif (e[0] not in (errno.ECONNRESET, errno.EPIPE) |
|
625 | elif (e[0] not in (errno.ECONNRESET, errno.EPIPE) | |
600 | and not first): |
|
626 | and not first): | |
601 | raise |
|
627 | raise | |
602 | reconnect('write') |
|
628 | self._reconnect('write') | |
603 | amt = self.sock.send(out) |
|
629 | amt = self.sock.send(out) | |
604 | logger.debug('sent %d', amt) |
|
630 | logger.debug('sent %d', amt) | |
605 | first = False |
|
631 | first = False | |
606 | # stash data we think we sent in case the socket breaks |
|
|||
607 | # when we read from it |
|
|||
608 | if was_first: |
|
|||
609 | sent_data = out[:amt] |
|
|||
610 | if out is body: |
|
632 | if out is body: | |
611 | body = out[amt:] |
|
633 | body = out[amt:] | |
612 | else: |
|
634 | else: | |
@@ -616,7 +638,6 b' class HTTPConnection(object):' | |||||
616 | # the whole request |
|
638 | # the whole request | |
617 | if response is None: |
|
639 | if response is None: | |
618 | response = self.response_class(self.sock, self.timeout, method) |
|
640 | response = self.response_class(self.sock, self.timeout, method) | |
619 | complete = response.complete() |
|
|||
620 | data_left = bool(outgoing_headers or body) |
|
641 | data_left = bool(outgoing_headers or body) | |
621 | if data_left: |
|
642 | if data_left: | |
622 | logger.info('stopped sending request early, ' |
|
643 | logger.info('stopped sending request early, ' | |
@@ -629,10 +650,14 b' class HTTPConnection(object):' | |||||
629 | self._current_response = response |
|
650 | self._current_response = response | |
630 |
|
651 | |||
631 | def getresponse(self): |
|
652 | def getresponse(self): | |
|
653 | """Returns the response to the most recent request.""" | |||
632 | if self._current_response is None: |
|
654 | if self._current_response is None: | |
633 | raise httplib.ResponseNotReady() |
|
655 | raise httplib.ResponseNotReady() | |
634 | r = self._current_response |
|
656 | r = self._current_response | |
635 | while r.headers is None: |
|
657 | while r.headers is None: | |
|
658 | # We're a friend of the response class, so let us use the | |||
|
659 | # private attribute. | |||
|
660 | # pylint: disable=W0212 | |||
636 | if not r._select() and not r.complete(): |
|
661 | if not r._select() and not r.complete(): | |
637 | raise _readers.HTTPRemoteClosedError() |
|
662 | raise _readers.HTTPRemoteClosedError() | |
638 | if r.will_close: |
|
663 | if r.will_close: |
@@ -33,7 +33,6 b' have any clients outside of httpplus.' | |||||
33 | """ |
|
33 | """ | |
34 |
|
34 | |||
35 | import httplib |
|
35 | import httplib | |
36 | import itertools |
|
|||
37 | import logging |
|
36 | import logging | |
38 |
|
37 | |||
39 | logger = logging.getLogger(__name__) |
|
38 | logger = logging.getLogger(__name__) | |
@@ -59,33 +58,35 b' class AbstractReader(object):' | |||||
59 | self._done_chunks = [] |
|
58 | self._done_chunks = [] | |
60 | self.available_data = 0 |
|
59 | self.available_data = 0 | |
61 |
|
60 | |||
62 | def addchunk(self, data): |
|
61 | def _addchunk(self, data): | |
63 | self._done_chunks.append(data) |
|
62 | self._done_chunks.append(data) | |
64 | self.available_data += len(data) |
|
63 | self.available_data += len(data) | |
65 |
|
64 | |||
66 | def pushchunk(self, data): |
|
65 | def _pushchunk(self, data): | |
67 | self._done_chunks.insert(0, data) |
|
66 | self._done_chunks.insert(0, data) | |
68 | self.available_data += len(data) |
|
67 | self.available_data += len(data) | |
69 |
|
68 | |||
70 | def popchunk(self): |
|
69 | def _popchunk(self): | |
71 | b = self._done_chunks.pop(0) |
|
70 | b = self._done_chunks.pop(0) | |
72 | self.available_data -= len(b) |
|
71 | self.available_data -= len(b) | |
73 |
|
72 | |||
74 | return b |
|
73 | return b | |
75 |
|
74 | |||
76 | def done(self): |
|
75 | def done(self): | |
|
76 | """Returns true if the response body is entirely read.""" | |||
77 | return self._finished |
|
77 | return self._finished | |
78 |
|
78 | |||
79 | def read(self, amt): |
|
79 | def read(self, amt): | |
|
80 | """Read amt bytes from the response body.""" | |||
80 | if self.available_data < amt and not self._finished: |
|
81 | if self.available_data < amt and not self._finished: | |
81 | raise ReadNotReady() |
|
82 | raise ReadNotReady() | |
82 | blocks = [] |
|
83 | blocks = [] | |
83 | need = amt |
|
84 | need = amt | |
84 | while self._done_chunks: |
|
85 | while self._done_chunks: | |
85 | b = self.popchunk() |
|
86 | b = self._popchunk() | |
86 | if len(b) > need: |
|
87 | if len(b) > need: | |
87 | nb = b[:need] |
|
88 | nb = b[:need] | |
88 | self.pushchunk(b[need:]) |
|
89 | self._pushchunk(b[need:]) | |
89 | b = nb |
|
90 | b = nb | |
90 | blocks.append(b) |
|
91 | blocks.append(b) | |
91 | need -= len(b) |
|
92 | need -= len(b) | |
@@ -107,11 +108,11 b' class AbstractReader(object):' | |||||
107 | blocks = [] |
|
108 | blocks = [] | |
108 |
|
109 | |||
109 | while self._done_chunks: |
|
110 | while self._done_chunks: | |
110 | b = self.popchunk() |
|
111 | b = self._popchunk() | |
111 | i = b.find(delimstr) + len(delimstr) |
|
112 | i = b.find(delimstr) + len(delimstr) | |
112 | if i: |
|
113 | if i: | |
113 | if i < len(b): |
|
114 | if i < len(b): | |
114 | self.pushchunk(b[i:]) |
|
115 | self._pushchunk(b[i:]) | |
115 | blocks.append(b[:i]) |
|
116 | blocks.append(b[:i]) | |
116 | break |
|
117 | break | |
117 | else: |
|
118 | else: | |
@@ -154,8 +155,9 b' class AbstractSimpleReader(AbstractReade' | |||||
154 | if data: |
|
155 | if data: | |
155 | assert not self._finished, ( |
|
156 | assert not self._finished, ( | |
156 | 'tried to add data (%r) to a closed reader!' % data) |
|
157 | 'tried to add data (%r) to a closed reader!' % data) | |
157 |
logger.debug('%s read an additional %d data', |
|
158 | logger.debug('%s read an additional %d data', | |
158 | self.addchunk(data) |
|
159 | self.name, len(data)) # pylint: disable=E1101 | |
|
160 | self._addchunk(data) | |||
159 |
|
161 | |||
160 |
|
162 | |||
161 | class CloseIsEndReader(AbstractSimpleReader): |
|
163 | class CloseIsEndReader(AbstractSimpleReader): | |
@@ -172,7 +174,7 b' class ContentLengthReader(AbstractSimple' | |||||
172 | name = 'content-length' |
|
174 | name = 'content-length' | |
173 |
|
175 | |||
174 | def __init__(self, amount): |
|
176 | def __init__(self, amount): | |
175 | AbstractReader.__init__(self) |
|
177 | AbstractSimpleReader.__init__(self) | |
176 | self._amount = amount |
|
178 | self._amount = amount | |
177 | if amount == 0: |
|
179 | if amount == 0: | |
178 | self._finished = True |
|
180 | self._finished = True | |
@@ -199,7 +201,8 b' class ChunkedReader(AbstractReader):' | |||||
199 | logger.debug('chunked read an additional %d data', len(data)) |
|
201 | logger.debug('chunked read an additional %d data', len(data)) | |
200 | position = 0 |
|
202 | position = 0 | |
201 | if self._leftover_data: |
|
203 | if self._leftover_data: | |
202 | logger.debug('chunked reader trying to finish block from leftover data') |
|
204 | logger.debug( | |
|
205 | 'chunked reader trying to finish block from leftover data') | |||
203 | # TODO: avoid this string concatenation if possible |
|
206 | # TODO: avoid this string concatenation if possible | |
204 | data = self._leftover_data + data |
|
207 | data = self._leftover_data + data | |
205 | position = self._leftover_skip_amt |
|
208 | position = self._leftover_skip_amt | |
@@ -224,6 +227,6 b' class ChunkedReader(AbstractReader):' | |||||
224 | self._finished = True |
|
227 | self._finished = True | |
225 | logger.debug('closing chunked reader due to chunk of length 0') |
|
228 | logger.debug('closing chunked reader due to chunk of length 0') | |
226 | return |
|
229 | return | |
227 | self.addchunk(data[block_start:block_start + amt]) |
|
230 | self._addchunk(data[block_start:block_start + amt]) | |
228 | position = block_start + amt + len(self._eol) |
|
231 | position = block_start + amt + len(self._eol) | |
229 | # no-check-code |
|
232 | # no-check-code |
@@ -39,7 +39,8 b' logger = logging.getLogger(__name__)' | |||||
39 |
|
39 | |||
40 | try: |
|
40 | try: | |
41 | import ssl |
|
41 | import ssl | |
42 |
|
|
42 | # make demandimporters load the module | |
|
43 | ssl.wrap_socket # pylint: disable=W0104 | |||
43 | have_ssl = True |
|
44 | have_ssl = True | |
44 | except ImportError: |
|
45 | except ImportError: | |
45 | import httplib |
|
46 | import httplib | |
@@ -52,12 +53,13 b' try:' | |||||
52 | create_connection = socket.create_connection |
|
53 | create_connection = socket.create_connection | |
53 | except AttributeError: |
|
54 | except AttributeError: | |
54 | def create_connection(address): |
|
55 | def create_connection(address): | |
|
56 | """Backport of socket.create_connection from Python 2.6.""" | |||
55 | host, port = address |
|
57 | host, port = address | |
56 | msg = "getaddrinfo returns an empty list" |
|
58 | msg = "getaddrinfo returns an empty list" | |
57 | sock = None |
|
59 | sock = None | |
58 | for res in socket.getaddrinfo(host, port, 0, |
|
60 | for res in socket.getaddrinfo(host, port, 0, | |
59 | socket.SOCK_STREAM): |
|
61 | socket.SOCK_STREAM): | |
60 | af, socktype, proto, _canonname, sa = res |
|
62 | af, socktype, proto, unused_canonname, sa = res | |
61 | try: |
|
63 | try: | |
62 | sock = socket.socket(af, socktype, proto) |
|
64 | sock = socket.socket(af, socktype, proto) | |
63 | logger.info("connect: (%s, %s)", host, port) |
|
65 | logger.info("connect: (%s, %s)", host, port) | |
@@ -80,8 +82,11 b' if ssl:' | |||||
80 | CERT_REQUIRED = ssl.CERT_REQUIRED |
|
82 | CERT_REQUIRED = ssl.CERT_REQUIRED | |
81 | else: |
|
83 | else: | |
82 | class FakeSocket(httplib.FakeSocket): |
|
84 | class FakeSocket(httplib.FakeSocket): | |
83 | """Socket wrapper that supports SSL. |
|
85 | """Socket wrapper that supports SSL.""" | |
84 | """ |
|
86 | ||
|
87 | # Silence lint about this goofy backport class | |||
|
88 | # pylint: disable=W0232,E1101,R0903,R0913,C0111 | |||
|
89 | ||||
85 | # backport the behavior from Python 2.6, which is to busy wait |
|
90 | # backport the behavior from Python 2.6, which is to busy wait | |
86 | # on the socket instead of anything nice. Sigh. |
|
91 | # on the socket instead of anything nice. Sigh. | |
87 | # See http://bugs.python.org/issue3890 for more info. |
|
92 | # See http://bugs.python.org/issue3890 for more info. | |
@@ -107,11 +112,16 b' else:' | |||||
107 | CERT_OPTIONAL = 1 |
|
112 | CERT_OPTIONAL = 1 | |
108 | CERT_REQUIRED = 2 |
|
113 | CERT_REQUIRED = 2 | |
109 |
|
114 | |||
|
115 | # Disable unused-argument because we're making a dumb wrapper | |||
|
116 | # that's like an upstream method. | |||
|
117 | # | |||
|
118 | # pylint: disable=W0613,R0913 | |||
110 | def wrap_socket(sock, keyfile=None, certfile=None, |
|
119 | def wrap_socket(sock, keyfile=None, certfile=None, | |
111 | server_side=False, cert_reqs=CERT_NONE, |
|
120 | server_side=False, cert_reqs=CERT_NONE, | |
112 | ssl_version=_PROTOCOL_SSLv23, ca_certs=None, |
|
121 | ssl_version=_PROTOCOL_SSLv23, ca_certs=None, | |
113 | do_handshake_on_connect=True, |
|
122 | do_handshake_on_connect=True, | |
114 | suppress_ragged_eofs=True): |
|
123 | suppress_ragged_eofs=True): | |
|
124 | """Backport of ssl.wrap_socket from Python 2.6.""" | |||
115 | if cert_reqs != CERT_NONE and ca_certs: |
|
125 | if cert_reqs != CERT_NONE and ca_certs: | |
116 | raise CertificateValidationUnsupported( |
|
126 | raise CertificateValidationUnsupported( | |
117 | 'SSL certificate validation requires the ssl module' |
|
127 | 'SSL certificate validation requires the ssl module' | |
@@ -120,6 +130,7 b' else:' | |||||
120 | # borrow httplib's workaround for no ssl.wrap_socket |
|
130 | # borrow httplib's workaround for no ssl.wrap_socket | |
121 | sock = FakeSocket(sock, sslob) |
|
131 | sock = FakeSocket(sock, sslob) | |
122 | return sock |
|
132 | return sock | |
|
133 | # pylint: enable=W0613,R0913 | |||
123 |
|
134 | |||
124 |
|
135 | |||
125 | class CertificateValidationUnsupported(Exception): |
|
136 | class CertificateValidationUnsupported(Exception): |
General Comments 0
You need to be logged in to leave comments.
Login now