Commit 6012bcf8 authored by Gustavo Niemeyer's avatar Gustavo Niemeyer

- 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.
parent d137150c
...@@ -56,6 +56,11 @@ them, instances of them or subclasses of them: ...@@ -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}
......
...@@ -267,6 +267,7 @@ class OpenerDirector: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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): ...@@ -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): ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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)
......
...@@ -80,6 +80,11 @@ Library ...@@ -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
----------- -----------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment