mirror of
https://github.com/python/cpython.git
synced 2025-11-03 11:23:31 +00:00
- 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:
parent
ef58adf8d6
commit
9556fba685
3 changed files with 34 additions and 11 deletions
|
|
@ -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:
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue