Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2f828f2

Browse files
committed
Test running of code in a sub-interpreter
(prelude to issue #6531).
1 parent 03757ec commit 2f828f2

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

Lib/test/test_capi.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from __future__ import with_statement
55
import os
6+
import pickle
67
import random
78
import subprocess
89
import sys
@@ -137,6 +138,22 @@ def test_pendingcalls_non_threaded(self):
137138
self.pendingcalls_submit(l, n)
138139
self.pendingcalls_wait(l, n)
139140

141+
def test_subinterps(self):
142+
# XXX this test leaks in refleak runs
143+
import builtins
144+
r, w = os.pipe()
145+
code = """if 1:
146+
import sys, builtins, pickle
147+
with open({:d}, "wb") as f:
148+
pickle.dump(id(sys.modules), f)
149+
pickle.dump(id(builtins), f)
150+
""".format(w)
151+
with open(r, "rb") as f:
152+
ret = _testcapi.run_in_subinterp(code)
153+
self.assertEqual(ret, 0)
154+
self.assertNotEqual(pickle.load(f), id(sys.modules))
155+
self.assertNotEqual(pickle.load(f), id(builtins))
156+
140157
# Bug #6012
141158
class Test6012(unittest.TestCase):
142159
def test(self):

Modules/_testcapimodule.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,6 +2300,32 @@ crash_no_current_thread(PyObject *self)
23002300
return NULL;
23012301
}
23022302

2303+
/* To run some code in a sub-interpreter. */
2304+
static PyObject *
2305+
run_in_subinterp(PyObject *self, PyObject *args)
2306+
{
2307+
const char *code;
2308+
int r;
2309+
PyThreadState *substate, *mainstate;
2310+
2311+
if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
2312+
&code))
2313+
return NULL;
2314+
2315+
mainstate = PyThreadState_Get();
2316+
2317+
PyThreadState_Swap(NULL);
2318+
2319+
substate = Py_NewInterpreter();
2320+
r = PyRun_SimpleString(code);
2321+
Py_EndInterpreter(substate);
2322+
2323+
PyThreadState_Swap(mainstate);
2324+
2325+
return PyLong_FromLong(r);
2326+
}
2327+
2328+
23032329
static PyMethodDef TestMethods[] = {
23042330
{"raise_exception", raise_exception, METH_VARARGS},
23052331
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
@@ -2385,6 +2411,7 @@ static PyMethodDef TestMethods[] = {
23852411
{"make_memoryview_from_NULL_pointer", (PyCFunction)make_memoryview_from_NULL_pointer,
23862412
METH_NOARGS},
23872413
{"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS},
2414+
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
23882415
{NULL, NULL} /* sentinel */
23892416
};
23902417

0 commit comments

Comments
 (0)