Commit e0287f1a authored by David Gobbi's avatar David Gobbi Committed by Ben Boeckel

Make Python modules load their dependencies.

If one vtk-python module depends on others, then it should load
those dependencies before doing anything else.
parent 1f1ec6fc
......@@ -132,6 +132,38 @@ $<$<BOOL:$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>>:
endif()
endforeach()
# find the python modules needed by this python module
string(REGEX REPLACE "Python$" "" _basename "${TARGET}")
string(REGEX REPLACE "Kit$" "" kit_basename "${_basename}")
if(_${kit_basename}_is_kit)
set(${_basename}_WRAP_DEPENDS)
foreach(kit_module IN LISTS _${kit_basename}_modules)
list(APPEND ${_basename}_WRAP_DEPENDS
${${kit_module}_WRAP_DEPENDS})
endforeach()
endif()
set(_python_module_depends)
foreach(dep IN LISTS ${_basename}_WRAP_DEPENDS)
if(dep STREQUAL "${_basename}" OR dep STREQUAL "${kit_basename}")
continue()
endif()
if(VTK_ENABLE_KITS AND ${dep}_KIT)
if(NOT ${dep}_KIT STREQUAL kit_basename)
list(APPEND _python_module_depends ${${dep}_KIT}KitPython)
endif()
elseif(TARGET ${dep}Python)
list(APPEND _python_module_depends ${dep}Python)
endif()
endforeach()
if(_python_module_depends)
# add a DEPENDS section to the Init.data file for this module
set(VTK_WRAPPER_INIT_DATA "${VTK_WRAPPER_INIT_DATA}\nDEPENDS")
list(REMOVE_DUPLICATES _python_module_depends)
foreach(dep IN LISTS _python_module_depends)
set(VTK_WRAPPER_INIT_DATA "${VTK_WRAPPER_INIT_DATA}\n${dep}")
endforeach()
endif()
# finish the data file for the init file
configure_file(
${VTK_CMAKE_DIR}/vtkWrapperInit.data.in
......
......@@ -901,83 +901,51 @@ PyTypeObject *vtkPythonUtil::FindEnum(const char *name)
}
//--------------------------------------------------------------------
PyTypeObject *vtkPythonUtil::FindClassTypeObject(
const char *mod, const char *name)
PyTypeObject *vtkPythonUtil::FindClassTypeObject(const char *name)
{
for (int i = 0; i < 2; i++)
PyVTKClass *info = vtkPythonUtil::FindClass(name);
if (info)
{
// see if the class is already loaded
PyVTKClass *info = vtkPythonUtil::FindClass(name);
if (info)
{
return info->py_type;
}
if (i == 0 && !vtkPythonUtil::LoadExtensionModule(mod))
{
break;
}
return info->py_type;
}
return nullptr;
}
//--------------------------------------------------------------------
PyTypeObject *vtkPythonUtil::FindSpecialTypeObject(
const char *mod, const char *name)
PyTypeObject *vtkPythonUtil::FindSpecialTypeObject(const char *name)
{
for (int i = 0; i < 2; i++)
PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(name);
if (info)
{
// see if the class is already loaded
PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(name);
if (info)
{
return info->py_type;
}
if (i == 0 && !vtkPythonUtil::LoadExtensionModule(mod))
{
break;
}
return info->py_type;
}
return nullptr;
}
//--------------------------------------------------------------------
bool vtkPythonUtil::LoadExtensionModule(const char *name)
bool vtkPythonUtil::ImportModule(const char *name, PyObject *globals)
{
for (int i = 0; i < 2; i++)
// try relative import (const-cast is needed for Python 2.x only)
PyObject *m = PyImport_ImportModuleLevel(const_cast<char *>(name), globals,
nullptr, nullptr, 1);
if (!m)
{
PyObject *m;
if (i == 0)
{
// try absolute import of "name"
m = PyImport_ImportModule(name);
}
else
{
// try import from "vtk" package
PyObject *l = PyList_New(1);
PyObject *s = PyString_FromString(name);
PyList_SET_ITEM(l, 0, s);
m = PyImport_ImportModuleLevel("vtk", nullptr, nullptr, l, 0);
Py_DECREF(l);
}
if (m)
{
Py_DECREF(m);
return true;
}
else if (i < 1)
{
PyErr_Clear();
}
else
{
PyErr_Print();
}
// clear error and retry with absolute import
PyErr_Clear();
m = PyImport_ImportModule(name);
}
if (!m)
{
PyErr_Clear();
return false;
}
return false;
Py_DECREF(m);
return true;
}
//--------------------------------------------------------------------
......
......@@ -183,27 +183,22 @@ public:
/**
* Find the PyTypeObject for a wrapped VTK class.
* This will call FindClass() first, and if the class is not found,
* it will try to load the module that the class is stored in.
* If it fails, then it will set an exception and return NULL.
*/
static PyTypeObject *FindClassTypeObject(
const char *mod, const char *name);
static PyTypeObject *FindClassTypeObject(const char *name);
/**
* Find the PyTypeObject for a wrapped VTK type (non-vtkObject class).
* This will call FindSpecialType() first, and if the type is not found,
* it will try to load the module that the type is stored in.
* If it fails, then it will set an exception and return NULL.
*/
static PyTypeObject *FindSpecialTypeObject(
const char *mod, const char *name);
static PyTypeObject *FindSpecialTypeObject(const char *name);
/**
* Try to load an extension module, by looking in all the usual places.
* On failure, this will raise an exception and return "false".
* The "globals" is the dict of the module that is doing the importing.
* First, a relative import is performed, and if that fails, then a
* global import is performed. A return value of "false" indicates
* failure, no exception is set.
*/
static bool LoadExtensionModule(const char *name);
static bool ImportModule(const char *name, PyObject *globals);
/**
* Utility function to build a docstring by concatenating a series
......
......@@ -402,7 +402,6 @@ static void vtkWrapPython_GenerateObjectNew(
HierarchyInfo *hinfo, int class_has_new)
{
char superclassname[1024];
const char *supermodule;
const char *name;
int is_external;
int has_constants = 0;
......@@ -474,8 +473,7 @@ static void vtkWrapPython_GenerateObjectNew(
if (name)
{
vtkWrapText_PythonName(name, superclassname);
supermodule = vtkWrapPython_HasWrappedSuperClass(
hinfo, data->Name, &is_external);
vtkWrapPython_HasWrappedSuperClass(hinfo, data->Name, &is_external);
if (!is_external) /* superclass is in the same module */
{
fprintf(fp,
......@@ -485,9 +483,8 @@ static void vtkWrapPython_GenerateObjectNew(
else /* superclass is in a different module */
{
fprintf(fp,
" pytype->tp_base = vtkPythonUtil::FindClassTypeObject(\n"
" \"%sPython\", \"%s\");\n\n",
supermodule, superclassname);
" pytype->tp_base = vtkPythonUtil::FindClassTypeObject(\"%s\");\n\n",
superclassname);
}
}
......
......@@ -43,6 +43,7 @@ static void CreateInitFile(const char *libName, FILE *fout)
/* warning this code is also in getclasses.cxx under pcmaker */
/* this routine creates the init file */
static void CreateImplFile(const char *libName,
int numDepends, char **depends,
int numFiles, char **files,
FILE *fout)
{
......@@ -51,8 +52,7 @@ static void CreateImplFile(const char *libName,
const char* dllexp = "VTK_ABI_EXPORT ";
fprintf(fout,"// Generated by vtkWrapPythonInit in VTK/Wrapping\n");
fprintf(fout,"#include \"vtkPython.h\"\n");
fprintf(fout,"#include \"vtkPythonCompatibility.h\"\n");
fprintf(fout,"#include \"vtkPythonUtil.h\"\n");
fprintf(fout,"#include \"vtkSystemIncludes.h\"\n");
fprintf(fout,"#include <string.h>\n");
fprintf(fout,"// Handle compiler warning messages, etc.\n"
......@@ -90,7 +90,7 @@ static void CreateImplFile(const char *libName,
fprintf(fout,"#ifdef VTK_PY3K\n");
fprintf(fout," PyObject *m = PyModule_Create(&Py%s_Module);\n",
libName);
fprintf(fout,"#else\n\n");
fprintf(fout,"#else\n");
fprintf(fout," PyObject *m = Py_InitModule(\"%s\",\n"
" Py%s_Methods);\n",
libName, libName);
......@@ -101,7 +101,27 @@ static void CreateImplFile(const char *libName,
fprintf(fout," {\n");
fprintf(fout," Py_FatalError(\"can't get dictionary for module %s\");\n",
libName);
fprintf(fout," }\n");
fprintf(fout," }\n\n");
/* import all the modules that we depend on */
if (numDepends > 0)
{
fprintf(fout," const char *depends[%d] = {\n", numDepends);
for (i = 0; i < numDepends; i++)
{
fprintf(fout," \"%s\",\n", depends[i]);
}
fprintf(fout," };\n\n");
fprintf(fout," for (int i = 0; i < %d; i++)\n", numDepends);
fprintf(fout," {\n");
fprintf(fout," if (!vtkPythonUtil::ImportModule(depends[i], d))\n");
fprintf(fout," {\n");
fprintf(fout," return PyErr_Format(PyExc_ImportError,\n"
" \"Failed to load %s: No module named %%s\",\n"
" depends[i]);\n", libName);
fprintf(fout," }\n");
fprintf(fout," }\n\n");
}
for (i = 0; i < numFiles; i++)
{
......@@ -121,9 +141,12 @@ int main(int argc,char *argv[])
FILE *fout_init;
FILE *fout_impl;
int numFiles = 0;
int numDepends = 0;
char libName[250];
char tmpVal[250];
char *files[4000];
char *depends[400];
int doDepends = 0;
if (argc < 4)
{
......@@ -148,8 +171,18 @@ int main(int argc,char *argv[])
/* read in the classes */
while (fscanf(file,"%s",tmpVal) != EOF)
{
files[numFiles] = strdup(tmpVal);
numFiles++;
if (strcmp(tmpVal,"DEPENDS") == 0)
{
doDepends = 1;
}
else if (doDepends)
{
depends[numDepends++] = strdup(tmpVal);
}
else
{
files[numFiles++] = strdup(tmpVal);
}
}
/* close the file */
fclose(file);
......@@ -177,7 +210,7 @@ int main(int argc,char *argv[])
}
CreateInitFile(libName, fout_init);
CreateImplFile(libName, numFiles, files, fout_impl);
CreateImplFile(libName, numDepends, depends, numFiles, files, fout_impl);
fclose(fout_init);
fclose(fout_impl);
......
......@@ -923,9 +923,9 @@ void vtkWrapPython_GenerateSpecialType(
else /* superclass is in a different module */
{
fprintf(fp,
" pytype->tp_base = vtkPythonUtil::FindSpecialTypeObject(\n"
" \"%sPython\", \"%s\");\n\n",
supermodule, supername);
" pytype->tp_base = vtkPythonUtil::FindSpecialTypeObject("
"\"%s\");\n\n",
supername);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment