Commit d3eb4043 authored by David Gobbi's avatar David Gobbi

Python API compatibility for py3k.

This is a large change that adds conditional compilation to support
both python 2 and python 3.  The header vtkPythonCompatibility.h
does a lot of the necessary work:
1) PyInt is redefined to PyLong for py3k
2) PyString is redefied to PyUnicode for py3k
3) PyBytes is redefined to PyString for python 2
parent c96458b9
......@@ -35,7 +35,18 @@ void vtkPythonAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Object: " << Object << std::endl;
if (str)
{
os << indent << "Object (string): " << PyString_AsString(str) << std::endl;
os << indent << "Object (string): ";
#ifndef VTK_PY3K
os << PyString_AsString(str);
#else
PyObject *bytes = PyUnicode_EncodeLocale(str, VTK_PYUNICODE_ENC);
if (bytes)
{
os << PyBytes_AsString(bytes);
Py_DECREF(bytes);
}
#endif
os << std::endl;
}
}
......@@ -131,7 +142,16 @@ static std::string GetPythonErrorString()
for (Py_ssize_t i = 0; i < sz; ++i)
{
PyObject* str = lst[i];
#ifndef VTK_PY3K
exc_string += PyString_AsString(str);
#else
PyObject *bytes = PyUnicode_EncodeLocale(str, VTK_PYUNICODE_ENC);
if (bytes)
{
exc_string += PyBytes_AsString(bytes);
Py_DECREF(bytes);
}
#endif
}
}
else
......@@ -139,7 +159,17 @@ static std::string GetPythonErrorString()
vtkSmartPyObject pyexc_string(PyObject_Str(sValue));
if (pyexc_string)
{
#ifndef VTK_PY3K
exc_string = PyString_AsString(pyexc_string);
#else
PyObject *bytes = PyUnicode_EncodeLocale(
pyexc_string, VTK_PYUNICODE_ENC);
if (bytes)
{
exc_string = PyBytes_AsString(bytes);
Py_DECREF(bytes);
}
#endif
}
else
{
......
......@@ -73,14 +73,18 @@ they are system headers. Do NOT add any #undef lines here. */
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if VTK_PYTHON_VERSION_HEX < 0x03040000
#define HAVE_ROUND
#endif
#endif
#include <Python.h>
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if VTK_PYTHON_VERSION_HEX < 0x03040000
#undef HAVE_ROUND
#endif
#endif
#if defined(_MSC_VER)
# pragma warning (pop)
......
......@@ -16,6 +16,7 @@
/* Minimal main program -- everything is loaded from the library */
#include "vtkPython.h"
#include "vtkPythonCompatibility.h"
#ifdef VTK_COMPILED_USING_MPI
# include <mpi.h>
......@@ -81,9 +82,20 @@ static void AtExitCallback()
#endif // VTK_COMPILED_USING_MPI
extern "C" {
extern DL_IMPORT(int) Py_Main(int, char **);
#ifdef VTK_PY3K
PyAPI_FUNC(int) Py_Main(int, wchar_t **);
#else
PyAPI_FUNC(int) Py_Main(int, char **);
#endif
}
#if defined(VTK_PY3K) && defined(__APPLE__)
extern "C" {
extern wchar_t*
_Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size);
}
#endif
static void vtkPythonAppInitEnableMSVCDebugHook();
static void vtkPythonAppInitPrependPath(const char* self_dir);
static void RemoveArgumentFromArgv(int &argc, char **&argv, int at);
......@@ -103,7 +115,6 @@ static void RemoveArgumentFromArgv(int &argc, char **&argv, int at);
#define VTK_PYTHON_TO_STRING1(x) #x
#define VTK_PYTHON_VERSION VTK_PYTHON_TO_STRING(PY_MAJOR_VERSION.PY_MINOR_VERSION)
int main(int argc, char **argv)
{
vtkPythonAppInitEnableMSVCDebugHook();
......@@ -147,9 +158,24 @@ int main(int argc, char **argv)
// Set the program name, so that we can ask python to provide us
// full path. We need to collapse the path name to aid relative
// path computation for the VTK python module installation.
static char argv0[VTK_PYTHON_MAXPATH];
std::string av0 = vtksys::SystemTools::CollapseFullPath(argv[0]);
#ifdef VTK_PY3K
wchar_t *argv0;
#ifdef __APPLE__
argv0 = _Py_DecodeUTF8_surrogateescape(av0.data(), av0.length());
#else
argv0 = _Py_char2wchar(av0.c_str(), NULL);
#endif
if (argv0 == 0)
{
fprintf(stderr, "Fatal vtkpython error: "
"unable to decode the program name\n");
return 1;
}
#else /* VTK < PY3K */
static char argv0[VTK_PYTHON_MAXPATH];
strcpy(argv0, av0.c_str());
#endif
Py_SetProgramName(argv0);
// This function is generated, and will register any static Python modules for VTK
......@@ -169,17 +195,62 @@ int main(int argc, char **argv)
// sys.executable variable contains the full path to the interpreter
// executable.
char tmpExe[] = "executable";
PyObject* executable = PySys_GetObject(tmpExe);
if(const char* exe_str = PyString_AsString(executable))
PyObject *executable = PySys_GetObject(tmpExe);
#ifdef VTK_PY3K
executable = PyUnicode_EncodeFSDefault(executable);
#endif
const char *exe_str = PyBytes_AsString(executable);
if (exe_str)
{
// Use the executable location to try to set sys.path to include
// the VTK python modules.
std::string self_dir = vtksys::SystemTools::GetFilenamePath(exe_str);
vtkPythonAppInitPrependPath(self_dir.c_str());
}
#ifdef VTK_PY3K
Py_DECREF(executable);
#endif
// Ok, all done, now enter python main.
#ifdef VTK_PY3K
// Need two copies of args, because programs might modify the first
wchar_t **argvWide = new wchar_t *[argc];
wchar_t **argvWide2 = new wchar_t *[argc];
for (int i = 0; i < argc; i++)
{
#ifdef __APPLE__
argvWide[i] = _Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i]));
#else
argvWide[i] = _Py_char2wchar(argv[i], NULL);
#endif
argvWide2[i] = argvWide[i];
if (argvWide[i] == 0)
{
fprintf(stderr, "Fatal vtkpython error: "
"unable to decode the command line argument #%i\n",
i + 1);
for (int k = 0; k < i; k++)
{
PyMem_Free(argvWide2[i]);
}
PyMem_Free(argv0);
delete [] argvWide;
delete [] argvWide2;
return 1;
}
}
int res = Py_Main(argc, argvWide);
PyMem_Free(argv0);
for (int i = 0; i < argc; i++)
{
PyMem_Free(argvWide2[i]);
}
delete [] argvWide;
delete [] argvWide2;
return res;
#else
return Py_Main(argc, argv);
#endif
}
// For a DEBUG build on MSVC, add a hook to prevent error dialogs when
......
......@@ -26,6 +26,12 @@
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
// Required for Python 2.5 through Python 2.7
#ifndef PyDescr_TYPE
#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
#endif
//--------------------------------------------------------------------
// C API
......@@ -37,11 +43,11 @@ PyObject *PyVTKMethodDescriptor_New(PyTypeObject *pytype, PyMethodDef *meth)
if (descr)
{
Py_XINCREF(pytype);
descr->d_type = pytype;
descr->d_name = PyString_InternFromString(meth->ml_name);
PyDescr_TYPE(descr) = pytype;
PyDescr_NAME(descr) = PyString_InternFromString(meth->ml_name);
descr->d_method = meth;
if (!descr->d_name)
if (!PyDescr_NAME(descr))
{
Py_DECREF(descr);
descr = 0;
......@@ -58,23 +64,28 @@ static void PyVTKMethodDescriptor_Delete(PyObject *ob)
{
PyMethodDescrObject *descr = (PyMethodDescrObject *)ob;
PyObject_GC_UnTrack(descr);
Py_XDECREF(descr->d_type);
Py_XDECREF(descr->d_name);
Py_XDECREF(PyDescr_TYPE(descr));
Py_XDECREF(PyDescr_NAME(descr));
PyObject_GC_Del(descr);
}
static PyObject *PyVTKMethodDescriptor_Repr(PyObject *ob)
{
PyMethodDescrObject *descr = (PyMethodDescrObject *)ob;
#ifdef VTK_PY3K
return PyUnicode_FromFormat("<method \'%U\' of \'%s\' objects>",
PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
#else
return PyString_FromFormat("<method \'%s\' of \'%s\' objects>",
PyString_AS_STRING(descr->d_name), descr->d_type->tp_name);
#endif
}
static int PyVTKMethodDescriptor_Traverse(
PyObject *ob, visitproc visit, void *arg)
{
PyMethodDescrObject *descr = (PyMethodDescrObject *)ob;
Py_VISIT(descr->d_type);
Py_VISIT(PyDescr_TYPE(descr));
return 0;
}
......@@ -84,7 +95,7 @@ static PyObject *PyVTKMethodDescriptor_Call(
PyMethodDescrObject *descr = (PyMethodDescrObject *)ob;
PyObject *result = 0;
PyObject *func = PyCFunction_New(
descr->d_method, (PyObject *)descr->d_type);
descr->d_method, (PyObject *)PyDescr_TYPE(descr));
if (func)
{
......@@ -107,17 +118,25 @@ static PyObject *PyVTKMethodDescriptor_Get(
return self;
}
if (PyObject_TypeCheck(obj, descr->d_type))
if (PyObject_TypeCheck(obj, PyDescr_TYPE(descr)))
{
// Bind the method to the object
return PyCFunction_New(descr->d_method, obj);
}
#ifdef VTK_PY3K
PyErr_Format(
PyExc_TypeError,
"descriptor '%U' for '%s' objects doesn't apply to '%s' object",
PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name,
Py_TYPE(obj)->tp_name);
#else
PyErr_Format(
PyExc_TypeError,
"descriptor '%s' for '%s' objects doesn't apply to '%s' object",
PyString_AS_STRING(descr->d_name), descr->d_type->tp_name,
PyString_AS_STRING(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name,
Py_TYPE(obj)->tp_name);
#endif
return NULL;
}
......
This diff is collapsed.
......@@ -395,7 +395,7 @@ PyVTKObject_AsBuffer_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
view->ndim = (ncomp > 1 ? 2 : 1);
view->format = (char *)format;
#if PY_VERSION_HEX >= 0x02070000
#if PY_VERSION_HEX >= 0x02070000 && PY_VERSION_HEX < 0x03030000
// use "smalltable" for 1D arrays, like memoryobject.c
view->shape = view->smalltable;
view->strides = &view->smalltable[1];
......@@ -498,22 +498,31 @@ PyObject *PyVTKObject_FromPointer(
PyObject *s = PyObject_GetAttrString((PyObject *)pytype, "__vtkname__");
if (s)
{
classname = PyString_AsString(s);
Py_DECREF(s);
#ifdef VTK_PY3K
PyObject *tmp = PyUnicode_AsUTF8String(s);
if (tmp)
{
Py_DECREF(s);
s = tmp;
}
#endif
classname = PyBytes_AsString(s);
if (classname == 0)
{
Py_DECREF(s);
return NULL;
}
}
cls = vtkPythonUtil::FindClass(classname);
if (cls == 0)
{
char errortext[280];
sprintf(errortext, "internal error, unknown VTK class %.200s",
classname);
PyErr_SetString(PyExc_ValueError, errortext);
PyErr_Format(PyExc_ValueError,
"internal error, unknown VTK class %.200s",
classname);
Py_XDECREF(s);
return NULL;
}
Py_XDECREF(s);
}
if (!ptr)
......
......@@ -64,16 +64,13 @@ PyObject *PyVTKSpecialObject_Repr(PyObject *self)
PyTypeObject *type = Py_TYPE(self);
const char *name = Py_TYPE(self)->tp_name;
PyObject *s = PyString_FromString("(");
PyString_ConcatAndDel(&s, PyString_FromString(name));
PyString_ConcatAndDel(&s, PyString_FromString(")"));
while (type->tp_base && !type->tp_str)
{
type = type->tp_base;
}
// use str() if available
PyObject *s = NULL;
if (type->tp_str && type->tp_str != (&PyBaseObject_Type)->tp_str)
{
PyObject *t = type->tp_str(self);
......@@ -84,15 +81,17 @@ PyObject *PyVTKSpecialObject_Repr(PyObject *self)
}
else
{
PyString_ConcatAndDel(&s, t);
#ifdef VTK_PY3K
s = PyString_FromFormat("(%.80s)%S", name, t);
#else
s = PyString_FromFormat("(%.80s)%s", name, PyString_AsString(t));
#endif
}
}
// otherwise just print address of object
else if (obj->vtk_ptr)
{
char buf[256];
sprintf(buf, "%p", obj->vtk_ptr);
PyString_ConcatAndDel(&s, PyString_FromString(buf));
s = PyString_FromFormat("(%.80s)%p", name, obj->vtk_ptr);
}
return s;
......@@ -133,7 +132,13 @@ PyObject *PyVTKSpecialObject_SequenceString(PyObject *self)
{
if (i > 0)
{
#ifdef VTK_PY3K
PyObject *tmp = PyUnicode_Concat(s, comma);
Py_DECREF(s);
s = tmp;
#else
PyString_Concat(&s, comma);
#endif
}
o = PySequence_GetItem(self, i);
t = NULL;
......@@ -144,7 +149,14 @@ PyObject *PyVTKSpecialObject_SequenceString(PyObject *self)
}
if (t)
{
#ifdef VTK_PY3K
PyObject *tmp = PyUnicode_Concat(s, t);
Py_DECREF(s);
Py_DECREF(t);
s = tmp;
#else
PyString_ConcatAndDel(&s, t);
#endif
}
else
{
......@@ -156,8 +168,16 @@ PyObject *PyVTKSpecialObject_SequenceString(PyObject *self)
if (s)
{
#ifdef VTK_PY3K
PyObject *tmp1 = PyString_FromStringAndSize(&bracket[4], 1);
PyObject *tmp2 = PyUnicode_Concat(s, tmp1);
Py_DECREF(s);
Py_DECREF(tmp1);
s = tmp2;
#else
PyString_ConcatAndDel(&s,
PyString_FromStringAndSize(&bracket[4], 1));
#endif
}
Py_DECREF(comma);
......
......@@ -214,13 +214,33 @@ PyVTKTemplate_GetItem(PyObject *ob, PyObject *key)
while (n && cp[n-1] != '.') { --n; }
o = PyString_FromString(&cp[n]);
}
else if (PyString_Check(o) && PyString_Size(o) == 1)
else
{
char *cp = PyString_AS_STRING(o);
int typechar = '\0';
if (PyBytes_Check(o) && PyBytes_Size(o) == 1)
{
typechar = PyBytes_AS_STRING(o)[0];
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(o))
{
#if PY_VERSION_HEX >= 0x03030000
if (PyUnicode_GetLength(o) == 1)
{
typechar = PyUnicode_ReadChar(o, 0);
}
#else
if (PyUnicode_GetSize(o) == 1)
{
typechar = PyUnicode_AS_UNICODE(o)[0];
}
#endif
}
#endif
int j;
for (j = 0; typecodes[j]; j++)
{
if (strcmp(cp, typecodes[j]) == 0)
if (typechar == typecodes[j][0])
{
o = PyString_FromString(typenames[j]);
break;
......@@ -231,10 +251,6 @@ PyVTKTemplate_GetItem(PyObject *ob, PyObject *key)
Py_INCREF(o);
}
}
else
{
Py_INCREF(o);
}
PyTuple_SET_ITEM(t, i, o);
}
......@@ -293,10 +309,17 @@ static PyObject *PyVTKTemplate_Repr(PyObject *op)
{
PyVTKTemplate *self = (PyVTKTemplate *)op;
#ifdef VTK_PY3K
return PyString_FromFormat("<%s %U.%U>",
Py_TYPE(op)->tp_name,
self->module,
self->name);
#else
return PyString_FromFormat("<%s %s.%s>",
Py_TYPE(op)->tp_name,
PyString_AS_STRING(self->module),
PyString_AS_STRING(self->name));
#endif
}
//--------------------------------------------------------------------
......@@ -330,7 +353,10 @@ PyTypeObject PyVTKTemplate_Type = {
PyObject_GenericGetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT, // tp_flags
#ifndef VTK_PY3K
Py_TPFLAGS_CHECKTYPES |
#endif
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT, // tp_flags
PyVTKTemplate_Doc, // tp_doc
PyVTKTemplate_Traverse, // tp_traverse
0, // tp_clear
......
......@@ -90,14 +90,18 @@ bool vtkPythonGetUnsignedLongLongValue(PyObject *o, T &a)
template <class T> inline
bool vtkPythonGetStringValue(PyObject *o, T *&a, const char *exctext)
{
if (PyString_Check(o))
if (PyBytes_Check(o))
{
a = PyString_AS_STRING(o);
a = PyBytes_AS_STRING(o);
return true;
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(o))
{
#if PYTHON_VERSION_HEX >= 0x03030000
a = PyUnicode_AsUTF8(o);
return true;
#else
#ifdef _PyUnicode_AsDefaultEncodedString
PyObject *s = _PyUnicode_AsDefaultEncodedString(o, NULL);
#else
......@@ -105,7 +109,7 @@ bool vtkPythonGetStringValue(PyObject *o, T *&a, const char *exctext)
#endif
if (s)
{
a = PyString_AS_STRING(s);
a = PyBytes_AS_STRING(s);
#ifndef _PyUnicode_AsDefaultEncodedString
Py_DECREF(s);
#endif
......@@ -113,6 +117,7 @@ bool vtkPythonGetStringValue(PyObject *o, T *&a, const char *exctext)
}
exctext = "(unicode conversion error)";
#endif
}
#endif
......@@ -122,17 +127,23 @@ bool vtkPythonGetStringValue(PyObject *o, T *&a, const char *exctext)
inline bool vtkPythonGetStdStringValue(PyObject *o, std::string &a, const char *exctext)
{
if (PyString_Check(o))
if (PyBytes_Check(o))
{
char* val;
Py_ssize_t len;
PyString_AsStringAndSize(o, &val, &len);
PyBytes_AsStringAndSize(o, &val, &len);
a = std::string(val, len);
return true;
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(o))
{
#if PYTHON_VERSION_HEX >= 0x03030000
Py_ssize_t len;
const char* val = PyUnicode_AsUTF8AndSize(o, &len);
a = std::string(val, len);
return true;
#else
#ifdef _PyUnicode_AsDefaultEncodedString
PyObject *s = _PyUnicode_AsDefaultEncodedString(o, NULL);
#else
......@@ -142,7 +153,7 @@ inline bool vtkPythonGetStdStringValue(PyObject *o, std::string &a, const char *
{
char* val;
Py_ssize_t len;
PyString_AsStringAndSize(s, &val, &len);
PyBytes_AsStringAndSize(s, &val, &len);
a = std::string(val, len);
#ifndef _PyUnicode_AsDefaultEncodedString
Py_DECREF(s);
......@@ -151,6 +162,7 @@ inline bool vtkPythonGetStdStringValue(PyObject *o, std::string &a, const char *
}
exctext = "(unicode conversion error)";
#endif
}
#endif
......@@ -164,25 +176,43 @@ inline bool vtkPythonGetStdStringValue(PyObject *o, std::string &a, const char *
static bool vtkPythonGetValue(
PyObject *o, const void *&a, Py_buffer *view)
{
const char *format = 0;
void *p = 0;
Py_ssize_t sz = 0;
#ifndef VTK_PY3K
const char *format = 0;
PyBufferProcs *b = Py_TYPE(o)->tp_as_buffer;
#endif
#if PY_VERSION_HEX >= 0x02060000
// use the new buffer interface
#if PY_VERSION_HEX < 0x02060000
(void)view;
#else
#ifdef VTK_PY3K
PyObject *bytes = NULL;
if (PyUnicode_Check(o))
{
bytes = PyUnicode_AsUTF8String(o);
PyBytes_AsStringAndSize(bytes, reinterpret_cast<char **>(&p), &sz);
}
else
#endif
if (PyObject_CheckBuffer(o))
{
// use the new buffer interface
if (PyObject_GetBuffer(o, view, PyBUF_SIMPLE) == -1)
{
return false;
}
p = view->buf;
sz = view->len;
#ifndef VTK_PY3K
format = view->format;
#endif
}
#ifndef VTK_PY3K
else
#endif
#endif
#ifndef VTK_PY3K
// use the old buffer interface
if (b && b->bf_getreadbuffer && b->bf_getsegcount)
{
......@@ -196,14 +226,22 @@ static bool vtkPythonGetValue(
return false;
}
}
#endif
#ifdef VTK_PY3K
if (bytes)
#else
if (p && sz >= 0 && sz <= VTK_INT_MAX &&
(format == 0 || format[0] == 'c' || format[0] == 'B'))
#endif
{
// check for pointer mangled as string
int s = static_cast<int>(sz);
a = vtkPythonUtil::UnmanglePointer(
reinterpret_cast<char *>(p), &s, "p_void");
#ifdef VTK_PY3K
Py_DECREF(bytes);
#endif
if (s >= 0)
{
return true;
......@@ -281,7 +319,7 @@ bool vtkPythonGetValue(PyObject *o, vtkUnicodeString &a)
PyObject *s = PyUnicode_AsUTF8String(o);
if (s)
{
a = vtkUnicodeString::from_utf8(PyString_AS_STRING(s));
a = vtkUnicodeString::from_utf8(PyBytes_AS_STRING(s));
Py_DECREF(s);
return true;
}
......@@ -1320,21 +1358,32 @@ bool vtkPythonArgs::RefineArgTypeError(int i)
PyErr_ExceptionMatches(PyExc_OverflowError))
{
PyObject *exc;
PyObject *val;
PyObject *val, *newval;
PyObject *frame;
char text[480];
const char *cp = "";
PyErr_Fetch(&exc, &val, &frame);
#ifdef VTK_PY3K
const char *cp = "";
if (val && !PyUnicode_Check(val))
{
Py_DECREF(val);
val = 0;
}
newval = PyUnicode_FromFormat("%s argument %d: %V",
this->MethodName, i+1, val, cp);
#else
const char *cp = "";
if (val && PyString_Check(val))
{
cp = PyString_AsString(val);
}
sprintf(text, "%.200s argument %d: %.200s",
this->MethodName, i+1, cp);
newval = PyString_FromFormat("%s argument %d: %s",
this->MethodName, i+1, cp);
#endif
Py_XDECREF(val);
val = PyString_FromString(text);
PyErr_Restore(exc, val, frame);
PyErr_Restore(exc, newval, frame);
}
return false;
}
......
......@@ -182,7 +182,17 @@ void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype,
}
else if (PyString_Check(callDataTypeObj))
{
char *callDataTypeString = PyString_AsString(callDataTypeObj);
#ifdef VTK_PY3K
PyObject *bytes = PyUnicode_AsEncodedString(
callDataTypeObj, 0, NULL);