summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/liburllib2.tex5
-rw-r--r--Lib/urllib2.py35
-rw-r--r--Misc/NEWS5
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
-----------