Skip to content

Commit 47892b7

Browse files
committed
Fix test_frame
* Move PyFrame C API tests from test_frame to test_capi.test_frame. * Add Lib/test/test_capi/test_frame.py.
1 parent d400238 commit 47892b7

File tree

4 files changed

+60
-49
lines changed

4 files changed

+60
-49
lines changed

Lib/test/test_capi/test_frame.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import sys
2+
import unittest
3+
from test.support import import_helper
4+
5+
6+
_testcapi = import_helper.import_module('_testcapi')
7+
8+
9+
class TestCAPI(unittest.TestCase):
10+
def getframe(self):
11+
return sys._getframe()
12+
13+
def test_frame_getters(self):
14+
frame = self.getframe()
15+
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
16+
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
17+
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
18+
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))
19+
20+
def test_getvar(self):
21+
current_frame = sys._getframe()
22+
x = 1
23+
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
24+
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
25+
with self.assertRaises(NameError):
26+
_testcapi.frame_getvar(current_frame, "y")
27+
with self.assertRaises(NameError):
28+
_testcapi.frame_getvarstring(current_frame, b"y")
29+
30+
# wrong name type
31+
with self.assertRaises(TypeError):
32+
_testcapi.frame_getvar(current_frame, b'x')
33+
with self.assertRaises(TypeError):
34+
_testcapi.frame_getvar(current_frame, 123)
35+
36+
def getgenframe(self):
37+
yield sys._getframe()
38+
39+
def test_frame_get_generator(self):
40+
gen = self.getgenframe()
41+
frame = next(gen)
42+
self.assertIs(gen, _testcapi.frame_getgenerator(frame))
43+
44+
def test_frame_fback_api(self):
45+
"""Test that accessing `f_back` does not cause a segmentation fault on
46+
a frame created with `PyFrame_New` (GH-99110)."""
47+
def dummy():
48+
pass
49+
50+
frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
51+
# The following line should not cause a segmentation fault.
52+
self.assertIsNone(frame.f_back)
53+
54+
55+
if __name__ == "__main__":
56+
unittest.main()

Lib/test/test_frame.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
import threading
77
import unittest
88
import weakref
9-
try:
10-
import _testcapi
11-
except ImportError:
12-
_testcapi = None
139

1410
from collections.abc import Mapping
1511
from test import support
@@ -773,51 +769,6 @@ def f():
773769
self.assertIs(catcher.unraisable.exc_type, TypeError)
774770
self.assertIsNone(weak())
775771

776-
@unittest.skipIf(_testcapi is None, 'need _testcapi')
777-
class TestCAPI(unittest.TestCase):
778-
def getframe(self):
779-
return sys._getframe()
780-
781-
def test_frame_getters(self):
782-
frame = self.getframe()
783-
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
784-
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
785-
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
786-
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))
787-
788-
def test_getvar(self):
789-
current_frame = sys._getframe()
790-
x = 1
791-
self.assertEqual(_testcapi.frame_getvar(current_frame, "x"), 1)
792-
self.assertEqual(_testcapi.frame_getvarstring(current_frame, b"x"), 1)
793-
with self.assertRaises(NameError):
794-
_testcapi.frame_getvar(current_frame, "y")
795-
with self.assertRaises(NameError):
796-
_testcapi.frame_getvarstring(current_frame, b"y")
797-
798-
# wrong name type
799-
with self.assertRaises(TypeError):
800-
_testcapi.frame_getvar(current_frame, b'x')
801-
with self.assertRaises(TypeError):
802-
_testcapi.frame_getvar(current_frame, 123)
803-
804-
def getgenframe(self):
805-
yield sys._getframe()
806-
807-
def test_frame_get_generator(self):
808-
gen = self.getgenframe()
809-
frame = next(gen)
810-
self.assertIs(gen, _testcapi.frame_getgenerator(frame))
811-
812-
def test_frame_fback_api(self):
813-
"""Test that accessing `f_back` does not cause a segmentation fault on
814-
a frame created with `PyFrame_New` (GH-99110)."""
815-
def dummy():
816-
pass
817-
818-
frame = _testcapi.frame_new(dummy.__code__, globals(), locals())
819-
# The following line should not cause a segmentation fault.
820-
self.assertIsNone(frame.f_back)
821772

822773
if __name__ == "__main__":
823774
unittest.main()

Modules/_testcapi/parts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,6 @@ int _PyTestCapi_Init_Object(PyObject *module);
6363
int _PyTestCapi_Init_Config(PyObject *mod);
6464
int _PyTestCapi_Init_Type(PyObject *mod);
6565
int _PyTestCapi_Init_Function(PyObject *mod);
66+
int _PyTestCapi_Init_Frame(PyObject *mod);
6667

6768
#endif // Py_TESTCAPI_PARTS_H

Modules/_testcapimodule.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,6 +3250,9 @@ PyInit__testcapi(void)
32503250
if (_PyTestCapi_Init_Function(m) < 0) {
32513251
return NULL;
32523252
}
3253+
if (_PyTestCapi_Init_Frame(m) < 0) {
3254+
return NULL;
3255+
}
32533256

32543257
PyState_AddModule(m, &_testcapimodule);
32553258
return m;

0 commit comments

Comments
 (0)