#ifndef _PY_GRAPH_MOD_H #define _PY_GRAPH_MOD_H #define PY_SSIZE_T_CLEAN #include #include #include "graph.h" #include "py_triple.h" typedef struct { PyObject_HEAD LSUP_Graph *ob_struct; } GraphObject; static int Graph_init (GraphObject *self, PyObject *args, PyObject *kwargs) { unsigned char store_type; if (!PyArg_ParseTuple (args, "b", &store_type)) return -1; self->ob_struct = LSUP_graph_new ((LSUP_store_type)store_type); if (!self->ob_struct) { PyErr_SetString (PyExc_ValueError, "Could not create graph."); return -1; } return 0; } static void Graph_dealloc (GraphObject *self) { LSUP_graph_free (self->ob_struct); Py_TYPE (self)->tp_free ((PyObject *) self); } static PyObject * Graph_get_uri (GraphObject *self, void *closure) { PyObject *uri = PyUnicode_FromString ( LSUP_graph_uri (self->ob_struct)->data); if ( UNLIKELY (!uri)) return NULL; Py_INCREF(uri); return uri; } static int Graph_set_uri (GraphObject *self, PyObject *value, void *closure) { if (!PyObject_TypeCheck (value, &TermType)) return -1; LSUP_rc rc = LSUP_graph_set_uri ( self->ob_struct, ((TermObject*)value)->ob_struct->data); return rc == LSUP_OK ? 0 : -1; } static PyGetSetDef Graph_getsetters[] = { { "uri", (getter) Graph_get_uri, (setter) Graph_set_uri, "Graph URI.", NULL }, {NULL} }; static PyObject * Graph_copy (PyTypeObject *cls, PyObject *src) { if (! PyObject_TypeCheck (src, cls)) return NULL; GraphObject *res = (GraphObject *) cls->tp_alloc(cls, 0); if (!res) return NULL; res->ob_struct = LSUP_graph_copy (((GraphObject *) src)->ob_struct); Py_INCREF(res); return (PyObject *) res; } static PyObject * Graph_richcmp (PyObject *self, PyObject *other, int op) { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; Py_RETURN_TRUE; // TODO use graph xor == 0 /* PyObject *res = NULL; LSUP_Graph *t1 = ((GraphObject *) self)->ob_struct; LSUP_Graph *t2 = ((GraphObject *) other)->ob_struct; if (LSUP_graph_equals (t1, t2) && op == Py_EQ) Py_RETURN_TRUE; Py_RETURN_FALSE; */ } static inline PyObject * Graph_bool_op ( PyTypeObject *cls, LSUP_bool_op op, PyObject *gr1, PyObject *gr2) { Py_RETURN_NONE; //TODO Implement mdbstore bool ops /* if (! PyObject_TypeCheck (gr1, cls) || ! PyObject_TypeCheck (gr2, cls)) return NULL; GraphObject *res = (GraphObject *) cls->tp_alloc (cls, 0); if (!res) return NULL; res->ob_struct = LSUP_graph_bool_op ( op, ((GraphObject *) gr1)->ob_struct, ((GraphObject *) gr2)->ob_struct); Py_INCREF(res); return (PyObject *) res; */ } static PyObject * Graph_add (PyObject *self, PyObject *triples) { // Triple may be any iterable. PyObject *iter = PyObject_GetIter (triples); if (! iter) { PyErr_SetString ( PyExc_ValueError, "Triples object cannot be iterated."); return NULL; } PyObject *trp_obj = NULL; int rc = 0; size_t i; LSUP_SerTriple *sspo = STRP_DUMMY; LSUP_GraphIterator *it = LSUP_graph_add_stream_init ( ((GraphObject *)self)->ob_struct); for (i = 0; (trp_obj = PyIter_Next (iter)); i++) { if (!PyObject_TypeCheck (trp_obj, &TripleType)) { PyErr_SetString ( PyExc_ValueError, "Object is not a triple."); rc = -1; goto finalize; } TRACE ("Inserting triple #%lu\n", i); LSUP_triple_serialize (((TripleObject *)trp_obj)->ob_struct, sspo); LSUP_rc db_rc = LSUP_graph_add_stream_iter (it, sspo); if (db_rc == LSUP_OK) rc = LSUP_OK; if (UNLIKELY (db_rc < 0)) { rc = -1; goto finalize; } } finalize: LSUP_graph_add_stream_done (it); LSUP_striple_free (sspo); PyObject *ret = PyLong_FromSize_t (LSUP_graph_iter_cur (it)); if (rc == 0) { Py_INCREF (ret); return ret; } return NULL; } static int Graph_remove (PyObject *self, PyObject *s, PyObject *p, PyObject *o) { return 0; } static PyObject *Graph_lookup ( PyObject *self, PyObject *s, PyObject *p, PyObject *o) { return NULL; } static PyMethodDef Graph_methods[] = { {"copy", (PyCFunction) Graph_copy, METH_CLASS, "Copy a graph."}, {"add", (PyCFunction) Graph_add, METH_O, "Add triples to a graph."}, { "remove", (PyCFunction) Graph_remove, METH_VARARGS, "Remove triples from a graph by matching a pattern." }, { "lookup", (PyCFunction) Graph_lookup, METH_VARARGS, "Look triples in a graph by matching a pattern." }, {NULL}, }; static inline PyObject *Graph_bool_and ( PyTypeObject *cls, PyObject *gr1, PyObject *gr2) { return Graph_bool_op (cls, LSUP_BOOL_INTERSECTION, gr1, gr2); } static inline PyObject *Graph_bool_or ( PyTypeObject *cls, PyObject *gr1, PyObject *gr2) { return Graph_bool_op (cls, LSUP_BOOL_UNION, gr1, gr2); } static inline PyObject *Graph_bool_subtract ( PyTypeObject *cls, PyObject *gr1, PyObject *gr2) { return Graph_bool_op (cls, LSUP_BOOL_SUBTRACTION, gr1, gr2); } static inline PyObject *Graph_bool_xor ( PyTypeObject *cls, PyObject *gr1, PyObject *gr2) { return Graph_bool_op (cls, LSUP_BOOL_XOR, gr1, gr2); } static PyNumberMethods Graph_number_methods = { .nb_and = (binaryfunc) Graph_bool_and, .nb_or = (binaryfunc) Graph_bool_or, .nb_subtract = (binaryfunc) Graph_bool_subtract, .nb_xor = (binaryfunc) Graph_bool_xor, }; static Py_ssize_t Graph_get_size (PyObject *self) { return LSUP_graph_size (((GraphObject *) self)->ob_struct); } static PySequenceMethods Graph_seq_methods = { .sq_length = (lenfunc) Graph_get_size, //.sq_contains = Graph_contains, // TODO }; PyTypeObject GraphType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "graph.Graph", .tp_doc = "RDF graph", .tp_basicsize = sizeof (GraphObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = PyType_GenericNew, .tp_init = (initproc) Graph_init, .tp_dealloc = (destructor) Graph_dealloc, .tp_getset = Graph_getsetters, .tp_methods = Graph_methods, .tp_richcompare = (richcmpfunc) Graph_richcmp, .tp_as_number = &Graph_number_methods, .tp_as_sequence = &Graph_seq_methods, }; #endif