From 9556fba68528e46873bf59c4e4642525adfd388b Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Sat, 7 Jun 2003 17:53:08 +0000 Subject: - 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. --- Doc/lib/liburllib2.tex | 5 +++++ Lib/urllib2.py | 35 ++++++++++++++++++++++++----------- Misc/NEWS | 5 +++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Doc/lib/liburllib2.tex b/Doc/lib/liburllib2.tex index 48afc9b..f88fd25 100644 --- a/Doc/lib/liburllib2.tex +++ b/Doc/lib/liburllib2.tex @@ -56,6 +56,11 @@ them, instances of them or subclasses of them: If the Python installation has SSL support (\function{socket.ssl()} 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} diff --git a/Lib/urllib2.py b/Lib/urllib2.py index ace3353..78cb29c 100644 --- a/Lib/urllib2.py +++ b/Lib/urllib2.py @@ -267,6 +267,7 @@ class OpenerDirector: protocol = meth[:-5] if protocol in self.handle_open: self.handle_open[protocol].append(handler) + self.handle_open[protocol].sort() else: self.handle_open[protocol] = [handler] added = 1 @@ -283,6 +284,7 @@ class OpenerDirector: dict = self.handle_error.get(proto, {}) if kind in dict: dict[kind].append(handler) + dict[kind].sort() else: dict[kind] = [handler] self.handle_error[proto] = dict @@ -290,6 +292,7 @@ class OpenerDirector: continue if added: self.handlers.append(handler) + self.handlers.sort() handler.add_parent(self) def __del__(self): @@ -355,17 +358,15 @@ class OpenerDirector: args = (dict, 'default', 'http_error_default') + orig_args return self._call_chain(*args) -# XXX probably also want an abstract factory that knows things like -# the fact that a ProxyHandler needs to get inserted first. -# would also know when it makes sense to skip a superclass in favor of -# a subclass and when it might make sense to include both +# XXX probably also want an abstract factory that knows when it makes +# sense to skip a superclass in favor of a subclass and when it might +# make sense to include both def build_opener(*handlers): """Create an opener object from a list of handlers. The opener will use several default handlers, including support - for HTTP and FTP. If there is a ProxyHandler, it must be at the - front of the list of handlers. (Yuck.) + for HTTP and FTP. If any of the handlers passed as arguments are subclasses of the default handlers, the default handlers will not be used. @@ -398,10 +399,20 @@ def build_opener(*handlers): return opener class BaseHandler: + handler_order = 500 + def add_parent(self, parent): self.parent = parent def close(self): 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): def http_error_default(self, req, fp, code, msg, hdrs): @@ -473,6 +484,9 @@ class HTTPRedirectHandler(BaseHandler): "The last 302 error message was:\n" class ProxyHandler(BaseHandler): + # Proxies must be in front + handler_order = 100 + def __init__(self, proxies=None): if proxies is None: proxies = getproxies() @@ -523,6 +537,9 @@ class CustomProxy: return self.addr class CustomProxyHandler(BaseHandler): + # Proxies must be in front + handler_order = 100 + def __init__(self, *proxies): self.proxies = {} @@ -1051,13 +1068,9 @@ class OpenerFactory: default_handlers = [UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler] - proxy_handlers = [ProxyHandler] handlers = [] replacement_handlers = [] - def add_proxy_handler(self, ph): - self.proxy_handlers = self.proxy_handlers + [ph] - def add_handler(self, h): self.handlers = self.handlers + [h] @@ -1066,7 +1079,7 @@ class OpenerFactory: def build_opener(self): opener = OpenerDirector() - for ph in self.proxy_handlers: + for ph in self.default_handlers: if inspect.isclass(ph): ph = ph() opener.add_handler(ph) diff --git a/Misc/NEWS b/Misc/NEWS index 9c9e3f8..adf68f8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,11 @@ Library - 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 ----------- -- cgit v0.12