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."
 		"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.
 # 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.
 depgraph: $(LSUP_SRC) $(CODEC_SRC) include/* include/codec/* ## Build a visual dependency graph of the code.
 	cinclude2dot --merge=module --include=$(DEPS) \
 	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
 ## Purpose
 
 
 The goal of this library is to provide efficient and compact handling of RDF
 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
 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
 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
 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.
 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
 ## Development Status
 
 
 **Alpha.** Considered feature-complete from an MVP standpoint. The API may
 **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
 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.
 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
 Run `doxygen` (see [Doxygen](https://www.doxygen.nl/index.html)) to generate
 HTML documentation in `docs/html`.
 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
-}
-