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

Skip to content

Commit 6c5bd40

Browse files
committed
issue13287 - Define __all__ for urllib.request and urllib.error and expose only
the relevant module. Other cleanup improvements. Patch by flox.
1 parent 712b14f commit 6c5bd40

4 files changed

Lines changed: 40 additions & 18 deletions

File tree

Lib/test/test_urllib2.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919
# parse_keqv_list, parse_http_list, HTTPDigestAuthHandler
2020

2121
class TrivialTests(unittest.TestCase):
22+
23+
def test___all__(self):
24+
# Verify which names are exposed
25+
for module in 'request', 'response', 'parse', 'error', 'robotparser':
26+
context = {}
27+
exec('from urllib.%s import *' % module, context)
28+
del context['__builtins__']
29+
for k, v in context.items():
30+
self.assertEqual(v.__module__, 'urllib.%s' % module,
31+
"%r is exposed in 'urllib.%s' but defined in %r" %
32+
(k, module, v.__module__))
33+
2234
def test_trivial(self):
2335
# A couple trivial tests
2436

Lib/urllib/error.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
import urllib.response
1515

16+
__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
17+
18+
1619
# do these error classes make sense?
1720
# make sure all of the IOError stuff is overridden. we just want to be
1821
# subtypes.

Lib/urllib/request.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
import io
9090
import os
9191
import posixpath
92-
import random
9392
import re
9493
import socket
9594
import sys
@@ -111,6 +110,22 @@
111110
else:
112111
_have_ssl = True
113112

113+
__all__ = [
114+
# Classes
115+
'Request', 'OpenerDirector', 'BaseHandler', 'HTTPDefaultErrorHandler',
116+
'HTTPRedirectHandler', 'HTTPCookieProcessor', 'ProxyHandler',
117+
'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm',
118+
'AbstractBasicAuthHandler', 'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler',
119+
'AbstractDigestAuthHandler', 'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler',
120+
'HTTPHandler', 'FileHandler', 'FTPHandler', 'CacheFTPHandler',
121+
'UnknownHandler', 'HTTPErrorProcessor',
122+
# Functions
123+
'urlopen', 'install_opener', 'build_opener',
124+
'pathname2url', 'url2pathname', 'getproxies',
125+
# Legacy interface
126+
'urlretrieve', 'urlcleanup', 'URLopener', 'FancyURLopener',
127+
]
128+
114129
# used in User-Agent header sent
115130
__version__ = sys.version[:3]
116131

@@ -885,9 +900,9 @@ def http_error_407(self, req, fp, code, msg, headers):
885900
return response
886901

887902

888-
def randombytes(n):
889-
"""Return n random bytes."""
890-
return os.urandom(n)
903+
# Return n random bytes.
904+
_randombytes = os.urandom
905+
891906

892907
class AbstractDigestAuthHandler:
893908
# Digest authentication is specified in RFC 2617.
@@ -951,7 +966,7 @@ def get_cnonce(self, nonce):
951966
# authentication, and to provide some message integrity protection.
952967
# This isn't a fabulous effort, but it's probably Good Enough.
953968
s = "%s:%s:%s:" % (self.nonce_count, nonce, time.ctime())
954-
b = s.encode("ascii") + randombytes(8)
969+
b = s.encode("ascii") + _randombytes(8)
955970
dig = hashlib.sha1(b).hexdigest()
956971
return dig[:16]
957972

@@ -1171,7 +1186,6 @@ def http_open(self, req):
11711186
http_request = AbstractHTTPHandler.do_request_
11721187

11731188
if hasattr(http.client, 'HTTPSConnection'):
1174-
import ssl
11751189

11761190
class HTTPSHandler(AbstractHTTPHandler):
11771191

@@ -1677,13 +1691,11 @@ def _open_generic_http(self, connection_factory, url, data):
16771691
if not host: raise IOError('http error', 'no host given')
16781692

16791693
if proxy_passwd:
1680-
import base64
16811694
proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii')
16821695
else:
16831696
proxy_auth = None
16841697

16851698
if user_passwd:
1686-
import base64
16871699
auth = base64.b64encode(user_passwd.encode()).decode('ascii')
16881700
else:
16891701
auth = None
@@ -1773,8 +1785,8 @@ def open_file(self, url):
17731785

17741786
def open_local_file(self, url):
17751787
"""Use local file."""
1776-
import mimetypes, email.utils
1777-
from io import StringIO
1788+
import email.utils
1789+
import mimetypes
17781790
host, file = splithost(url)
17791791
localname = url2pathname(file)
17801792
try:
@@ -1806,7 +1818,6 @@ def open_ftp(self, url):
18061818
if not isinstance(url, str):
18071819
raise URLError('ftp error', 'proxy support for ftp protocol currently not implemented')
18081820
import mimetypes
1809-
from io import StringIO
18101821
host, path = splithost(url)
18111822
if not host: raise URLError('ftp error', 'no host given')
18121823
host, port = splitport(host)
@@ -1888,7 +1899,6 @@ def open_data(self, url, data=None):
18881899
time.gmtime(time.time())))
18891900
msg.append('Content-type: %s' % type)
18901901
if encoding == 'base64':
1891-
import base64
18921902
# XXX is this encoding/decoding ok?
18931903
data = base64.decodebytes(data.encode('ascii')).decode('latin-1')
18941904
else:
@@ -1984,7 +1994,6 @@ def http_error_401(self, url, fp, errcode, errmsg, headers, data=None,
19841994
URLopener.http_error_default(self, url, fp,
19851995
errcode, errmsg, headers)
19861996
stuff = headers['www-authenticate']
1987-
import re
19881997
match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
19891998
if not match:
19901999
URLopener.http_error_default(self, url, fp,
@@ -2010,7 +2019,6 @@ def http_error_407(self, url, fp, errcode, errmsg, headers, data=None,
20102019
URLopener.http_error_default(self, url, fp,
20112020
errcode, errmsg, headers)
20122021
stuff = headers['proxy-authenticate']
2013-
import re
20142022
match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
20152023
if not match:
20162024
URLopener.http_error_default(self, url, fp,
@@ -2302,8 +2310,6 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
23022310
'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.1', '10.0/16']
23032311
}
23042312
"""
2305-
import re
2306-
import socket
23072313
from fnmatch import fnmatch
23082314

23092315
hostonly, port = splitport(host)
@@ -2406,7 +2412,6 @@ def getproxies_registry():
24062412
for p in proxyServer.split(';'):
24072413
protocol, address = p.split('=', 1)
24082414
# See if address has a type:// prefix
2409-
import re
24102415
if not re.match('^([^/:]+)://', address):
24112416
address = '%s://%s' % (protocol, address)
24122417
proxies[protocol] = address
@@ -2438,7 +2443,6 @@ def getproxies():
24382443
def proxy_bypass_registry(host):
24392444
try:
24402445
import winreg
2441-
import re
24422446
except ImportError:
24432447
# Std modules, so should be around - but you never know!
24442448
return 0

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ Core and Builtins
350350
Library
351351
-------
352352

353+
- Issue #13287: urllib.request and urllib.error now contains a __all__ and
354+
exposes only relevant Classes, Functions. Patch by Florent Xicluna.
355+
353356
- Issue #670664: Fix HTMLParser to correctly handle the content of
354357
``<script>...</script>`` and ``<style>...</style>``.
355358

0 commit comments

Comments
 (0)