/*========================================================================= Program: Visualization Toolkit Module: PyVTKTemplate.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /*----------------------------------------------------------------------- The PyVTKTemplate was created in May 2011 by David Gobbi. This object is a container for instantiations of templated types. Essentially, it is a "dict" that accepts template args as keys, and provides the corresponding instantiation of the template. It is implemented as a subclass of PyModule. -----------------------------------------------------------------------*/ #include "PyVTKTemplate.h" #include "vtkPythonUtil.h" #include // Silence warning like // "dereferencing type-punned pointer will break strict-aliasing rules" // it happens because this kind of expression: (long *)&ptr #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif //------------------------------------------------------------------------------ static const char* PyVTKTemplate_Doc = "A container for instantiations of class and function templates.\n\n" "This is a dictionary for templates, provide the template args\n" "in square brackets to get the desired kind of class.\n"; //------------------------------------------------------------------------------ // Methods to help with name mangling and unmangling PyObject* PyVTKTemplate_KeyFromName(PyObject* self, PyObject* arg); PyObject* PyVTKTemplate_NameFromKey(PyObject* self, PyObject* key); //------------------------------------------------------------------------------ // Methods for python static PyObject* PyVTKTemplate_HasKey(PyObject* ob, PyObject* args) { PyObject* key = nullptr; if (PyArg_ParseTuple(args, "O:has_key", &key)) { PyObject* rval = nullptr; PyObject* name = PyVTKTemplate_NameFromKey(ob, key); if (name) { PyObject* dict = PyModule_GetDict(ob); rval = PyDict_GetItem(dict, name); Py_DECREF(name); } if (rval) { Py_DECREF(rval); Py_INCREF(Py_True); return Py_True; } else if (!PyErr_Occurred()) { Py_INCREF(Py_False); return Py_False; } } return nullptr; } static PyObject* PyVTKTemplate_Keys(PyObject* ob, PyObject* args) { if (PyArg_ParseTuple(args, ":keys")) { PyObject* dict = PyModule_GetDict(ob); PyObject* l = PyList_New(0); Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(dict, &pos, &key, &value)) { key = PyVTKTemplate_KeyFromName(ob, key); if (key) { PyList_Append(l, key); Py_DECREF(key); } } return l; } return nullptr; } static PyObject* PyVTKTemplate_Values(PyObject* ob, PyObject* args) { if (PyArg_ParseTuple(args, ":values")) { PyObject* dict = PyModule_GetDict(ob); PyObject* l = PyList_New(0); Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(dict, &pos, &key, &value)) { key = PyVTKTemplate_KeyFromName(ob, key); if (key) { PyList_Append(l, value); Py_DECREF(key); } } return l; } return nullptr; } static PyObject* PyVTKTemplate_Items(PyObject* ob, PyObject* args) { if (PyArg_ParseTuple(args, ":items")) { PyObject* dict = PyModule_GetDict(ob); PyObject* l = PyList_New(0); Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(dict, &pos, &key, &value)) { key = PyVTKTemplate_KeyFromName(ob, key); if (key) { Py_INCREF(value); PyObject* t = PyTuple_New(2); PyTuple_SET_ITEM(t, 0, key); PyTuple_SET_ITEM(t, 1, value); PyList_Append(l, t); Py_DECREF(t); } } return l; } return nullptr; } static PyObject* PyVTKTemplate_Get(PyObject* ob, PyObject* args) { PyObject* key = nullptr; PyObject* def = Py_None; if (PyArg_ParseTuple(args, "O|O:get", &key, &def)) { PyObject* rval = nullptr; PyObject* dict = PyModule_GetDict(ob); key = PyVTKTemplate_NameFromKey(ob, key); if (key) { rval = PyDict_GetItem(dict, key); Py_DECREF(key); } if (rval) { return rval; } else if (!PyErr_Occurred()) { Py_INCREF(def); return def; } } return nullptr; } static PyMethodDef PyVTKTemplate_Methods[] = { { "has_key", PyVTKTemplate_HasKey, METH_VARARGS, "T.has_key(args) -> True only the template args are allowed." }, { "keys", PyVTKTemplate_Keys, METH_VARARGS, "T.keys() -> list of allowed template args." }, { "values", PyVTKTemplate_Values, METH_VARARGS, "T.values() -> list of provided template instantiations." }, { "items", PyVTKTemplate_Items, METH_VARARGS, "T.items() -> list of (args,types) pairs." }, { "get", PyVTKTemplate_Get, METH_VARARGS, "T.get(args) -> get instantiated template type or None." }, { nullptr, nullptr, 0, nullptr } }; //------------------------------------------------------------------------------ // Mapping protocol static Py_ssize_t PyVTKTemplate_Size(PyObject* ob) { Py_ssize_t l = 0; PyObject* dict = PyModule_GetDict(ob); Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(dict, &pos, &key, &value)) { key = PyVTKTemplate_KeyFromName(ob, key); if (key) { Py_DECREF(key); l++; } } return l; } static PyObject* PyVTKTemplate_GetItem(PyObject* ob, PyObject* key) { PyObject* r = nullptr; PyObject* dict = PyModule_GetDict(ob); PyObject* name = PyVTKTemplate_NameFromKey(ob, key); if (name) { // see if the named class is present r = PyObject_GetItem(dict, name); Py_DECREF(name); if (r == nullptr) { // clear the error (it will be set below) PyErr_Clear(); } } if (r == nullptr) { // set a key error PyObject* t = PyTuple_Pack(1, key); PyErr_SetObject(PyExc_KeyError, t); Py_DECREF(t); } return r; } //------------------------------------------------------------------------------ static PyMappingMethods PyVTKTemplate_AsMapping = { PyVTKTemplate_Size, // mp_length PyVTKTemplate_GetItem, // mp_subscript nullptr, // mp_ass_subscript }; //------------------------------------------------------------------------------ static PyObject* PyVTKTemplate_Repr(PyObject* self) { return PyString_FromFormat("