Skip to content

Commit

Permalink
Python fix (#1073)
Browse files Browse the repository at this point in the history
* Changes to support Python 3.12

* Cleanup for python version related macros.
  • Loading branch information
feldergast authored May 9, 2024
1 parent be15c10 commit ce168a5
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 118 deletions.
47 changes: 8 additions & 39 deletions src/sst/core/model/python/pymacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,32 @@ DISABLE_WARN_DEPRECATED_REGISTER
#include <Python.h>
REENABLE_WARNING

#if PY_MAJOR_VERSION >= 3
#define SST_PY_OBJ_HEAD PyVarObject_HEAD_INIT(nullptr, 0)
#define SST_ConvertToPythonLong(x) PyLong_FromLong(x)
#define SST_ConvertToPythonBool(x) PyBool_FromLong(x)
#define SST_ConvertToCppLong(x) PyLong_AsLong(x)
#define SST_ConvertToPythonString(x) PyUnicode_FromString(x)
#define SST_ConvertToCppString(x) PyUnicode_AsUTF8(x)
#define SST_TP_FINALIZE nullptr,
#define SST_TP_VECTORCALL_OFFSET 0,
#define SST_TP_PRINT
#define SST_TP_COMPARE(x)
#define SST_TP_RICH_COMPARE(x) x,
#define SST_TP_AS_SYNC nullptr,
#define SST_PY_INIT_MODULE(name, methods, moddef) PyModule_Create(&moddef)

#if PY_MINOR_VERSION == 8
#define SST_TP_PRINT_DEP nullptr,
//#define SST_TP_PRINT_DEP DISABLE_WARN_DEPRECATED_DECLARATION nullptr, REENABLE_WARNING
#else
#define SST_TP_PRINT_DEP
#endif

#if PY_MINOR_VERSION >= 8
#define SST_TP_VECTORCALL nullptr,
#else
#define SST_TP_VECTORCALL
#endif

#if PY_MINOR_VERSION >= 12
#define SST_TP_WATCHED 0,
#else
#define SST_TP_WATCHED
#endif

// Number protocol macros
#define SST_NB_DIVIDE(x)
#define SST_NB_COERCE
Expand All @@ -57,35 +57,4 @@ REENABLE_WARNING
#define SST_NB_MATRIX_MULTIPLY nullptr,
#define SST_NB_INPLACE_MATRIX_MULTIPLY nullptr,

#else

#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#define SST_PY_OBJ_HEAD PyVarObject_HEAD_INIT(nullptr, 0)
#define SST_ConvertToPythonLong(x) PyInt_FromLong(x)
#define SST_ConvertToPythonBool(x) PyBool_FromLong(x)
#define SST_ConvertToCppLong(x) PyInt_AsLong(x)
#define SST_ConvertToPythonString(x) PyString_FromString(x)
#define SST_ConvertToCppString(x) PyString_AsString(x)
#define SST_TP_FINALIZE
#define SST_TP_VECTORCALL_OFFSET
#define SST_TP_PRINT nullptr,
#define SST_TP_COMPARE(x) x,
#define SST_TP_RICH_COMPARE(x) nullptr,
#define SST_TP_AS_SYNC
#define SST_TP_VECTORCALL
#define SST_TP_PRINT_DEP
#define SST_PY_INIT_MODULE(name, methods, moddef) Py_InitModule(name, methods)

// Number protocol macros
#define SST_NB_DIVIDE(x) x,
#define SST_NB_COERCE nullptr,
#define SST_NB_INTLONG(x) x, x,
#define SST_NB_RESERVED
#define SST_NB_OCT nullptr,
#define SST_NB_HEX nullptr,
#define SST_NB_INPLACE_DIVIDE(x) x,
#define SST_NB_MATRIX_MULTIPLY
#define SST_NB_INPLACE_MATRIX_MULTIPLY
#endif

#endif // SST_CORE_MODEL_PYTHON_PYMACROS_H
79 changes: 56 additions & 23 deletions src/sst/core/model/python/pymodel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ static PyObject* setStatisticLoadLevelForComponentType(PyObject* self, PyObject*
static PyObject* setCallPythonFinalize(PyObject* self, PyObject* args);

static PyObject* mlFindModule(PyObject* self, PyObject* args);
static PyObject* mlLoadModule(PyObject* self, PyObject* args);
static PyObject* mlCreateModule(PyObject* self, PyObject* args);
static PyObject* mlExecModule(PyObject* self, PyObject* args);

static PyMethodDef mlMethods[] = { { "find_module", mlFindModule, METH_VARARGS, "Finds an SST Element Module" },
{ "load_module", mlLoadModule, METH_VARARGS, "Loads an SST Element Module" },
{ "create_module", mlCreateModule, METH_VARARGS, "Loads an SST Element Module" },
{ "exec_module", mlExecModule, METH_VARARGS, "Loads an SST Element Module" },
{ nullptr, nullptr, 0, nullptr } };

#if PY_MAJOR_VERSION == 3
Expand All @@ -90,12 +92,10 @@ static PyTypeObject ModuleLoaderType = {
sizeof(ModuleLoaderPy_t), /* tp_basicsize */
0, /* tp_itemsize */
nullptr, /* tp_dealloc */
SST_TP_VECTORCALL_OFFSET /* Python3 only */
SST_TP_PRINT /* Python2 only */
0, /* tp_vectorcall_offset */
nullptr, /* tp_getattr */
nullptr, /* tp_setattr */
SST_TP_COMPARE(nullptr) /* Python2 only */
SST_TP_AS_SYNC /* Python3 only */
nullptr, /* tp_as_sync */
nullptr, /* tp_repr */
nullptr, /* tp_as_number */
nullptr, /* tp_as_sequence */
Expand All @@ -110,7 +110,7 @@ static PyTypeObject ModuleLoaderType = {
"SST Module Loader", /* tp_doc */
nullptr, /* tp_traverse */
nullptr, /* tp_clear */
SST_TP_RICH_COMPARE(nullptr) /* Python3 only */
nullptr, /* tp_rich_compare */
0, /* tp_weaklistoffset */
nullptr, /* tp_iter */
nullptr, /* tp_iternext */
Expand All @@ -134,9 +134,10 @@ static PyTypeObject ModuleLoaderType = {
nullptr, /* tp_weaklist */
nullptr, /* tp_del */
0, /* tp_version_tag */
SST_TP_FINALIZE /* Python3 only */
SST_TP_VECTORCALL /* Python3 only */
SST_TP_PRINT_DEP /* Python3.8 only */
nullptr, /* tp_finalize */
SST_TP_VECTORCALL /* Python3.8+ */
SST_TP_PRINT_DEP /* Python3.8 only */
SST_TP_WATCHED /* Python3.12+ */
};
#if PY_MAJOR_VERSION == 3
#if PY_MINOR_VERSION == 8
Expand Down Expand Up @@ -203,23 +204,44 @@ static struct PyModuleDef emptyModDef
#endif

static PyObject*
mlLoadModule(PyObject* UNUSED(self), PyObject* args)
mlExecModule(PyObject* UNUSED(self), PyObject* args)
{
char* name;
if ( !PyArg_ParseTuple(args, "s", &name) ) return nullptr;
return args;
}

static PyObject*
mlCreateModule(PyObject* UNUSED(self), PyObject* args)
{
PyObject* spec;
// The argument is a ModuleSpec, but I don't know how to check for
// that. If we can find the right type, this would be similar to:

// if ( !PyArg_ParseTuple(args, "O!", &PyModuleSpec_Type, &spec) ) return nullptr;

// For now, we can just use PyObject_GetAttrString to get the
// right field from it. If there is no name field, then it will
// error there.
if ( !PyArg_ParseTuple(args, "O", &spec) ) return nullptr;

PyObject* nameobj;
const char* name;

nameobj = PyObject_GetAttrString(spec, "name");
if ( nameobj == nullptr ) { return nullptr; }
name = SST_ConvertToCppString(nameobj);

if ( strncmp(name, "sst.", 4) ) {
// We know how to handle only sst.<module>
return nullptr; // ERROR!
}

char* modName = name + 4; // sst.<modName>
const char* modName = name + 4; // sst.<modName>

// fprintf(stderr, "Loading SST module '%s' (from %s)\n", modName, name);
// genPythonModuleFunction func = Factory::getFactory()->getPythonModule(modName);
SSTElementPythonModule* pymod = Factory::getFactory()->getPythonModule(modName);
PyObject* mod = nullptr;
if ( !pymod ) { mod = SST_PY_INIT_MODULE(name, emptyModMethods, emptyModDef); }
if ( !pymod ) { mod = PyModule_Create(&emptyModDef); }
else {
mod = static_cast<PyObject*>(pymod->load());
}
Expand Down Expand Up @@ -991,7 +1013,7 @@ PyInit_sst(void)
}

// Create the module
PyObject* module = SST_PY_INIT_MODULE("sst", sstModuleMethods, sstModuleDef);
PyObject* module = PyModule_Create(&sstModuleDef);
if ( !module ) return nullptr;

Py_INCREF(&PyModel_ComponentType);
Expand Down Expand Up @@ -1069,12 +1091,6 @@ SSTPythonModelDefinition::initModel(

PyConfig_Clear(&config);
}
// For 3.11 and on, we need to append the current working
// directory to the path
PyRun_SimpleString("import sys\n"
"import sst\n"
"sys.meta_path.append(sst.ModuleLoader())\n"
"sys.path.append(\".\")");
#else
// Set arguments; Python3 takes wchar_t* arg instead of char*
wchar_t** wargv = (wchar_t**)PyMem_Malloc(sizeof(wchar_t*) * argc);
Expand All @@ -1085,9 +1101,26 @@ SSTPythonModelDefinition::initModel(
// Get the Python scripting engine started
Py_Initialize();
PySys_SetArgv(argc, wargv);
#endif

PyRun_SimpleString("import sys\n"
"import sst\n"
"sys.meta_path.append(sst.ModuleLoader())\n");
"import importlib\n"
"import importlib.machinery\n"
"spec = importlib.machinery.ModuleSpec(\"sst loader\", sst.ModuleLoader())\n"
"class SSTModuleFinder:\n"
" def find_spec(self, fullname, path, target=None):\n"
" loader = sst.ModuleLoader()\n"
" found_loader = loader.find_module(fullname)\n"
" if found_loader: return importlib.machinery.ModuleSpec(fullname, found_loader)\n"
" else: return None\n"
"sys.meta_path.append(SSTModuleFinder())\n"
"sys.path.append(\".\")");

#if PY_MINOR_VERSION >= 11
// // For 3.11 and on, we need to append the current working
// // directory to the path
PyRun_SimpleString("sys.meta_path.append(sst.ModuleLoader())\n");
#endif
}

Expand Down
30 changes: 14 additions & 16 deletions src/sst/core/model/python/pymodel_comp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -569,12 +569,10 @@ PyTypeObject PyModel_ComponentType = {
sizeof(ComponentPy_t), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)compDealloc, /* tp_dealloc */
SST_TP_VECTORCALL_OFFSET /* Python3 only */
SST_TP_PRINT /* Python2 only */
0, /* tp_vectorcall_offset */
nullptr, /* tp_getattr */
nullptr, /* tp_setattr */
SST_TP_COMPARE(compCompare) /* Python2 only */
SST_TP_AS_SYNC /* Python3 only */
nullptr, /* tp_as_sync */
nullptr, /* tp_repr */
nullptr, /* tp_as_number */
nullptr, /* tp_as_sequence */
Expand All @@ -589,7 +587,7 @@ PyTypeObject PyModel_ComponentType = {
"SST Component", /* tp_doc */
nullptr, /* tp_traverse */
nullptr, /* tp_clear */
SST_TP_RICH_COMPARE(compCompare) /* Python3 only */
compCompare, /* tp_rich_compare */
0, /* tp_weaklistoffset */
nullptr, /* tp_iter */
nullptr, /* tp_iternext */
Expand All @@ -613,9 +611,10 @@ PyTypeObject PyModel_ComponentType = {
nullptr, /* tp_weaklist */
nullptr, /* tp_del */
0, /* tp_version_tag */
SST_TP_FINALIZE /* Python3 only */
SST_TP_VECTORCALL /* Python3 only */
SST_TP_PRINT_DEP /* Python3.8 only */
nullptr, /* tp_finalize */
SST_TP_VECTORCALL /* Python3.8+ */
SST_TP_PRINT_DEP /* Python3.8 only */
SST_TP_WATCHED /* Python3.12+ only */
};
#if PY_MAJOR_VERSION == 3
#if PY_MINOR_VERSION == 8
Expand Down Expand Up @@ -681,12 +680,10 @@ PyTypeObject PyModel_SubComponentType = {
sizeof(ComponentPy_t), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)subCompDealloc, /* tp_dealloc */
SST_TP_VECTORCALL_OFFSET /* Python3 only */
SST_TP_PRINT /* Python2 only */
0, /* tp_vectorcall_offset */
nullptr, /* tp_getattr */
nullptr, /* tp_setattr */
SST_TP_COMPARE(nullptr) /* Python2 only */
SST_TP_AS_SYNC /* Python3 only */
nullptr, /* tp_as_sync */
nullptr, /* tp_repr */
nullptr, /* tp_as_number */
nullptr, /* tp_as_sequence */
Expand All @@ -701,7 +698,7 @@ PyTypeObject PyModel_SubComponentType = {
"SST SubComponent", /* tp_doc */
nullptr, /* tp_traverse */
nullptr, /* tp_clear */
SST_TP_RICH_COMPARE(compCompare) /* Python3 only */
compCompare, /* tp_rich_compare */
0, /* tp_weaklistoffset */
nullptr, /* tp_iter */
nullptr, /* tp_iternext */
Expand All @@ -725,9 +722,10 @@ PyTypeObject PyModel_SubComponentType = {
nullptr, /* tp_weaklist */
nullptr, /* tp_del */
0, /* tp_version_tag */
SST_TP_FINALIZE /* Python3 only */
SST_TP_VECTORCALL /* Python3 only */
SST_TP_PRINT_DEP /* Python3.8 only */
nullptr, /* tp_finalize */
SST_TP_VECTORCALL /* Python3.8+ */
SST_TP_PRINT_DEP /* Python3.8 only */
SST_TP_WATCHED /* Python3.12+ */
};
#if PY_MAJOR_VERSION == 3
#if PY_MINOR_VERSION == 8
Expand Down
13 changes: 6 additions & 7 deletions src/sst/core/model/python/pymodel_link.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,10 @@ PyTypeObject PyModel_LinkType = {
sizeof(LinkPy_t), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)linkDealloc, /* tp_dealloc */
SST_TP_VECTORCALL_OFFSET /* Python3 only */
SST_TP_PRINT /* Python2 only */
0, /* tp_vectorcall_offset */
nullptr, /* tp_getattr */
nullptr, /* tp_setattr */
SST_TP_COMPARE(nullptr) /* Python2 only */
SST_TP_AS_SYNC /* Python3 only */
nullptr, /* tp_as_sync */
nullptr, /* tp_repr */
nullptr, /* tp_as_number */
nullptr, /* tp_as_sequence */
Expand Down Expand Up @@ -192,9 +190,10 @@ PyTypeObject PyModel_LinkType = {
nullptr, /* tp_weaklist */
nullptr, /* tp_del */
0, /* tp_version_tag */
SST_TP_FINALIZE /* Python3 only */
SST_TP_VECTORCALL /* Python3 only */
SST_TP_PRINT_DEP /* Python3.8 only */
nullptr, /* tp_finalize */
SST_TP_VECTORCALL /* Python3.8+ */
SST_TP_PRINT_DEP /* Python3.8 only */
SST_TP_WATCHED /* Python3.12+ */
};
#if PY_MAJOR_VERSION == 3
#if PY_MINOR_VERSION == 8
Expand Down
15 changes: 7 additions & 8 deletions src/sst/core/model/python/pymodel_stat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,10 @@ PyTypeObject PyModel_StatType = {
sizeof(StatisticPy_t), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)statDealloc, /* tp_dealloc */
SST_TP_VECTORCALL_OFFSET /* Python3 only */
SST_TP_PRINT /* Python2 only */
0, /* tp_vectorcall_offset */
nullptr, /* tp_getattr */
nullptr, /* tp_setattr */
SST_TP_COMPARE(nullptr) /* Python2 only */
SST_TP_AS_SYNC /* Python3 only */
nullptr, /* tp_as_sync */
nullptr, /* tp_repr */
nullptr, /* tp_as_number */
nullptr, /* tp_as_sequence */
Expand All @@ -195,7 +193,7 @@ PyTypeObject PyModel_StatType = {
"SST Statistic", /* tp_doc */
nullptr, /* tp_traverse */
nullptr, /* tp_clear */
SST_TP_RICH_COMPARE(statCompare) /* Python3 only */
statCompare, /* tp_rich_compare */
0, /* tp_weaklistoffset */
nullptr, /* tp_iter */
nullptr, /* tp_iternext */
Expand All @@ -219,9 +217,10 @@ PyTypeObject PyModel_StatType = {
nullptr, /* tp_weaklist */
nullptr, /* tp_del */
0, /* tp_version_tag */
SST_TP_FINALIZE /* Python3 only */
SST_TP_VECTORCALL /* Python3 only */
SST_TP_PRINT_DEP /* Python3.8 only */
nullptr, /* tp_finalize */
SST_TP_VECTORCALL /* Python3.8+ */
SST_TP_PRINT_DEP /* Python3.8 only */
SST_TP_WATCHED /* Python3.12+ */
};
#if PY_MAJOR_VERSION == 3
#if PY_MINOR_VERSION == 8
Expand Down
Loading

0 comments on commit ce168a5

Please sign in to comment.