- urllib2.py now knows how to order proxy classes, so the user doesn't

have to insert it in front of other classes, nor do dirty tricks like
  inserting a "dummy" HTTPHandler after a ProxyHandler when building an
  opener with proxy support.
This commit is contained in:
Gustavo Niemeyer 2003-06-07 17:53:08 +00:00
parent ef58adf8d6
commit 9556fba685
3 changed files with 34 additions and 11 deletions

View file

@ -56,6 +56,11 @@ them, instances of them or subclasses of them:
If the Python installation has SSL support (\function{socket.ssl()} If the Python installation has SSL support (\function{socket.ssl()}
exists), \class{HTTPSHandler} will also be added. exists), \class{HTTPSHandler} will also be added.
Beginning in Python 2.3, a \class{BaseHandler} subclass may also change its
\var{handler_order} member variable to modify its position in the handlers
list. Besides \class{ProxyHandler}, which has \var{handler_order} of
\code{100}, all handlers currently have it set to \code{500}.
\end{funcdesc} \end{funcdesc}

View file

@ -267,6 +267,7 @@ class OpenerDirector:
protocol = meth[:-5] protocol = meth[:-5]
if protocol in self.handle_open: if protocol in self.handle_open:
self.handle_open[protocol].append(handler) self.handle_open[protocol].append(handler)
self.handle_open[protocol].sort()
else: else:
self.handle_open[protocol] = [handler] self.handle_open[protocol] = [handler]
added = 1 added = 1
@ -283,6 +284,7 @@ class OpenerDirector:
dict = self.handle_error.get(proto, {}) dict = self.handle_error.get(proto, {})
if kind in dict: if kind in dict:
dict[kind].append(handler) dict[kind].append(handler)
dict[kind].sort()
else: else:
dict[kind] = [handler] dict[kind] = [handler]
self.handle_error[proto] = dict self.handle_error[proto] = dict
@ -290,6 +292,7 @@ class OpenerDirector:
continue continue
if added: if added:
self.handlers.append(handler) self.handlers.append(handler)
self.handlers.sort()
handler.add_parent(self) handler.add_parent(self)
def __del__(self): def __del__(self):
@ -355,17 +358,15 @@ class OpenerDirector:
args = (dict, 'default', 'http_error_default') + orig_args args = (dict, 'default', 'http_error_default') + orig_args
return self._call_chain(*args) return self._call_chain(*args)
# XXX probably also want an abstract factory that knows things like # XXX probably also want an abstract factory that knows when it makes
# the fact that a ProxyHandler needs to get inserted first. # sense to skip a superclass in favor of a subclass and when it might
# would also know when it makes sense to skip a superclass in favor of # make sense to include both
# a subclass and when it might make sense to include both
def build_opener(*handlers): def build_opener(*handlers):
"""Create an opener object from a list of handlers. """Create an opener object from a list of handlers.
The opener will use several default handlers, including support The opener will use several default handlers, including support
for HTTP and FTP. If there is a ProxyHandler, it must be at the for HTTP and FTP.
front of the list of handlers. (Yuck.)
If any of the handlers passed as arguments are subclasses of the If any of the handlers passed as arguments are subclasses of the
default handlers, the default handlers will not be used. default handlers, the default handlers will not be used.
@ -398,10 +399,20 @@ def build_opener(*handlers):
return opener return opener
class BaseHandler: class BaseHandler:
handler_order = 500
def add_parent(self, parent): def add_parent(self, parent):
self.parent = parent self.parent = parent
def close(self): def close(self):
self.parent = None self.parent = None
def __lt__(self, other):
if not hasattr(other, "handler_order"):
# Try to preserve the old behavior of having custom classes
# inserted after default ones (works only for custom user
# classes which are not aware of handler_order).
return True
return self.handler_order < other.handler_order
class HTTPDefaultErrorHandler(BaseHandler): class HTTPDefaultErrorHandler(BaseHandler):
def http_error_default(self, req, fp, code, msg, hdrs): def http_error_default(self, req, fp, code, msg, hdrs):
@ -473,6 +484,9 @@ class HTTPRedirectHandler(BaseHandler):
"The last 302 error message was:\n" "The last 302 error message was:\n"
class ProxyHandler(BaseHandler): class ProxyHandler(BaseHandler):
# Proxies must be in front
handler_order = 100
def __init__(self, proxies=None): def __init__(self, proxies=None):
if proxies is None: if proxies is None:
proxies = getproxies() proxies = getproxies()
@ -523,6 +537,9 @@ class CustomProxy:
return self.addr return self.addr
class CustomProxyHandler(BaseHandler): class CustomProxyHandler(BaseHandler):
# Proxies must be in front
handler_order = 100
def __init__(self, *proxies): def __init__(self, *proxies):
self.proxies = {} self.proxies = {}
@ -1051,13 +1068,9 @@ class OpenerFactory:
default_handlers = [UnknownHandler, HTTPHandler, default_handlers = [UnknownHandler, HTTPHandler,
HTTPDefaultErrorHandler, HTTPRedirectHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler,
FTPHandler, FileHandler] FTPHandler, FileHandler]
proxy_handlers = [ProxyHandler]
handlers = [] handlers = []
replacement_handlers = [] replacement_handlers = []
def add_proxy_handler(self, ph):
self.proxy_handlers = self.proxy_handlers + [ph]
def add_handler(self, h): def add_handler(self, h):
self.handlers = self.handlers + [h] self.handlers = self.handlers + [h]
@ -1066,7 +1079,7 @@ class OpenerFactory:
def build_opener(self): def build_opener(self):
opener = OpenerDirector() opener = OpenerDirector()
for ph in self.proxy_handlers: for ph in self.default_handlers:
if inspect.isclass(ph): if inspect.isclass(ph):
ph = ph() ph = ph()
opener.add_handler(ph) opener.add_handler(ph)

View file

@ -80,6 +80,11 @@ Library
- timeit.py now checks the current directory for imports. - timeit.py now checks the current directory for imports.
- urllib2.py now knows how to order proxy classes, so the user doesn't
have to insert it in front of other classes, nor do dirty tricks like
inserting a "dummy" HTTPHandler after a ProxyHandler when building an
opener with proxy support.
Tools/Demos Tools/Demos
----------- -----------