diff options
author | Petr Viktorin <encukou@gmail.com> | 2020-05-07 13:39:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-07 13:39:59 (GMT) |
commit | e1becf46b4e3ba6d7d32ebf4bbd3e0804766a423 (patch) | |
tree | be3fda5019edbdc78e82ee21985ea963686f3eb8 /Lib | |
parent | 4638c6429575bd6de26b12b2af5df74d6568b553 (diff) | |
download | cpython-e1becf46b4e3ba6d7d32ebf4bbd3e0804766a423.zip cpython-e1becf46b4e3ba6d7d32ebf4bbd3e0804766a423.tar.gz cpython-e1becf46b4e3ba6d7d32ebf4bbd3e0804766a423.tar.bz2 |
bpo-38787: C API for module state access from extension methods (PEP 573) (GH-19936)
Module C state is now accessible from C-defined heap type methods (PEP 573).
Patch by Marcel Plch and Petr Viktorin.
Co-authored-by: Marcel Plch <mplch@redhat.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_capi.py | 73 | ||||
-rw-r--r-- | Lib/test/test_sys.py | 2 |
2 files changed, 74 insertions, 1 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index f9578d3..5c7526a 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -13,6 +13,8 @@ import threading import time import unittest import weakref +import importlib.machinery +import importlib.util from test import support from test.support import MISSING_C_DOCSTRINGS from test.support.script_helper import assert_python_failure, assert_python_ok @@ -774,5 +776,76 @@ class PyMemDefaultTests(PyMemDebugTests): PYTHONMALLOC = '' +class Test_ModuleStateAccess(unittest.TestCase): + """Test access to module start (PEP 573)""" + + # The C part of the tests lives in _testmultiphase, in a module called + # _testmultiphase_meth_state_access. + # This module has multi-phase initialization, unlike _testcapi. + + def setUp(self): + fullname = '_testmultiphase_meth_state_access' # XXX + origin = importlib.util.find_spec('_testmultiphase').origin + loader = importlib.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) + self.module = module + + def test_subclass_get_module(self): + """PyType_GetModule for defining_class""" + class StateAccessType_Subclass(self.module.StateAccessType): + pass + + instance = StateAccessType_Subclass() + self.assertIs(instance.get_defining_module(), self.module) + + def test_subclass_get_module_with_super(self): + class StateAccessType_Subclass(self.module.StateAccessType): + def get_defining_module(self): + return super().get_defining_module() + + instance = StateAccessType_Subclass() + self.assertIs(instance.get_defining_module(), self.module) + + def test_state_access(self): + """Checks methods defined with and without argument clinic + + This tests a no-arg method (get_count) and a method with + both a positional and keyword argument. + """ + + a = self.module.StateAccessType() + b = self.module.StateAccessType() + + methods = { + 'clinic': a.increment_count_clinic, + 'noclinic': a.increment_count_noclinic, + } + + for name, increment_count in methods.items(): + with self.subTest(name): + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 0) + + increment_count() + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 1) + + increment_count(3) + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 4) + + increment_count(-2, twice=True) + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 0) + + with self.assertRaises(TypeError): + increment_count(thrice=3) + + with self.assertRaises(TypeError): + increment_count(1, 2, 3) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 91a645b..33b3459 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1322,7 +1322,7 @@ class SizeofTest(unittest.TestCase): '3P' # PyMappingMethods '10P' # PySequenceMethods '2P' # PyBufferProcs - '4P') + '5P') class newstyleclass(object): pass # Separate block for PyDictKeysObject with 8 keys and 5 entries check(newstyleclass, s + calcsize("2nP2n0P") + 8 + 5*calcsize("n2P")) |