Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9556fba

Browse files
committed
- 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.
1 parent ef58adf commit 9556fba

3 files changed

Lines changed: 34 additions & 11 deletions

File tree

Doc/lib/liburllib2.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ \section{\module{urllib2} ---
5656

5757
If the Python installation has SSL support (\function{socket.ssl()}
5858
exists), \class{HTTPSHandler} will also be added.
59+
60+
Beginning in Python 2.3, a \class{BaseHandler} subclass may also change its
61+
\var{handler_order} member variable to modify its position in the handlers
62+
list. Besides \class{ProxyHandler}, which has \var{handler_order} of
63+
\code{100}, all handlers currently have it set to \code{500}.
5964
\end{funcdesc}
6065

6166

Lib/urllib2.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ def add_handler(self, handler):
267267
protocol = meth[:-5]
268268
if protocol in self.handle_open:
269269
self.handle_open[protocol].append(handler)
270+
self.handle_open[protocol].sort()
270271
else:
271272
self.handle_open[protocol] = [handler]
272273
added = 1
@@ -283,13 +284,15 @@ def add_handler(self, handler):
283284
dict = self.handle_error.get(proto, {})
284285
if kind in dict:
285286
dict[kind].append(handler)
287+
dict[kind].sort()
286288
else:
287289
dict[kind] = [handler]
288290
self.handle_error[proto] = dict
289291
added = 1
290292
continue
291293
if added:
292294
self.handlers.append(handler)
295+
self.handlers.sort()
293296
handler.add_parent(self)
294297

295298
def __del__(self):
@@ -355,17 +358,15 @@ def error(self, proto, *args):
355358
args = (dict, 'default', 'http_error_default') + orig_args
356359
return self._call_chain(*args)
357360

358-
# XXX probably also want an abstract factory that knows things like
359-
# the fact that a ProxyHandler needs to get inserted first.
360-
# would also know when it makes sense to skip a superclass in favor of
361-
# a subclass and when it might make sense to include both
361+
# XXX probably also want an abstract factory that knows when it makes
362+
# sense to skip a superclass in favor of a subclass and when it might
363+
# make sense to include both
362364

363365
def build_opener(*handlers):
364366
"""Create an opener object from a list of handlers.
365367
366368
The opener will use several default handlers, including support
367-
for HTTP and FTP. If there is a ProxyHandler, it must be at the
368-
front of the list of handlers. (Yuck.)
369+
for HTTP and FTP.
369370
370371
If any of the handlers passed as arguments are subclasses of the
371372
default handlers, the default handlers will not be used.
@@ -398,10 +399,20 @@ def build_opener(*handlers):
398399
return opener
399400

400401
class BaseHandler:
402+
handler_order = 500
403+
401404
def add_parent(self, parent):
402405
self.parent = parent
403406
def close(self):
404407
self.parent = None
408+
def __lt__(self, other):
409+
if not hasattr(other, "handler_order"):
410+
# Try to preserve the old behavior of having custom classes
411+
# inserted after default ones (works only for custom user
412+
# classes which are not aware of handler_order).
413+
return True
414+
return self.handler_order < other.handler_order
415+
405416

406417
class HTTPDefaultErrorHandler(BaseHandler):
407418
def http_error_default(self, req, fp, code, msg, hdrs):
@@ -473,6 +484,9 @@ def http_error_302(self, req, fp, code, msg, headers):
473484
"The last 302 error message was:\n"
474485

475486
class ProxyHandler(BaseHandler):
487+
# Proxies must be in front
488+
handler_order = 100
489+
476490
def __init__(self, proxies=None):
477491
if proxies is None:
478492
proxies = getproxies()
@@ -523,6 +537,9 @@ def get_proxy(self):
523537
return self.addr
524538

525539
class CustomProxyHandler(BaseHandler):
540+
# Proxies must be in front
541+
handler_order = 100
542+
526543
def __init__(self, *proxies):
527544
self.proxies = {}
528545

@@ -1051,13 +1068,9 @@ class OpenerFactory:
10511068
default_handlers = [UnknownHandler, HTTPHandler,
10521069
HTTPDefaultErrorHandler, HTTPRedirectHandler,
10531070
FTPHandler, FileHandler]
1054-
proxy_handlers = [ProxyHandler]
10551071
handlers = []
10561072
replacement_handlers = []
10571073

1058-
def add_proxy_handler(self, ph):
1059-
self.proxy_handlers = self.proxy_handlers + [ph]
1060-
10611074
def add_handler(self, h):
10621075
self.handlers = self.handlers + [h]
10631076

@@ -1066,7 +1079,7 @@ def replace_handler(self, h):
10661079

10671080
def build_opener(self):
10681081
opener = OpenerDirector()
1069-
for ph in self.proxy_handlers:
1082+
for ph in self.default_handlers:
10701083
if inspect.isclass(ph):
10711084
ph = ph()
10721085
opener.add_handler(ph)

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ Library
8080

8181
- timeit.py now checks the current directory for imports.
8282

83+
- urllib2.py now knows how to order proxy classes, so the user doesn't
84+
have to insert it in front of other classes, nor do dirty tricks like
85+
inserting a "dummy" HTTPHandler after a ProxyHandler when building an
86+
opener with proxy support.
87+
8388
Tools/Demos
8489
-----------
8590

0 commit comments

Comments
 (0)