summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorOren Milman <orenmn@gmail.com>2017-09-27 14:04:37 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2017-09-27 14:04:37 (GMT)
commit5837d0418f47933b2e3c139bdee8a79c248a943c (patch)
treea3b7dfdca108fe5b67d63a878f85c2b829f4fe41 /Lib/test
parent236329ed9fee01edb85d698d30682e304439d198 (diff)
downloadcpython-5837d0418f47933b2e3c139bdee8a79c248a943c.zip
cpython-5837d0418f47933b2e3c139bdee8a79c248a943c.tar.gz
cpython-5837d0418f47933b2e3c139bdee8a79c248a943c.tar.bz2
bpo-31588: Validate return value of __prepare__() methods (GH-3764)
Class execution requires that __prepare__() methods return a proper execution namespace. Check for that immediately after calling __prepare__(), rather than passing it through to the code execution machinery and potentially triggering SystemError (in debug builds) or a cryptic TypeError (in release builds). Patch by Oren Milman.
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_types.py22
1 files changed, 22 insertions, 0 deletions
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index 3fd66db..966ef6d 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -864,6 +864,28 @@ class ClassCreationTests(unittest.TestCase):
self.assertIs(ns, expected_ns)
self.assertEqual(len(kwds), 0)
+ def test_bad___prepare__(self):
+ # __prepare__() must return a mapping.
+ class BadMeta(type):
+ @classmethod
+ def __prepare__(*args):
+ return None
+ with self.assertRaisesRegex(TypeError,
+ r'^BadMeta\.__prepare__\(\) must '
+ r'return a mapping, not NoneType$'):
+ class Foo(metaclass=BadMeta):
+ pass
+ # Also test the case in which the metaclass is not a type.
+ class BadMeta:
+ @classmethod
+ def __prepare__(*args):
+ return None
+ with self.assertRaisesRegex(TypeError,
+ r'^<metaclass>\.__prepare__\(\) must '
+ r'return a mapping, not NoneType$'):
+ class Bar(metaclass=BadMeta()):
+ pass
+
def test_metaclass_derivation(self):
# issue1294232: correct metaclass calculation
new_calls = [] # to check the order of __new__ calls