Browse Source

Remove Python bindings.

scossu 1 week ago
parent
commit
dd4c8d247b
13 changed files with 10 additions and 2416 deletions
  1. 0 18
      Dockerfile
  2. 0 3
      MANIFEST.in
  3. 0 30
      Makefile
  4. 10 18
      README.md
  5. 0 30
      cpython/lsup_rdf/__init__.py
  6. 0 682
      cpython/py_graph.h
  7. 0 197
      cpython/py_lsup_rdf.c
  8. 0 189
      cpython/py_namespace.h
  9. 0 478
      cpython/py_term.h
  10. 0 144
      cpython/py_triple.h
  11. 0 3
      pyproject.toml
  12. 0 125
      setup.py
  13. 0 499
      valgrind-python.supp

+ 0 - 18
Dockerfile

@@ -1,18 +0,0 @@
-FROM --platform=linux/amd64 archlinux:base-devel
-
-RUN pacman -Syu --noconfirm
-RUN pacman -S --noconfirm git xxhash lmdb re2c valgrind gdb graphviz
-
-WORKDIR /opt/lsup/lsup_rdf/src
-RUN git clone --recurse-submodules https://git.knowledgetx.com/scossu/lsup_rdf.git
-WORKDIR lsup_rdf
-
-RUN useradd --create-home -G wheel lsup
-RUN echo "%wheel ALL=(ALL:ALL) NOPASSWD:ALL" >| /etc/sudoers.d/wheel
-RUN chown -R lsup:lsup .
-
-USER lsup
-
-ENV LD_LIBRARY_PATH /opt/local/lsup
-
-CMD ["/usr/bin/bash"]

+ 0 - 3
MANIFEST.in

@@ -1,3 +0,0 @@
-graft include
-include cpython/*.h ext/hashmap/*.h ext/tpl/src/*.h ext/log/src/*.h ext/openldap/libraries/liblmdb/*.h
-include Makefile bin/.keep src/codec/Makefile src/codec/*.y src/codec/*.re ext/sqlite/tool/*.c

+ 0 - 30
Makefile

@@ -245,36 +245,6 @@ footprint: bin/perftest ## Measure memory footprint by generating and storing 10
 		"massif-visualizer or similar."
 
 
-venv:
-	test -d venv || python3 -m venv ./venv
-
-
-.PHONY: py
-py: venv codec  ## Build and install python library.
-	source ./venv/bin/activate && (\
-		pip3 install build~=1.2; \
-		pip3 uninstall -y lsup_rdf; \
-		python3 -m build; \
-		pip3 install --no-index --find-links=dist/ lsup_rdf \
-	)
-
-
-.PHONY: py_dbg
-py_dbg: venv codec_dbg  ## Build and install python library with debug symbols.
-	source ./venv/bin/activate && (\
-		pip3 install build~=1.2; \
-		pip3 uninstall -y lsup_rdf; \
-		DEBUG=1 python3 -m build; \
-		pip3 install --no-index --find-links=dist/ lsup_rdf \
-	)
-
-
-.PHONY: pytest
-pytest: py_dbg ## Run a test suite for the Python package.
-	source ./venv/bin/activate && (\
-		python3 test/cpython_test.py )
-
-
 # Requires cinclude2dot (https://www.flourish.org/cinclude2dot) and Graphviz.
 depgraph: $(LSUP_SRC) $(CODEC_SRC) include/* include/codec/* ## Build a visual dependency graph of the code.
 	cinclude2dot --merge=module --include=$(DEPS) \

+ 10 - 18
README.md

@@ -7,7 +7,8 @@ Embedded RDF (and maybe later, generic graph) store and manipulation library.
 ## Purpose
 
 The goal of this library is to provide efficient and compact handling of RDF
-data. At least a complete C API and Python bindings are planned.
+data. At least a complete C API and Python bindings (in a separate project) are
+planned.
 
 This library can be thought of as SQLite or BerkeleyDB for graphs. It can be
 embedded directly in a program and store persistent data without the need of
@@ -25,22 +26,18 @@ and write performance (in order of importance).
 The code offers an interface to write a custom back end implementation with
 minimal changes to the core. More documentation on the topic will follow.
 
-This library was initially meant to replace RDFLib dependency and Cython code
-in [Lakesuperior](https://notabug.org/scossu/lakesuperior) in an effort to
-reduce code clutter and speed up RDF handling; it is now a project for an
-independent RDF library, but unless the contributor base expands, it will
-remain focused on serving Lakesuperior.
-
 
 ## Development Status
 
 **Alpha.** Considered feature-complete from an MVP standpoint. The API may
-still change significantly. The code may not compile, or throw a fit when run.
-The Python API may be behind the C API and not work. Test coverage is not
-sufficient. Documentation is fairly extensive but needs reformatting. This code
-is being integrated in the higher-level `lsup_repo` project and is being
-improved as issues arise. The status will move to beta as soon as `lsup_repo`
-covers a significant range of `lsup_rdf` features.
+still change significantly. The code may not compile, or throw a fit when run;
+however, most commits (not prefixed with "WIP") should be pushed after tests
+pass with a clean `memcheck` output.
+
+Test coverage is not sufficient. Documentation is fairly extensive but needs
+reformatting. This code is being integrated in the higher-level `lsup_repo`
+project and is being improved as issues arise. The status will move to beta as
+soon as `lsup_repo` covers a significant range of `lsup_rdf` features.
 
 This is also my first stab at writing a C library (coming from Python) and an
 unpaid fun project, so don't be surprised if you find some gross stuff.
@@ -163,8 +160,3 @@ to 1Tb for 64-bit systems and 4Gb for 32-bit systems.
 
 Run `doxygen` (see [Doxygen](https://www.doxygen.nl/index.html)) to generate
 HTML documentation in `docs/html`.
-
-
-### Python API Documentation
-
-*TODO*

+ 0 - 30
cpython/lsup_rdf/__init__.py

@@ -1,30 +0,0 @@
-# lsup_rdf package.
-# All "modules" are inside the monolythic lsup_rdf extension because they have
-# cross-linked symbols, so they need a bit of work to be exposed at the main
-# level.
-
-import importlib.util
-import sys
-
-import _lsup_rdf
-from _lsup_rdf import env_init
-
-
-pkg_path = _lsup_rdf.__file__
-
-
-def _load_module(mod_name, path):
-    """
-    Replacement of deprecated imp.load_dynamic(). See
-    https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
-    """
-    spec = importlib.util.spec_from_file_location(mod_name, path)
-    module = importlib.util.module_from_spec(spec)
-    sys.modules['lsup_rdf.' + mod_name] = module
-    spec.loader.exec_module(module)
-
-    return module
-
-
-for mod_name in ('term', 'triple', 'namespace', 'graph'):
-    locals()[mod_name] = _load_module(mod_name, pkg_path)

+ 0 - 682
cpython/py_graph.h

@@ -1,682 +0,0 @@
-#ifndef _PY_GRAPH_MOD_H
-#define _PY_GRAPH_MOD_H
-
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-#include <structmember.h>
-
-#include "graph.h"
-#include "codec/codec_nt.h"
-#include "codec/codec_ttl.h"
-#include "py_triple.h"
-
-
-/*
- * Iterator helpers.
- */
-
-/*
- * String iterator for encoder output.
- *
- * Yields one string (one or more lines) at a time.
- */
-typedef struct {
-    PyObject_HEAD
-    void *it;
-    const LSUP_Codec *codec;
-    char *line;
-} StringIteratorObject;
-
-
-static void
-StringIterator_dealloc (StringIteratorObject *it_obj)
-{ it_obj->codec->encode_graph_done (it_obj->it); }
-
-
-static PyObject *
-StringIterator_next (StringIteratorObject *it_obj)
-{
-    LSUP_rc rc = it_obj->codec->encode_graph_iter (
-            it_obj->it, &it_obj->line);
-    if (rc != LSUP_OK) {
-        if (rc != LSUP_END)
-            PyErr_SetString (PyExc_ValueError, "Error encoding graph.");
-
-        // If not an error, this raises StopIteration.
-        return NULL;
-    }
-
-    return PyUnicode_FromString ((char *) it_obj->line);
-}
-
-
-/*
- * String iterator type.
- *
- * Objects of this type are never generated from Python code, rather from
- * Graph_encode, hence the type has no special new or init function.
- */
-PyTypeObject StringIteratorType = {
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    .tp_name            = "graph.StringIterator",
-    .tp_basicsize       = sizeof (StringIteratorObject),
-    .tp_itemsize        = 0,
-    .tp_flags           = Py_TPFLAGS_DEFAULT,
-    .tp_dealloc         = (destructor) StringIterator_dealloc,
-    .tp_iter            = PyObject_SelfIter,
-    .tp_iternext        = (iternextfunc)StringIterator_next,
-};
-
-
-/*
- * Graph iterator.
- *
- * Yields one triple at a time.
- */
-typedef struct {
-    PyObject_HEAD
-    LSUP_GraphIterator *it;
-    LSUP_Triple *spo;
-} GraphIteratorObject;
-
-
-static void
-GraphIterator_dealloc (GraphIteratorObject *it_obj)
-{
-    LSUP_graph_iter_free (it_obj->it);
-    free (it_obj->spo);
-}
-
-
-static PyObject *
-GraphIterator_next (GraphIteratorObject *it_obj)
-{
-    LSUP_rc rc = LSUP_graph_iter_next (it_obj->it, &it_obj->spo);
-    if (rc != LSUP_OK) {
-        if (rc != LSUP_END)
-            PyErr_SetString (PyExc_ValueError, "Error encoding graph.");
-
-        // If not an error, this raises StopIteration.
-        return NULL;
-    }
-
-    return build_triple (it_obj->spo);
-}
-
-
-/*
- * Graph iterator type.
- */
-PyTypeObject GraphIteratorType = {
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    .tp_name            = "graph.GraphIterator",
-    .tp_basicsize       = sizeof (GraphIteratorObject),
-    .tp_itemsize        = 0,
-    .tp_flags           = Py_TPFLAGS_DEFAULT,
-    .tp_dealloc         = (destructor) GraphIterator_dealloc,
-    .tp_iter            = PyObject_SelfIter,
-    .tp_iternext        = (iternextfunc) GraphIterator_next,
-};
-
-
-/*
- * Graph stuff.
- */
-
-typedef struct {
-    PyObject_HEAD
-    LSUP_Graph *ob_struct;
-} GraphObject;
-
-
-static int
-Graph_init (GraphObject *self, PyObject *args, PyObject *kwargs)
-{
-    unsigned char store_type;
-    PyObject *uri_obj = NULL;
-    char *uri_str = NULL;
-
-    static char *kwlist[] = {"", "uri_str", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords (
-            args, kwargs, "b|s", kwlist, &store_type, &uri_str))
-        return -1;
-
-    // Set up the store if a function for that is defined.
-    const LSUP_StoreInt *sif = LSUP_store_int (store_type);
-    if (UNLIKELY (!sif)) {
-            PyErr_SetString (
-                    PyExc_TypeError,
-                    "No interface defined for given store type.");
-            return -1;
-    }
-
-    // TODO Move store creation fn and handle into a separate module.
-    LSUP_Store *store = LSUP_store_new (store_type, NULL, 0);
-    if (sif->setup_fn) {
-        if (sif->setup_fn(NULL, false) < LSUP_OK) {
-            PyErr_SetString (
-                    PyExc_IOError, "Error initializing back end store.");
-            return -1;
-        }
-    }
-
-    // TODO Make store ID, nsm and initial size accessible.
-    self->ob_struct = LSUP_graph_new (store, uri_str, NULL);
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create graph.");
-        return -1;
-    }
-    if (uri_str) free (uri_str);
-
-    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)
-{
-    const LSUP_Term *uri = LSUP_graph_uri (self->ob_struct);
-    LOG_DEBUG("Graph URI address: %p", uri);
-    LOG_DEBUG("Graph URI: %s", uri->data);
-
-    return PyUnicode_FromString (uri->data);
-}
-
-
-static int
-Graph_set_uri (GraphObject *self, PyObject *args)
-{
-    char *uri_str = NULL;
-    if (! PyArg_ParseTuple (args, "s", &uri_str)) return NULL;
-
-    LSUP_rc rc = LSUP_graph_set_uri (self->ob_struct, uri_str);
-    free (uri_str);
-
-    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_new_from_rdf (PyTypeObject *cls, PyObject *args)
-{
-    PyObject *buf, *fileno_fn, *fileno_obj;
-    const char *type;
-    if (! PyArg_ParseTuple (args, "Os", &buf, &type)) return NULL;
-
-    // Get the file descriptor from the Python BufferedIO object.
-    // FIXME This is not sure to be reliable. See
-    // https://docs.python.org/3/library/io.html?highlight=io%20bufferedreader#io.IOBase.fileno
-    if (! (fileno_fn = PyObject_GetAttrString (buf, "fileno"))) {
-        PyErr_SetString (PyExc_TypeError, "Object has no fileno function.");
-        return NULL;
-    }
-    PyObject* fileno_args = PyTuple_New(0);
-    if (! (fileno_obj = PyObject_CallObject (fileno_fn, fileno_args))) {
-        PyErr_SetString (PyExc_SystemError, "Error calling fileno function.");
-        return NULL;
-    }
-    int fd = PyLong_AsSize_t (fileno_obj);
-
-    /*
-     * From the Linux man page:
-     *
-     * > The file descriptor is not dup'ed, and will be closed when the stream
-     * > created by fdopen() is closed. The result of applying fdopen() to a
-     * > shared memory object is undefined.
-     *
-     * Hence the `dup()`.
-     */
-    fd = dup (fd);
-    FILE *fh = fdopen (fd, "r");
-
-    GraphObject *res = (GraphObject *) cls->tp_alloc(cls, 0);
-    if (!res) return PyErr_NoMemory();
-
-    const LSUP_Codec *codec;
-    if (strcmp(type, "nt") == 0) codec = &nt_codec;
-    else if (strcmp (type, "ttl") == 0) codec = &ttl_codec;
-    // TODO other codecs here.
-    else {
-            PyErr_SetString (PyExc_ValueError, "Unsupported codec.");
-            return NULL;
-    }
-
-    size_t ct;
-    char *err;
-    codec->decode_graph (fh, &res->ob_struct, &ct, &err);
-    fclose (fh);
-
-    LOG_DEBUG("Decoded %lu triples.", ct);
-    if (UNLIKELY (err)) {
-        PyErr_SetString (PyExc_IOError, err);
-        return NULL;
-    }
-
-    Py_INCREF (res);
-
-    return (PyObject *) res;
-}
-
-
-/** @brief Build a triple pattern for lookup purposes.
- */
-inline static int build_trp_pattern (PyObject *args, LSUP_Term *spo[])
-{
-    PyObject *s_obj, *p_obj, *o_obj;
-
-    if (! (PyArg_ParseTuple (args, "OOO", &s_obj, &p_obj, &o_obj)))
-        return -1;
-
-    if (s_obj != Py_None && !PyObject_TypeCheck (s_obj, &TermType)) {
-        PyErr_SetString (PyExc_TypeError, "Subject must be a term or None.");
-        return -1;
-    }
-    if (p_obj != Py_None && !PyObject_TypeCheck (p_obj, &TermType)) {
-        PyErr_SetString (PyExc_TypeError, "Predicate must be a term or None.");
-        return -1;
-    }
-    if (o_obj != Py_None && !PyObject_TypeCheck (o_obj, &TermType)) {
-        PyErr_SetString (PyExc_TypeError, "Object must be a term or None.");
-        return -1;
-    }
-
-    spo[0] = s_obj != Py_None ? ((TermObject *)s_obj)->ob_struct : NULL;
-    spo[1] = p_obj != Py_None ? ((TermObject *)p_obj)->ob_struct : NULL;
-    spo[2] = o_obj != Py_None ? ((TermObject *)o_obj)->ob_struct : NULL;
-
-    return 0;
-}
-
-/** @brief Converter for a term struct in `O&` notation.
- *
- * See https://docs.python.org/3/c-api/arg.html#other-objects
- * Convert a PyObject argument into a LSUP_term. `Py_None` is acceptable.
- *
- * @param[in] obj Argument passed to calling function.
- *
- * @param[out] result Result of transform process.
- *
- * @return 1 on conversion success; 0 in failure.
- */
-static int arg_term_converter (PyObject *obj, void *result)
-{
-    if (obj != Py_None && !PyObject_TypeCheck (obj, &TermType)) {
-        PyErr_SetString (PyExc_TypeError, "Variable must be a Term or None.");
-        return 0;
-    }
-
-    LSUP_Term **term = result;
-    *term = obj != Py_None ? ((TermObject *)obj)->ob_struct : NULL;
-
-    return 1;
-}
-
-
-/** @brief Converter for a graph struct in `O&` notation.
- *
- * See https://docs.python.org/3/c-api/arg.html#other-objects
- * Convert a PyObject argument into a LSUP_term.
- *
- * @param[in] obj Argument passed to calling function.
- *
- * @param[out] result Result of transform process.
- *
- * @return 1 on conversion success; 0 in failure.
- */
-static int arg_graph_converter (PyObject *obj, void *result);
-
-
-static PyObject *
-Graph_copy_contents (GraphObject *self, PyObject *args, PyObject *kwargs)
-{
-    assert (!PyErr_Occurred());
-    assert (args || kwargs);
-
-    LSUP_Term *spo[3];
-    LSUP_Graph *dest;
-
-    static char *kwlist[] = {"", "s", "p", "o", NULL};
-    if (!PyArg_ParseTupleAndKeywords(
-        args, kwargs, "O&|O&O&O&", kwlist,
-        arg_graph_converter, &dest,
-        arg_term_converter, spo,
-        arg_term_converter, spo + 1,
-        arg_term_converter, spo + 2
-    )) return NULL;
-
-    if (LSUP_graph_copy_contents (
-                self->ob_struct, dest,
-                spo[0], spo[1], spo[2])
-            < LSUP_OK)
-    {
-        PyErr_SetString (PyExc_ValueError, "Error copying graph contents.");
-
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-};
-
-
-static PyObject *
-Graph_richcmp (PyObject *self, PyObject *other, int op)
-{
-    // Only equality and non-equality are supported.
-    if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED;
-
-    LSUP_Graph *t1 = ((GraphObject *) self)->ob_struct;
-    LSUP_Graph *t2 = ((GraphObject *) other)->ob_struct;
-
-    if (LSUP_graph_equals (t1, t2) ^ (op == Py_NE)) Py_RETURN_TRUE;
-    Py_RETURN_FALSE;
- }
-
-
-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;
-
-    LSUP_Graph *dest = LSUP_graph_new (NULL, NULL, NULL);
-    if (!dest) {
-        PyErr_SetString (PyExc_Exception, "Could not create destination graph.");
-        return NULL;
-    }
-
-    LSUP_rc rc = LSUP_graph_bool_op (
-            op, ((GraphObject *) gr1)->ob_struct,
-            ((GraphObject *) gr2)->ob_struct, res->ob_struct);
-    if (rc < LSUP_OK) {
-        PyErr_SetString (PyExc_Exception, "Error performing boolean operation.");
-        return NULL;
-    }
-
-    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;
-    int rc = 0;
-    size_t ct = 0;
-    LSUP_GraphIterator *it = LSUP_graph_add_init (
-            ((GraphObject *)self)->ob_struct);
-
-    while ((trp_obj = PyIter_Next (iter))) {
-        if (!PyObject_TypeCheck (trp_obj, &TripleType)) {
-            PyErr_SetString (
-                    PyExc_ValueError, "Object is not a triple.");
-            rc = -1;
-            goto finally;
-        }
-
-        LOG_TRACE("Inserting triple #%lu", ct);
-
-        LSUP_rc db_rc = LSUP_graph_add_iter (
-                it, ((TripleObject *) trp_obj)->ob_struct);
-
-        if (db_rc == LSUP_OK) {
-            rc = LSUP_OK;
-            ct++;
-        } else if (UNLIKELY (db_rc < 0)) {
-            PyErr_SetString (PyExc_ValueError, "Error while adding triples.");
-            rc = -1;
-            goto finally;
-        }
-        // If db_rc > 0, it's a no-op and the counter is not increased.
-    }
-
-finally:
-    LSUP_graph_add_done (it);
-
-    if (rc == LSUP_OK) return PyLong_FromSize_t (ct);
-    return NULL;
-}
-
-
-static PyObject *Graph_remove (PyObject *self, PyObject *args)
-{
-    LSUP_rc rc;
-    LSUP_Term *spo[3];
-
-    if (!PyArg_ParseTuple (
-        args,
-        "O&O&O&",
-        arg_term_converter, spo,
-        arg_term_converter, spo + 1,
-        arg_term_converter, spo + 2
-    )) Py_RETURN_NONE;
-
-    size_t ct;
-    rc = LSUP_graph_remove (
-            ((GraphObject *)self)->ob_struct, spo[0], spo[1], spo[2], &ct);
-
-    if (rc < 0) {
-        // TODO implement strerror for more details.
-        PyErr_SetString (PyExc_SystemError, "Error removing triples.");
-        goto finally;
-    }
-    LOG_DEBUG("Removed %lu triples.", ct);
-
-finally:
-    if (rc < 0) return NULL;
-
-    Py_RETURN_NONE;
-}
-
-
-static PyObject *Graph_lookup (PyObject *self, PyObject *args)
-{
-    LSUP_rc rc;
-    GraphIteratorObject *it_obj = NULL;
-    LSUP_Term *spo[3];
-
-    if (!PyArg_ParseTuple (
-        args,
-        "O&O&O&",
-        arg_term_converter, spo,
-        arg_term_converter, spo + 1,
-        arg_term_converter, spo + 2
-    )) Py_RETURN_NONE;
-
-    size_t ct;
-    LSUP_GraphIterator *it = LSUP_graph_lookup (
-            ((GraphObject *)self)->ob_struct, spo[0], spo[1], spo[2], &ct);
-    if (UNLIKELY (!it)) {
-        // TODO implement LSUP_strerror for more details.
-        PyErr_SetString (PyExc_SystemError, "Error looking up triples.");
-        rc = -1;
-        goto finally;
-    }
-    LOG_DEBUG("Found %lu triples.", ct);
-
-    // Initialize the generator object.
-    it_obj = PyObject_New (
-            GraphIteratorObject, &GraphIteratorType);
-    if (UNLIKELY (!it_obj)) return PyErr_NoMemory();
-
-    it_obj->it = it;
-    it_obj->spo = TRP_DUMMY;
-
-    Py_INCREF (it_obj);
-
-finally:
-    return (PyObject *)it_obj;
-}
-
-
-static PyObject *
-Graph_encode (PyObject *self, PyObject *args)
-{
-    const char *type;
-
-    if (! PyArg_ParseTuple (args, "s", &type)) return NULL;
-
-    // Initialize the generator object.
-    StringIteratorObject *it_obj = PyObject_New (
-            StringIteratorObject, &StringIteratorType);
-    if (!it_obj) return NULL;
-
-    if (strcmp (type, "nt") == 0) it_obj->codec = &nt_codec;
-    else if (strcmp (type, "ttl") == 0) it_obj->codec = &ttl_codec;
-    // TODO other codecs here.
-    else {
-        PyErr_SetString (PyExc_ValueError, "Unsupported codec.");
-        return NULL;
-    }
-
-    it_obj->it = it_obj->codec->encode_graph_init (
-            ((GraphObject *)self)->ob_struct);
-
-    it_obj->line = NULL;
-
-    Py_INCREF (it_obj);
-    return (PyObject *)it_obj;
-}
-
-
-static PyMethodDef Graph_methods[] = {
-    {
-        "copy", (PyCFunction) Graph_copy_contents,
-        METH_VARARGS | METH_KEYWORDS,
-        "Copy the contents of a graph into another."
-    },
-    {
-        "from_rdf", (PyCFunction) Graph_new_from_rdf,
-        METH_CLASS | METH_VARARGS,
-        "Create a graph from a RDF file."
-    },
-    {"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."
-    },
-    {
-        "to_rdf", (PyCFunction) Graph_encode, METH_VARARGS,
-        "Encode a graph into a RDF byte buffer."
-    },
-    {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 int
-Graph_contains (PyObject *self, PyObject *value)
-{
-    if (!PyObject_TypeCheck (value, &TripleType)) {
-        PyErr_SetString (PyExc_ValueError, "Error parsing input value.");
-        return -1;
-    }
-
-    int rc = LSUP_graph_contains (
-            ((GraphObject *) self)->ob_struct,
-            ((TripleObject *) value)->ob_struct);
-
-    return rc;
-}
-
-
-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 = (objobjproc) Graph_contains,
-};
-
-
-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,
-};
-
-
-static int arg_graph_converter (PyObject *obj, void *result)
-{
-    if (!PyObject_TypeCheck (obj, &GraphType)) {
-        PyErr_SetString (PyExc_TypeError, "Variable must be a Graph object.");
-        return 0;
-    }
-
-    LSUP_Graph **gr = result;
-    *gr = ((GraphObject *)obj)->ob_struct;
-
-    return 1;
-}
-
-#endif

+ 0 - 197
cpython/py_lsup_rdf.c

@@ -1,197 +0,0 @@
-/** @file lsup_rdf_mod.c
- *
- * @brief LSUP_RDF package.
- *
- * This "package" module includes all RDF modules in a monolithic compiled
- * object, in order to resolve internal symbol dependencies. Individual modules
- * are extracted and exposed by the package __init__.py .
- */
-
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-
-#include "py_graph.h"
-
-
-static PyObject *
-env_init (PyObject *self)
-{
-    if (LSUP_init() != LSUP_OK) {
-        PyErr_SetString (PyExc_SystemError, "Error initializing environment.");
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-
-static PyMethodDef lsup_rdf_methods[] = {
-    {
-        "env_init", (PyCFunction)env_init, METH_NOARGS,
-        "Initialize the LSUP_RDF environment."
-    },
-    {NULL}
-};
-
-static PyModuleDef _lsup_rdf_pkg = {
-    PyModuleDef_HEAD_INIT,
-    .m_name = "_lsup_rdf",
-    .m_doc = "Lakesuperior RDF package.",
-    .m_size = -1,
-    .m_methods = lsup_rdf_methods,
-};
-
-PyMODINIT_FUNC
-PyInit__lsup_rdf (void)
-{ return PyModule_Create (&_lsup_rdf_pkg); }
-
-
-static PyModuleDef term_mod = {
-    PyModuleDef_HEAD_INIT,
-    .m_name = "term",
-    .m_doc = "RDF term module.",
-    .m_size = -1,
-};
-
-
-PyMODINIT_FUNC
-PyInit_term()
-{
-    if (
-        PyType_Ready (&TermType) < 0
-        || PyType_Ready (&IRIRefType) < 0
-        || PyType_Ready (&LiteralType) < 0
-        || PyType_Ready (&BNodeType) < 0
-    ) return NULL;
-
-    PyObject *m = PyModule_Create(&term_mod);
-    if (m == NULL) return NULL;
-
-    if (
-        PyModule_AddIntConstant (m, "TERM_UNDEFINED", LSUP_TERM_UNDEFINED) < 0
-        || PyModule_AddIntConstant (m, "TERM_IRIREF", LSUP_TERM_IRIREF) < 0
-        || PyModule_AddIntConstant (m, "TERM_BNODE", LSUP_TERM_BNODE) < 0
-        || PyModule_AddIntConstant (m, "TERM_LITERAL", LSUP_TERM_LITERAL) < 0
-        || PyModule_AddIntConstant (
-                m, "TERM_LT_LITERAL", LSUP_TERM_LT_LITERAL) < 0
-    ) return NULL;
-
-    Py_INCREF(&TermType);
-    if (PyModule_AddObject(m, "Term", (PyObject *) &TermType) < 0) {
-        Py_DECREF(&TermType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    Py_INCREF(&IRIRefType);
-    if (PyModule_AddObject(m, "IRIRef", (PyObject *) &IRIRefType) < 0) {
-        Py_DECREF(&IRIRefType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    Py_INCREF(&LiteralType);
-    if (PyModule_AddObject(m, "Literal", (PyObject *) &LiteralType) < 0) {
-        Py_DECREF(&LiteralType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    Py_INCREF(&BNodeType);
-    if (PyModule_AddObject(m, "BNode", (PyObject *) &BNodeType) < 0) {
-        Py_DECREF(&BNodeType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    return m;
-}
-
-
-static PyModuleDef triple_mod = {
-    PyModuleDef_HEAD_INIT,
-    .m_name = "triple",
-    .m_doc = "RDF triple module.",
-    .m_size = -1,
-};
-
-
-PyMODINIT_FUNC
-PyInit_triple()
-{
-    if (PyType_Ready (&TripleType) < 0) return NULL;
-
-    PyObject *m = PyModule_Create(&triple_mod);
-    if (m == NULL) return NULL;
-
-    Py_INCREF(&TripleType);
-    if (PyModule_AddObject(m, "Triple", (PyObject *) &TripleType) < 0) {
-        Py_DECREF(&TripleType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    return m;
-}
-
-
-static PyModuleDef namespace_mod = {
-    PyModuleDef_HEAD_INIT,
-    .m_name = "namespace",
-    .m_doc = "RDF namespace module.",
-    .m_size = -1,
-};
-
-
-PyMODINIT_FUNC
-PyInit_namespace()
-{
-    if (PyType_Ready (&NSMapType) < 0) return NULL;
-
-    PyObject *m = PyModule_Create(&namespace_mod);
-    if (m == NULL) return NULL;
-
-    Py_INCREF(&NSMapType);
-    if (PyModule_AddObject(m, "NSMap", (PyObject *) &NSMapType) < 0) {
-        Py_DECREF(&NSMapType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    return m;
-}
-
-
-static PyModuleDef graph_mod = {
-    PyModuleDef_HEAD_INIT,
-    .m_name = "graph",
-    .m_doc = "RDF graph module.",
-    .m_size = -1,
-};
-
-
-PyMODINIT_FUNC
-PyInit_graph()
-{
-    if (PyType_Ready (&GraphType) < 0) return NULL;
-
-    PyObject *m = PyModule_Create(&graph_mod);
-    if (!m) return NULL;
-
-#define ENTRY(a, b) \
-    if (PyModule_AddIntConstant (m, "STORE_" #a, LSUP_STORE_##a) < 0) \
-        return NULL;
-    BACKEND_TBL
-#undef ENTRY
-
-    Py_INCREF(&GraphType);
-    if (PyModule_AddObject(m, "Graph", (PyObject *) &GraphType) < 0) {
-        Py_DECREF(&GraphType);
-        Py_DECREF(m);
-        return NULL;
-    }
-
-    return m;
-}
-

+ 0 - 189
cpython/py_namespace.h

@@ -1,189 +0,0 @@
-#ifndef _PY_NAMESPACE_OBJ_H
-#define _PY_NAMESPACE_OBJ_H
-
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-#include <structmember.h>
-
-#include "namespace.h"
-
-
-typedef struct {
-    PyObject_HEAD
-    LSUP_NSMap      *ob_struct;
-} NSMapObject;
-
-
-static int
-NSMap_init (NSMapObject *self, PyObject *args)
-{
-    self->ob_struct = LSUP_nsmap_new();
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_SystemError, "Could not create namespace.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static void
-NSMap_dealloc (NSMapObject *self)
-{
-    LSUP_nsmap_free (self->ob_struct);
-    Py_TYPE (self)->tp_free ((PyObject *) self);
-}
-
-
-static PyObject *
-NSMap_add (PyObject *self, PyObject *args)
-{
-    const char *pfx, *ns;
-    if (! PyArg_ParseTuple (args, "ss", &pfx, &ns)) return NULL;
-
-    if (LSUP_nsmap_add (((NSMapObject *)self)->ob_struct, pfx, ns) < 0) {
-        PyErr_SetString (PyExc_ValueError, "Error adding namespace.");
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-
-static PyObject *
-NSMap_remove (PyObject *self, PyObject *pfx_obj)
-{
-    if (PyUnicode_READY (pfx_obj) < 0) return NULL;
-    const char *pfx = PyUnicode_AsUTF8 (pfx_obj);
-
-    if (LSUP_nsmap_remove (((NSMapObject *)self)->ob_struct, pfx) < 0) {
-        PyErr_SetString (PyExc_ValueError, "Error removing namespace.");
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-
-static PyObject *
-NSMap_get (PyObject *self, PyObject *pfx_obj)
-{
-    if (PyUnicode_READY (pfx_obj) < 0) return NULL;
-    const char *pfx = PyUnicode_AsUTF8 (pfx_obj);
-
-    const char *ns = LSUP_nsmap_get_ns (((NSMapObject *)self)->ob_struct, pfx);
-    if (!ns) Py_RETURN_NONE;
-
-    PyObject *ns_obj = PyUnicode_FromString (ns);
-
-    Py_INCREF (ns_obj);
-    return (ns_obj);
-}
-
-
-static PyObject *
-NSMap_denormalize_uri (PyObject *self, PyObject *fq_uri_obj)
-{
-    if (PyUnicode_READY (fq_uri_obj) < 0) return NULL;
-    const char *fq_uri = PyUnicode_AsUTF8 (fq_uri_obj);
-
-    char *pfx_uri;
-    LSUP_rc rc = LSUP_nsmap_denormalize_uri (
-            ((NSMapObject *)self)->ob_struct, fq_uri, &pfx_uri);
-    if (rc < 0)  {
-        PyErr_SetString (PyExc_ValueError, "Error normalizing URI.");
-        return NULL;
-    } else if (rc == LSUP_NORESULT) Py_RETURN_NONE;
-
-    PyObject *uri_obj = PyUnicode_FromString (pfx_uri);
-
-    Py_INCREF (uri_obj);
-    return (uri_obj);
-}
-
-
-static PyObject *
-NSMap_normalize_uri (PyObject *self, PyObject *pfx_uri_obj)
-{
-    if (PyUnicode_READY (pfx_uri_obj) < 0) return NULL;
-    const char *pfx_uri = PyUnicode_AsUTF8 (pfx_uri_obj);
-
-    char *fq_uri;
-    LSUP_rc rc = LSUP_nsmap_normalize_uri (
-            ((NSMapObject *)self)->ob_struct, pfx_uri, &fq_uri);
-    if (rc < 0)  {
-        PyErr_SetString (PyExc_ValueError, "Error denormalizing URI.");
-        return NULL;
-    }
-
-    PyObject *uri_obj = PyUnicode_FromString (fq_uri);
-
-    Py_INCREF (uri_obj);
-    return (uri_obj);
-}
-
-
-static PyObject *
-NSMap_as_dict (PyObject *self)
-{
-    const char ***data = LSUP_nsmap_dump (((NSMapObject *)self)->ob_struct);
-
-    PyObject *data_obj = PyDict_New();
-    // TODO PyDictProxy_New(PyObject *mapping)
-
-    for (size_t i = 0; data[i] != NULL; i++) {
-        PyObject *val_obj = PyUnicode_FromString(data[i][1]);
-        if (PyDict_SetItemString (data_obj, data[i][0], val_obj) < 0)
-            return NULL;
-    }
-
-    Py_INCREF (data_obj);
-    return data_obj;
-}
-
-
-static PyMethodDef NSMap_methods[] = {
-    {
-        "add", (PyCFunction) NSMap_add, METH_VARARGS,
-        "Add a namespace prefix."
-    },
-    {
-        "remove", (PyCFunction) NSMap_remove, METH_O,
-        "Remove a namespace prefix."
-    },
-    {
-        "get", (PyCFunction) NSMap_get, METH_O,
-        "Get the fully qualified namespace for a prefix."
-    },
-    {
-        "normalize_uri", (PyCFunction) NSMap_normalize_uri, METH_O,
-        "Normalize a URI (i.e. convert from prefixed to fully qualified)."
-    },
-    {
-        "denormalize_uri", (PyCFunction) NSMap_denormalize_uri, METH_O,
-        "Denormalize a URI (i.e. convert from fully qualified to prefixed)."
-    },
-    {
-        "as_dict", (PyCFunction) NSMap_as_dict, METH_NOARGS,
-        "Namespace map as a dictionary of prefixes and namespaces.",
-    },
-    {NULL},
-};
-
-
-PyTypeObject NSMapType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name            = "namespace.NSMap",
-    .tp_doc             = "Namespace prefix map.",
-    .tp_basicsize       = sizeof(NSMapObject),
-    .tp_itemsize        = 0,
-    .tp_flags           = Py_TPFLAGS_DEFAULT,
-    .tp_new             = PyType_GenericNew,
-    .tp_init            = (initproc) NSMap_init,
-    .tp_dealloc         = (destructor) NSMap_dealloc,
-    .tp_methods         = NSMap_methods,
-};
-
-
-#endif  /* _PY_NAMESPACE_OBJ */

+ 0 - 478
cpython/py_term.h

@@ -1,478 +0,0 @@
-#ifndef _PY_TERM_OBJ_H
-#define _PY_TERM_OBJ_H
-
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-#include <structmember.h>
-
-#include "term.h"
-#include "py_namespace.h"
-
-
-typedef struct {
-    PyObject_HEAD
-    LSUP_Term * ob_struct;
-} TermObject;
-
-
-static int
-Term_init (TermObject *self, PyObject *args, PyObject *kwargs)
-{
-    unsigned char term_type;
-    char *data = NULL, *datatype = NULL, *lang = NULL;
-
-    static char *kwlist[] = {"", "", "datatype", "lang", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords (
-            args, kwargs, "bs|zz", kwlist,
-            &term_type, &data, &datatype, &lang))
-        return -1;
-
-    if (datatype) {
-        LSUP_Term *dtype_uri = LSUP_term_new (
-                LSUP_TERM_IRIREF, datatype, NULL);
-        self->ob_struct = LSUP_term_new (
-                (LSUP_TermType) term_type, data, dtype_uri);
-    } else {
-        self->ob_struct = LSUP_term_new (
-                (LSUP_TermType) term_type, data, lang);
-    }
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create term.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-Term_iriref_init (TermObject *self, PyObject *args, PyObject *kwargs)
-{
-    char *data = NULL;
-    NSMapObject *nsm = NULL;
-
-    static char *kwlist[] = {"data", "nsm", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords (
-            args, kwargs, "|sO", kwlist, &data, &nsm))
-        return -1;
-
-    if (nsm && !PyObject_TypeCheck (nsm, &NSMapType)) {
-        PyErr_SetString (PyExc_TypeError, "nsm is not a NSMap type.");
-        return -1;
-    }
-
-    self->ob_struct = LSUP_iriref_new (
-            data, (nsm ? nsm->ob_struct : NULL));
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create term.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-Term_literal_init (TermObject *self, PyObject *args, PyObject *kwargs)
-{
-    char *data = NULL, *datatype = NULL, *lang = NULL;
-
-    static char *kwlist[] = {"", "datatype", "lang", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords (
-            args, kwargs, "s|zz", kwlist, &data, &datatype, &lang))
-        return -1;
-
-    if (lang)
-        self->ob_struct = LSUP_lt_literal_new (data, lang);
-    else {
-        LSUP_Term *dtype = (datatype) ? LSUP_iriref_new (datatype, NULL) : NULL;
-        self->ob_struct = LSUP_literal_new (data, dtype);
-    }
-
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create term.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-Term_bnode_init (TermObject *self, PyObject *args, PyObject *kwargs)
-{
-    char *data;
-    static char *kwlist[] = {"data", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|s", kwlist, &data))
-        return -1;
-
-    self->ob_struct = LSUP_term_new (LSUP_TERM_BNODE, data, NULL);
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create term.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static void
-Term_dealloc (TermObject *self)
-{
-    LSUP_term_free (self->ob_struct);
-    Py_TYPE (self)->tp_free ((PyObject *) self);
-}
-
-
-static PyObject *
-Term_get_type (TermObject *self, void *closure)
-{
-    return PyLong_FromLong (self->ob_struct->type);
-}
-
-
-static PyObject *
-Term_get_data (TermObject *self, void *closure)
-{ return PyUnicode_FromString (self->ob_struct->data); }
-
-
-static PyObject *
-Term_iriref_get_nsm (TermObject *self, void *closure)
-{
-    LSUP_Term *term = self->ob_struct;
-    if (!LSUP_IS_IRI(term))
-        Py_RETURN_NONE;
-
-    LSUP_NSMap *nsm = LSUP_iriref_nsm (term);
-    if (!nsm) Py_RETURN_NONE;
-
-    NSMapObject *nsm_obj = PyObject_New (NSMapObject, &NSMapType);
-    if (UNLIKELY (!nsm_obj)) return PyErr_NoMemory();
-
-    nsm_obj->ob_struct = nsm;
-
-    Py_INCREF (nsm_obj);
-    return (PyObject *) nsm_obj;
-}
-
-
-static PyObject *
-Term_iriref_get_prefix (TermObject *self, void *closure)
-{
-    LSUP_Term *term = self->ob_struct;
-    if (! LSUP_IS_IRI (term))
-        Py_RETURN_NONE;
-
-    return PyUnicode_FromString (LSUP_iriref_prefix (term));
-}
-
-
-static PyObject *
-Term_iriref_get_path (TermObject *self, void *closure)
-{
-    LSUP_Term *term = self->ob_struct;
-    if (! LSUP_IS_IRI (term))
-        Py_RETURN_NONE;
-
-    return PyUnicode_FromString (LSUP_iriref_path (term));
-}
-
-
-static PyObject *
-Term_iriref_get_frag (TermObject *self, void *closure)
-{
-    LSUP_Term *term = self->ob_struct;
-    if (! LSUP_IS_IRI (term))
-        Py_RETURN_NONE;
-
-    return PyUnicode_FromString (LSUP_iriref_frag (term));
-}
-
-
-static PyObject *
-Term_lit_get_datatype (TermObject *self, void *closure)
-{
-    if (!self->ob_struct->datatype) Py_RETURN_NONE;
-
-    char *dtype_data =
-        self->ob_struct->type == LSUP_TERM_LT_LITERAL ? DEFAULT_DTYPE :
-        self->ob_struct->datatype->data;
-
-    TermObject *datatype = (TermObject *) Py_TYPE (self)->tp_alloc (
-            Py_TYPE (self), 0);
-    if (!datatype) return PyErr_NoMemory();
-
-    datatype->ob_struct = LSUP_iriref_new (dtype_data, NULL);
-
-    Py_INCREF (datatype);
-    return (PyObject *) datatype;
-}
-
-
-static PyObject *
-Term_lit_get_lang (TermObject *self, void *closure)
-{
-    if (
-            self->ob_struct->type != LSUP_TERM_LT_LITERAL
-            || self->ob_struct->lang[0] == '\0')
-        Py_RETURN_NONE;
-
-    return PyUnicode_FromString (self->ob_struct->lang);
-}
-
-
-static PyGetSetDef Term_getsetters[] = {
-    {"_type", (getter) Term_get_type, NULL, "Term type.", NULL},
-    {"_data", (getter) Term_get_data, NULL, "Term data.", NULL},
-    {
-        "_nsm", (getter) Term_iriref_get_nsm,
-        NULL, "IRI ref namespace map.", NULL
-    },
-    {
-        "_prefix", (getter) Term_iriref_get_prefix,
-        NULL, "IRI ref prefix.", NULL
-    },
-    {
-        "_path", (getter) Term_iriref_get_path,
-        NULL, "IRI ref path after prefix.", NULL
-    },
-    {
-        "_frag", (getter) Term_iriref_get_frag,
-        NULL, "IRI ref fragment.", NULL
-    },
-    {
-        "_datatype", (getter) Term_lit_get_datatype,
-        NULL, "Literal term data type.", NULL
-    },
-    {
-        "_lang", (getter) Term_lit_get_lang,
-        NULL, "Literal term language tag.", NULL
-    },
-    {NULL}
-};
-
-
-static PyGetSetDef IRIRef_getsetters[] = {
-    {"data", (getter) Term_get_data, NULL, "IRI string.", NULL},
-    {
-        "nsm", (getter) Term_iriref_get_nsm,
-        NULL, "Namespace map.", NULL
-    },
-    {
-        "prefix", (getter) Term_iriref_get_prefix,
-        NULL, "IRI ref prefix.", NULL
-    },
-    {
-        "path", (getter) Term_iriref_get_path,
-        NULL, "IRI ref path after prefix.", NULL
-    },
-    {
-        "frag", (getter) Term_iriref_get_frag,
-        NULL, "IRI ref fragment.", NULL
-    },
-    {NULL}
-};
-
-
-static PyGetSetDef Literal_getsetters[] = {
-    {"data", (getter) Term_get_data, NULL, "Literal data.", NULL},
-    {
-        "datatype", (getter) Term_lit_get_datatype,
-        NULL, "Data type.", NULL
-    },
-    {
-        "lang", (getter) Term_lit_get_lang,
-        NULL, "Language tag.", NULL
-    },
-    {NULL}
-};
-
-
-static PyGetSetDef BNode_getsetters[] = {
-    {"data", (getter) Term_get_data, NULL, "Blank node label.", NULL},
-    {NULL}
-};
-
-
-static PyObject *
-Term_repr (PyObject *self)
-{
-    TermObject *term_obj = (TermObject *)self;
-    LSUP_Term *term = term_obj->ob_struct;
-    char *term_repr_ptn = "<%s @%p> '%s'";
-    char *term_nt = NULL;
-    if (UNLIKELY (nt_codec.encode_term (term, NULL, &term_nt) != LSUP_OK)) {
-        free (term_nt);
-        PyErr_SetString (PyExc_ValueError, "Error serializing term.");
-        return NULL;
-    }
-
-    char *term_repr = malloc (
-            strlen (term_repr_ptn) +
-            strlen (term_nt) +
-            strlen (self->ob_type->tp_name) + 32); // 32 for ptr addr + NUL
-    if (UNLIKELY (!term_repr)) return PyErr_NoMemory();
-    sprintf (
-            term_repr, term_repr_ptn,
-            self->ob_type->tp_name, term_obj, term_nt);
-    free (term_nt);
-
-    PyObject *result = PyUnicode_FromString (term_repr);
-    free (term_repr);
-    if (UNLIKELY (!result)) return PyErr_NoMemory();
-
-    Py_INCREF (result);
-    return result;
-}
-
-
-static PyObject *
-Term_str (PyObject *self)
-{
-    TermObject *term_obj = (TermObject *)self;
-    LSUP_Term *term = term_obj->ob_struct;
-
-    PyObject *result = PyUnicode_FromString (term->data);
-    if (UNLIKELY (!result)) return PyErr_NoMemory();
-
-    Py_INCREF (result);
-    return result;
-}
-
-
-static PyObject *
-Term_richcmp (PyObject *obj1, PyObject *obj2, int op);
-
-
-static Py_hash_t
-Term_hash (PyObject *self)
-{ return LSUP_term_hash (((TermObject *)self)->ob_struct); }
-
-
-PyTypeObject TermType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name = "term.Term",
-    .tp_doc = "RDF term",
-    .tp_basicsize = sizeof (TermObject),
-    .tp_itemsize = 0,
-    .tp_flags = Py_TPFLAGS_DEFAULT,
-    .tp_new = PyType_GenericNew,
-    .tp_init = (initproc) Term_init,
-    .tp_dealloc = (destructor) Term_dealloc,
-    .tp_repr = Term_repr,
-    .tp_str = Term_str,
-    .tp_getset = Term_getsetters,
-    .tp_richcompare = Term_richcmp,
-    .tp_hash = Term_hash,
-};
-
-
-PyTypeObject IRIRefType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name = "term.IRIRef",
-    .tp_doc = "RDF IRI reference.",
-    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    .tp_base = &TermType,
-    .tp_init = (initproc) Term_iriref_init,
-    .tp_getset = IRIRef_getsetters,
-};
-
-
-PyTypeObject LiteralType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name = "term.Literal",
-    .tp_doc = "RDF Literal.",
-    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    .tp_base = &TermType,
-    .tp_init = (initproc) Term_literal_init,
-    .tp_getset = Literal_getsetters,
-};
-
-
-PyTypeObject BNodeType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name = "term.BNode",
-    .tp_doc = "RDF Blanbk Node.",
-    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    .tp_base = &TermType,
-    .tp_init = (initproc) Term_bnode_init,
-    .tp_getset = BNode_getsetters,
-};
-
-
-static PyObject *
-Term_richcmp (PyObject *obj1, PyObject *obj2, int op)
-{
-    PyObject *result = NULL;
-
-    if (
-        ! PyObject_TypeCheck (obj1, &TermType) ||
-        ! PyObject_TypeCheck (obj2, &TermType)
-    ) return NULL;
-
-    int c = 0;
-    LSUP_Term *t1 = ((TermObject *) obj1)->ob_struct;
-    LSUP_Term *t2 = ((TermObject *) obj2)->ob_struct;
-
-    switch (op) {
-        case Py_LT: result = Py_NotImplemented; break;
-        case Py_LE: result = Py_NotImplemented; break;
-        case Py_EQ: c = LSUP_term_equals (t1, t2); break;
-        case Py_NE: c = ! LSUP_term_equals (t1, t2); break;
-        case Py_GT: result = Py_NotImplemented; break;
-        case Py_GE: result = Py_NotImplemented; break;
-    }
-
-    if (!result) result = c ? Py_True : Py_False;
-
-    Py_INCREF(result);
-    return result;
- }
-
-
-PyObject *
-build_term (LSUP_Term *t)
-{
-    LOG_TRACE("Building term: %s", t->data);
-    PyTypeObject *term_obj_type;
-    PyObject *term_args;
-    switch (t->type) {
-        case LSUP_TERM_IRIREF:
-            term_obj_type = &IRIRefType;
-            term_args = Py_BuildValue ("(s)", t->data);
-            break;
-        case LSUP_TERM_NS_IRIREF:
-            term_obj_type = &IRIRefType;
-            term_args = Py_BuildValue ("sO", t->data, LSUP_iriref_nsm (t));
-            break;
-        case LSUP_TERM_BNODE:
-            term_obj_type = &BNodeType;
-            term_args = Py_BuildValue ("(s)", t->data);
-            break;
-        case LSUP_TERM_LITERAL:
-            term_obj_type = &LiteralType;
-            term_args = Py_BuildValue ("sz", t->data, t->datatype->data, NULL);
-            break;
-        case LSUP_TERM_LT_LITERAL:
-            term_obj_type = &LiteralType;
-            term_args = Py_BuildValue ("sz", t->data, NULL, t->lang);
-            break;
-        default:
-            return NULL;
-    }
-    if (UNLIKELY (!term_args)) return NULL;
-    PyObject *t_obj = PyObject_CallObject (
-            (PyObject *)term_obj_type, term_args);
-    Py_DECREF (term_args);
-    if (UNLIKELY (!t_obj)) return NULL;
-
-    return t_obj;
-}
-
-// END _PY_TERM_OBJ_H
-#endif

+ 0 - 144
cpython/py_triple.h

@@ -1,144 +0,0 @@
-#ifndef _PY_TRIPLE_OBJ_H
-#define _PY_TRIPLE_OBJ_H
-
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-#include <structmember.h>
-
-#include "py_term.h"
-
-
-typedef struct {
-    PyObject_HEAD
-    LSUP_Triple * ob_struct;
-    PyObject *s;
-    PyObject *p;
-    PyObject *o;
-} TripleObject;
-
-
-static int
-Triple_init (TripleObject *self, PyObject *args)
-{
-    PyObject *s = NULL, *p = NULL, *o = NULL, *tmp;
-
-    if (! PyArg_ParseTuple (args, "OOO", &s, &p, &o)) return -1;
-
-    // TODO check for null s, p, o
-    tmp = self->s;
-    Py_INCREF(s);
-    self->s = s;
-    Py_XDECREF(tmp);
-
-    tmp = self->p;
-    Py_INCREF(p);
-    self->p = p;
-    Py_XDECREF(tmp);
-
-    tmp = self->o;
-    Py_INCREF(o);
-    self->o = o;
-    Py_XDECREF(tmp);
-
-    self->ob_struct = LSUP_triple_new (
-            ((TermObject *) self->s)->ob_struct,
-            ((TermObject *) self->p)->ob_struct,
-            ((TermObject *) self->o)->ob_struct);
-    if (!self->ob_struct) {
-        PyErr_SetString (PyExc_ValueError, "Could not create triple.");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static void
-Triple_dealloc (TripleObject *self)
-{
-    Py_XDECREF(self->s);
-    Py_XDECREF(self->p);
-    Py_XDECREF(self->o);
-    free (self->ob_struct); // Term pointers were allocated independently.
-    Py_TYPE (self)->tp_free ((PyObject *) self);
-}
-
-
-static PyMemberDef Triple_members[] = {
-    {"s", T_OBJECT_EX, offsetof(TripleObject, s), 0, "Triple subject."},
-    {"p", T_OBJECT_EX, offsetof(TripleObject, p), 0, "Triple predicate."},
-    {"o", T_OBJECT_EX, offsetof(TripleObject, o), 0, "Triple object."},
-    {NULL}
-};
-
-
-static PyObject *
-Triple_richcmp (PyObject *obj1, PyObject *obj2, int op)
-{
-    // Only equality and non-equality supported.
-    if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED;
-
-    LSUP_Triple *t1 = ((TripleObject *) obj1)->ob_struct;
-    LSUP_Triple *t2 = ((TripleObject *) obj2)->ob_struct;
-
-    if (
-        (
-            LSUP_term_equals (t1->s, t2->s) &&
-            LSUP_term_equals (t1->p, t2->p) &&
-            LSUP_term_equals (t1->o, t2->o)
-        ) ^ (op == Py_NE)
-    ) Py_RETURN_TRUE;
-
-    Py_RETURN_FALSE;
-}
-
-
-static Py_hash_t
-Triple_hash (PyObject *self)
-{ return LSUP_triple_hash (((TripleObject *)self)->ob_struct); }
-
-
-PyTypeObject TripleType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    .tp_name = "triple.Triple",
-    .tp_doc = "RDF triple.",
-    .tp_basicsize = sizeof(TripleObject),
-    .tp_itemsize = 0,
-    .tp_flags = Py_TPFLAGS_DEFAULT,
-    .tp_new = PyType_GenericNew,
-    .tp_init = (initproc) Triple_init,
-    .tp_dealloc = (destructor) Triple_dealloc,
-    .tp_members = Triple_members,
-    .tp_richcompare = Triple_richcmp,
-    .tp_hash = Triple_hash,
-};
-
-
-/** @brief Build a triple object from a LSUP_Triple struct.
- */
-PyObject *
-build_triple (LSUP_Triple *spo)
-{
-    PyObject
-        *s_obj = build_term (spo->s),
-        *p_obj = build_term (spo->p),
-        *o_obj = build_term (spo->o);
-
-    LOG_TRACE("Building triple.");
-    PyObject *trp_args = Py_BuildValue ("OOO", s_obj, p_obj, o_obj);
-    if (UNLIKELY (!trp_args)) {
-        PyErr_SetString (PyExc_SystemError, "Error building triple args.");
-        return NULL;
-    }
-    PyObject *spo_obj = PyObject_CallObject ((PyObject *)&TripleType, trp_args);
-    Py_DECREF (trp_args);
-    if (UNLIKELY (!spo_obj)) {
-        PyErr_SetString (PyExc_SystemError, "Error building triple object.");
-        return NULL;
-    }
-
-    return spo_obj;
-}
-
-#endif

+ 0 - 3
pyproject.toml

@@ -1,3 +0,0 @@
-[build-system]
-requires = ["setuptools>=75"]
-build-backend = "setuptools.build_meta"

+ 0 - 125
setup.py

@@ -1,125 +0,0 @@
-from glob import glob
-from os import environ
-from setuptools import Extension, find_packages, setup
-from setuptools.command.install import install
-from subprocess import check_output
-
-
-ROOT_DIR = "."
-SRC_DIR = f"{ROOT_DIR}/src"
-CODEC_DIR = f"{SRC_DIR}/codec"
-CPY_DIR = f"{ROOT_DIR}/cpython"
-INCL_DIR = f"{ROOT_DIR}/include"
-EXT_DIR = f"{ROOT_DIR}/ext"
-
-LEXER = "re2c"
-PARSER = "lemon"
-
-
-sources = (
-    glob(f"{SRC_DIR}/*.c") +
-    glob(f"{CODEC_DIR}/grammar_*.c") +
-    glob(f"{CODEC_DIR}/parser_*.c") +
-    glob(f"{CODEC_DIR}/codec_*.c") +
-    glob(f"{CPY_DIR}/*.c") +
-    [
-        f"{EXT_DIR}/hashmap/hashmap.c",
-        f"{EXT_DIR}/tpl/src/tpl.c",
-        f"{EXT_DIR}/log/src/log.c",
-    ]
-)
-
-include_dirs = [
-    # ROOT_DIR,
-    INCL_DIR,
-    f"{INCL_DIR}/codec",
-    CPY_DIR,
-    f"{EXT_DIR}/hashmap",
-    f"{EXT_DIR}/tpl/src",
-    f"{EXT_DIR}/log/src",
-]
-
-debug = bool(environ.get("DEBUG"))
-
-compile_args = [
-    "-std=gnu11",
-    "-Wall",
-    # "-Wextra",
-    "-fPIC",
-    "-MMD",
-]
-if debug:
-    print("Compiling with debug flags.")
-    compile_args.extend([
-        "-UNDEBUG", "-DDEBUG", "-D_FORTIFY_SOURCE=0", "-g3", "-O0"
-    ])
-else:
-    compile_args.extend(["-g0", "-O3"])
-
-# with open(path.join(ROOT_DIR, "README.md"), "r") as fh:
-#     long_description = fh.read()
-
-
-class LSUPInstallCmd(install):
-    """
-    Run LSUP-specific hooks in extension build phase.
-
-    TODO Extending the Extension class may be best to narrow the scope to the
-    C module.
-    """
-
-    def run(self):
-        print("Generating parsers.")
-        target = "codec_dbg" if debug else "codec"
-        print(f"Making {target}.")
-        check_output(["make", target])
-
-        install.run(self)
-
-
-setup(
-    name="lsup_rdf",
-    version="1.0a5",
-    description="Ultra-compact RDF library.",
-    # long_description=long_description,
-    # long_description_content_type="text/markdown",
-    author="Stefano Cossu <https://git.knowledgetx.com/scossu>",
-    url="https://git.knowledgetx.com/scossu/lsup_rdf",
-    license="https://git.knowledgetx.com/scossu/lsup_rdf/src/master/LICENSE",
-    package_dir={"lsup_rdf": "cpython/lsup_rdf"},
-    packages=find_packages(where="cpython"),
-    include_package_data=True,
-    # cmdclass={"install": LSUPInstallCmd},
-    classifiers=[
-        "Development Status :: 3 - Alpha",
-        "Environment :: Console",
-        "Intended Audience :: Developers",
-        "Intended Audience :: Information Technology",
-        "Intended Audience :: Science/Research",
-        "Intended Audience :: Telecommunications Industry",
-        "License :: CC-PDDC",
-        "Natural Language :: English",
-        "Operating System :: POSIX :: BSD",
-        "Operating System :: POSIX :: Linux",
-        "Operating System :: POSIX :: Other",
-        "Programming Language :: C",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: Implementation :: CPython",
-        "Topic :: Database :: Database Engines/Servers",
-        "Topic :: Internet",
-        "Topic :: Scientific/Engineering",
-        "Topic :: Software Development :: Embedded Systems",
-        "Topic :: Software Development :: Libraries",
-    ],
-    ext_modules=[
-        Extension(
-            "_lsup_rdf",
-            sources,
-            language="c",
-            include_dirs=include_dirs,
-            libraries=["xxhash", "lmdb", "uuid"],
-            extra_compile_args=compile_args,
-        ),
-    ],
-    python_requires=">=3.8",
-)

+ 0 - 499
valgrind-python.supp

@@ -1,499 +0,0 @@
-#
-# This is a valgrind suppression file that should be used when using valgrind.
-#
-#  Here's an example of running valgrind:
-#
-#	cd python/dist/src
-#	valgrind --tool=memcheck --suppressions=Misc/valgrind-python.supp \
-#		./python -E ./Lib/test/regrtest.py -u gui,network
-#
-# You must edit Objects/obmalloc.c and uncomment Py_USING_MEMORY_DEBUGGER
-# to use the preferred suppressions with address_in_range.
-#
-# If you do not want to recompile Python, you can uncomment
-# suppressions for _PyObject_Free and _PyObject_Realloc.
-#
-# See Misc/README.valgrind for more information.
-
-# all tool names: Addrcheck,Memcheck,cachegrind,helgrind,massif
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Addr4
-   fun:address_in_range
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Value4
-   fun:address_in_range
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64)
-   Memcheck:Value8
-   fun:address_in_range
-}
-
-{
-   ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
-   Memcheck:Cond
-   fun:address_in_range
-}
-
-#
-# Leaks (including possible leaks)
-#    Hmmm, I wonder if this masks some real leaks.  I think it does.
-#    Will need to fix that.
-#
-
-{
-   Suppress leaking the GIL.  Happens once per process, see comment in ceval.c.
-   Memcheck:Leak
-   fun:malloc
-   fun:PyThread_allocate_lock
-   fun:PyEval_InitThreads
-}
-
-{
-   Suppress leaking the GIL after a fork.
-   Memcheck:Leak
-   fun:malloc
-   fun:PyThread_allocate_lock
-   fun:PyEval_ReInitThreads
-}
-
-{
-   Suppress leaking the autoTLSkey.  This looks like it shouldn't leak though.
-   Memcheck:Leak
-   fun:malloc
-   fun:PyThread_create_key
-   fun:_PyGILState_Init
-   fun:Py_InitializeEx
-   fun:Py_Main
-}
-
-{
-   Hmmm, is this a real leak or like the GIL?
-   Memcheck:Leak
-   fun:malloc
-   fun:PyThread_ReInitTLS
-}
-
-{
-   Handle PyMalloc confusing valgrind (possibly leaked)
-   Memcheck:Leak
-   fun:realloc
-   fun:_PyObject_GC_Resize
-   fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
-}
-
-{
-   Handle PyMalloc confusing valgrind (possibly leaked)
-   Memcheck:Leak
-   fun:malloc
-   fun:_PyObject_GC_New
-   fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
-}
-
-{
-   Handle PyMalloc confusing valgrind (possibly leaked)
-   Memcheck:Leak
-   fun:malloc
-   fun:_PyObject_GC_NewVar
-   fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
-}
-
-#
-# Non-python specific leaks
-#
-
-{
-   Handle pthread issue (possibly leaked)
-   Memcheck:Leak
-   fun:calloc
-   fun:allocate_dtv
-   fun:_dl_allocate_tls_storage
-   fun:_dl_allocate_tls
-}
-
-{
-   Handle pthread issue (possibly leaked)
-   Memcheck:Leak
-   fun:memalign
-   fun:_dl_allocate_tls_storage
-   fun:_dl_allocate_tls
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Addr4
-   fun:_PyObject_Free
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Value4
-   fun:_PyObject_Free
-}
-
-{
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
-   Memcheck:Addr8
-   fun:_PyObject_Free
-}
-
-{
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
-   Memcheck:Value8
-   fun:_PyObject_Free
-}
-
-{
-   ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
-   Memcheck:Cond
-   fun:_PyObject_Free
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Addr4
-   fun:_PyObject_Realloc
-}
-
-{
-   ADDRESS_IN_RANGE/Invalid read of size 4
-   Memcheck:Value4
-   fun:_PyObject_Realloc
-}
-
-{
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
-   Memcheck:Addr8
-   fun:_PyObject_Realloc
-}
-
-{
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
-   Memcheck:Value8
-   fun:_PyObject_Realloc
-}
-
-{
-   ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
-   Memcheck:Cond
-   fun:_PyObject_Realloc
-}
-
-###
-### All the suppressions below are for errors that occur within libraries
-### that Python uses.  The problems to not appear to be related to Python's
-### use of the libraries.
-###
-
-{
-   Generic ubuntu ld problems
-   Memcheck:Addr8
-   obj:/lib/ld-2.4.so
-   obj:/lib/ld-2.4.so
-   obj:/lib/ld-2.4.so
-   obj:/lib/ld-2.4.so
-}
-
-{
-   Generic gentoo ld problems
-   Memcheck:Cond
-   obj:/lib/ld-2.3.4.so
-   obj:/lib/ld-2.3.4.so
-   obj:/lib/ld-2.3.4.so
-   obj:/lib/ld-2.3.4.so
-}
-
-{
-   DBM problems, see test_dbm
-   Memcheck:Param
-   write(buf)
-   fun:write
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   fun:dbm_close
-}
-
-{
-   DBM problems, see test_dbm
-   Memcheck:Value8
-   fun:memmove
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   fun:dbm_store
-   fun:dbm_ass_sub
-}
-
-{
-   DBM problems, see test_dbm
-   Memcheck:Cond
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   fun:dbm_store
-   fun:dbm_ass_sub
-}
-
-{
-   DBM problems, see test_dbm
-   Memcheck:Cond
-   fun:memmove
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   obj:/usr/lib/libdb1.so.2
-   fun:dbm_store
-   fun:dbm_ass_sub
-}
-
-{
-   GDBM problems, see test_gdbm
-   Memcheck:Param
-   write(buf)
-   fun:write
-   fun:gdbm_open
-
-}
-
-{
-   Uninitialised byte(s) false alarm, see bpo-35561
-   Memcheck:Param
-   epoll_ctl(event)
-   fun:epoll_ctl
-   fun:pyepoll_internal_ctl
-}
-
-{
-   ZLIB problems, see test_gzip
-   Memcheck:Cond
-   obj:/lib/libz.so.1.2.3
-   obj:/lib/libz.so.1.2.3
-   fun:deflate
-}
-
-{
-   Avoid problems w/readline doing a putenv and leaking on exit
-   Memcheck:Leak
-   fun:malloc
-   fun:xmalloc
-   fun:sh_set_lines_and_columns
-   fun:_rl_get_screen_size
-   fun:_rl_init_terminal_io
-   obj:/lib/libreadline.so.4.3
-   fun:rl_initialize
-}
-
-# Valgrind emits "Conditional jump or move depends on uninitialised value(s)"
-# false alarms on GCC builtin strcmp() function. The GCC code is correct.
-#
-# Valgrind bug: https://bugs.kde.org/show_bug.cgi?id=264936
-{
-   bpo-38118: Valgrind emits false alarm on GCC builtin strcmp()
-   Memcheck:Cond
-   fun:PyUnicode_Decode
-}
-
-
-###
-### These occur from somewhere within the SSL, when running
-###  test_socket_sll.  They are too general to leave on by default.
-###
-###{
-###   somewhere in SSL stuff
-###   Memcheck:Cond
-###   fun:memset
-###}
-###{
-###   somewhere in SSL stuff
-###   Memcheck:Value4
-###   fun:memset
-###}
-###
-###{
-###   somewhere in SSL stuff
-###   Memcheck:Cond
-###   fun:MD5_Update
-###}
-###
-###{
-###   somewhere in SSL stuff
-###   Memcheck:Value4
-###   fun:MD5_Update
-###}
-
-# Fedora's package "openssl-1.0.1-0.1.beta2.fc17.x86_64" on x86_64
-# See http://bugs.python.org/issue14171
-{
-   openssl 1.0.1 prng 1
-   Memcheck:Cond
-   fun:bcmp
-   fun:fips_get_entropy
-   fun:FIPS_drbg_instantiate
-   fun:RAND_init_fips
-   fun:OPENSSL_init_library
-   fun:SSL_library_init
-   fun:init_hashlib
-}
-
-{
-   openssl 1.0.1 prng 2
-   Memcheck:Cond
-   fun:fips_get_entropy
-   fun:FIPS_drbg_instantiate
-   fun:RAND_init_fips
-   fun:OPENSSL_init_library
-   fun:SSL_library_init
-   fun:init_hashlib
-}
-
-{
-   openssl 1.0.1 prng 3
-   Memcheck:Value8
-   fun:_x86_64_AES_encrypt_compact
-   fun:AES_encrypt
-}
-
-#
-# All of these problems come from using test_socket_ssl
-#
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:BN_bin2bn
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:BN_num_bits_word
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   fun:BN_num_bits_word
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:BN_mod_exp_mont_word
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:BN_mod_exp_mont
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Param
-   write(buf)
-   fun:write
-   obj:/usr/lib/libcrypto.so.0.9.7
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:RSA_verify
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   fun:RSA_verify
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   fun:DES_set_key_unchecked
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   fun:DES_encrypt2
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   obj:/usr/lib/libssl.so.0.9.7
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   obj:/usr/lib/libssl.so.0.9.7
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:BUF_MEM_grow_clean
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:memcpy
-   fun:ssl3_read_bytes
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Cond
-   fun:SHA1_Update
-}
-
-{
-   from test_socket_ssl
-   Memcheck:Value4
-   fun:SHA1_Update
-}
-
-{
-   test_buffer_non_debug
-   Memcheck:Addr4
-   fun:PyUnicodeUCS2_FSConverter
-}
-
-{
-   test_buffer_non_debug
-   Memcheck:Addr4
-   fun:PyUnicode_FSConverter
-}
-
-{
-   wcscmp_false_positive
-   Memcheck:Addr8
-   fun:wcscmp
-   fun:_PyOS_GetOpt
-   fun:Py_Main
-   fun:main
-}
-
-# Additional suppressions for the unified decimal tests:
-{
-   test_decimal
-   Memcheck:Addr4
-   fun:PyUnicodeUCS2_FSConverter
-}
-
-{
-   test_decimal2
-   Memcheck:Addr4
-   fun:PyUnicode_FSConverter
-}
-