]> granicus.if.org Git - python/commitdiff
Test running of code in a sub-interpreter
authorAntoine Pitrou <solipsis@pitrou.net>
Tue, 17 Jan 2012 23:21:11 +0000 (00:21 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Tue, 17 Jan 2012 23:21:11 +0000 (00:21 +0100)
(prelude to issue #6531).

Lib/test/test_capi.py
Modules/_testcapimodule.c

index ada393d9b469ee9d4a773196dad4627c6435986e..c2c633ff5dd76947aa158f4dcf56340656f66b11 100644 (file)
@@ -3,6 +3,7 @@
 
 from __future__ import with_statement
 import os
+import pickle
 import random
 import subprocess
 import sys
@@ -137,6 +138,22 @@ class TestPendingCalls(unittest.TestCase):
         self.pendingcalls_submit(l, n)
         self.pendingcalls_wait(l, n)
 
+    def test_subinterps(self):
+        # XXX this test leaks in refleak runs
+        import builtins
+        r, w = os.pipe()
+        code = """if 1:
+            import sys, builtins, pickle
+            with open({:d}, "wb") as f:
+                pickle.dump(id(sys.modules), f)
+                pickle.dump(id(builtins), f)
+            """.format(w)
+        with open(r, "rb") as f:
+            ret = _testcapi.run_in_subinterp(code)
+            self.assertEqual(ret, 0)
+            self.assertNotEqual(pickle.load(f), id(sys.modules))
+            self.assertNotEqual(pickle.load(f), id(builtins))
+
 # Bug #6012
 class Test6012(unittest.TestCase):
     def test(self):
index 6c61f7db8e4074b3e9751e77fd16fe50ef321413..94b6e6793a57d47350975c2971ef4f3b0299a142 100644 (file)
@@ -2300,6 +2300,32 @@ crash_no_current_thread(PyObject *self)
     return NULL;
 }
 
+/* To run some code in a sub-interpreter. */
+static PyObject *
+run_in_subinterp(PyObject *self, PyObject *args)
+{
+    const char *code;
+    int r;
+    PyThreadState *substate, *mainstate;
+
+    if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
+                          &code))
+        return NULL;
+
+    mainstate = PyThreadState_Get();
+
+    PyThreadState_Swap(NULL);
+
+    substate = Py_NewInterpreter();
+    r = PyRun_SimpleString(code);
+    Py_EndInterpreter(substate);
+
+    PyThreadState_Swap(mainstate);
+
+    return PyLong_FromLong(r);
+}
+
+
 static PyMethodDef TestMethods[] = {
     {"raise_exception",         raise_exception,                 METH_VARARGS},
     {"raise_memoryerror",   (PyCFunction)raise_memoryerror,  METH_NOARGS},
@@ -2385,6 +2411,7 @@ static PyMethodDef TestMethods[] = {
     {"make_memoryview_from_NULL_pointer", (PyCFunction)make_memoryview_from_NULL_pointer,
      METH_NOARGS},
     {"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS},
+    {"run_in_subinterp",        run_in_subinterp,                METH_VARARGS},
     {NULL, NULL} /* sentinel */
 };