Commit 6c5bd40a authored by Senthil Kumaran's avatar Senthil Kumaran

issue13287 - Define __all__ for urllib.request and urllib.error and expose only

the relevant module. Other cleanup improvements. Patch by flox.
parent 712b14fc
...@@ -19,6 +19,18 @@ import urllib.error ...@@ -19,6 +19,18 @@ import urllib.error
# parse_keqv_list, parse_http_list, HTTPDigestAuthHandler # parse_keqv_list, parse_http_list, HTTPDigestAuthHandler
class TrivialTests(unittest.TestCase): 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): def test_trivial(self):
# A couple trivial tests # A couple trivial tests
......
...@@ -13,6 +13,9 @@ response. ...@@ -13,6 +13,9 @@ response.
import urllib.response import urllib.response
__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
# do these error classes make sense? # do these error classes make sense?
# make sure all of the IOError stuff is overridden. we just want to be # make sure all of the IOError stuff is overridden. we just want to be
# subtypes. # subtypes.
......
...@@ -89,7 +89,6 @@ import http.client ...@@ -89,7 +89,6 @@ import http.client
import io import io
import os import os
import posixpath import posixpath
import random
import re import re
import socket import socket
import sys import sys
...@@ -111,6 +110,22 @@ except ImportError: ...@@ -111,6 +110,22 @@ except ImportError:
else: else:
_have_ssl = True _have_ssl = True
__all__ = [
# Classes
'Request', 'OpenerDirector', 'BaseHandler', 'HTTPDefaultErrorHandler',
'HTTPRedirectHandler', 'HTTPCookieProcessor', 'ProxyHandler',
'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm',
'AbstractBasicAuthHandler', 'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler',
'AbstractDigestAuthHandler', 'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler',
'HTTPHandler', '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 # used in User-Agent header sent
__version__ = sys.version[:3] __version__ = sys.version[:3]
...@@ -885,9 +900,9 @@ class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): ...@@ -885,9 +900,9 @@ class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
return response return response
def randombytes(n): # Return n random bytes.
"""Return n random bytes.""" _randombytes = os.urandom
return os.urandom(n)
class AbstractDigestAuthHandler: class AbstractDigestAuthHandler:
# Digest authentication is specified in RFC 2617. # Digest authentication is specified in RFC 2617.
...@@ -951,7 +966,7 @@ class AbstractDigestAuthHandler: ...@@ -951,7 +966,7 @@ class AbstractDigestAuthHandler:
# authentication, and to provide some message integrity protection. # authentication, and to provide some message integrity protection.
# This isn't a fabulous effort, but it's probably Good Enough. # This isn't a fabulous effort, but it's probably Good Enough.
s = "%s:%s:%s:" % (self.nonce_count, nonce, time.ctime()) 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() dig = hashlib.sha1(b).hexdigest()
return dig[:16] return dig[:16]
...@@ -1171,7 +1186,6 @@ class HTTPHandler(AbstractHTTPHandler): ...@@ -1171,7 +1186,6 @@ class HTTPHandler(AbstractHTTPHandler):
http_request = AbstractHTTPHandler.do_request_ http_request = AbstractHTTPHandler.do_request_
if hasattr(http.client, 'HTTPSConnection'): if hasattr(http.client, 'HTTPSConnection'):
import ssl
class HTTPSHandler(AbstractHTTPHandler): class HTTPSHandler(AbstractHTTPHandler):
...@@ -1677,13 +1691,11 @@ class URLopener: ...@@ -1677,13 +1691,11 @@ class URLopener:
if not host: raise IOError('http error', 'no host given') if not host: raise IOError('http error', 'no host given')
if proxy_passwd: if proxy_passwd:
import base64
proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii') proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii')
else: else:
proxy_auth = None proxy_auth = None
if user_passwd: if user_passwd:
import base64
auth = base64.b64encode(user_passwd.encode()).decode('ascii') auth = base64.b64encode(user_passwd.encode()).decode('ascii')
else: else:
auth = None auth = None
...@@ -1773,8 +1785,8 @@ class URLopener: ...@@ -1773,8 +1785,8 @@ class URLopener:
def open_local_file(self, url): def open_local_file(self, url):
"""Use local file.""" """Use local file."""
import mimetypes, email.utils import email.utils
from io import StringIO import mimetypes
host, file = splithost(url) host, file = splithost(url)
localname = url2pathname(file) localname = url2pathname(file)
try: try:
...@@ -1806,7 +1818,6 @@ class URLopener: ...@@ -1806,7 +1818,6 @@ class URLopener:
if not isinstance(url, str): if not isinstance(url, str):
raise URLError('ftp error', 'proxy support for ftp protocol currently not implemented') raise URLError('ftp error', 'proxy support for ftp protocol currently not implemented')
import mimetypes import mimetypes
from io import StringIO
host, path = splithost(url) host, path = splithost(url)
if not host: raise URLError('ftp error', 'no host given') if not host: raise URLError('ftp error', 'no host given')
host, port = splitport(host) host, port = splitport(host)
...@@ -1888,7 +1899,6 @@ class URLopener: ...@@ -1888,7 +1899,6 @@ class URLopener:
time.gmtime(time.time()))) time.gmtime(time.time())))
msg.append('Content-type: %s' % type) msg.append('Content-type: %s' % type)
if encoding == 'base64': if encoding == 'base64':
import base64
# XXX is this encoding/decoding ok? # XXX is this encoding/decoding ok?
data = base64.decodebytes(data.encode('ascii')).decode('latin-1') data = base64.decodebytes(data.encode('ascii')).decode('latin-1')
else: else:
...@@ -1984,7 +1994,6 @@ class FancyURLopener(URLopener): ...@@ -1984,7 +1994,6 @@ class FancyURLopener(URLopener):
URLopener.http_error_default(self, url, fp, URLopener.http_error_default(self, url, fp,
errcode, errmsg, headers) errcode, errmsg, headers)
stuff = headers['www-authenticate'] stuff = headers['www-authenticate']
import re
match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
if not match: if not match:
URLopener.http_error_default(self, url, fp, URLopener.http_error_default(self, url, fp,
...@@ -2010,7 +2019,6 @@ class FancyURLopener(URLopener): ...@@ -2010,7 +2019,6 @@ class FancyURLopener(URLopener):
URLopener.http_error_default(self, url, fp, URLopener.http_error_default(self, url, fp,
errcode, errmsg, headers) errcode, errmsg, headers)
stuff = headers['proxy-authenticate'] stuff = headers['proxy-authenticate']
import re
match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff) match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
if not match: if not match:
URLopener.http_error_default(self, url, fp, URLopener.http_error_default(self, url, fp,
...@@ -2302,8 +2310,6 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings): ...@@ -2302,8 +2310,6 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.1', '10.0/16'] 'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.1', '10.0/16']
} }
""" """
import re
import socket
from fnmatch import fnmatch from fnmatch import fnmatch
hostonly, port = splitport(host) hostonly, port = splitport(host)
...@@ -2406,7 +2412,6 @@ elif os.name == 'nt': ...@@ -2406,7 +2412,6 @@ elif os.name == 'nt':
for p in proxyServer.split(';'): for p in proxyServer.split(';'):
protocol, address = p.split('=', 1) protocol, address = p.split('=', 1)
# See if address has a type:// prefix # See if address has a type:// prefix
import re
if not re.match('^([^/:]+)://', address): if not re.match('^([^/:]+)://', address):
address = '%s://%s' % (protocol, address) address = '%s://%s' % (protocol, address)
proxies[protocol] = address proxies[protocol] = address
...@@ -2438,7 +2443,6 @@ elif os.name == 'nt': ...@@ -2438,7 +2443,6 @@ elif os.name == 'nt':
def proxy_bypass_registry(host): def proxy_bypass_registry(host):
try: try:
import winreg import winreg
import re
except ImportError: except ImportError:
# Std modules, so should be around - but you never know! # Std modules, so should be around - but you never know!
return 0 return 0
......
...@@ -350,6 +350,9 @@ Core and Builtins ...@@ -350,6 +350,9 @@ Core and Builtins
Library Library
------- -------
- Issue #13287: urllib.request and urllib.error now contains a __all__ and
exposes only relevant Classes, Functions. Patch by Florent Xicluna.
- Issue #670664: Fix HTMLParser to correctly handle the content of - Issue #670664: Fix HTMLParser to correctly handle the content of
``<script>...</script>`` and ``<style>...</style>``. ``<script>...</script>`` and ``<style>...</style>``.
......
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