[3.10] bpo-43988: Add test.support.check_disallow_instantiation() (GH-25757) (GH-26885)

(cherry picked from commit 4f725261c6, fbff5387c3, and 8cec740820)

Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>

Automerge-Triggered-By: GH:vstinner
This commit is contained in:
Erlend Egeberg Aasland 2021-06-24 01:46:25 +02:00 committed by GitHub
parent ece3841d3d
commit 0a3452e7cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 58 additions and 53 deletions

View file

@ -928,8 +928,16 @@ The :mod:`test.support` module defines the following functions:
.. versionadded:: 3.10 .. versionadded:: 3.10
.. function:: check_disallow_instantiation(test_case, tp, *args, **kwds)
Assert that type *tp* cannot be instantiated using *args* and *kwds*.
.. versionadded:: 3.10
The :mod:`test.support` module defines the following classes: The :mod:`test.support` module defines the following classes:
.. class:: SuppressCrashReport() .. class:: SuppressCrashReport()
A context manager used to try to prevent crash dialog popups on tests that A context manager used to try to prevent crash dialog popups on tests that

View file

@ -25,6 +25,7 @@ import unittest
import sqlite3 as sqlite import sqlite3 as sqlite
import sys import sys
from test.support import check_disallow_instantiation
from test.support.os_helper import TESTFN, unlink from test.support.os_helper import TESTFN, unlink
@ -94,8 +95,7 @@ class ModuleTests(unittest.TestCase):
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
cx = sqlite.connect(":memory:") cx = sqlite.connect(":memory:")
tp = type(cx("select 1")) check_disallow_instantiation(self, type(cx("select 1")))
self.assertRaises(TypeError, tp)
class ConnectionTests(unittest.TestCase): class ConnectionTests(unittest.TestCase):

View file

@ -40,6 +40,7 @@ __all__ = [
"requires_IEEE_754", "requires_zlib", "requires_IEEE_754", "requires_zlib",
"anticipate_failure", "load_package_tests", "detect_api_mismatch", "anticipate_failure", "load_package_tests", "detect_api_mismatch",
"check__all__", "skip_if_buggy_ucrt_strfptime", "check__all__", "skip_if_buggy_ucrt_strfptime",
"check_disallow_instantiation",
# sys # sys
"is_jython", "is_android", "check_impl_detail", "unix_shell", "is_jython", "is_android", "check_impl_detail", "unix_shell",
"setswitchinterval", "setswitchinterval",
@ -1992,3 +1993,19 @@ def infinite_recursion(max_depth=75):
yield yield
finally: finally:
sys.setrecursionlimit(original_depth) sys.setrecursionlimit(original_depth)
def check_disallow_instantiation(testcase, tp, *args, **kwds):
"""
Check that given type cannot be instantiated using *args and **kwds.
See bpo-43916: Add Py_TPFLAGS_DISALLOW_INSTANTIATION type flag.
"""
mod = tp.__module__
name = tp.__name__
if mod != 'builtins':
qualname = f"{mod}.{name}"
else:
qualname = f"{name}"
msg = f"cannot create '{re.escape(qualname)}' instances"
testcase.assertRaisesRegex(TypeError, msg, tp, *args, **kwds)

View file

@ -42,9 +42,10 @@ class MiscTest(unittest.TestCase):
@support.cpython_only @support.cpython_only
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) my_array = array.array("I")
tp = type(iter(array.array('I'))) support.check_disallow_instantiation(
self.assertRaises(TypeError, tp) self, type(iter(my_array)), my_array
)
@support.cpython_only @support.cpython_only
def test_immutable(self): def test_immutable(self):

View file

@ -6,7 +6,8 @@ import sys
import tempfile import tempfile
import unittest import unittest
from test.support import requires, verbose, SaveSignals, cpython_only from test.support import (requires, verbose, SaveSignals, cpython_only,
check_disallow_instantiation)
from test.support.import_helper import import_module from test.support.import_helper import import_module
# Optionally test curses module. This currently requires that the # Optionally test curses module. This currently requires that the
@ -1052,7 +1053,7 @@ class TestCurses(unittest.TestCase):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
w = curses.newwin(10, 10) w = curses.newwin(10, 10)
panel = curses.panel.new_panel(w) panel = curses.panel.new_panel(w)
self.assertRaises(TypeError, type(panel)) check_disallow_instantiation(self, type(panel))
@requires_curses_func('is_term_resized') @requires_curses_func('is_term_resized')
def test_is_term_resized(self): def test_is_term_resized(self):

View file

@ -31,8 +31,7 @@ class TestGdbm(unittest.TestCase):
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
self.g = gdbm.open(filename, 'c') self.g = gdbm.open(filename, 'c')
tp = type(self.g) support.check_disallow_instantiation(self, type(self.g))
self.assertRaises(TypeError, tp)
def test_key_methods(self): def test_key_methods(self):
self.g = gdbm.open(filename, 'c') self.g = gdbm.open(filename, 'c')

View file

@ -1541,9 +1541,7 @@ class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase):
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
fd = self.get_stdout_fd() fd = self.get_stdout_fd()
printer = self.create_printer(fd) printer = self.create_printer(fd)
PyStdPrinter_Type = type(printer) support.check_disallow_instantiation(self, type(printer))
with self.assertRaises(TypeError):
PyStdPrinter_Type(fd)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -951,8 +951,9 @@ class TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
@support.cpython_only @support.cpython_only
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
tp = type(c_functools.cmp_to_key(None)) support.check_disallow_instantiation(
self.assertRaises(TypeError, tp) self, type(c_functools.cmp_to_key(None))
)
class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase): class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):

View file

@ -915,20 +915,13 @@ class HashLibTestCase(unittest.TestCase):
except ValueError: except ValueError:
continue continue
with self.subTest(constructor=constructor): with self.subTest(constructor=constructor):
hash_type = type(h) support.check_disallow_instantiation(self, type(h))
self.assertRaises(TypeError, hash_type)
@unittest.skipUnless(HASH is not None, 'need _hashlib') @unittest.skipUnless(HASH is not None, 'need _hashlib')
def test_hash_disallow_instanciation(self): def test_hash_disallow_instantiation(self):
# internal types like _hashlib.HASH are not constructable # internal types like _hashlib.HASH are not constructable
with self.assertRaisesRegex( support.check_disallow_instantiation(self, HASH)
TypeError, "cannot create '_hashlib.HASH' instance" support.check_disallow_instantiation(self, HASHXOF)
):
HASH()
with self.assertRaisesRegex(
TypeError, "cannot create '_hashlib.HASHXOF' instance"
):
HASHXOF()
def test_readonly_types(self): def test_readonly_types(self):
for algorithm, constructors in self.constructors_to_test.items(): for algorithm, constructors in self.constructors_to_test.items():

View file

@ -6,7 +6,7 @@ import unittest
import unittest.mock import unittest.mock
import warnings import warnings
from test.support import hashlib_helper from test.support import hashlib_helper, check_disallow_instantiation
from _operator import _compare_digest as operator_compare_digest from _operator import _compare_digest as operator_compare_digest
@ -439,11 +439,7 @@ class ConstructorTestCase(unittest.TestCase):
@unittest.skipUnless(C_HMAC is not None, 'need _hashlib') @unittest.skipUnless(C_HMAC is not None, 'need _hashlib')
def test_internal_types(self): def test_internal_types(self):
# internal types like _hashlib.C_HMAC are not constructable # internal types like _hashlib.C_HMAC are not constructable
with self.assertRaisesRegex( check_disallow_instantiation(self, C_HMAC)
TypeError, "cannot create '_hashlib.HMAC' instance"
):
C_HMAC()
with self.assertRaisesRegex(TypeError, "immutable type"): with self.assertRaisesRegex(TypeError, "immutable type"):
C_HMAC.value = None C_HMAC.value = None

View file

@ -1,5 +1,6 @@
from test.support import (gc_collect, bigmemtest, _2G, from test.support import (gc_collect, bigmemtest, _2G,
cpython_only, captured_stdout) cpython_only, captured_stdout,
check_disallow_instantiation)
import locale import locale
import re import re
import sre_compile import sre_compile
@ -2218,11 +2219,10 @@ class ImplementationTest(unittest.TestCase):
@cpython_only @cpython_only
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
self.assertRaises(TypeError, re.Match) check_disallow_instantiation(self, re.Match)
self.assertRaises(TypeError, re.Pattern) check_disallow_instantiation(self, re.Pattern)
pat = re.compile("") pat = re.compile("")
tp = type(pat.scanner("")) check_disallow_instantiation(self, type(pat.scanner("")))
self.assertRaises(TypeError, tp)
class ExternalTests(unittest.TestCase): class ExternalTests(unittest.TestCase):

View file

@ -88,12 +88,10 @@ class SelectTestCase(unittest.TestCase):
self.assertEqual(select.select([], a, []), ([], a[:5], [])) self.assertEqual(select.select([], a, []), ([], a[:5], []))
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
tp = type(select.poll()) support.check_disallow_instantiation(self, type(select.poll()))
self.assertRaises(TypeError, tp)
if hasattr(select, 'devpoll'): if hasattr(select, 'devpoll'):
tp = type(select.devpoll()) support.check_disallow_instantiation(self, type(select.devpoll()))
self.assertRaises(TypeError, tp)
def tearDownModule(): def tearDownModule():
support.reap_children() support.reap_children()

View file

@ -358,11 +358,7 @@ class BasicSocketTests(unittest.TestCase):
with self.subTest(ssl_type=ssl_type): with self.subTest(ssl_type=ssl_type):
with self.assertRaisesRegex(TypeError, "immutable type"): with self.assertRaisesRegex(TypeError, "immutable type"):
ssl_type.value = None ssl_type.value = None
with self.assertRaisesRegex( support.check_disallow_instantiation(self, _ssl.Certificate)
TypeError,
"cannot create '_ssl.Certificate' instances"
):
_ssl.Certificate()
def test_private_init(self): def test_private_init(self):
with self.assertRaisesRegex(TypeError, "public constructor"): with self.assertRaisesRegex(TypeError, "public constructor"):

View file

@ -124,8 +124,7 @@ class ThreadTests(BaseTestCase):
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
lock = threading.Lock() lock = threading.Lock()
tp = type(lock) test.support.check_disallow_instantiation(self, type(lock))
self.assertRaises(TypeError, tp)
# Create a bunch of threads, let each do some work, wait until all are # Create a bunch of threads, let each do some work, wait until all are
# done. # done.

View file

@ -12,7 +12,7 @@ import sys
import unicodedata import unicodedata
import unittest import unittest
from test.support import (open_urlresource, requires_resource, script_helper, from test.support import (open_urlresource, requires_resource, script_helper,
cpython_only) cpython_only, check_disallow_instantiation)
class UnicodeMethodsTest(unittest.TestCase): class UnicodeMethodsTest(unittest.TestCase):
@ -229,7 +229,7 @@ class UnicodeMiscTest(UnicodeDatabaseTest):
@cpython_only @cpython_only
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
self.assertRaises(TypeError, unicodedata.UCD) check_disallow_instantiation(self, unicodedata.UCD)
def test_failed_import_during_compiling(self): def test_failed_import_during_compiling(self):
# Issue 4367 # Issue 4367

View file

@ -132,10 +132,8 @@ class ExceptionTestCase(unittest.TestCase):
@support.cpython_only @support.cpython_only
def test_disallow_instantiation(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916) # Ensure that the type disallows instantiation (bpo-43916)
comp_type = type(zlib.compressobj()) support.check_disallow_instantiation(self, type(zlib.compressobj()))
decomp_type = type(zlib.decompressobj()) support.check_disallow_instantiation(self, type(zlib.decompressobj()))
self.assertRaises(TypeError, comp_type)
self.assertRaises(TypeError, decomp_type)
class BaseCompressTestCase(object): class BaseCompressTestCase(object):