# HG changeset patch # Parent e4d44c2e8e81ff94777087908cb1473f6352927e diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -19,6 +19,18 @@ # parse_keqv_list, parse_http_list, HTTPDigestAuthHandler class TrivialTests(unittest.TestCase): + + def test___all__(self): + # Verify which names are exposed + for module in 'request', 'response', 'parse', 'error', 'robotparser': + context = {} + exec('from urllib.%s import *' % module, context) + del context['__builtins__'] + for k, v in context.items(): + self.assertEqual(v.__module__, 'urllib.%s' % module, + "%r is exposed in 'urllib.%s' but defined in %r" % + (k, module, v.__module__)) + def test_trivial(self): # A couple trivial tests diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py --- a/Lib/urllib/error.py +++ b/Lib/urllib/error.py @@ -13,6 +13,9 @@ import urllib.response +__all__ = ['URLError', 'HTTPError', 'ContentTooShortError'] + + # do these error classes make sense? # make sure all of the IOError stuff is overridden. we just want to be # subtypes. diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -89,7 +89,6 @@ import io import os import posixpath -import random import re import socket import sys @@ -111,6 +110,22 @@ else: _have_ssl = True +__all__ = [ + # Classes + 'Request', 'OpenerDirector', 'BaseHandler', 'HTTPDefaultErrorHandler', + 'HTTPRedirectHandler', 'HTTPCookieProcessor', 'ProxyHandler', + 'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm', + 'AbstractBasicAuthHandler', 'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler', + 'AbstractDigestAuthHandler', 'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler', + 'HTTPHandler', 'HTTPSHandler', 'FileHandler', 'FTPHandler', 'CacheFTPHandler', + 'UnknownHandler', 'HTTPErrorProcessor', + # Functions + 'urlopen', 'install_opener', 'build_opener', + 'pathname2url', 'url2pathname', 'getproxies', + # Legacy interface + 'urlretrieve', 'urlcleanup', 'URLopener', 'FancyURLopener', +] + # used in User-Agent header sent __version__ = sys.version[:3] @@ -885,9 +900,9 @@ return response -def randombytes(n): - """Return n random bytes.""" - return os.urandom(n) +# Return n random bytes. +_randombytes = os.urandom + class AbstractDigestAuthHandler: # Digest authentication is specified in RFC 2617. @@ -951,7 +966,7 @@ # authentication, and to provide some message integrity protection. # This isn't a fabulous effort, but it's probably Good Enough. s = "%s:%s:%s:" % (self.nonce_count, nonce, time.ctime()) - b = s.encode("ascii") + randombytes(8) + b = s.encode("ascii") + _randombytes(8) dig = hashlib.sha1(b).hexdigest() return dig[:16] @@ -1171,7 +1186,6 @@ http_request = AbstractHTTPHandler.do_request_ if hasattr(http.client, 'HTTPSConnection'): - import ssl class HTTPSHandler(AbstractHTTPHandler): @@ -1677,13 +1691,11 @@ if not host: raise IOError('http error', 'no host given') if proxy_passwd: - import base64 proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii') else: proxy_auth = None if user_passwd: - import base64 auth = base64.b64encode(user_passwd.encode()).decode('ascii') else: auth = None @@ -1773,8 +1785,8 @@ def open_local_file(self, url): """Use local file.""" - import mimetypes, email.utils - from io import StringIO + import email.utils + import mimetypes host, file = splithost(url) localname = url2pathname(file) try: @@ -1806,7 +1818,6 @@ if not isinstance(url, str): raise URLError('ftp error', 'proxy support for ftp protocol currently not implemented') import mimetypes - from io import StringIO host, path = splithost(url) if not host: raise URLError('ftp error', 'no host given') host, port = splitport(host) @@ -1888,7 +1899,6 @@ time.gmtime(time.time()))) msg.append('Content-type: %s' % type) if encoding == 'base64': - import base64 # XXX is this encoding/decoding ok? data = base64.decodebytes(data.encode('ascii')).decode('latin-1') else: @@ -1984,7 +1994,6 @@ URLopener.http_error_default(self, url, fp, errcode, errmsg, headers) stuff = headers['www-authenticate'] - import re match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) if not match: URLopener.http_error_default(self, url, fp, @@ -2010,7 +2019,6 @@ URLopener.http_error_default(self, url, fp, errcode, errmsg, headers) stuff = headers['proxy-authenticate'] - import re match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) if not match: URLopener.http_error_default(self, url, fp, @@ -2302,8 +2310,6 @@ 'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.1', '10.0/16'] } """ - import re - import socket from fnmatch import fnmatch hostonly, port = splitport(host) @@ -2406,7 +2412,6 @@ for p in proxyServer.split(';'): protocol, address = p.split('=', 1) # See if address has a type:// prefix - import re if not re.match('^([^/:]+)://', address): address = '%s://%s' % (protocol, address) proxies[protocol] = address @@ -2438,7 +2443,6 @@ def proxy_bypass_registry(host): try: import winreg - import re except ImportError: # Std modules, so should be around - but you never know! return 0