[Python-checkins] bpo-41521: Replace whitelist/blacklist with allowlist/denylist (GH-21822)

Victor Stinner webhook-mailer at python.org
Tue Aug 11 09:27:08 EDT 2020


https://github.com/python/cpython/commit/fabd7bb8e0450f16ed5c5c0ad575aa413d65712d
commit: fabd7bb8e0450f16ed5c5c0ad575aa413d65712d
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-08-11T06:26:59-07:00
summary:

bpo-41521: Replace whitelist/blacklist with allowlist/denylist (GH-21822)



Automerge-Triggered-By: @tiran

files:
M Doc/library/http.cookiejar.rst
M Doc/library/urllib.parse.rst
M Lib/codecs.py
M Lib/ipaddress.py
M Lib/test/test___all__.py
M Lib/test/test_httplib.py
M Lib/test/test_httpservers.py
M Lib/test/test_nntplib.py
M Lib/test/test_tools/test_sundry.py
M Lib/test/test_traceback.py
M Objects/typeobject.c
M Tools/clinic/clinic.py

diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst
index 9ac5d52a2ab09..0a9ee7eb516f4 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 536cf952bda43..f9c8ba7398f66 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 7f23e9775df80..3935490d88c8d 100644
--- a/Lib/codecs.py
+++ b/Lib/codecs.py
@@ -83,7 +83,7 @@
 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 bc662c415b2a4..160b16dbc162f 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1214,7 +1214,7 @@ def _parse_octet(cls, octet_str):
         """
         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 @@ def _parse_hextet(cls, hextet_str):
               [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 0a03dd20065fe..c6ce64864c0db 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -69,8 +69,8 @@ def walk_modules(self, basedir, modpath):
             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 @@ def test_all(self):
         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 3431bb80ea6de..a3f268be97921 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -1434,9 +1434,9 @@ def test_all(self):
         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 a7e1719ab60ee..2859abb21fc9f 100644
--- a/Lib/test/test_httpservers.py
+++ b/Lib/test/test_httpservers.py
@@ -1189,9 +1189,9 @@ def test_windows_colon(self):
 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 1df64fa7c6b00..b11c19c84d3fb 100644
--- a/Lib/test/test_nntplib.py
+++ b/Lib/test/test_nntplib.py
@@ -197,11 +197,11 @@ def test_article_head_body(self):
         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 8b5a963e25bd1..52369ec09a77f 100644
--- a/Lib/test/test_tools/test_sundry.py
+++ b/Lib/test/test_tools/test_sundry.py
@@ -16,18 +16,18 @@
 
 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 c5fbd8700ae9b..730596efd8bce 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 49b3c859e35c1..c66f8fcec8ed5 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 92334d9195fcc..1bbbd4f9fb193 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -4433,7 +4433,7 @@ def state_parameter(self, line):
 
                 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 @@ def bad_node(self, node):
                         # "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.



More information about the Python-checkins mailing list