A GitLab update will be applied today, 9/24. The site may be slow between 12pm - 12:45pm Fri 9/24 EDT (UTC -400).

Commit 3257075e authored by David Gobbi's avatar David Gobbi Committed by Marcus D. Hanwell
Browse files

ENH: Add comparison operators for special types in python

parent a233e8ce
......@@ -21,16 +21,17 @@
//--------------------------------------------------------------------
PyVTKSpecialType::PyVTKSpecialType(
char *cname, char *cdocs[], PyMethodDef *cmethods, PyMethodDef *ccons,
PyVTKSpecialCopyFunc copyfunc, PyVTKSpecialDeleteFunc deletefunc,
PyVTKSpecialPrintFunc printfunc)
PyVTKSpecialMethods *smethods)
{
this->classname = PyString_FromString(cname);
this->docstring = vtkPythonUtil::BuildDocString(cdocs);
this->methods = cmethods;
this->constructors = ccons;
this->copy_func = copyfunc;
this->delete_func = deletefunc;
this->print_func = printfunc;
this->copy_func = smethods->copy_func;
this->delete_func = smethods->delete_func;
this->print_func = smethods->print_func;
this->compare_func = smethods->compare_func;
this->hash_func = smethods->hash_func;
}
//--------------------------------------------------------------------
......@@ -134,6 +135,57 @@ static void PyVTKSpecialObject_PyDelete(PyVTKSpecialObject *self)
#endif
}
//--------------------------------------------------------------------
static long PyVTKSpecialObject_PyHash(PyVTKSpecialObject *self)
{
if (self->vtk_ptr && self->vtk_info->hash_func)
{
long val = self->vtk_info->hash_func(self->vtk_ptr);
if (val != -1)
{
return val;
}
}
// python 2.6
#if PY_VERSION_HEX >= 0x02060000
return PyObject_HashNotImplemented((PyObject *)self);
#else
PyErr_SetString(PyExc_TypeError, (char *)"object is not hashable");
return -1;
#endif
}
//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyRichCompare(
PyVTKSpecialObject *self, PyVTKSpecialObject *o, int opid)
{
if (self->vtk_ptr && self->vtk_info->compare_func)
{
int val = self->vtk_info->compare_func(self->vtk_ptr, o->vtk_ptr, opid);
if (val == 0)
{
Py_INCREF(Py_False);
return Py_False;
}
else if (val != -1)
{
Py_INCREF(Py_True);
return Py_True;
}
}
PyErr_SetString(PyExc_TypeError, (char *)"operation not available");
return NULL;
// Returning "None" is also valid, but not as informative
#if PY_VERSION_HEX >= 0x02010000
// Py_INCREF(Py_NotImplemented);
// return Py_NotImplemented;
#else
// Py_INCREF(Py_None);
// return Py_None;
#endif
}
//--------------------------------------------------------------------
static PyTypeObject PyVTKSpecialObjectType = {
PyObject_HEAD_INIT(&PyType_Type)
......@@ -150,17 +202,17 @@ static PyTypeObject PyVTKSpecialObjectType = {
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
(hashfunc)0, // tp_hash
(hashfunc)PyVTKSpecialObject_PyHash, // tp_hash
(ternaryfunc)0, // tp_call
(reprfunc)PyVTKSpecialObject_PyString, // tp_string
(getattrofunc)PyVTKSpecialObject_PyGetAttr, // tp_getattro
(setattrofunc)0, // tp_setattro
0, // tp_as_buffer
0, // tp_flags
Py_TPFLAGS_HAVE_RICHCOMPARE, // tp_flags
(char*)"vtkspecialobject - a vtk object not derived from vtkObjectBase.", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
(richcmpfunc)PyVTKSpecialObject_PyRichCompare, // tp_richcompare
0, // tp_weaklistoffset
VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
};
......@@ -206,16 +258,12 @@ PyObject *PyVTKSpecialObject_New(char *classname, void *ptr, int copy)
//--------------------------------------------------------------------
PyObject *PyVTKSpecialType_New(
PyMethodDef *newmethod, PyMethodDef *methods, PyMethodDef *constructors,
char *classname, char *docstring[],
PyVTKSpecialCopyFunc copy_func,
PyVTKSpecialDeleteFunc delete_func,
PyVTKSpecialPrintFunc print_func)
char *classname, char *docstring[], PyVTKSpecialMethods *smethods)
{
// Add this type to the special type map
PyVTKSpecialType *info =
vtkPythonUtil::AddSpecialTypeToMap(
classname, docstring, methods, constructors,
copy_func, delete_func, print_func);
classname, docstring, methods, constructors, smethods);
// Add the built docstring to the method
newmethod->ml_doc = PyString_AsString(info->docstring);
......
......@@ -22,9 +22,30 @@
// This for objects not derived from vtkObjectBase
// Prototypes for per-type copy, delete, and print funcs
// copy the object and return the copy
typedef void *(*PyVTKSpecialCopyFunc)(void *);
// delete the object
typedef void (*PyVTKSpecialDeleteFunc)(void *);
// print the object to the stream
typedef void (*PyVTKSpecialPrintFunc)(ostream& os, void *);
// compare objects, final arg is on of the following:
// Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE
// return "-1" if the comparison is impossible
typedef int (*PyVTKSpecialCompareFunc)(void *, void *, int);
// return a hash from the value of the object, or -1 if error
typedef long (*PyVTKSpecialHashFunc)(void *);
// Struct to hold special methods, the first three are mandatory
// and the rest are optional.
struct PyVTKSpecialMethods
{
PyVTKSpecialCopyFunc copy_func;
PyVTKSpecialDeleteFunc delete_func;
PyVTKSpecialPrintFunc print_func;
PyVTKSpecialCompareFunc compare_func;
PyVTKSpecialHashFunc hash_func;
};
// Unlike PyVTKObject, there is no "meta-type" like PyVTKClass.
// Instead, there is just the following class that contains info
......@@ -38,8 +59,7 @@ public:
PyVTKSpecialType(
char *cname, char *cdocs[], PyMethodDef *cmethods, PyMethodDef *ccons,
PyVTKSpecialCopyFunc copyfunc, PyVTKSpecialDeleteFunc deletefunc,
PyVTKSpecialPrintFunc printfunc);
PyVTKSpecialMethods *smethods);
// general information
PyObject *classname;
......@@ -50,6 +70,9 @@ public:
PyVTKSpecialCopyFunc copy_func;
PyVTKSpecialDeleteFunc delete_func;
PyVTKSpecialPrintFunc print_func;
// optional functions
PyVTKSpecialCompareFunc compare_func;
PyVTKSpecialHashFunc hash_func;
};
// The PyVTKSpecialObject is very lightweight.
......@@ -64,10 +87,7 @@ extern "C"
VTK_PYTHON_EXPORT
PyObject *PyVTKSpecialType_New(
PyMethodDef *newmethod, PyMethodDef *methods, PyMethodDef *constructors,
char *classname, char *docstring[],
PyVTKSpecialCopyFunc copy_func,
PyVTKSpecialDeleteFunc delete_func,
PyVTKSpecialPrintFunc print_func);
char *classname, char *docstring[], PyVTKSpecialMethods *smethods);
VTK_PYTHON_EXPORT
int PyVTKSpecialObject_Check(PyObject *obj);
......
......@@ -870,8 +870,7 @@ vtkObjectBase *vtkPythonUtil::VTKParseTuple(
//--------------------------------------------------------------------
PyVTKSpecialType *vtkPythonUtil::AddSpecialTypeToMap(
char *classname, char *docstring[], PyMethodDef *methods,
PyMethodDef *constructors, PyVTKSpecialCopyFunc copy_func,
PyVTKSpecialDeleteFunc delete_func, PyVTKSpecialPrintFunc print_func)
PyMethodDef *constructors, PyVTKSpecialMethods *smethods)
{
if (vtkPythonMap == NULL)
{
......@@ -897,8 +896,8 @@ PyVTKSpecialType *vtkPythonUtil::AddSpecialTypeToMap(
i = vtkPythonMap->SpecialTypeMap->insert(i,
vtkPythonSpecialTypeMap::value_type(
classname,
PyVTKSpecialType(classname, docstring, methods, constructors,
copy_func, delete_func, print_func)));
PyVTKSpecialType(classname, docstring, methods,
constructors, smethods)));
#ifdef VTKPYTHONDEBUG
// vtkGenericWarningMacro("Added type to map type = " << typeObject);
......
......@@ -109,8 +109,7 @@ public:
// later create object given only the class name.
static PyVTKSpecialType *AddSpecialTypeToMap(
char *classname, char *docstring[], PyMethodDef *methods,
PyMethodDef *constructors, PyVTKSpecialCopyFunc copyfunc,
PyVTKSpecialDeleteFunc deletefunc, PyVTKSpecialPrintFunc printfunc);
PyMethodDef *constructors, PyVTKSpecialMethods *smethods);
// Description:
// Get information about a special VTK type, given the type name.
......
......@@ -2438,8 +2438,13 @@ static void vtkWrapPython_ClassDoc(FILE *fp, FileInfo *data)
void vtkParseOutput(FILE *fp, FileInfo *data)
{
int i;
static char *compare_consts[6] = {
"Py_LT", "Py_LE", "Py_EQ", "Py_NE", "Py_GT", "Py_GE" };
static char *compare_tokens[6] = {
"<", "<=", "==", "!=", ">", ">=" };
int compare_ops = 0;
int class_has_new = 0;
int i;
/* the VTK_WRAPPING_CXX tells header files where they're included from */
fprintf(fp,
......@@ -2766,20 +2771,90 @@ void vtkParseOutput(FILE *fp, FileInfo *data)
"\n",
data->ClassName, data->ClassName);
/* hard-code comparison operators until vtkParse provides
* operator information */
if (strcmp(data->ClassName, "vtkVariant") == 0)
{
compare_ops =
( (1 << Py_LT) | (1 << Py_LE) | (1 << Py_EQ) |
(1 << Py_NE) | (1 << Py_GT) | (1 << Py_GE));
}
else if (strcmp(data->ClassName, "vtkTimeStamp") == 0)
{
compare_ops =
( (1 << Py_LT) | (1 << Py_GT) );
}
/* the compare function */
if (compare_ops != 0)
{
fprintf(fp,
"static int vtkSpecial_%sCompare(void *o1, void *o2, int opid)\n"
"{\n"
" const %s &so1 = *((%s *)o1);\n"
" const %s &so2 = *((%s *)o2);\n"
" switch (opid)\n"
" {\n",
data->ClassName, data->ClassName, data->ClassName,
data->ClassName, data->ClassName);
for (i = Py_LT; i <= Py_GE; i++)
{
if ( ((compare_ops >> i) & 1) != 0 )
{
fprintf(fp,
" case %s:\n"
" return (so1 %s so2);\n",
compare_consts[i-Py_LT], compare_tokens[i-Py_LT]);
}
}
fprintf(fp,
" }"
" return -1;\n"
"}\n"
"\n");
}
/* the table to hold these special methods */
fprintf(fp,
"static PyVTKSpecialMethods vtkSpecial_%sSpecialMethods =\n"
"{\n"
" &vtkSpecial_%sCopy,\n"
" &vtkSpecial_%sDelete,\n"
" &vtkSpecial_%sPrint,\n",
data->ClassName, data->ClassName, data->ClassName,
data->ClassName);
if (compare_ops != 0)
{
fprintf(fp,
" &vtkSpecial_%sCompare,\n",
data->ClassName);
}
else
{
fprintf(fp,
" 0,\n");
}
fprintf(fp,
" 0,\n"
"};\n"
"\n");
/* the exported New method */
fprintf(fp,
"PyObject *PyVTKClass_%sNew(char *)\n"
"{\n"
" return PyVTKSpecialType_New(\n"
" &Py%sNewMethod, Py%sMethods, Py%s_%sMethods,"
" (char *)\"%s\", (char**)%sDoc(), &vtkSpecial_%sCopy,\n"
" &vtkSpecial_%sDelete, &vtkSpecial_%sPrint);\n"
" (char *)\"%s\", (char**)%sDoc(),\n"
" &vtkSpecial_%sSpecialMethods);\n"
"}\n"
"\n",
data->ClassName, data->ClassName, data->ClassName,
data->ClassName, data->ClassName, data->ClassName,
data->ClassName, data->ClassName, data->ClassName,
data->ClassName);
data->ClassName, data->ClassName);
}
/* the New method for un-wrappable classes returns "NULL" */
......
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