/** * e4py.cpp -- * * This file contains global functions. * * Authors: Mike Krimerman. * hemkond@yahoo.com * * Copyright (c) 2003, Mike Krimerman. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF * MIKE KRIMERMAN IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "e4py.h" #include "marshal.h" static char doc_e4py[] = "\ This is the Python interface for the e4graph database library.\n\ Example of use:\n\ import e4py\n\ s = e4py.Storage('demo.dat')\n"; /** PyStorage_DefineEventCode. * */ static PyObject* PyStorage_DefineEventCode(PyObject* self, PyObject* args) { int ec; if (!PyArg_ParseTuple(args, "i", &ec)) return 0; if (!e4_Storage::DefineEventCode(ec)) { PyErr_SetString(e4pyExc_APIFailure, "DefineEventCode: Cannot define code"); return 0; } return PyInt_FromLong(ec); } /** PyStorage_UndefineEventCode. * */ static PyObject* PyStorage_UndefineEventCode(PyObject* self, PyObject* args) { int ec; if (!PyArg_ParseTuple(args, "i", &ec)) return 0; if (!e4_Storage::UndefineEventCode(ec)) { PyErr_SetString(e4pyExc_APIFailure, "UndefineEventCode: Cannot undefine code"); return 0; } Py_INCREF(Py_None); return Py_None; } /** PyStorage_IsEventCodeDefined. * */ static PyObject* PyStorage_IsEventCodeDefined(PyObject* self, PyObject* args) { int ec; if (!PyArg_ParseTuple(args, "i", &ec)) return 0; return PyInt_FromLong(long(e4_Storage::IsEventCodeDefined(ec))); } /** Method list */ /* doc */ static char doc_Storage[] = "\ Storage(name[, kind[, mode]]) -> Storage\n\ Creates and returns a new storage.\n\ name (string) - file name for storage\n\ kind (string) - driver name, use E4_METAKIT constant for Metakit\n\ mode (int) - Commit, Garbage-collection and allocation policy\n\ E4_COMMITATCLOSE: If set, the storage is committed before it is closed (default on).\n\ E4_AUTOCOMMIT: If set, the storage is committed periodically when changes exist in the storage (default off).\n\ E4_OPENGC: If set, a garbage collection is performed when the storage is opened (default on).\n\ E4_GCBEFORECOMMIT: If set, a garbage collection is performed before every commit (default off).\n\ E4_AUTOGC: If set, a garbage collection is performed whenever an entity (node or vertex) becomes unreachable (default on).\n\ E4_BIGPREALLOC: If set, space is preallocated in the storage in big increment (default off).\n\ E4_COMPACTATCLOSE: If turned on, space is compacted when the storage is closed (default off).\n\ E4_DEFAULTSTATE: Sets the defaults.\n"; static char doc_StorageVisitor[] = "\ StorageVisitor() -> StorageVisitor\n\ Returns a new storage visitor\n"; static PyMethodDef e4pyMethods[] = { {"Storage", PyStorage_new, METH_VARARGS, doc_Storage}, {"StorageVisitor", PyStorageVisitor_new, METH_VARARGS, doc_StorageVisitor}, {"NodeVisitor", PyNodeVisitor_new, METH_VARARGS, "NodeVisitor(...) - creates a node visitor"}, {"VertexVisitor", PyVertexVisitor_new, METH_VARARGS, "VertexVisitor(...) - creates a vertex visitor"}, {"DefineEventCode", PyStorage_DefineEventCode, METH_VARARGS, "DefineEventCode -- "}, {"UndefineEventCode", PyStorage_UndefineEventCode, METH_VARARGS, "UndefineEventCode -- "}, {"IsEventCodeDefined", PyStorage_IsEventCodeDefined, METH_VARARGS, "IsEventCodeDefined -- "}, {0, 0, 0, 0} }; //Function pointers for pickling when using the cPickle module //static PyObject *dumps = NULL; //static PyObject *loads = NULL; /** PickleTo. * */ PyObject *PickleTo(PyObject *value) { return PyMarshal_WriteObjectToString(value); // return PyObject_CallFunction(dumps, "Oi", value, 1); } /** PickleFrom. * */ PyObject *PickleFrom(const char* buffer, int count) { return PyMarshal_ReadObjectFromString((char*)buffer, count); // return count == 0 ? // PyObject_CallFunction(loads, "s", buffer) : // PyObject_CallFunction(loads, "s#", buffer, count); } /** e4Value_FromPyObject. * @note If data is returned as E4_VTBINARY, it should be freed by PyMem_Free */ e4_Value e4_Value_FromPyObject(PyObject *py_value) { e4_Value value; value.vertexType = E4_VTUNKNOWN; if (py_value == NULL) { return value; } if (PyInt_CheckExact(py_value)) { value.u.i = PyInt_AsLong(py_value); value.vertexType = E4_VTINT; } else if (PyFloat_CheckExact(py_value)) { value.u.d = PyFloat_AsDouble(py_value); value.vertexType = E4_VTDOUBLE; } else if (PyString_CheckExact(py_value)) { value.u.s = PyString_AsString(py_value); value.vertexType = E4_VTSTRING; } else if (PyNode_Check(py_value)) { value.n = PyNode_AsNode(py_value); value.vertexType = E4_VTNODE; } else { //binary PyObject *data = PickleTo(py_value); if (data && PyString_Check(data)) { value.u.b.nbytes = PyString_Size(data); value.u.b.bytes = PyMem_Malloc(value.u.b.nbytes); memcpy(value.u.b.bytes, PyString_AsString(data), value.u.b.nbytes); value.vertexType = E4_VTBINARY; } if (data) Py_DECREF(data); } return value; } /** PyObject_Frome4_Value. * */ PyObject *PyObject_Frome4_Value(e4_Value value) { PyObject *py_value = NULL; switch (value.vertexType) { case E4_VTNODE: py_value = PyNode_FromNode(value.n); break; case E4_VTINT: py_value = PyInt_FromLong(value.u.i); break; case E4_VTDOUBLE: py_value = PyFloat_FromDouble(value.u.d); break; case E4_VTSTRING: py_value = PyString_FromString(value.u.s); break; case E4_VTBINARY: py_value = PickleFrom((const char*)value.u.b.bytes, value.u.b.nbytes); break; default: PyErr_SetString(e4pyExc_APIFailure, "Unknown value type"); break; } return py_value; } //extern "C" __declspec(dllexport) void DL_EXPORT(void) inite4py(void) { PyObject* m = Py_InitModule3("e4py", e4pyMethods, doc_e4py); ///@todo: these attrbiutes aren't read-only! PyModule_AddStringConstant(m, "version", (char*)e4_Storage::version()); //Affective as of version 1.08a PyModule_AddIntConstant(m, "major_version", e4_Storage::major_version()); PyModule_AddIntConstant(m, "minor_version", e4_Storage::minor_version()); PyModule_AddIntConstant(m, "release_status", e4_Storage::release_status()); PyModule_AddIntConstant(m, "release_iteration", e4_Storage::release_iteration()); //register an exception for reporting False results from e4graph methods if (e4pyExc_APIFailure = PyErr_NewException("e4py.APIFailure", PyExc_RuntimeError, NULL)) PyObject_SetAttrString(m, "error", e4pyExc_APIFailure); //cPickle module used to store binaries /*no need for this, use python marshler instead PyObject *pickle_module = PyImport_ImportModule("cPickle"); PyModule_AddObject(m, "pickle", pickle_module); PyObject *pickle_dict = PyModule_GetDict(pickle_module); dumps = PyDict_GetItemString(pickle_dict, "dumps"); loads = PyDict_GetItemString(pickle_dict, "loads"); */ //register class-types PyObject_SetAttrString(m, "StorageType", (PyObject*)&PyStorageType); PyObject_SetAttrString(m, "NodeType", (PyObject*)&PyNodeType); PyObject_SetAttrString(m, "VertexType", (PyObject*)&PyVertexType); PyObject_SetAttrString(m, "StorageVisitorType", (PyObject*)&PyStorageVisitorType); PyObject_SetAttrString(m, "NodeVisitorType", (PyObject*)&PyNodeVisitorType); PyObject_SetAttrString(m, "VertexVisitorType", (PyObject*)&PyVertexVisitorType); //register all enums and #defines PyModule_AddStringConstant(m, "E4_METAKIT", E4_METAKIT); //search result PyModule_AddIntConstant(m, "E4_VERTEXNOTFOUND", E4_VERTEXNOTFOUND); PyModule_AddIntConstant(m, "E4_VERTEXNOTCREATED", E4_VERTEXNOTCREATED); PyModule_AddIntConstant(m, "E4_NODENOTFOUND", E4_NODENOTFOUND); PyModule_AddIntConstant(m, "E4_RANKNOTUSED", E4_RANKNOTUSED); PyModule_AddIntConstant(m, "E4_INVALIDUNIQUEID", E4_INVALIDUNIQUEID); //storage states PyModule_AddIntConstant(m, "E4_COMMITATCLOSE", E4_COMMITATCLOSE); PyModule_AddIntConstant(m, "E4_AUTOCOMMIT", E4_AUTOCOMMIT); PyModule_AddIntConstant(m, "E4_OPENGC", E4_OPENGC); PyModule_AddIntConstant(m, "E4_GCBEFORECOMMIT", E4_GCBEFORECOMMIT); PyModule_AddIntConstant(m, "E4_AUTOGC", E4_AUTOGC); PyModule_AddIntConstant(m, "E4_BIGPREALLOC", E4_BIGPREALLOC); PyModule_AddIntConstant(m, "E4_COMPACTATCLOSE", E4_COMPACTATCLOSE); PyModule_AddIntConstant(m, "E4_DEFAULTSTATE", E4_DEFAULTSTATE); //e4_RefKind PyModule_AddIntConstant(m, "E4_RKINVALID", E4_RKINVALID); PyModule_AddIntConstant(m, "E4_RKSTORAGE", E4_RKSTORAGE); PyModule_AddIntConstant(m, "E4_RKNODE", E4_RKNODE); PyModule_AddIntConstant(m, "E4_RKVERTEX", E4_RKVERTEX); //e4_VertexType PyModule_AddIntConstant(m, "E4_VTUNKNOWN", E4_VTUNKNOWN); PyModule_AddIntConstant(m, "E4_VTNODE", E4_VTNODE); PyModule_AddIntConstant(m, "E4_VTINT", E4_VTINT); PyModule_AddIntConstant(m, "E4_VTDOUBLE", E4_VTDOUBLE); PyModule_AddIntConstant(m, "E4_VTSTRING", E4_VTSTRING); PyModule_AddIntConstant(m, "E4_VTBINARY", E4_VTBINARY); //E4_VTLASTVERTEXTYPE //e4_InsertOrder PyModule_AddIntConstant(m, "E4_IONONE", E4_IONONE); PyModule_AddIntConstant(m, "E4_IOAT", E4_IOAT); PyModule_AddIntConstant(m, "E4_IOFIRST", E4_IOFIRST); PyModule_AddIntConstant(m, "E4_IOLAST", E4_IOLAST); PyModule_AddIntConstant(m, "E4_IOBEFORE", E4_IOBEFORE); PyModule_AddIntConstant(m, "E4_IOAFTER", E4_IOAFTER); //E4_IOLASTINSERTORDER //e4_VisitMethod PyModule_AddIntConstant(m, "E4_VMUNKNOWN", E4_VMUNKNOWN); PyModule_AddIntConstant(m, "E4_VMSTORAGE", E4_VMSTORAGE); PyModule_AddIntConstant(m, "E4_VMNODE", E4_VMNODE); PyModule_AddIntConstant(m, "E4_VMNODERANDOM", E4_VMNODERANDOM); //E4_VMLASTMETHOD //e4_DetachChoice PyModule_AddIntConstant(m, "E4_DCDETACHED", E4_DCDETACHED); PyModule_AddIntConstant(m, "E4_DCATTACHED", E4_DCATTACHED); PyModule_AddIntConstant(m, "E4_DCBOTH", E4_DCBOTH); //visit PyModule_AddIntConstant(m, "E4_VFNONE", E4_VFNONE); PyModule_AddIntConstant(m, "E4_VFNAME", E4_VFNAME); PyModule_AddIntConstant(m, "E4_VFTYPE", E4_VFTYPE); //e4_Space PyModule_AddIntConstant(m, "E4_SPNODE", E4_SPNODE); PyModule_AddIntConstant(m, "E4_SPVERTEX", E4_SPVERTEX); PyModule_AddIntConstant(m, "E4_SPNAME", E4_SPNAME); PyModule_AddIntConstant(m, "E4_SPSTRING", E4_SPSTRING); PyModule_AddIntConstant(m, "E4_SPINT", E4_SPINT); PyModule_AddIntConstant(m, "E4_SPDOUBLE", E4_SPDOUBLE); PyModule_AddIntConstant(m, "E4_SPBINARY", E4_SPBINARY); //E4_SPLAST //e4_SpaceStat PyModule_AddIntConstant(m, "E4_SSUSED", E4_SSUSED); PyModule_AddIntConstant(m, "E4_SSAVAIL", E4_SSAVAIL); PyModule_AddIntConstant(m, "E4_SSFREED", E4_SSFREED); PyModule_AddIntConstant(m, "E4_SSALLOC", E4_SSALLOC); PyModule_AddIntConstant(m, "E4_SSLAST", E4_SSLAST); //event codes PyModule_AddIntConstant(m, "E4_ECADDNODE", E4_ECADDNODE); PyModule_AddIntConstant(m, "E4_ECDETNODE", E4_ECDETNODE); PyModule_AddIntConstant(m, "E4_ECATTNODE", E4_ECATTNODE); PyModule_AddIntConstant(m, "E4_ECMODNODE", E4_ECMODNODE); PyModule_AddIntConstant(m, "E4_ECADDVERTEX", E4_ECADDVERTEX); PyModule_AddIntConstant(m, "E4_ECDETVERTEX", E4_ECDETVERTEX); PyModule_AddIntConstant(m, "E4_ECATTVERTEX", E4_ECATTVERTEX); PyModule_AddIntConstant(m, "E4_ECMODVERTEX", E4_ECMODVERTEX); PyModule_AddIntConstant(m, "E4_ECCHANGESTG", E4_ECCHANGESTG); //user event codes PyModule_AddIntConstant(m, "E4_FIRSTUSERDEFINEDEVENTCODE", E4_FIRSTUSERDEFINEDEVENTCODE); PyModule_AddIntConstant(m, "E4_LASTUSERDEFINEDEVENTCODE", E4_LASTUSERDEFINEDEVENTCODE); //e4_ModNodeEventReason PyModule_AddIntConstant(m, "E4_ERMNADDVERTEX", E4_ERMNADDVERTEX); PyModule_AddIntConstant(m, "E4_ERMNDETVERTEX", E4_ERMNDETVERTEX); PyModule_AddIntConstant(m, "E4_ERMNRENVERTEX", E4_ERMNRENVERTEX); PyModule_AddIntConstant(m, "E4_ERMNMOVVERTEX", E4_ERMNMOVVERTEX); //e4_ModVertexEventReason PyModule_AddIntConstant(m, "E4_ERMVMODVALUE", E4_ERMVMODVALUE); PyModule_AddIntConstant(m, "E4_ERMVRENAME", E4_ERMVRENAME); PyModule_AddIntConstant(m, "E4_ERMVREPARENT", E4_ERMVREPARENT); PyModule_AddIntConstant(m, "E4_ERMVDETVERTEX", E4_ERMVDETVERTEX); }