diff -r bb1796870739 Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst Mon Mar 14 16:38:26 2011 -0400 +++ b/Doc/library/urllib.request.rst Mon Mar 14 18:01:40 2011 -0400 @@ -204,7 +204,7 @@ A class to handle HTTP Cookies. -.. class:: ProxyHandler(proxies=None) +.. class:: ProxyHandler(proxies=None, bypass=None) Cause requests to go through a proxy. If *proxies* is given, it must be a dictionary mapping protocol names to URLs of proxies. The default is to read the @@ -216,6 +216,17 @@ To disable autodetected proxy pass an empty dictionary. + If *bypass* is given, it must be a list of DNS suffixes separated by + commas or '*' for all hosts. Hostnames matching this list are excluded + from proxying. The default is to read the list of bypass hosts from + the environment variable :envvar:`no_proxy`. If no bypass settings as + set, in a Windows environment, proxy bypass settings are obtained from the + registry's Internet Settings section and in a Mac OS X environment, + proxy bypass information is retrieved from the OS X System + Configuration Framework. + + To disable autodetected proxy bypass settings pass an empty list. + .. class:: HTTPPasswordMgr() diff -r bb1796870739 Lib/test/test_urllib2_localnet.py --- a/Lib/test/test_urllib2_localnet.py Mon Mar 14 16:38:26 2011 -0400 +++ b/Lib/test/test_urllib2_localnet.py Mon Mar 14 18:01:40 2011 -0400 @@ -17,6 +17,7 @@ # Self-signed cert file for 'fakehostname' CERT_fakehostname = os.path.join(here, 'keycert2.pem') + # Loopback http server infrastructure class LoopbackHttpServer(http.server.HTTPServer): @@ -249,7 +250,7 @@ self.server.start() self.server.ready.wait() proxy_url = "http://127.0.0.1:%d" % self.server.port - handler = urllib.request.ProxyHandler({"http" : proxy_url}) + handler = urllib.request.ProxyHandler({"http" : proxy_url}, bypass=[]) self.proxy_digest_handler = urllib.request.ProxyDigestAuthHandler() self.opener = urllib.request.build_opener( handler, self.proxy_digest_handler) diff -r bb1796870739 Lib/urllib/request.py --- a/Lib/urllib/request.py Mon Mar 14 16:38:26 2011 -0400 +++ b/Lib/urllib/request.py Mon Mar 14 18:01:40 2011 -0400 @@ -661,7 +661,7 @@ # Proxies must be in front handler_order = 100 - def __init__(self, proxies=None): + def __init__(self, proxies=None, bypass=None): if proxies is None: proxies = getproxies() assert hasattr(proxies, 'keys'), "proxies must be a mapping" @@ -670,6 +670,10 @@ setattr(self, '%s_open' % type, lambda r, proxy=url, type=type, meth=self.proxy_open: \ meth(r, proxy, type)) + if bypass is None: + self.bypass_test = proxy_bypass + else: + self.bypass_test = lambda host: test_proxy_bypass(host, ','.join(bypass)) def proxy_open(self, req, proxy, type): orig_type = req.type @@ -677,7 +681,7 @@ if proxy_type is None: proxy_type = orig_type - if req.host and proxy_bypass(req.host): + if req.host and self.bypass_test(req.host): return None if user and password: @@ -2188,6 +2192,24 @@ proxies[name[:-6]] = value return proxies +def test_proxy_bypass(host, bypass): + """Test if proxies should not be used for a particular host. + + *bypass* argument should be a list of DNS suffixes separated by commas, + or '*' for all hosts. + """ + # '*' is special case for always bypass + if bypass == '*': + return 1 + # strip port off host + hostonly, port = splitport(host) + # check if the host ends with any of the DNS suffixes + for name in bypass.split(','): + if name and (hostonly.endswith(name) or host.endswith(name)): + return 1 + # otherwise, don't bypass + return 0 + def proxy_bypass_environment(host): """Test if proxies should not be used for a particular host. @@ -2195,17 +2217,7 @@ be a list of DNS suffixes separated by commas, or '*' for all hosts. """ no_proxy = os.environ.get('no_proxy', '') or os.environ.get('NO_PROXY', '') - # '*' is special case for always bypass - if no_proxy == '*': - return 1 - # strip port off host - hostonly, port = splitport(host) - # check if the host ends with any of the DNS suffixes - for name in no_proxy.split(','): - if name and (hostonly.endswith(name) or host.endswith(name)): - return 1 - # otherwise, don't bypass - return 0 + return test_proxy_bypass(no_proxy) # This code tests an OSX specific data structure but is testable on all