| 
									
										
										
										
											2020-05-14 18:46:24 +02:00
										 |  |  | /* interpreters module */ | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | /* low-level access to interpreter primitives */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 13:53:19 +02:00
										 |  |  | #ifndef Py_BUILD_CORE_BUILTIN
 | 
					
						
							|  |  |  | #  define Py_BUILD_CORE_MODULE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | #include "pycore_abstract.h"      // _PyIndex_Check()
 | 
					
						
							| 
									
										
										
										
											2023-10-30 16:53:10 -06:00
										 |  |  | #include "pycore_crossinterp.h"   // struct _xid
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | #include "pycore_interp.h"        // _PyInterpreterState_IDIncref()
 | 
					
						
							| 
									
										
										
										
											2023-08-31 13:53:19 +02:00
										 |  |  | #include "pycore_initconfig.h"    // _PyErr_SetFromPyStatus()
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | #include "pycore_long.h"          // _PyLong_IsNegative()
 | 
					
						
							| 
									
										
										
										
											2023-10-17 14:30:31 +02:00
										 |  |  | #include "pycore_modsupport.h"    // _PyArg_BadArgument()
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | #include "pycore_namespace.h"     // _PyNamespace_New()
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | #include "pycore_pybuffer.h"      // _PyBuffer_ReleaseInInterpreterAndRawFree()
 | 
					
						
							|  |  |  | #include "pycore_pyerrors.h"      // _Py_excinfo
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | #include "pycore_pylifecycle.h"   // _PyInterpreterConfig_AsDict()
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:12:12 -06:00
										 |  |  | #include "pycore_pystate.h"       // _PyInterpreterState_SetRunningMain()
 | 
					
						
							| 
									
										
										
										
											2023-10-17 14:30:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | #include "marshal.h"              // PyMarshal_ReadObjectFromString()
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | #include "_interpreters_common.h"
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-24 10:18:24 -06:00
										 |  |  | #define MODULE_NAME _interpreters
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | #define MODULE_NAME_STR Py_STRINGIFY(MODULE_NAME)
 | 
					
						
							|  |  |  | #define MODINIT_FUNC_NAME RESOLVE_MODINIT_FUNC_NAME(MODULE_NAME)
 | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 18:46:24 +02:00
										 |  |  | static PyInterpreterState * | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | _get_current_interp(void) | 
					
						
							| 
									
										
										
										
											2020-05-07 08:56:01 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-14 18:46:24 +02:00
										 |  |  |     // PyInterpreterState_Get() aborts if lookup fails, so don't need
 | 
					
						
							|  |  |  |     // to check the result for NULL.
 | 
					
						
							|  |  |  |     return PyInterpreterState_Get(); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 09:56:12 -06:00
										 |  |  | #define look_up_interp _PyInterpreterState_LookUpIDObject
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _get_current_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     PyObject *name = PyUnicode_FromString(MODULE_NAME_STR); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     if (name == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *mod = PyImport_GetModule(name); | 
					
						
							|  |  |  |     Py_DECREF(name); | 
					
						
							|  |  |  |     if (mod == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     assert(mod != Py_None); | 
					
						
							|  |  |  |     return mod; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 18:20:20 -06:00
										 |  |  | static int | 
					
						
							|  |  |  | is_running_main(PyInterpreterState *interp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_PyInterpreterState_IsRunningMain(interp)) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Unlike with the general C-API, we can be confident that someone
 | 
					
						
							|  |  |  |     // using this module for the main interpreter is doing so through
 | 
					
						
							|  |  |  |     // the main program.  Thus we can make this extra check.  This benefits
 | 
					
						
							|  |  |  |     // applications that embed Python but haven't been updated yet
 | 
					
						
							|  |  |  |     // to call_PyInterpreterState_SetRunningMain().
 | 
					
						
							|  |  |  |     if (_Py_IsMainInterpreter(interp)) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | /* Cross-interpreter Buffer Views *******************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX Release when the original interpreter is destroyed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     Py_buffer *view; | 
					
						
							|  |  |  |     int64_t interpid; | 
					
						
							|  |  |  | } XIBufferViewObject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | xibufferview_from_xid(PyTypeObject *cls, _PyCrossInterpreterData *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     assert(_PyCrossInterpreterData_DATA(data) != NULL); | 
					
						
							|  |  |  |     assert(_PyCrossInterpreterData_OBJ(data) == NULL); | 
					
						
							|  |  |  |     assert(_PyCrossInterpreterData_INTERPID(data) >= 0); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     XIBufferViewObject *self = PyObject_Malloc(sizeof(XIBufferViewObject)); | 
					
						
							|  |  |  |     if (self == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject_Init((PyObject *)self, cls); | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     self->view = (Py_buffer *)_PyCrossInterpreterData_DATA(data); | 
					
						
							|  |  |  |     self->interpid = _PyCrossInterpreterData_INTERPID(data); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     return (PyObject *)self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | xibufferview_dealloc(XIBufferViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyInterpreterState *interp = _PyInterpreterState_LookUpID(self->interpid); | 
					
						
							|  |  |  |     /* If the interpreter is no longer alive then we have problems,
 | 
					
						
							|  |  |  |        since other objects may be using the buffer still. */ | 
					
						
							|  |  |  |     assert(interp != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_PyBuffer_ReleaseInInterpreterAndRawFree(interp, self->view) < 0) { | 
					
						
							|  |  |  |         // XXX Emit a warning?
 | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(self); | 
					
						
							|  |  |  |     tp->tp_free(self); | 
					
						
							|  |  |  |     /* "Instances of heap-allocated types hold a reference to their type."
 | 
					
						
							|  |  |  |      * See: https://docs.python.org/3.11/howto/isolating-extensions.html#garbage-collection-protocol
 | 
					
						
							|  |  |  |      * See: https://docs.python.org/3.11/c-api/typeobj.html#c.PyTypeObject.tp_traverse
 | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     // XXX Why don't we implement Py_TPFLAGS_HAVE_GC, e.g. Py_tp_traverse,
 | 
					
						
							|  |  |  |     // like we do for _abc._abc_data?
 | 
					
						
							|  |  |  |     Py_DECREF(tp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | xibufferview_getbuf(XIBufferViewObject *self, Py_buffer *view, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* Only PyMemoryView_FromObject() should ever call this,
 | 
					
						
							|  |  |  |        via _memoryview_from_xid() below. */ | 
					
						
							|  |  |  |     *view = *self->view; | 
					
						
							|  |  |  |     view->obj = (PyObject *)self; | 
					
						
							|  |  |  |     // XXX Should we leave it alone?
 | 
					
						
							|  |  |  |     view->internal = NULL; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Slot XIBufferViewType_slots[] = { | 
					
						
							|  |  |  |     {Py_tp_dealloc, (destructor)xibufferview_dealloc}, | 
					
						
							|  |  |  |     {Py_bf_getbuffer, (getbufferproc)xibufferview_getbuf}, | 
					
						
							|  |  |  |     // We don't bother with Py_bf_releasebuffer since we don't need it.
 | 
					
						
							|  |  |  |     {0, NULL}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec XIBufferViewType_spec = { | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     .name = MODULE_NAME_STR ".CrossInterpreterBufferView", | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     .basicsize = sizeof(XIBufferViewObject), | 
					
						
							|  |  |  |     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | 
					
						
							|  |  |  |               Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), | 
					
						
							|  |  |  |     .slots = XIBufferViewType_slots, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject * _get_current_xibufferview_type(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _memoryview_from_xid(_PyCrossInterpreterData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyTypeObject *cls = _get_current_xibufferview_type(); | 
					
						
							|  |  |  |     if (cls == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *obj = xibufferview_from_xid(cls, data); | 
					
						
							|  |  |  |     if (obj == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyMemoryView_FromObject(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _memoryview_shared(PyThreadState *tstate, PyObject *obj, | 
					
						
							|  |  |  |                    _PyCrossInterpreterData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_buffer *view = PyMem_RawMalloc(sizeof(Py_buffer)); | 
					
						
							|  |  |  |     if (view == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyObject_GetBuffer(obj, view, PyBUF_FULL_RO) < 0) { | 
					
						
							|  |  |  |         PyMem_RawFree(view); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _PyCrossInterpreterData_Init(data, tstate->interp, view, NULL, | 
					
						
							|  |  |  |                                  _memoryview_from_xid); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | register_memoryview_xid(PyObject *mod, PyTypeObject **p_state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // XIBufferView
 | 
					
						
							|  |  |  |     assert(*p_state == NULL); | 
					
						
							|  |  |  |     PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec( | 
					
						
							|  |  |  |                 mod, &XIBufferViewType_spec, NULL); | 
					
						
							|  |  |  |     if (cls == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddType(mod, cls) < 0) { | 
					
						
							|  |  |  |         Py_DECREF(cls); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *p_state = cls; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Register XID for the builtin memoryview type.
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     if (ensure_xid_class(&PyMemoryView_Type, _memoryview_shared) < 0) { | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // We don't ever bother un-registering memoryview.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-02 21:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  | /* module state *************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     int _notused; | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* heap types */ | 
					
						
							|  |  |  |     PyTypeObject *XIBufferViewType; | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  | } module_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline module_state * | 
					
						
							|  |  |  | get_module_state(PyObject *mod) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(mod != NULL); | 
					
						
							|  |  |  |     module_state *state = PyModule_GetState(mod); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | static module_state * | 
					
						
							|  |  |  | _get_current_module_state(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *mod = _get_current_module(); | 
					
						
							|  |  |  |     if (mod == NULL) { | 
					
						
							|  |  |  |         // XXX import it?
 | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_RuntimeError, | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |                         MODULE_NAME_STR " module not imported yet"); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     module_state *state = get_module_state(mod); | 
					
						
							|  |  |  |     Py_DECREF(mod); | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  | static int | 
					
						
							|  |  |  | traverse_module_state(module_state *state, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     /* heap types */ | 
					
						
							|  |  |  |     Py_VISIT(state->XIBufferViewType); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | clear_module_state(module_state *state) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     /* heap types */ | 
					
						
							|  |  |  |     Py_CLEAR(state->XIBufferViewType); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | static PyTypeObject * | 
					
						
							|  |  |  | _get_current_xibufferview_type(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     module_state *state = _get_current_module_state(); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return state->XIBufferViewType; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | /* Python code **************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * | 
					
						
							|  |  |  | check_code_str(PyUnicodeObject *text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(text != NULL); | 
					
						
							|  |  |  |     if (PyUnicode_GET_LENGTH(text) == 0) { | 
					
						
							|  |  |  |         return "too short"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // XXX Verify that it parses?
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * | 
					
						
							|  |  |  | check_code_object(PyCodeObject *code) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(code != NULL); | 
					
						
							|  |  |  |     if (code->co_argcount > 0 | 
					
						
							|  |  |  |         || code->co_posonlyargcount > 0 | 
					
						
							|  |  |  |         || code->co_kwonlyargcount > 0 | 
					
						
							|  |  |  |         || code->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return "arguments not supported"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (code->co_ncellvars > 0) { | 
					
						
							|  |  |  |         return "closures not supported"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // We trust that no code objects under co_consts have unbound cell vars.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     if (_PyCode_HAS_EXECUTORS(code) || _PyCode_HAS_INSTRUMENTATION(code)) { | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |         return "only basic functions are supported"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (code->_co_monitoring != NULL) { | 
					
						
							|  |  |  |         return "only basic functions are supported"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (code->co_extra != NULL) { | 
					
						
							|  |  |  |         return "only basic functions are supported"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RUN_TEXT 1
 | 
					
						
							|  |  |  | #define RUN_CODE 2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * | 
					
						
							|  |  |  | get_code_str(PyObject *arg, Py_ssize_t *len_p, PyObject **bytes_p, int *flags_p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *codestr = NULL; | 
					
						
							|  |  |  |     Py_ssize_t len = -1; | 
					
						
							|  |  |  |     PyObject *bytes_obj = NULL; | 
					
						
							|  |  |  |     int flags = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyUnicode_Check(arg)) { | 
					
						
							|  |  |  |         assert(PyUnicode_CheckExact(arg) | 
					
						
							|  |  |  |                && (check_code_str((PyUnicodeObject *)arg) == NULL)); | 
					
						
							|  |  |  |         codestr = PyUnicode_AsUTF8AndSize(arg, &len); | 
					
						
							|  |  |  |         if (codestr == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (strlen(codestr) != (size_t)len) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                             "source code string cannot contain null bytes"); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         flags = RUN_TEXT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         assert(PyCode_Check(arg) | 
					
						
							|  |  |  |                && (check_code_object((PyCodeObject *)arg) == NULL)); | 
					
						
							|  |  |  |         flags = RUN_CODE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Serialize the code object.
 | 
					
						
							|  |  |  |         bytes_obj = PyMarshal_WriteObjectToString(arg, Py_MARSHAL_VERSION); | 
					
						
							|  |  |  |         if (bytes_obj == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         codestr = PyBytes_AS_STRING(bytes_obj); | 
					
						
							|  |  |  |         len = PyBytes_GET_SIZE(bytes_obj); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *flags_p = flags; | 
					
						
							|  |  |  |     *bytes_p = bytes_obj; | 
					
						
							|  |  |  |     *len_p = len; | 
					
						
							|  |  |  |     return codestr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  | /* interpreter-specific code ************************************************/ | 
					
						
							| 
									
										
										
										
											2018-02-02 21:49:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | static int | 
					
						
							|  |  |  | init_named_config(PyInterpreterConfig *config, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (name == NULL | 
					
						
							|  |  |  |             || strcmp(name, "") == 0 | 
					
						
							|  |  |  |             || strcmp(name, "default") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         name = "isolated"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (strcmp(name, "isolated") == 0) { | 
					
						
							|  |  |  |         *config = (PyInterpreterConfig)_PyInterpreterConfig_INIT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (strcmp(name, "legacy") == 0) { | 
					
						
							|  |  |  |         *config = (PyInterpreterConfig)_PyInterpreterConfig_LEGACY_INIT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (strcmp(name, "empty") == 0) { | 
					
						
							|  |  |  |         *config = (PyInterpreterConfig){0}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "unsupported config name '%s'", name); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | config_from_object(PyObject *configobj, PyInterpreterConfig *config) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (configobj == NULL || configobj == Py_None) { | 
					
						
							|  |  |  |         if (init_named_config(config, NULL) < 0) { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyUnicode_Check(configobj)) { | 
					
						
							|  |  |  |         if (init_named_config(config, PyUnicode_AsUTF8(configobj)) < 0) { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         PyObject *dict = PyObject_GetAttrString(configobj, "__dict__"); | 
					
						
							|  |  |  |         if (dict == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, "bad config %R", configobj); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         int res = _PyInterpreterConfig_InitFromDict(config, dict); | 
					
						
							|  |  |  |         Py_DECREF(dict); | 
					
						
							|  |  |  |         if (res < 0) { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | _run_script(PyObject *ns, const char *codestr, Py_ssize_t codestrlen, int flags) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  |     if (flags & RUN_TEXT) { | 
					
						
							|  |  |  |         result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (flags & RUN_CODE) { | 
					
						
							|  |  |  |         PyObject *code = PyMarshal_ReadObjectFromString(codestr, codestrlen); | 
					
						
							|  |  |  |         if (code != NULL) { | 
					
						
							|  |  |  |             result = PyEval_EvalCode(code, ns, ns); | 
					
						
							|  |  |  |             Py_DECREF(code); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         Py_UNREACHABLE(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (result == NULL) { | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     Py_DECREF(result);  // We throw away the result.
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  | _run_in_interpreter(PyInterpreterState *interp, | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |                     const char *codestr, Py_ssize_t codestrlen, | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |                     PyObject *shareables, int flags, | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |                     PyObject **p_excinfo) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  |     _PyXI_session session = {0}; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     // Prep and switch interpreters.
 | 
					
						
							|  |  |  |     if (_PyXI_Enter(&session, interp, shareables) < 0) { | 
					
						
							|  |  |  |         assert(!PyErr_Occurred()); | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |         PyObject *excinfo = _PyXI_ApplyError(session.error); | 
					
						
							|  |  |  |         if (excinfo != NULL) { | 
					
						
							|  |  |  |             *p_excinfo = excinfo; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |         assert(PyErr_Occurred()); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Run the script.
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     int res = _run_script(session.main_ns, codestr, codestrlen, flags); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     // Clean up and switch back.
 | 
					
						
							|  |  |  |     _PyXI_Exit(&session); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Propagate any exception out to the caller.
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |         PyObject *excinfo = _PyXI_ApplyCapturedException(&session); | 
					
						
							|  |  |  |         if (excinfo != NULL) { | 
					
						
							|  |  |  |             *p_excinfo = excinfo; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     else { | 
					
						
							|  |  |  |         assert(!_PyXI_HasCapturedException(&session)); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* module level code ********************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | static long | 
					
						
							|  |  |  | get_whence(PyInterpreterState *interp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _PyInterpreterState_GetWhence(interp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyInterpreterState * | 
					
						
							|  |  |  | resolve_interp(PyObject *idobj, int restricted, int reqready, const char *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyInterpreterState *interp; | 
					
						
							|  |  |  |     if (idobj == NULL) { | 
					
						
							|  |  |  |         interp = PyInterpreterState_Get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         interp = look_up_interp(idobj); | 
					
						
							|  |  |  |         if (interp == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (reqready && !_PyInterpreterState_IsReady(interp)) { | 
					
						
							|  |  |  |         if (idobj == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_InterpreterError, | 
					
						
							|  |  |  |                          "cannot %s current interpreter (not ready)", op); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_InterpreterError, | 
					
						
							|  |  |  |                          "cannot %s interpreter %R (not ready)", op, idobj); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (restricted && get_whence(interp) != _PyInterpreterState_WHENCE_STDLIB) { | 
					
						
							|  |  |  |         if (idobj == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_InterpreterError, | 
					
						
							|  |  |  |                          "cannot %s unrecognized current interpreter", op); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_InterpreterError, | 
					
						
							|  |  |  |                          "cannot %s unrecognized interpreter %R", op, idobj); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return interp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | get_summary(PyInterpreterState *interp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *idobj = _PyInterpreterState_GetIDObject(interp); | 
					
						
							|  |  |  |     if (idobj == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     PyObject *whenceobj = PyLong_FromLong( | 
					
						
							|  |  |  |                             get_whence(interp)); | 
					
						
							|  |  |  |     if (whenceobj == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(idobj); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *res = PyTuple_Pack(2, idobj, whenceobj); | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     Py_DECREF(idobj); | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     Py_DECREF(whenceobj); | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | interp_new_config(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     const char *name = NULL; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "|s:" MODULE_NAME_STR ".new_config", | 
					
						
							|  |  |  |                           &name)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *overrides = kwds; | 
					
						
							| 
									
										
										
										
											2020-05-01 11:33:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     PyInterpreterConfig config; | 
					
						
							|  |  |  |     if (init_named_config(&config, name) < 0) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     if (overrides != NULL && PyDict_GET_SIZE(overrides) > 0) { | 
					
						
							|  |  |  |         if (_PyInterpreterConfig_UpdateFromDict(&config, overrides) < 0) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-03 09:20:48 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     PyObject *dict = _PyInterpreterConfig_AsDict(&config); | 
					
						
							|  |  |  |     if (dict == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *configobj = _PyNamespace_New(dict); | 
					
						
							|  |  |  |     Py_DECREF(dict); | 
					
						
							|  |  |  |     return configobj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(new_config_doc, | 
					
						
							|  |  |  | "new_config(name='isolated', /, **overrides) -> type.SimpleNamespace\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a representation of a new PyInterpreterConfig.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | The name determines the initial values of the config.  Supported named\n\ | 
					
						
							|  |  |  | configs are: default, isolated, legacy, and empty.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Any keyword arguments are set on the corresponding config fields,\n\ | 
					
						
							|  |  |  | overriding the initial values."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interp_create(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *kwlist[] = {"config", "reqrefs", NULL}; | 
					
						
							|  |  |  |     PyObject *configobj = NULL; | 
					
						
							|  |  |  |     int reqrefs = 0; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O$p:create", kwlist, | 
					
						
							|  |  |  |                                      &configobj, &reqrefs)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyInterpreterConfig config; | 
					
						
							|  |  |  |     if (config_from_object(configobj, &config) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     long whence = _PyInterpreterState_WHENCE_STDLIB; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             _PyXI_NewInterpreter(&config, &whence, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         // XXX Move the chained exception to interpreters.create()?
 | 
					
						
							| 
									
										
										
										
											2023-03-21 10:49:12 -06:00
										 |  |  |         PyObject *exc = PyErr_GetRaisedException(); | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |         assert(exc != NULL); | 
					
						
							| 
									
										
										
										
											2024-04-03 10:58:39 -06:00
										 |  |  |         PyErr_SetString(PyExc_InterpreterError, "interpreter creation failed"); | 
					
						
							| 
									
										
										
										
											2023-03-21 10:49:12 -06:00
										 |  |  |         _PyErr_ChainExceptions1(exc); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     assert(_PyInterpreterState_IsReady(interp)); | 
					
						
							| 
									
										
										
										
											2023-10-03 09:20:48 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     PyObject *idobj = _PyInterpreterState_GetIDObject(interp); | 
					
						
							|  |  |  |     if (idobj == NULL) { | 
					
						
							|  |  |  |         _PyXI_EndInterpreter(interp, NULL, NULL); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     if (reqrefs) { | 
					
						
							|  |  |  |         // Decref to 0 will destroy the interpreter.
 | 
					
						
							|  |  |  |         _PyInterpreterState_RequireIDRef(interp, 1); | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-03 09:20:48 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     return idobj; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | PyDoc_STRVAR(create_doc, | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | "create([config], *, reqrefs=False) -> ID\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | Create a new interpreter and return a unique generated ID.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | The caller is responsible for destroying the interpreter before exiting,\n\ | 
					
						
							|  |  |  | typically by using _interpreters.destroy().  This can be managed \n\ | 
					
						
							|  |  |  | automatically by passing \"reqrefs=True\" and then using _incref() and\n\
 | 
					
						
							|  |  |  | _decref()` appropriately.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | \"config\" must be a valid interpreter config or the name of a\n\
 | 
					
						
							|  |  |  | predefined config (\"isolated\" or \"legacy\").  The default\n\
 | 
					
						
							|  |  |  | is \"isolated\"."); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  | interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     PyObject *id; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |     // XXX Use "L" for id?
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "O|$p:destroy", kwlist, &id, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Look up the interpreter.
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int reqready = 0; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "destroy"); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Ensure we don't try to destroy the current interpreter.
 | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |     PyInterpreterState *current = _get_current_interp(); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (current == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (interp == current) { | 
					
						
							| 
									
										
										
										
											2024-04-03 10:58:39 -06:00
										 |  |  |         PyErr_SetString(PyExc_InterpreterError, | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |                         "cannot destroy the current interpreter"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Ensure the interpreter isn't running.
 | 
					
						
							|  |  |  |     /* XXX We *could* support destroying a running interpreter but
 | 
					
						
							|  |  |  |        aren't going to worry about it for now. */ | 
					
						
							| 
									
										
										
										
											2024-03-21 18:20:20 -06:00
										 |  |  |     if (is_running_main(interp)) { | 
					
						
							| 
									
										
										
										
											2024-04-03 10:58:39 -06:00
										 |  |  |         PyErr_Format(PyExc_InterpreterError, "interpreter running"); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Destroy the interpreter.
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     _PyXI_EndInterpreter(interp, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(destroy_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "destroy(id, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Destroy the identified interpreter.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2024-04-03 10:58:39 -06:00
										 |  |  | Attempting to destroy the current interpreter raises InterpreterError.\n\ | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | So does an unrecognized ID."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | interp_list_all(PyObject *self, PyObject *args, PyObject *kwargs) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"require_ready", NULL}; | 
					
						
							|  |  |  |     int reqready = 0; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwargs, | 
					
						
							|  |  |  |                                      "|$p:" MODULE_NAME_STR ".list_all", | 
					
						
							|  |  |  |                                      kwlist, &reqready)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     PyObject *ids = PyList_New(0); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (ids == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     PyInterpreterState *interp = PyInterpreterState_Head(); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     while (interp != NULL) { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |         if (!reqready || _PyInterpreterState_IsReady(interp)) { | 
					
						
							|  |  |  |             PyObject *item = get_summary(interp); | 
					
						
							|  |  |  |             if (item == NULL) { | 
					
						
							|  |  |  |                 Py_DECREF(ids); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |             // insert at front of list
 | 
					
						
							|  |  |  |             int res = PyList_Insert(ids, 0, item); | 
					
						
							|  |  |  |             Py_DECREF(item); | 
					
						
							|  |  |  |             if (res < 0) { | 
					
						
							|  |  |  |                 Py_DECREF(ids); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         interp = PyInterpreterState_Next(interp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ids; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(list_all_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "list_all() -> [(ID, whence)]\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return a list containing the ID of every existing interpreter."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |     PyInterpreterState *interp =_get_current_interp(); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     assert(_PyInterpreterState_IsReady(interp)); | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     return get_summary(interp); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(get_current_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "get_current() -> (ID, whence)\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return the ID of current interpreter."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     PyInterpreterState *interp = _PyInterpreterState_Main(); | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     assert(_PyInterpreterState_IsReady(interp)); | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     return get_summary(interp); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(get_main_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "get_main() -> (ID, whence)\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return the ID of main interpreter."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "updates", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  |     PyObject *id, *updates; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwargs, | 
					
						
							|  |  |  |                                      "OO|$p:" MODULE_NAME_STR ".set___main___attrs", | 
					
						
							|  |  |  |                                      kwlist, &id, &updates, &restricted)) | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Look up the interpreter.
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "update __main__ for"); | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check the updates.
 | 
					
						
							|  |  |  |     if (updates != Py_None) { | 
					
						
							|  |  |  |         Py_ssize_t size = PyObject_Size(updates); | 
					
						
							|  |  |  |         if (size < 0) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (size == 0) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                             "arg 2 must be a non-empty mapping"); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _PyXI_session session = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Prep and switch interpreters, including apply the updates.
 | 
					
						
							|  |  |  |     if (_PyXI_Enter(&session, interp, updates) < 0) { | 
					
						
							|  |  |  |         if (!PyErr_Occurred()) { | 
					
						
							|  |  |  |             _PyXI_ApplyCapturedException(&session); | 
					
						
							|  |  |  |             assert(PyErr_Occurred()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             assert(!_PyXI_HasCapturedException(&session)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Clean up and switch back.
 | 
					
						
							|  |  |  |     _PyXI_Exit(&session); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(set___main___attrs_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "set___main___attrs(id, ns, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Bind the given attributes in the interpreter's __main__ module."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | static PyUnicodeObject * | 
					
						
							|  |  |  | convert_script_arg(PyObject *arg, const char *fname, const char *displayname, | 
					
						
							|  |  |  |                    const char *expected) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyUnicodeObject *str = NULL; | 
					
						
							|  |  |  |     if (PyUnicode_CheckExact(arg)) { | 
					
						
							|  |  |  |         str = (PyUnicodeObject *)Py_NewRef(arg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyUnicode_Check(arg)) { | 
					
						
							|  |  |  |         // XXX str = PyUnicode_FromObject(arg);
 | 
					
						
							|  |  |  |         str = (PyUnicodeObject *)Py_NewRef(arg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         _PyArg_BadArgument(fname, displayname, expected, arg); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *err = check_code_str(str); | 
					
						
							|  |  |  |     if (err != NULL) { | 
					
						
							|  |  |  |         Py_DECREF(str); | 
					
						
							|  |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "%.200s(): bad script text (%s)", fname, err); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return str; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyCodeObject * | 
					
						
							|  |  |  | convert_code_arg(PyObject *arg, const char *fname, const char *displayname, | 
					
						
							|  |  |  |                  const char *expected) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *kind = NULL; | 
					
						
							|  |  |  |     PyCodeObject *code = NULL; | 
					
						
							|  |  |  |     if (PyFunction_Check(arg)) { | 
					
						
							|  |  |  |         if (PyFunction_GetClosure(arg) != NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                          "%.200s(): closures not supported", fname); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         code = (PyCodeObject *)PyFunction_GetCode(arg); | 
					
						
							|  |  |  |         if (code == NULL) { | 
					
						
							|  |  |  |             if (PyErr_Occurred()) { | 
					
						
							|  |  |  |                 // This chains.
 | 
					
						
							|  |  |  |                 PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                              "%.200s(): bad func", fname); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                              "%.200s(): func.__code__ missing", fname); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_INCREF(code); | 
					
						
							|  |  |  |         kind = "func"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyCode_Check(arg)) { | 
					
						
							|  |  |  |         code = (PyCodeObject *)Py_NewRef(arg); | 
					
						
							|  |  |  |         kind = "code object"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         _PyArg_BadArgument(fname, displayname, expected, arg); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *err = check_code_object(code); | 
					
						
							|  |  |  |     if (err != NULL) { | 
					
						
							|  |  |  |         Py_DECREF(code); | 
					
						
							|  |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "%.200s(): bad %s (%s)", fname, kind, err); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return code; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | _interp_exec(PyObject *self, PyInterpreterState *interp, | 
					
						
							|  |  |  |              PyObject *code_arg, PyObject *shared_arg, PyObject **p_excinfo) | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | { | 
					
						
							|  |  |  |     // Extract code.
 | 
					
						
							|  |  |  |     Py_ssize_t codestrlen = -1; | 
					
						
							|  |  |  |     PyObject *bytes_obj = NULL; | 
					
						
							|  |  |  |     int flags = 0; | 
					
						
							|  |  |  |     const char *codestr = get_code_str(code_arg, | 
					
						
							|  |  |  |                                        &codestrlen, &bytes_obj, &flags); | 
					
						
							|  |  |  |     if (codestr == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Run the code in the interpreter.
 | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     int res = _run_in_interpreter(interp, codestr, codestrlen, | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |                                   shared_arg, flags, p_excinfo); | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     Py_XDECREF(bytes_obj); | 
					
						
							| 
									
										
										
										
											2023-11-01 17:36:40 -06:00
										 |  |  |     if (res < 0) { | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | interp_exec(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "code", "shared", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     PyObject *id, *code; | 
					
						
							|  |  |  |     PyObject *shared = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "OO|O$p:" MODULE_NAME_STR ".exec", kwlist, | 
					
						
							|  |  |  |                                      &id, &code, &shared, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "exec code for"); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     const char *expected = "a string, a function, or a code object"; | 
					
						
							|  |  |  |     if (PyUnicode_Check(code)) { | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |          code = (PyObject *)convert_script_arg(code, MODULE_NAME_STR ".exec", | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |                                                "argument 2", expected); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |          code = (PyObject *)convert_code_arg(code, MODULE_NAME_STR ".exec", | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |                                              "argument 2", expected); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (code == NULL) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     PyObject *excinfo = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int res = _interp_exec(self, interp, code, shared, &excinfo); | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     Py_DECREF(code); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |         assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); | 
					
						
							|  |  |  |         return excinfo; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(exec_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "exec(id, code, shared=None, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Execute the provided code in the identified interpreter.\n\ | 
					
						
							|  |  |  | This is equivalent to running the builtin exec() under the target\n\ | 
					
						
							|  |  |  | interpreter, using the __dict__ of its __main__ module as both\n\ | 
					
						
							|  |  |  | globals and locals.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | \"code\" may be a string containing the text of a Python script.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Functions (and code objects) are also supported, with some restrictions.\n\ | 
					
						
							|  |  |  | The code/function must not take any arguments or be a closure\n\ | 
					
						
							|  |  |  | (i.e. have cell vars).  Methods and other callables are not supported.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | If a function is provided, its code object is used and all its state\n\ | 
					
						
							|  |  |  | is ignored, including its __globals__ dict."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | interp_call(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "callable", "args", "kwargs", | 
					
						
							|  |  |  |                              "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     PyObject *id, *callable; | 
					
						
							|  |  |  |     PyObject *args_obj = NULL; | 
					
						
							|  |  |  |     PyObject *kwargs_obj = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "OO|OO$p:" MODULE_NAME_STR ".call", kwlist, | 
					
						
							|  |  |  |                                      &id, &callable, &args_obj, &kwargs_obj, | 
					
						
							|  |  |  |                                      &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "make a call in"); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (args_obj != NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "got unexpected args"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (kwargs_obj != NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "got unexpected kwargs"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *code = (PyObject *)convert_code_arg(callable, MODULE_NAME_STR ".call", | 
					
						
							|  |  |  |                                                   "argument 2", "a function"); | 
					
						
							|  |  |  |     if (code == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *excinfo = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int res = _interp_exec(self, interp, code, NULL, &excinfo); | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     Py_DECREF(code); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); | 
					
						
							|  |  |  |         return excinfo; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(call_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "call(id, callable, args=None, kwargs=None, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Call the provided object in the identified interpreter.\n\ | 
					
						
							|  |  |  | Pass the given args and kwargs, if possible.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | \"callable\" may be a plain function with no free vars that takes\n\
 | 
					
						
							|  |  |  | no arguments.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | The function's code object is used and all its state\n\ | 
					
						
							|  |  |  | is ignored, including its __globals__ dict."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "script", "shared", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     PyObject *id, *script; | 
					
						
							|  |  |  |     PyObject *shared = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "OU|O$p:" MODULE_NAME_STR ".run_string", | 
					
						
							|  |  |  |                                      kwlist, &id, &script, &shared, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "run a string in"); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     script = (PyObject *)convert_script_arg(script, MODULE_NAME_STR ".exec", | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |                                             "argument 2", "a string"); | 
					
						
							|  |  |  |     if (script == NULL) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     PyObject *excinfo = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int res = _interp_exec(self, interp, script, shared, &excinfo); | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     Py_DECREF(script); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |         assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); | 
					
						
							|  |  |  |         return excinfo; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(run_string_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "run_string(id, script, shared=None, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Execute the provided string in the identified interpreter.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | (See " MODULE_NAME_STR ".exec()."); | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "func", "shared", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     PyObject *id, *func; | 
					
						
							|  |  |  |     PyObject *shared = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "OO|O$p:" MODULE_NAME_STR ".run_func", | 
					
						
							|  |  |  |                                      kwlist, &id, &func, &shared, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "run a function in"); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     PyCodeObject *code = convert_code_arg(func, MODULE_NAME_STR ".exec", | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |                                           "argument 2", | 
					
						
							|  |  |  |                                           "a function or a code object"); | 
					
						
							|  |  |  |     if (code == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |     PyObject *excinfo = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int res = _interp_exec(self, interp, (PyObject *)code, shared, &excinfo); | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     Py_DECREF(code); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							| 
									
										
										
										
											2023-11-22 17:55:00 -07:00
										 |  |  |         assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); | 
					
						
							|  |  |  |         return excinfo; | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(run_func_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "run_func(id, func, shared=None, *, restrict=False)\n\
 | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Execute the body of the provided function in the identified interpreter.\n\ | 
					
						
							|  |  |  | Code objects are also supported.  In both cases, closures and args\n\ | 
					
						
							|  |  |  | are not supported.  Methods and other callables are not supported either.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | (See " MODULE_NAME_STR ".exec()."); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  | object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |     static char *kwlist[] = {"obj", NULL}; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     PyObject *obj; | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							|  |  |  |                                      "O:is_shareable", kwlist, &obj)) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (_PyObject_CheckCrossInterpreterData(obj) == 0) { | 
					
						
							|  |  |  |         Py_RETURN_TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyErr_Clear(); | 
					
						
							|  |  |  |     Py_RETURN_FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(is_shareable_doc, | 
					
						
							|  |  |  | "is_shareable(obj) -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if the object's data may be shared between interpreters and\n\ | 
					
						
							|  |  |  | False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  | interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     PyObject *id; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "O|$p:is_running", kwlist, | 
					
						
							|  |  |  |                                      &id, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "check if running for"); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 18:20:20 -06:00
										 |  |  |     if (is_running_main(interp)) { | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |         Py_RETURN_TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(is_running_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "is_running(id, *, restrict=False) -> bool\n\
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return whether or not the identified interpreter is running."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:12:12 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | interp_get_config(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     PyObject *idobj = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "O|$p:get_config", kwlist, | 
					
						
							|  |  |  |                                      &idobj, &restricted)) | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     if (idobj == Py_None) { | 
					
						
							|  |  |  |         idobj = NULL; | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     int reqready = 0; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(idobj, restricted, reqready, "get the config of"); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyInterpreterConfig config; | 
					
						
							|  |  |  |     if (_PyInterpreterConfig_InitFromState(&config, interp) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *dict = _PyInterpreterConfig_AsDict(&config); | 
					
						
							|  |  |  |     if (dict == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *configobj = _PyNamespace_New(dict); | 
					
						
							|  |  |  |     Py_DECREF(dict); | 
					
						
							|  |  |  |     return configobj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(get_config_doc, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | "get_config(id, *, restrict=False) -> types.SimpleNamespace\n\
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return a representation of the config used to initialize the interpreter."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | interp_whence(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *kwlist[] = {"id", NULL}; | 
					
						
							|  |  |  |     PyObject *id; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							|  |  |  |                                      "O:whence", kwlist, &id)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyInterpreterState *interp = look_up_interp(id); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     long whence = get_whence(interp); | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     return PyLong_FromLong(whence); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(whence_doc, | 
					
						
							|  |  |  | "whence(id) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return an identifier for where the interpreter was created."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | interp_incref(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "implieslink", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     PyObject *id; | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     int implieslink = 0; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "O|$pp:incref", kwlist, | 
					
						
							|  |  |  |                                      &id, &implieslink, &restricted)) | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "incref"); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (implieslink) { | 
					
						
							|  |  |  |         // Decref to 0 will destroy the interpreter.
 | 
					
						
							|  |  |  |         _PyInterpreterState_RequireIDRef(interp, 1); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     _PyInterpreterState_IDIncref(interp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interp_decref(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     static char *kwlist[] = {"id", "restrict", NULL}; | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     PyObject *id; | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int restricted = 0; | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |                                      "O|$p:decref", kwlist, &id, &restricted)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     int reqready = 1; | 
					
						
							|  |  |  |     PyInterpreterState *interp = \ | 
					
						
							|  |  |  |             resolve_interp(id, restricted, reqready, "decref"); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     _PyInterpreterState_IDDecref(interp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | capture_exception(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *kwlist[] = {"exc", NULL}; | 
					
						
							|  |  |  |     PyObject *exc_arg = NULL; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							|  |  |  |                                      "|O:capture_exception", kwlist, | 
					
						
							|  |  |  |                                      &exc_arg)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *exc = exc_arg; | 
					
						
							|  |  |  |     if (exc == NULL || exc == Py_None) { | 
					
						
							|  |  |  |         exc = PyErr_GetRaisedException(); | 
					
						
							|  |  |  |         if (exc == NULL) { | 
					
						
							|  |  |  |             Py_RETURN_NONE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (!PyExceptionInstance_Check(exc)) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, "expected exception, got %R", exc); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *captured = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _PyXI_excinfo info = {0}; | 
					
						
							|  |  |  |     if (_PyXI_InitExcInfo(&info, exc) < 0) { | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     captured = _PyXI_ExcInfoAsObject(&info); | 
					
						
							|  |  |  |     if (captured == NULL) { | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *formatted = _PyXI_FormatExcInfo(&info); | 
					
						
							|  |  |  |     if (formatted == NULL) { | 
					
						
							|  |  |  |         Py_CLEAR(captured); | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyObject_SetAttrString(captured, "formatted", formatted); | 
					
						
							|  |  |  |     Py_DECREF(formatted); | 
					
						
							|  |  |  |     if (res < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(captured); | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | finally: | 
					
						
							|  |  |  |     _PyXI_ClearExcInfo(&info); | 
					
						
							|  |  |  |     if (exc != exc_arg) { | 
					
						
							|  |  |  |         if (PyErr_Occurred()) { | 
					
						
							|  |  |  |             PyErr_SetRaisedException(exc); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             _PyErr_ChainExceptions1(exc); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return captured; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(capture_exception_doc, | 
					
						
							|  |  |  | "capture_exception(exc=None) -> types.SimpleNamespace\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a snapshot of an exception.  If \"exc\" is None\n\
 | 
					
						
							|  |  |  | then the current exception, if any, is used (but not cleared).\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | The returned snapshot is the same as what _interpreters.exec() returns."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | static PyMethodDef module_functions[] = { | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     {"new_config",                _PyCFunction_CAST(interp_new_config), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, new_config_doc}, | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-03 21:42:14 +02:00
										 |  |  |     {"create",                    _PyCFunction_CAST(interp_create), | 
					
						
							| 
									
										
										
										
											2020-05-01 11:33:44 +02:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, create_doc}, | 
					
						
							| 
									
										
										
										
											2022-05-03 21:42:14 +02:00
										 |  |  |     {"destroy",                   _PyCFunction_CAST(interp_destroy), | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, destroy_doc}, | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     {"list_all",                  _PyCFunction_CAST(interp_list_all), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, list_all_doc}, | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  |     {"get_current",               interp_get_current, | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |      METH_NOARGS, get_current_doc}, | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  |     {"get_main",                  interp_get_main, | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |      METH_NOARGS, get_main_doc}, | 
					
						
							| 
									
										
										
										
											2023-02-03 18:14:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-03 21:42:14 +02:00
										 |  |  |     {"is_running",                _PyCFunction_CAST(interp_is_running), | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, is_running_doc}, | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     {"get_config",                _PyCFunction_CAST(interp_get_config), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, get_config_doc}, | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     {"whence",                    _PyCFunction_CAST(interp_whence), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, whence_doc}, | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     {"exec",                      _PyCFunction_CAST(interp_exec), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, exec_doc}, | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     {"call",                      _PyCFunction_CAST(interp_call), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, call_doc}, | 
					
						
							| 
									
										
										
										
											2022-05-03 21:42:14 +02:00
										 |  |  |     {"run_string",                _PyCFunction_CAST(interp_run_string), | 
					
						
							| 
									
										
										
										
											2018-05-16 15:04:57 -04:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, run_string_doc}, | 
					
						
							| 
									
										
										
										
											2023-10-06 17:52:22 -06:00
										 |  |  |     {"run_func",                  _PyCFunction_CAST(interp_run_func), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, run_func_doc}, | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 11:06:06 -07:00
										 |  |  |     {"set___main___attrs",        _PyCFunction_CAST(interp_set___main___attrs), | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, set___main___attrs_doc}, | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     {"incref",                    _PyCFunction_CAST(interp_incref), | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, NULL}, | 
					
						
							| 
									
										
										
										
											2024-04-02 17:16:50 -06:00
										 |  |  |     {"decref",                    _PyCFunction_CAST(interp_decref), | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |      METH_VARARGS | METH_KEYWORDS, NULL}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  |     {"is_shareable",              _PyCFunction_CAST(object_is_shareable), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     {"capture_exception",         _PyCFunction_CAST(capture_exception), | 
					
						
							|  |  |  |      METH_VARARGS | METH_KEYWORDS, capture_exception_doc}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  |     {NULL,                        NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* initialization function */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(module_doc, | 
					
						
							|  |  |  | "This module provides primitive operations to manage Python interpreters.\n\
 | 
					
						
							|  |  |  | The 'interpreters' module provides a more convenient interface."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | static int | 
					
						
							|  |  |  | module_exec(PyObject *mod) | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     PyInterpreterState *interp = PyInterpreterState_Get(); | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     module_state *state = get_module_state(mod); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | #define ADD_WHENCE(NAME) \
 | 
					
						
							|  |  |  |     if (PyModule_AddIntConstant(mod, "WHENCE_" #NAME,                   \ | 
					
						
							|  |  |  |                                 _PyInterpreterState_WHENCE_##NAME) < 0) \ | 
					
						
							|  |  |  |     {                                                                   \ | 
					
						
							|  |  |  |         goto error;                                                     \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ADD_WHENCE(UNKNOWN) | 
					
						
							|  |  |  |     ADD_WHENCE(RUNTIME) | 
					
						
							|  |  |  |     ADD_WHENCE(LEGACY_CAPI) | 
					
						
							|  |  |  |     ADD_WHENCE(CAPI) | 
					
						
							|  |  |  |     ADD_WHENCE(XI) | 
					
						
							| 
									
										
										
										
											2024-04-11 17:23:25 -06:00
										 |  |  |     ADD_WHENCE(STDLIB) | 
					
						
							| 
									
										
										
										
											2024-04-10 18:37:01 -06:00
										 |  |  | #undef ADD_WHENCE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     // exceptions
 | 
					
						
							|  |  |  |     if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterError) < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-28 16:08:08 -07:00
										 |  |  |     PyObject *PyExc_NotShareableError = \ | 
					
						
							|  |  |  |                 _PyInterpreterState_GetXIState(interp)->PyExc_NotShareableError; | 
					
						
							|  |  |  |     if (PyModule_AddType(mod, (PyTypeObject *)PyExc_NotShareableError) < 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (register_memoryview_xid(mod, &state->XIBufferViewType) < 0) { | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |         goto error; | 
					
						
							| 
									
										
										
										
											2018-02-16 18:53:40 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  | static struct PyModuleDef_Slot module_slots[] = { | 
					
						
							|  |  |  |     {Py_mod_exec, module_exec}, | 
					
						
							| 
									
										
										
										
											2023-05-05 15:11:27 -06:00
										 |  |  |     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | 
					
						
							| 
									
										
										
										
											2024-05-03 08:30:55 -07:00
										 |  |  |     {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     {0, NULL}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | module_traverse(PyObject *mod, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     module_state *state = get_module_state(mod); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     traverse_module_state(state, visit, arg); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | module_clear(PyObject *mod) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     module_state *state = get_module_state(mod); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     clear_module_state(state); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | module_free(void *mod) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     module_state *state = get_module_state(mod); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     clear_module_state(state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | static struct PyModuleDef moduledef = { | 
					
						
							|  |  |  |     .m_base = PyModuleDef_HEAD_INIT, | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  |     .m_name = MODULE_NAME_STR, | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |     .m_doc = module_doc, | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     .m_size = sizeof(module_state), | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  |     .m_methods = module_functions, | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     .m_slots = module_slots, | 
					
						
							|  |  |  |     .m_traverse = module_traverse, | 
					
						
							|  |  |  |     .m_clear = module_clear, | 
					
						
							|  |  |  |     .m_free = (freefunc)module_free, | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							| 
									
										
										
										
											2024-02-13 14:56:49 -07:00
										 |  |  | MODINIT_FUNC_NAME(void) | 
					
						
							| 
									
										
										
										
											2022-12-02 11:36:57 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-12-05 13:40:20 -07:00
										 |  |  |     return PyModuleDef_Init(&moduledef); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:23:44 -07:00
										 |  |  | } |