1212# Lesser General Public License for more details.
1313#
1414# You should have received a copy of the GNU Lesser General Public
15- # License along with this library; if not, write to the
16- # Free Software Foundation, Inc.,
17- # 59 Temple Place, Suite 330,
15+ # License along with this library; if not, write to the
16+ # Free Software Foundation, Inc.,
17+ # 59 Temple Place, Suite 330,
1818# Boston, MA 02111-1307 USA
1919
2020# This file was part of urlgrabber, a high-level cross-protocol url-grabber
2828>>> keepalive_handler = HTTPHandler()
2929>>> opener = _urllib.request.build_opener(keepalive_handler)
3030>>> _urllib.request.install_opener(opener)
31- >>>
31+ >>>
3232>>> fo = _urllib.request.urlopen('http://www.python.org')
3333
3434If a connection to a given host is requested, and all of the existing
@@ -154,14 +154,18 @@ def remove(self, connection):
154154 else :
155155 del self ._connmap [connection ]
156156 del self ._readymap [connection ]
157- self ._hostmap [host ].remove (connection )
157+ try :
158+ self ._hostmap [host ].remove (connection )
159+ except ValueError :
160+ pass
158161 if not self ._hostmap [host ]: del self ._hostmap [host ]
159162 finally :
160163 self ._lock .release ()
161164
162165 def set_ready (self , connection , ready ):
163- try : self ._readymap [connection ] = ready
164- except KeyError : pass
166+ self ._lock .acquire ()
167+ if connection in self ._readymap : self ._readymap [connection ] = ready
168+ self ._lock .release ()
165169
166170 def get_ready_conn (self , host ):
167171 conn = None
@@ -178,10 +182,14 @@ def get_ready_conn(self, host):
178182 return conn
179183
180184 def get_all (self , host = None ):
181- if host :
182- return list (self ._hostmap .get (host , []))
183- else :
184- return dict (self ._hostmap )
185+ self ._lock .acquire ()
186+ try :
187+ if host :
188+ return list (self ._hostmap .get (host , []))
189+ else :
190+ return dict (self ._hostmap )
191+ finally :
192+ self ._lock .release ()
185193
186194class KeepAliveHandler :
187195 def __init__ (self ):
@@ -242,9 +250,9 @@ def do_open(self, req):
242250 h = self ._get_connection (host )
243251 if DEBUG : DEBUG .info ("creating new connection to %s (%d)" ,
244252 host , id (h ))
245- self ._cm .add (host , h , 0 )
246253 self ._start_transaction (h , req )
247254 r = h .getresponse ()
255+ self ._cm .add (host , h , 0 )
248256 except (socket .error , _http_client .HTTPException ) as err :
249257 raise _urllib .error .URLError (err )
250258
@@ -254,20 +262,20 @@ def do_open(self, req):
254262 if r .will_close :
255263 if DEBUG : DEBUG .info ('server will close connection, discarding' )
256264 self ._cm .remove (h )
265+ h .close ()
257266
258267 r ._handler = self
259268 r ._host = host
260269 r ._url = req .get_full_url ()
261270 r ._connection = h
262271 r .code = r .status
263272 r .headers = r .msg
264- r .msg = r .reason
265273
266274 if r .status == 200 or not HANDLE_ERRORS :
267275 return r
268276 else :
269277 return self .parent .error ('http' , req , r ,
270- r .status , r .msg , r .headers )
278+ r .status , r .reason , r .headers )
271279
272280 def _reuse_connection (self , h , req , host ):
273281 """start the transaction with a re-used connection
@@ -283,7 +291,7 @@ def _reuse_connection(self, h, req, host):
283291 # worked. We'll check the version below, too.
284292 except (socket .error , _http_client .HTTPException ):
285293 r = None
286- except :
294+ except Exception :
287295 # adding this block just in case we've missed
288296 # something we will still raise the exception, but
289297 # lets try and close the connection and remove it
@@ -314,16 +322,16 @@ def _reuse_connection(self, h, req, host):
314322
315323 def _start_transaction (self , h , req ):
316324 try :
317- if req .data :
325+ if req .data is not None :
318326 data = req .data
319327 if hasattr (req , 'selector' ):
320328 h .putrequest (req .get_method () or 'POST' , req .selector , skip_host = req .has_header ("Host" ), skip_accept_encoding = req .has_header ("Accept-encoding" ))
321329 else :
322330 h .putrequest (req .get_method () or 'POST' , req .get_selector (), skip_host = req .has_header ("Host" ), skip_accept_encoding = req .has_header ("Accept-encoding" ))
323- if 'Content-type' not in req . headers :
331+ if not req . has_header ( 'Content-type' ) :
324332 h .putheader ('Content-type' ,
325333 'application/x-www-form-urlencoded' )
326- if 'Content-length' not in req . headers :
334+ if not req . has_header ( 'Content-length' ) :
327335 h .putheader ('Content-length' , '%d' % len (data ))
328336 else :
329337 if hasattr (req , 'selector' ):
@@ -333,20 +341,20 @@ def _start_transaction(self, h, req):
333341 except (socket .error , _http_client .HTTPException ) as err :
334342 raise _urllib .error .URLError (err )
335343
336- if 'Connection' not in req .headers :
337- req . headers [ 'Connection' ] = 'keep-alive'
344+ if not req .has_header ( 'Connection' ) :
345+ h . putheader ( 'Connection' , 'keep-alive' )
338346
339347 for args in self .parent .addheaders :
340- if args [ 0 ] not in req .headers :
348+ if not req .has_header ( args [ 0 ]) :
341349 h .putheader (* args )
342350 for k , v in req .headers .items ():
343351 h .putheader (k , v )
344352 h .endheaders ()
345- if req .data :
353+ if req .data is not None :
346354 h .send (data )
347355
348356 def _get_connection (self , host ):
349- return NotImplementedError
357+ raise NotImplementedError ()
350358
351359class HTTPHandler (KeepAliveHandler , _urllib .request .HTTPHandler ):
352360 def __init__ (self ):
@@ -373,8 +381,10 @@ def https_open(self, req):
373381 return self .do_open (req )
374382
375383 def _get_connection (self , host ):
376- try : return self ._ssl_factory .get_https_connection (host )
377- except AttributeError : return HTTPSConnection (host )
384+ if self ._ssl_factory :
385+ return self ._ssl_factory .get_https_connection (host )
386+ else :
387+ return HTTPSConnection (host )
378388
379389class HTTPResponse (_http_client .HTTPResponse ):
380390 # we need to subclass HTTPResponse in order to
@@ -397,9 +407,9 @@ class HTTPResponse(_http_client.HTTPResponse):
397407
398408
399409 def __init__ (self , sock , debuglevel = 0 , strict = 0 , method = None ):
400- if method : # the httplib in python 2.3 uses the method arg
401- _http_client .HTTPResponse .__init__ (self , sock , debuglevel , method )
402- else : # 2.2 doesn't
410+ if method :
411+ _http_client .HTTPResponse .__init__ (self , sock , debuglevel , method = method )
412+ else :
403413 _http_client .HTTPResponse .__init__ (self , sock , debuglevel )
404414 self .fileno = sock .fileno
405415 self .code = None
@@ -453,11 +463,11 @@ def read(self, amt=None):
453463
454464 def readline (self , limit = - 1 ):
455465 data = b""
456- i = self ._rbuf .find ('\n ' )
466+ i = self ._rbuf .find (b '\n ' )
457467 while i < 0 and not (0 < limit <= len (self ._rbuf )):
458468 new = self ._raw_read (self ._rbufsize )
459469 if not new : break
460- i = new .find ('\n ' )
470+ i = new .find (b '\n ' )
461471 if i >= 0 : i = i + len (self ._rbuf )
462472 self ._rbuf = self ._rbuf + new
463473 if i < 0 : i = len (self ._rbuf )
@@ -468,15 +478,15 @@ def readline(self, limit=-1):
468478
469479 def readlines (self , sizehint = 0 ):
470480 total = 0
471- list = []
481+ lines = []
472482 while 1 :
473483 line = self .readline ()
474484 if not line : break
475- list .append (line )
485+ lines .append (line )
476486 total += len (line )
477487 if sizehint and total >= sizehint :
478488 break
479- return list
489+ return lines
480490
481491
482492class HTTPConnection (_http_client .HTTPConnection ):
@@ -540,10 +550,10 @@ def continuity(url):
540550 print (format % ('keepalive read' , m .hexdigest ()))
541551
542552 fo = _urllib .request .urlopen (url )
543- foo = ''
553+ foo = b ''
544554 while 1 :
545555 f = fo .readline ()
546- if f : foo = foo + f
556+ if f : foo += f
547557 else : break
548558 fo .close ()
549559 m = md5 (foo )
0 commit comments