#ifndef _PY_GRAPH_MOD_H #define _PY_GRAPH_MOD_H #define PY_SSIZE_T_CLEAN #include #include #include "graph.h" #include "triple_obj.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_size (GraphObject *self, void *closure) { size_t gr_size = LSUP_graph_size (self->ob_struct); PyObject *size = PyLong_FromSize_t (gr_size); Py_INCREF (size); return size; } /* * FIXME This should be deleted and the setter set to NULL or omitted, but * in doing so Python 3.8 raises a SystemError: bad call flags. See * https://bugs.python.org/issue39884 No resolution is clear yet. */ static int Graph_set_size (GraphObject *self, PyObject value, void *closure) { return -1; } static PyObject * Graph_get_uri (GraphObject *self, void *closure) { PyObject *uri = PyUnicode_FromString ( LSUP_graph_uri (self->ob_struct)->data); Py_INCREF (uri); return uri; } static int Graph_set_uri (GraphObject *self, PyObject *uri, void *closure) { if (PyUnicode_READY (uri) != 0) return -1; // TODO redundant? if (PyUnicode_KIND (uri) != PyUnicode_1BYTE_KIND) return -1; LSUP_rc rc = LSUP_graph_set_uri (self->ob_struct, PyUnicode_DATA (uri)); return rc == LSUP_OK ? 0 : -1; } static PyGetSetDef Graph_getsetters[] = { { .name = "__len__", .get = (getter) Graph_get_size, .set = (setter) Graph_set_size, .doc = "Number of triples in the graph.", //.closure = NULL, }, { "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; } /* TODO implement LSUP_graph_equals static PyObject * Graph_richcmp (PyObject *gr1, PyObject *gr2, int op) { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; PyObject *res = NULL; LSUP_Graph *t1 = ((GraphObject *) gr1)->ob_struct; LSUP_Graph *t2 = ((GraphObject *) gr2)->ob_struct; if (LSUP_graph_equals (t1, t2) && op == Py_EQ) Py_RETURN_TRUE; Py_RETURN_FALSE; } */ /* TODO Implement mdbstore bool ops static inline PyObject * Graph_bool_op ( PyTypeObject *cls, LSUP_bool_op op, PyObject *gr1, PyObject *gr2) { 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 int Graph_add (PyObject *self, PyObject *triples) { // Triple may be any iterable. if (! PyIter_Check (triples)) return -1; 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 (triples)); i++) { if (!PyObject_TypeCheck (trp_obj, &TripleType)) { 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; } } LSUP_striple_free (sspo); finalize: LSUP_graph_add_stream_done (it); LSUP_striple_free (sspo); return rc; } 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." }, }; /* TODO Implement mdbstore bool ops 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, }; */ 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_methods = Graph_methods, .tp_getset = Graph_getsetters, //.tp_richcompare = Graph_richcmp, TODO implement LSUP_graph_equals //.tp_as_number = &Graph_number_methods, }; #endif