@@ -267,6 +267,7 @@ def add_handler(self, handler):
267267 protocol = meth [:- 5 ]
268268 if protocol in self .handle_open :
269269 self .handle_open [protocol ].append (handler )
270+ self .handle_open [protocol ].sort ()
270271 else :
271272 self .handle_open [protocol ] = [handler ]
272273 added = 1
@@ -283,13 +284,15 @@ def add_handler(self, handler):
283284 dict = self .handle_error .get (proto , {})
284285 if kind in dict :
285286 dict [kind ].append (handler )
287+ dict [kind ].sort ()
286288 else :
287289 dict [kind ] = [handler ]
288290 self .handle_error [proto ] = dict
289291 added = 1
290292 continue
291293 if added :
292294 self .handlers .append (handler )
295+ self .handlers .sort ()
293296 handler .add_parent (self )
294297
295298 def __del__ (self ):
@@ -355,17 +358,15 @@ def error(self, proto, *args):
355358 args = (dict , 'default' , 'http_error_default' ) + orig_args
356359 return self ._call_chain (* args )
357360
358- # XXX probably also want an abstract factory that knows things like
359- # the fact that a ProxyHandler needs to get inserted first.
360- # would also know when it makes sense to skip a superclass in favor of
361- # a subclass and when it might make sense to include both
361+ # XXX probably also want an abstract factory that knows when it makes
362+ # sense to skip a superclass in favor of a subclass and when it might
363+ # make sense to include both
362364
363365def build_opener (* handlers ):
364366 """Create an opener object from a list of handlers.
365367
366368 The opener will use several default handlers, including support
367- for HTTP and FTP. If there is a ProxyHandler, it must be at the
368- front of the list of handlers. (Yuck.)
369+ for HTTP and FTP.
369370
370371 If any of the handlers passed as arguments are subclasses of the
371372 default handlers, the default handlers will not be used.
@@ -398,10 +399,20 @@ def build_opener(*handlers):
398399 return opener
399400
400401class BaseHandler :
402+ handler_order = 500
403+
401404 def add_parent (self , parent ):
402405 self .parent = parent
403406 def close (self ):
404407 self .parent = None
408+ def __lt__ (self , other ):
409+ if not hasattr (other , "handler_order" ):
410+ # Try to preserve the old behavior of having custom classes
411+ # inserted after default ones (works only for custom user
412+ # classes which are not aware of handler_order).
413+ return True
414+ return self .handler_order < other .handler_order
415+
405416
406417class HTTPDefaultErrorHandler (BaseHandler ):
407418 def http_error_default (self , req , fp , code , msg , hdrs ):
@@ -473,6 +484,9 @@ def http_error_302(self, req, fp, code, msg, headers):
473484 "The last 302 error message was:\n "
474485
475486class ProxyHandler (BaseHandler ):
487+ # Proxies must be in front
488+ handler_order = 100
489+
476490 def __init__ (self , proxies = None ):
477491 if proxies is None :
478492 proxies = getproxies ()
@@ -523,6 +537,9 @@ def get_proxy(self):
523537 return self .addr
524538
525539class CustomProxyHandler (BaseHandler ):
540+ # Proxies must be in front
541+ handler_order = 100
542+
526543 def __init__ (self , * proxies ):
527544 self .proxies = {}
528545
@@ -1051,13 +1068,9 @@ class OpenerFactory:
10511068 default_handlers = [UnknownHandler , HTTPHandler ,
10521069 HTTPDefaultErrorHandler , HTTPRedirectHandler ,
10531070 FTPHandler , FileHandler ]
1054- proxy_handlers = [ProxyHandler ]
10551071 handlers = []
10561072 replacement_handlers = []
10571073
1058- def add_proxy_handler (self , ph ):
1059- self .proxy_handlers = self .proxy_handlers + [ph ]
1060-
10611074 def add_handler (self , h ):
10621075 self .handlers = self .handlers + [h ]
10631076
@@ -1066,7 +1079,7 @@ def replace_handler(self, h):
10661079
10671080 def build_opener (self ):
10681081 opener = OpenerDirector ()
1069- for ph in self .proxy_handlers :
1082+ for ph in self .default_handlers :
10701083 if inspect .isclass (ph ):
10711084 ph = ph ()
10721085 opener .add_handler (ph )
0 commit comments