Throw ImportError instead of cryptic failure when importing extension module from incompatible version of Python
This commit is contained in:
parent
75caef56aa
commit
33d183d4f7
|
|
@ -128,6 +128,28 @@ int write_python_table_native(ostream &out) {
|
|||
out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n";
|
||||
}
|
||||
|
||||
out.put('\n');
|
||||
|
||||
out << "#if PY_MAJOR_VERSION >= 3 || !defined(NDEBUG)\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "#endif\n";
|
||||
|
||||
out << "#if PY_MAJOR_VERSION < 3 || !defined(NDEBUG)\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) void init" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" void init" << library_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "#endif\n";
|
||||
|
||||
out << "\n"
|
||||
<< "#if PY_MAJOR_VERSION >= 3\n"
|
||||
<< "static struct PyModuleDef py_" << library_name << "_module = {\n"
|
||||
|
|
@ -139,14 +161,6 @@ int write_python_table_native(ostream &out) {
|
|||
<< " NULL, NULL, NULL, NULL\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "\n"
|
||||
<< "PyObject *PyInit_" << library_name << "() {\n";
|
||||
|
||||
if (track_interpreter) {
|
||||
|
|
@ -184,15 +198,16 @@ int write_python_table_native(ostream &out) {
|
|||
<< " return module;\n"
|
||||
<< "}\n"
|
||||
<< "\n"
|
||||
<< "#else // Python 2 case\n"
|
||||
<< "\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) void init" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" void init" << library_name << "();\n"
|
||||
|
||||
<< "#ifndef NDEBUG\n"
|
||||
<< "void init" << library_name << "() {\n"
|
||||
<< " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was "
|
||||
<< "compiled for Python \" PY_VERSION \", which is incompatible "
|
||||
<< "with Python 2\");\n"
|
||||
<< "}\n"
|
||||
<< "#endif\n"
|
||||
|
||||
<< "#else // Python 2 case\n"
|
||||
<< "\n"
|
||||
<< "void init" << library_name << "() {\n";
|
||||
|
||||
|
|
@ -228,6 +243,15 @@ int write_python_table_native(ostream &out) {
|
|||
|
||||
out << " }\n"
|
||||
<< "}\n"
|
||||
<< "\n"
|
||||
<< "#ifndef NDEBUG\n"
|
||||
<< "PyObject *PyInit_" << library_name << "() {\n"
|
||||
<< " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was "
|
||||
<< "compiled for Python \" PY_VERSION \", which is incompatible "
|
||||
<< "with Python 3\");\n"
|
||||
<< " return (PyObject *)NULL;\n"
|
||||
<< "}\n"
|
||||
<< "#endif\n"
|
||||
<< "#endif\n"
|
||||
<< "\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -597,17 +597,18 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
#endif
|
||||
// Check the version so we can print a helpful error if it doesn't match.
|
||||
string version = Py_GetVersion();
|
||||
if (interrogatedb_cat.is_debug()) {
|
||||
interrogatedb_cat.debug()
|
||||
<< "Python " << version << "\n";
|
||||
}
|
||||
|
||||
if (version[0] != '0' + PY_MAJOR_VERSION ||
|
||||
version[2] != '0' + PY_MINOR_VERSION) {
|
||||
interrogatedb_cat.error()
|
||||
<< "This module was compiled for Python "
|
||||
<< PY_MAJOR_VERSION << "." << PY_MINOR_VERSION << ", which is incompatible "
|
||||
<< "with Python " << version << ".\n";
|
||||
// Raise a helpful error message. We can safely do this because the
|
||||
// signature and behavior for PyErr_SetString has remained consistent.
|
||||
ostringstream errs;
|
||||
errs << "this module was compiled for Python "
|
||||
<< PY_MAJOR_VERSION << "." << PY_MINOR_VERSION << ", which is "
|
||||
<< "incompatible with Python " << version.substr(0, 3);
|
||||
string error = errs.str();
|
||||
PyErr_SetString(PyExc_ImportError, error.c_str());
|
||||
return (PyObject *)NULL;
|
||||
}
|
||||
|
||||
// Initialize the base class of everything.
|
||||
|
|
@ -649,6 +650,12 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
// to do that. Perhaps we'll find a better place for this in the future.
|
||||
static bool initialized_main_dir = false;
|
||||
if (!initialized_main_dir) {
|
||||
if (interrogatedb_cat.is_debug()) {
|
||||
// Good opportunity to print this out once, at startup.
|
||||
interrogatedb_cat.debug()
|
||||
<< "Python " << version << "\n";
|
||||
}
|
||||
|
||||
// Grab the __main__ module.
|
||||
PyObject *main_module = PyImport_ImportModule("__main__");
|
||||
if (main_module == NULL) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue