From fabd7bb8e0450f16ed5c5c0ad575aa413d65712d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 11 Aug 2020 15:26:59 +0200 Subject: [PATCH] bpo-41521: Replace whitelist/blacklist with allowlist/denylist (GH-21822) Automerge-Triggered-By: @tiran --- Doc/library/http.cookiejar.rst | 12 ++++++------ Doc/library/urllib.parse.rst | 2 +- Lib/codecs.py | 2 +- Lib/ipaddress.py | 4 ++-- Lib/test/test___all__.py | 12 ++++++------ Lib/test/test_httplib.py | 4 ++-- Lib/test/test_httpservers.py | 4 ++-- Lib/test/test_nntplib.py | 6 +++--- Lib/test/test_tools/test_sundry.py | 10 +++++----- Lib/test/test_traceback.py | 4 ++-- Objects/typeobject.c | 4 ++-- Tools/clinic/clinic.py | 8 ++++---- 12 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 9ac5d52a2ab..0a9ee7eb516 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -462,16 +462,16 @@ receiving cookies. There are also some strictness switches that allow you to tighten up the rather loose Netscape protocol rules a little bit (at the cost of blocking some benign cookies). -A domain blacklist and whitelist is provided (both off by default). Only domains -not in the blacklist and present in the whitelist (if the whitelist is active) +A domain denylist and allowlist is provided (both off by default). Only domains +not in the denylist and present in the allowlist (if the allowlist is active) participate in cookie setting and returning. Use the *blocked_domains* constructor argument, and :meth:`blocked_domains` and :meth:`set_blocked_domains` methods (and the corresponding argument and methods -for *allowed_domains*). If you set a whitelist, you can turn it off again by +for *allowed_domains*). If you set an allowlist, you can turn it off again by setting it to :const:`None`. Domains in block or allow lists that do not start with a dot must equal the -cookie domain to be matched. For example, ``"example.com"`` matches a blacklist +cookie domain to be matched. For example, ``"example.com"`` matches a denylist entry of ``"example.com"``, but ``"www.example.com"`` does not. Domains that do start with a dot are matched by more specific domains too. For example, both ``"www.example.com"`` and ``"www.coyote.example.com"`` match ``".example.com"`` @@ -494,7 +494,7 @@ and ``".168.1.2"``, 192.168.1.2 is blocked, but 193.168.1.2 is not. .. method:: DefaultCookiePolicy.is_blocked(domain) - Return whether *domain* is on the blacklist for setting or receiving cookies. + Return whether *domain* is on the denylist for setting or receiving cookies. .. method:: DefaultCookiePolicy.allowed_domains() @@ -509,7 +509,7 @@ and ``".168.1.2"``, 192.168.1.2 is blocked, but 193.168.1.2 is not. .. method:: DefaultCookiePolicy.is_not_allowed(domain) - Return whether *domain* is not on the whitelist for setting or receiving + Return whether *domain* is not on the allowlist for setting or receiving cookies. :class:`DefaultCookiePolicy` instances have the following attributes, which are diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 536cf952bda..f9c8ba7398f 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -153,7 +153,7 @@ or on combining URL components into a URL string. .. versionchanged:: 3.3 The fragment is now parsed for all URL schemes (unless *allow_fragment* is - false), in accordance with :rfc:`3986`. Previously, a whitelist of + false), in accordance with :rfc:`3986`. Previously, an allowlist of schemes that support fragments existed. .. versionchanged:: 3.6 diff --git a/Lib/codecs.py b/Lib/codecs.py index 7f23e9775df..3935490d88c 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -83,7 +83,7 @@ BOM64_BE = BOM_UTF32_BE class CodecInfo(tuple): """Codec details when looking up the codec registry""" - # Private API to allow Python 3.4 to blacklist the known non-Unicode + # Private API to allow Python 3.4 to denylist the known non-Unicode # codecs in the standard library. A more general mechanism to # reliably distinguish test encodings from other codecs will hopefully # be defined for Python 3.5 diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index bc662c415b2..160b16dbc16 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1214,7 +1214,7 @@ class _BaseV4: """ if not octet_str: raise ValueError("Empty octet not permitted") - # Whitelist the characters, since int() allows a lot of bizarre stuff. + # Reject non-ASCII digits. if not (octet_str.isascii() and octet_str.isdigit()): msg = "Only decimal digits permitted in %r" raise ValueError(msg % octet_str) @@ -1719,7 +1719,7 @@ class _BaseV6: [0..FFFF]. """ - # Whitelist the characters, since int() allows a lot of bizarre stuff. + # Reject non-ASCII digits. if not cls._HEX_DIGITS.issuperset(hextet_str): raise ValueError("Only hex digits permitted in %r" % hextet_str) # We do the length check second, since the invalid character error diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index 0a03dd20065..c6ce64864c0 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -69,8 +69,8 @@ class AllTest(unittest.TestCase): yield path, modpath + fn[:-3] def test_all(self): - # Blacklisted modules and packages - blacklist = set([ + # List of denied modules and packages + denylist = set([ # Will raise a SyntaxError when compiling the exec statement '__future__', ]) @@ -85,13 +85,13 @@ class AllTest(unittest.TestCase): lib_dir = os.path.dirname(os.path.dirname(__file__)) for path, modname in self.walk_modules(lib_dir, ""): m = modname - blacklisted = False + denylisted = False while m: - if m in blacklist: - blacklisted = True + if m in denylist: + denylisted = True break m = m.rpartition('.')[0] - if blacklisted: + if denylisted: continue if support.verbose: print(modname) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 3431bb80ea6..a3f268be979 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1434,9 +1434,9 @@ class OfflineTest(TestCase): expected = {"responses"} # White-list documented dict() object # HTTPMessage, parse_headers(), and the HTTP status code constants are # intentionally omitted for simplicity - blacklist = {"HTTPMessage", "parse_headers"} + denylist = {"HTTPMessage", "parse_headers"} for name in dir(client): - if name.startswith("_") or name in blacklist: + if name.startswith("_") or name in denylist: continue module_object = getattr(client, name) if getattr(module_object, "__module__", None) == "http.client": diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index a7e1719ab60..2859abb21fc 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -1189,9 +1189,9 @@ class SimpleHTTPRequestHandlerTestCase(unittest.TestCase): class MiscTestCase(unittest.TestCase): def test_all(self): expected = [] - blacklist = {'executable', 'nobody_uid', 'test'} + denylist = {'executable', 'nobody_uid', 'test'} for name in dir(server): - if name.startswith('_') or name in blacklist: + if name.startswith('_') or name in denylist: continue module_object = getattr(server, name) if getattr(module_object, '__module__', None) == 'http.server': diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py index 1df64fa7c6b..b11c19c84d3 100644 --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -197,11 +197,11 @@ class NetworkedNNTPTestsMixin: self.assertTrue(resp.startswith("220 "), resp) self.check_article_resp(resp, article, art_num) # Tolerate running the tests from behind a NNTP virus checker - blacklist = lambda line: line.startswith(b'X-Antivirus') + denylist = lambda line: line.startswith(b'X-Antivirus') filtered_head_lines = [line for line in head.lines - if not blacklist(line)] + if not denylist(line)] filtered_lines = [line for line in article.lines - if not blacklist(line)] + if not denylist(line)] self.assertEqual(filtered_lines, filtered_head_lines + [b''] + body.lines) def test_capabilities(self): diff --git a/Lib/test/test_tools/test_sundry.py b/Lib/test/test_tools/test_sundry.py index 8b5a963e25b..52369ec09a7 100644 --- a/Lib/test/test_tools/test_sundry.py +++ b/Lib/test/test_tools/test_sundry.py @@ -16,18 +16,18 @@ skip_if_missing() class TestSundryScripts(unittest.TestCase): # At least make sure the rest don't have syntax errors. When tests are - # added for a script it should be added to the whitelist below. + # added for a script it should be added to the allowlist below. # scripts that have independent tests. - whitelist = ['reindent', 'pdeps', 'gprof2html', 'md5sum'] + allowlist = ['reindent', 'pdeps', 'gprof2html', 'md5sum'] # scripts that can't be imported without running - blacklist = ['make_ctype'] + denylist = ['make_ctype'] # scripts that use windows-only modules windows_only = ['win_add2path'] - # blacklisted for other reasons + # denylisted for other reasons other = ['analyze_dxp', '2to3'] - skiplist = blacklist + whitelist + windows_only + other + skiplist = denylist + allowlist + windows_only + other def test_sundry(self): old_modules = import_helper.modules_setup() diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index c5fbd8700ae..730596efd8b 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1191,9 +1191,9 @@ class MiscTest(unittest.TestCase): def test_all(self): expected = set() - blacklist = {'print_list'} + denylist = {'print_list'} for name in dir(traceback): - if name.startswith('_') or name in blacklist: + if name.startswith('_') or name in denylist: continue module_object = getattr(traceback, name) if getattr(module_object, '__module__', None) == 'traceback': diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 49b3c859e35..c66f8fcec8e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4171,10 +4171,10 @@ object_set_class(PyObject *self, PyObject *value, void *closure) In theory the proper fix would be to identify which classes rely on this invariant and somehow disallow __class__ assignment only for them, perhaps via some mechanism like a new Py_TPFLAGS_IMMUTABLE flag (a - "blacklisting" approach). But in practice, since this problem wasn't + "denylisting" approach). But in practice, since this problem wasn't noticed late in the 3.5 RC cycle, we're taking the conservative approach and reinstating the same HEAPTYPE->HEAPTYPE check that we used - to have, plus a "whitelist". For now, the whitelist consists only of + to have, plus an "allowlist". For now, the allowlist consists only of ModuleType subtypes, since those are the cases that motivated the patch in the first place -- see https://bugs.python.org/issue22986 -- and since module objects are mutable we can be sure that they are diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 92334d9195f..1bbbd4f9fb1 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -4433,7 +4433,7 @@ class DSLParser: if 'c_default' not in kwargs: # we can only represent very simple data values in C. - # detect whether default is okay, via a blacklist + # detect whether default is okay, via a denylist # of disallowed ast nodes. class DetectBadNodes(ast.NodeVisitor): bad = False @@ -4456,9 +4456,9 @@ class DSLParser: # "starred": "a = [1, 2, 3]; *a" visit_Starred = bad_node - blacklist = DetectBadNodes() - blacklist.visit(module) - bad = blacklist.bad + denylist = DetectBadNodes() + denylist.visit(module) + bad = denylist.bad else: # if they specify a c_default, we can be more lenient about the default value. # but at least make an attempt at ensuring it's a valid expression.