@@ -63,6 +63,18 @@ std::string getPythonExceptionInfo()
6363 return message;
6464}
6565
66+ void checkPythonError (bool condition, const std::string& message) {
67+ if (condition) {
68+ if (PyErr_Occurred ()) {
69+ PyErr_PrintEx (0 );
70+ }
71+ throw Cantera::CanteraError (
72+ " PythonExtensionManager::PythonExtensionManager" ,
73+ message
74+ );
75+ }
76+ }
77+
6678} // end anonymous namespace
6779
6880namespace Cantera
@@ -115,40 +127,31 @@ PythonExtensionManager::PythonExtensionManager()
115127 " Failed to import 'pythonExtensions' module" );
116128 }
117129
118- // Following example creation of minimal ModuleSpec from Python's import.c
119- PyObject *attrs = Py_BuildValue (" {ss}" , " name" , " pythonExtensions" );
120- if (attrs == nullptr ) {
121- if (PyErr_Occurred ()) {
122- PyErr_PrintEx (0 );
123- }
124- throw CanteraError (" PythonExtensionManager::PythonExtensionManager" ,
125- " Py_BuildValue failed" );
126- }
127- PyObject *spec = _PyNamespace_New (attrs);
128- Py_DECREF (attrs);
129- if (spec == nullptr ) {
130- if (PyErr_Occurred ()) {
131- PyErr_PrintEx (0 );
132- }
133- throw CanteraError (" PythonExtensionManager::PythonExtensionManager" ,
134- " _PyNamespace_New failed" );
135- }
130+ // Create a minimal ModuleSpec
131+ PyObject* typesModule = PyImport_ImportModule (" types" );
132+ checkPythonError (typesModule == nullptr , " 'import types' failed" );
133+ PyObject* simpleNamespaceType = PyObject_GetAttrString (typesModule,
134+ " SimpleNamespace" );
135+ checkPythonError (simpleNamespaceType == nullptr ,
136+ " 'Get SimpleNamespace type failed" );
137+ Py_DecRef (simpleNamespaceType);
138+ Py_DecRef (typesModule);
139+ PyObject* empty_tuple = PyTuple_New (0 );
140+ PyObject* kwargs = PyDict_New ();
141+ PyObject* strArg = PyUnicode_FromString (" pythonExtensions" );
142+ PyDict_SetItemString (kwargs, " name" , strArg);
143+ PyObject* spec = PyObject_Call (simpleNamespaceType, empty_tuple, kwargs);
144+ checkPythonError (spec == nullptr , " Creating SimpleNamespace failed" );
145+ Py_DecRef (empty_tuple);
146+ Py_DecRef (kwargs);
147+ Py_DecRef (empty_tuple);
148+ Py_DecRef (strArg);
149+
150+ // Build the module definition and execute it
136151 PyObject* pyModule = PyModule_FromDefAndSpec (modDef, spec);
137- if (pyModule == nullptr ) {
138- if (PyErr_Occurred ()) {
139- PyErr_PrintEx (0 );
140- }
141- CanteraError (" PythonExtensionManager::PythonExtensionManager" ,
142- " PyModule_FromDefAndSpec failed" );
143- }
152+ checkPythonError (pyModule == nullptr , " PyModule_FromDefAndSpec failed" );
144153 int code = PyModule_ExecDef (pyModule, modDef);
145- if (code) {
146- if (PyErr_Occurred ()) {
147- PyErr_PrintEx (0 );
148- }
149- CanteraError (" PythonExtensionManager::PythonExtensionManager" ,
150- " PyModule_ExecDef failed" );
151- }
154+ checkPythonError (code, " PyModule_ExecDef failed" );
152155 Py_DECREF (spec);
153156 Py_DECREF (pyModule);
154157 s_imported = true ;
0 commit comments