Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,16 @@ The :mod:`test.support` module defines the following functions:
.. 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:


.. class:: SuppressCrashReport()

A context manager used to try to prevent crash dialog popups on tests that
Expand Down
4 changes: 2 additions & 2 deletions Lib/sqlite3/test/dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import sqlite3 as sqlite
import sys

from test.support import check_disallow_instantiation
from test.support.os_helper import TESTFN, unlink


Expand Down Expand Up @@ -94,8 +95,7 @@ def test_shared_cache_deprecated(self):

def test_disallow_instantiation(self):
cx = sqlite.connect(":memory:")
tp = type(cx("select 1"))
self.assertRaises(TypeError, tp)
check_disallow_instantiation(self, type(cx("select 1")))


class ConnectionTests(unittest.TestCase):
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"requires_IEEE_754", "requires_zlib",
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
"check__all__", "skip_if_buggy_ucrt_strfptime",
"check_disallow_instantiation",
# sys
"is_jython", "is_android", "check_impl_detail", "unix_shell",
"setswitchinterval",
Expand Down Expand Up @@ -1992,3 +1993,19 @@ def infinite_recursion(max_depth=75):
yield
finally:
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)
7 changes: 4 additions & 3 deletions Lib/test/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ def test_bad_constructor(self):

@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
tp = type(iter(array.array('I')))
self.assertRaises(TypeError, tp)
my_array = array.array("I")
support.check_disallow_instantiation(
self, type(iter(my_array)), my_array
)

@support.cpython_only
def test_immutable(self):
Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_curses.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import tempfile
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

# Optionally test curses module. This currently requires that the
Expand Down Expand Up @@ -1052,7 +1053,7 @@ def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
w = curses.newwin(10, 10)
panel = curses.panel.new_panel(w)
self.assertRaises(TypeError, type(panel))
check_disallow_instantiation(self, type(panel))

@requires_curses_func('is_term_resized')
def test_is_term_resized(self):
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_dbm_gnu.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ def tearDown(self):
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
self.g = gdbm.open(filename, 'c')
tp = type(self.g)
self.assertRaises(TypeError, tp)
support.check_disallow_instantiation(self, type(self.g))

def test_key_methods(self):
self.g = gdbm.open(filename, 'c')
Expand Down
4 changes: 1 addition & 3 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -1541,9 +1541,7 @@ def test_methods(self):
def test_disallow_instantiation(self):
fd = self.get_stdout_fd()
printer = self.create_printer(fd)
PyStdPrinter_Type = type(printer)
with self.assertRaises(TypeError):
PyStdPrinter_Type(fd)
support.check_disallow_instantiation(self, type(printer))


if __name__ == "__main__":
Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,8 +951,9 @@ class TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
tp = type(c_functools.cmp_to_key(None))
self.assertRaises(TypeError, tp)
support.check_disallow_instantiation(
self, type(c_functools.cmp_to_key(None))
)


class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):
Expand Down
15 changes: 4 additions & 11 deletions Lib/test/test_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,20 +915,13 @@ def test_disallow_instantiation(self):
except ValueError:
continue
with self.subTest(constructor=constructor):
hash_type = type(h)
self.assertRaises(TypeError, hash_type)
support.check_disallow_instantiation(self, type(h))

@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
with self.assertRaisesRegex(
TypeError, "cannot create '_hashlib.HASH' instance"
):
HASH()
with self.assertRaisesRegex(
TypeError, "cannot create '_hashlib.HASHXOF' instance"
):
HASHXOF()
support.check_disallow_instantiation(self, HASH)
support.check_disallow_instantiation(self, HASHXOF)

def test_readonly_types(self):
for algorithm, constructors in self.constructors_to_test.items():
Expand Down
8 changes: 2 additions & 6 deletions Lib/test/test_hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import unittest.mock
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

Expand Down Expand Up @@ -439,11 +439,7 @@ def test_withmodule(self):
@unittest.skipUnless(C_HMAC is not None, 'need _hashlib')
def test_internal_types(self):
# internal types like _hashlib.C_HMAC are not constructable
with self.assertRaisesRegex(
TypeError, "cannot create '_hashlib.HMAC' instance"
):
C_HMAC()

check_disallow_instantiation(self, C_HMAC)
with self.assertRaisesRegex(TypeError, "immutable type"):
C_HMAC.value = None

Expand Down
10 changes: 5 additions & 5 deletions Lib/test/test_re.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from test.support import (gc_collect, bigmemtest, _2G,
cpython_only, captured_stdout)
cpython_only, captured_stdout,
check_disallow_instantiation)
import locale
import re
import sre_compile
Expand Down Expand Up @@ -2218,11 +2219,10 @@ def test_signedness(self):
@cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
self.assertRaises(TypeError, re.Match)
self.assertRaises(TypeError, re.Pattern)
check_disallow_instantiation(self, re.Match)
check_disallow_instantiation(self, re.Pattern)
pat = re.compile("")
tp = type(pat.scanner(""))
self.assertRaises(TypeError, tp)
check_disallow_instantiation(self, type(pat.scanner("")))


class ExternalTests(unittest.TestCase):
Expand Down
6 changes: 2 additions & 4 deletions Lib/test/test_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,10 @@ def fileno(self):
self.assertEqual(select.select([], a, []), ([], a[:5], []))

def test_disallow_instantiation(self):
tp = type(select.poll())
self.assertRaises(TypeError, tp)
support.check_disallow_instantiation(self, type(select.poll()))

if hasattr(select, 'devpoll'):
tp = type(select.devpoll())
self.assertRaises(TypeError, tp)
support.check_disallow_instantiation(self, type(select.devpoll()))

def tearDownModule():
support.reap_children()
Expand Down
6 changes: 1 addition & 5 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,7 @@ def test_ssl_types(self):
with self.subTest(ssl_type=ssl_type):
with self.assertRaisesRegex(TypeError, "immutable type"):
ssl_type.value = None
with self.assertRaisesRegex(
TypeError,
"cannot create '_ssl.Certificate' instances"
):
_ssl.Certificate()
support.check_disallow_instantiation(self, _ssl.Certificate)

def test_private_init(self):
with self.assertRaisesRegex(TypeError, "public constructor"):
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ def func(): pass
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
lock = threading.Lock()
tp = type(lock)
self.assertRaises(TypeError, tp)
test.support.check_disallow_instantiation(self, type(lock))

# Create a bunch of threads, let each do some work, wait until all are
# done.
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_unicodedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import unicodedata
import unittest
from test.support import (open_urlresource, requires_resource, script_helper,
cpython_only)
cpython_only, check_disallow_instantiation)


class UnicodeMethodsTest(unittest.TestCase):
Expand Down Expand Up @@ -229,7 +229,7 @@ class UnicodeMiscTest(UnicodeDatabaseTest):
@cpython_only
def test_disallow_instantiation(self):
# 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):
# Issue 4367
Expand Down
6 changes: 2 additions & 4 deletions Lib/test/test_zlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,8 @@ def test_overflow(self):
@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
comp_type = type(zlib.compressobj())
decomp_type = type(zlib.decompressobj())
self.assertRaises(TypeError, comp_type)
self.assertRaises(TypeError, decomp_type)
support.check_disallow_instantiation(self, type(zlib.compressobj()))
support.check_disallow_instantiation(self, type(zlib.decompressobj()))


class BaseCompressTestCase(object):
Expand Down