git » nmdb » commit ffe4fc4

bindings/python: Unify Python 2 and 3 bindings

author Alberto Bertogli
2010-04-26 18:22:50 UTC
committer Alberto Bertogli
2010-04-26 19:04:54 UTC
parent 69ac3b2861a62b2448cd98f2238ebb4b447cd574

bindings/python: Unify Python 2 and 3 bindings

The differences among both bindings are really not worth the trouble of
having the two versions apart.

This patch unifies both into a single binding, that can be built and
installed using either version.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

.gitignore +0 -1
LICENSE +0 -1
Makefile +3 -3
bindings/python/nmdb.py +2 -2
bindings/python/nmdb_ll.c +91 -36
bindings/python/setup.py +9 -1
bindings/python3/LICENSE +0 -30
bindings/python3/nmdb.py +0 -252
bindings/python3/nmdb_ll.c +0 -452
bindings/python3/setup.py +0 -17

diff --git a/.gitignore b/.gitignore
index ee35c58..1ce400d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,7 +20,6 @@ gmon.out
 /libnmdb/doxygen/Doxyfile.base
 /tags
 /bindings/python/build
-/bindings/python3/build
 /tests/perf/out
 /tests/perf/ag-data
 /tests/perf/graph
diff --git a/LICENSE b/LICENSE
index b857b79..0c8c297 100644
--- a/LICENSE
+++ b/LICENSE
@@ -15,7 +15,6 @@ As a brief resume, here's how each sub-project is licensed:
  * bindings/haskell: BOLA (Public domain)
  * bindings/newlisp: BOLA (Public domain)
  * bindings/python: BOLA (Public domain)
- * bindings/python3: BOLA (Public domain)
  * bindings/ruby: BOLA (Public domain)
 
 
diff --git a/Makefile b/Makefile
index 5ef8582..7c61c5e 100644
--- a/Makefile
+++ b/Makefile
@@ -33,13 +33,13 @@ python_clean:
 	cd bindings/python && rm -rf build/
 
 python3:
-	cd bindings/python3 && python3 setup.py build
+	cd bindings/python && python3 setup.py build
 
 python3_install:
-	cd bindings/python3 && python3 setup.py install
+	cd bindings/python && python3 setup.py install
 
 python3_clean:
-	cd bindings/python3 && rm -rf build/
+	cd bindings/python && rm -rf build/
 
 
 .PHONY: default all clean nmdb libnmdb utils \
diff --git a/bindings/python/nmdb.py b/bindings/python/nmdb.py
index b5b73c4..fbad7a9 100644
--- a/bindings/python/nmdb.py
+++ b/bindings/python/nmdb.py
@@ -183,8 +183,8 @@ class GenericDB (object):
 		elif r == 1:
 			# no match, because the value didn't have the right
 			# format
-			raise TypeError, \
-				"The value must be a NULL-terminated string"
+			raise TypeError(
+				"The value must be a NULL-terminated string")
 		elif r == 0:
 			# not in
 			raise KeyError
diff --git a/bindings/python/nmdb_ll.c b/bindings/python/nmdb_ll.c
index 9b51bbb..6c329a3 100644
--- a/bindings/python/nmdb_ll.c
+++ b/bindings/python/nmdb_ll.c
@@ -1,12 +1,14 @@
 
 /*
- * Python bindings for libnmdb
+ * Python 2 and 3 bindings for libnmdb
  * Alberto Bertogli (albertito@blitiri.com.ar)
  *
  * This is the low-level module, used by the python one to construct
  * friendlier objects.
  */
 
+#define PY_SSIZE_T_CLEAN 1
+
 #include <Python.h>
 #include <nmdb.h>
 
@@ -19,7 +21,6 @@ typedef struct {
 	PyObject_HEAD;
 	nmdb_t *db;
 } nmdbobject;
-static PyTypeObject nmdbType;
 
 /*
  * The nmdb object
@@ -92,7 +93,7 @@ static PyObject *db_add_udp_server(nmdbobject *db, PyObject *args)
 static PyObject *db_cache_set(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *val;
-	int ksize, vsize;
+	size_t ksize, vsize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#s#:cache_set", &key, &ksize,
@@ -111,8 +112,8 @@ static PyObject *db_cache_set(nmdbobject *db, PyObject *args)
 static PyObject *db_cache_get(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *val;
-	int ksize, vsize;
-	long rv;
+	size_t ksize, vsize;
+	ssize_t rv;
 	PyObject *r;
 
 	if (!PyArg_ParseTuple(args, "s#:cache_get", &key, &ksize)) {
@@ -136,7 +137,11 @@ static PyObject *db_cache_get(nmdbobject *db, PyObject *args)
 		/* Miss, handled in the high-level module. */
 		r = PyLong_FromLong(-1);
 	} else {
+#ifdef PYTHON3
+		r = PyBytes_FromStringAndSize((char *) val, rv);
+#elif PYTHON2
 		r = PyString_FromStringAndSize((char *) val, rv);
+#endif
 	}
 
 	free(val);
@@ -147,7 +152,7 @@ static PyObject *db_cache_get(nmdbobject *db, PyObject *args)
 static PyObject *db_cache_delete(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
+	size_t ksize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#:cache_delete", &key, &ksize)) {
@@ -165,7 +170,7 @@ static PyObject *db_cache_delete(nmdbobject *db, PyObject *args)
 static PyObject *db_cache_cas(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *oldval, *newval;
-	int ksize, ovsize, nvsize;
+	size_t ksize, ovsize, nvsize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#s#s#:cache_cas", &key, &ksize,
@@ -186,7 +191,7 @@ static PyObject *db_cache_cas(nmdbobject *db, PyObject *args)
 static PyObject *db_cache_incr(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
+	size_t ksize;
 	int rv;
 	long long int increment;
 	int64_t newval;
@@ -200,7 +205,7 @@ static PyObject *db_cache_incr(nmdbobject *db, PyObject *args)
 	rv = nmdb_cache_incr(db->db, key, ksize, increment, &newval);
 	Py_END_ALLOW_THREADS
 
-	return Py_BuildValue("LL", rv, newval);
+	return Py_BuildValue("iL", rv, newval);
 }
 
 
@@ -208,7 +213,7 @@ static PyObject *db_cache_incr(nmdbobject *db, PyObject *args)
 static PyObject *db_set(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *val;
-	int ksize, vsize;
+	size_t ksize, vsize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#s#:set", &key, &ksize,
@@ -227,8 +232,8 @@ static PyObject *db_set(nmdbobject *db, PyObject *args)
 static PyObject *db_get(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *val;
-	int ksize, vsize;
-	long rv;
+	size_t ksize, vsize;
+	ssize_t rv;
 	PyObject *r;
 
 	if (!PyArg_ParseTuple(args, "s#:get", &key, &ksize)) {
@@ -252,7 +257,11 @@ static PyObject *db_get(nmdbobject *db, PyObject *args)
 		/* Miss, handled in the high-level module. */
 		r = PyLong_FromLong(-1);
 	} else {
+#ifdef PYTHON3
+		r = PyBytes_FromStringAndSize((char *) val, rv);
+#elif PYTHON2
 		r = PyString_FromStringAndSize((char *) val, rv);
+#endif
 	}
 
 	free(val);
@@ -263,7 +272,7 @@ static PyObject *db_get(nmdbobject *db, PyObject *args)
 static PyObject *db_delete(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
+	size_t ksize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#:delete", &key, &ksize)) {
@@ -281,7 +290,7 @@ static PyObject *db_delete(nmdbobject *db, PyObject *args)
 static PyObject *db_cas(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *oldval, *newval;
-	int ksize, ovsize, nvsize;
+	size_t ksize, ovsize, nvsize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#s#s#:cas", &key, &ksize,
@@ -301,7 +310,7 @@ static PyObject *db_cas(nmdbobject *db, PyObject *args)
 static PyObject *db_incr(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
+	size_t ksize;
 	int rv;
 	long long int increment;
 	int64_t newval;
@@ -322,7 +331,7 @@ static PyObject *db_incr(nmdbobject *db, PyObject *args)
 static PyObject *db_set_sync(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *val;
-	int ksize, vsize;
+	size_t ksize, vsize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#s#:set_sync", &key, &ksize,
@@ -341,7 +350,7 @@ static PyObject *db_set_sync(nmdbobject *db, PyObject *args)
 static PyObject *db_delete_sync(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
+	size_t ksize;
 	int rv;
 
 	if (!PyArg_ParseTuple(args, "s#:delete_sync", &key, &ksize)) {
@@ -359,8 +368,8 @@ static PyObject *db_delete_sync(nmdbobject *db, PyObject *args)
 static PyObject *db_firstkey(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key;
-	int ksize;
-	long rv;
+	size_t ksize;
+	ssize_t rv;
 	PyObject *r;
 
 	if (!PyArg_ParseTuple(args, "")) {
@@ -385,7 +394,11 @@ static PyObject *db_firstkey(nmdbobject *db, PyObject *args)
 		 * module. */
 		r = PyLong_FromLong(-1);
 	} else {
+#ifdef PYTHON3
+		r = PyBytes_FromStringAndSize((char *) key, rv);
+#elif PYTHON2
 		r = PyString_FromStringAndSize((char *) key, rv);
+#endif
 	}
 
 	free(key);
@@ -396,8 +409,8 @@ static PyObject *db_firstkey(nmdbobject *db, PyObject *args)
 static PyObject *db_nextkey(nmdbobject *db, PyObject *args)
 {
 	unsigned char *key, *newkey;
-	int ksize, nksize;
-	long rv;
+	size_t ksize, nksize;
+	ssize_t rv;
 	PyObject *r;
 
 	if (!PyArg_ParseTuple(args, "s#:nextkey", &key, &ksize)) {
@@ -421,7 +434,11 @@ static PyObject *db_nextkey(nmdbobject *db, PyObject *args)
 		/* End, handled in the high-level module. */
 		r = PyLong_FromLong(-1);
 	} else {
+#ifdef PYTHON3
+		r = PyBytes_FromStringAndSize((char *) newkey, rv);
+#elif PYTHON2
 		r = PyString_FromStringAndSize((char *) newkey, rv);
+#endif
 	}
 
 	free(newkey);
@@ -456,21 +473,6 @@ static PyMethodDef nmdb_methods[] = {
 	{ NULL }
 };
 
-static PyObject *db_getattr(nmdbobject *db, char *name)
-{
-	return Py_FindMethod(nmdb_methods, (PyObject *)db, name);
-}
-
-static PyTypeObject nmdbType = {
-	PyObject_HEAD_INIT(NULL)
-	0,
-	"nmdb_ll.nmdb",
-	sizeof(nmdbobject),
-	0,
-	(destructor) db_dealloc,
-	0,
-	(getattrfunc) db_getattr,
-};
 
 
 /*
@@ -478,11 +480,16 @@ static PyTypeObject nmdbType = {
  */
 
 /* new, returns an nmdb object */
+static PyTypeObject nmdbType;
 static PyObject *db_new(PyObject *self, PyObject *args)
 {
 	nmdbobject *db;
 
+#ifdef PYTHON3
+	db = (nmdbobject *) nmdbType.tp_alloc(&nmdbType, 0);
+#elif PYTHON2
 	db = PyObject_New(nmdbobject, &nmdbType);
+#endif
 	if (db == NULL)
 		return NULL;
 
@@ -509,6 +516,53 @@ static PyMethodDef nmdb_functions[] = {
 	{ NULL }
 };
 
+
+#ifdef PYTHON3
+static PyTypeObject nmdbType = {
+	PyObject_HEAD_INIT(NULL)
+	.tp_name = "nmdb_ll.nmdb",
+	.tp_itemsize = sizeof(nmdbobject),
+	.tp_dealloc = (destructor) db_dealloc,
+	.tp_methods = nmdb_methods,
+};
+
+static PyModuleDef nmdb_module = {
+	PyModuleDef_HEAD_INIT,
+	.m_name = "nmdb_ll",
+	.m_doc = NULL,
+	.m_size = -1,
+	.m_methods = nmdb_functions,
+};
+
+PyMODINIT_FUNC PyInit_nmdb_ll(void)
+{
+	PyObject *m;
+
+	if (PyType_Ready(&nmdbType) < 0)
+		return NULL;
+
+	m = PyModule_Create(&nmdb_module);
+
+	return m;
+}
+
+#elif PYTHON2
+static PyObject *db_getattr(nmdbobject *db, char *name)
+{
+	return Py_FindMethod(nmdb_methods, (PyObject *)db, name);
+}
+
+static PyTypeObject nmdbType = {
+	PyObject_HEAD_INIT(NULL)
+	0,
+	"nmdb_ll.nmdb",
+	sizeof(nmdbobject),
+	0,
+	(destructor) db_dealloc,
+	0,
+	(getattrfunc) db_getattr,
+};
+
 PyMODINIT_FUNC initnmdb_ll(void)
 {
 	PyObject *m;
@@ -518,5 +572,6 @@ PyMODINIT_FUNC initnmdb_ll(void)
 	m = Py_InitModule("nmdb_ll", nmdb_functions);
 }
 
+#endif
 
 
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index 54c1bcd..dce1df3 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -1,9 +1,17 @@
 
+import sys
 from distutils.core import setup, Extension
 
+if sys.version_info[0] == 2:
+	ver_define = ('PYTHON2', '1')
+elif sys.version_info[0] == 3:
+	ver_define = ('PYTHON3', '1')
+
+
 nmdb_ll = Extension("nmdb_ll",
 		libraries = ['nmdb'],
-		sources = ['nmdb_ll.c'])
+		sources = ['nmdb_ll.c'],
+		define_macros = [ver_define])
 
 setup(
 	name = 'nmdb',
diff --git a/bindings/python3/LICENSE b/bindings/python3/LICENSE
deleted file mode 100644
index 987d3b9..0000000
--- a/bindings/python3/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-
-I don't like licenses, because I don't like having to worry about all this
-legal stuff just for a simple piece of software I don't really mind anyone
-using. But I also believe that it's important that people share and give back;
-so I'm placing this work under the following license.
-
-
-BOLA - Buena Onda License Agreement (v1.1)
-------------------------------------------
-
-This work is provided 'as-is', without any express or implied warranty. In no
-event will the authors be held liable for any damages arising from the use of
-this work.
-
-To all effects and purposes, this work is to be considered Public Domain.
-
-
-However, if you want to be "buena onda", you should:
-
-1. Not take credit for it, and give proper recognition to the authors.
-2. Share your modifications, so everybody benefits from them.
-3. Do something nice for the authors.
-4. Help someone who needs it: sign up for some volunteer work or help your
-   neighbour paint the house.
-5. Don't waste. Anything, but specially energy that comes from natural
-   non-renewable resources. Extra points if you discover or invent something
-   to replace them.
-6. Be tolerant. Everything that's good in nature comes from cooperation.
-
-
diff --git a/bindings/python3/nmdb.py b/bindings/python3/nmdb.py
deleted file mode 100644
index 2c0b88c..0000000
--- a/bindings/python3/nmdb.py
+++ /dev/null
@@ -1,252 +0,0 @@
-
-"""
-libnmdb python 3 wrapper
-
-This module is a wrapper for the libnmdb, the C library used to implement
-clients to the nmdb server.
-
-It provides three similar classes: DB, SyncDB and Cache. They all present the
-same dictionary-alike interface, but differ in how they interact with the
-server.
-
-The DB class allows you to set, get and delete (key, value) pairs from the
-database; the SyncDB class works like DB, but does so in a synchronous way; and
-the Cache class affects only the cache and do not impact the backend database.
-
-Note that mixing cache sets with DB sets can create inconsistencies between
-the database and the cache. You shouldn't do that unless you know what you're
-doing.
-
-The classes use pickle to allow you to store and retrieve python objects in a
-transparent way. To disable it, set .autopickle to False.
-
-Here is an example using the DB class:
-
->>> import nmdb
->>> db = nmdb.DB()
->>> db.add_tipc_server()
->>> db[1] = { 'english': 'one', 'castellano': 'uno', 'quechua': 'huk' }
->>> print(db[1])
-{'english': 'one', 'castellano': 'uno', 'quechua': 'huk'}
->>> db[(1, 2)] = (True, False)
->>> print(db[(1, 2)])
-(True, False)
->>> del db[(1, 2)]
->>> print(db[(1, 2)])
-Traceback (most recent call last):
-  File "<stdin>", line 1, in <module>
-  File "/usr/local/lib/python3.0/dist-packages/nmdb.py", line 206, in __getitem__
-    return self.get(key)
-  File "/usr/local/lib/python3.0/dist-packages/nmdb.py", line 102, in normal_get
-    return self.generic_get(self._db.get, key)
-  File "/usr/local/lib/python3.0/dist-packages/nmdb.py", line 93, in generic_get
-    raise KeyError
-KeyError
->>>
-"""
-
-import pickle
-import nmdb_ll
-
-
-class NetworkError (Exception):
-	pass
-
-
-class GenericDB:
-	def __init__(self):
-		self._db = nmdb_ll.nmdb()
-		self.autopickle = True
-
-	def add_tipc_server(self, port = -1):
-		"Adds a TIPC server to the server pool."
-		rv = self._db.add_tipc_server(port)
-		if not rv:
-			raise NetworkError
-		return rv
-
-	def add_tcp_server(self, addr, port = -1):
-		"Adds a TCP server to the server pool."
-		rv = self._db.add_tcp_server(addr, port)
-		if not rv:
-			raise NetworkError
-		return rv
-
-	def add_udp_server(self, addr, port = -1):
-		"Adds an UDP server to the server pool."
-		rv = self._db.add_udp_server(addr, port)
-		if not rv:
-			raise NetworkError
-		return rv
-
-
-	def generic_get(self, getf, key):
-		"d[k]   Returns the value associated with the key k."
-		if self.autopickle:
-			key = pickle.dumps(key, protocol = -1)
-		try:
-			r = getf(key)
-		except:
-			raise NetworkError
-		if r == -1:
-			# For key errors, get returns -1 instead of a string
-			# so we know it's a miss.
-			raise KeyError
-		if self.autopickle:
-			r = pickle.loads(r)
-		return r
-
-	def cache_get(self, key):
-		return self.generic_get(self._db.cache_get, key)
-
-	def normal_get(self, key):
-		return self.generic_get(self._db.get, key)
-
-
-	def generic_set(self, setf, key, val):
-		"d[k] = v   Associates the value v to the key k."
-		if self.autopickle:
-			key = pickle.dumps(key, protocol = -1)
-			val = pickle.dumps(val, protocol = -1)
-		r = setf(key, val)
-		if r <= 0:
-			raise NetworkError
-		return 1
-
-	def cache_set(self, key, val):
-		return self.generic_set(self._db.cache_set, key, val)
-
-	def normal_set(self, key, val):
-		return self.generic_set(self._db.set, key, val)
-
-	def set_sync(self, key, val):
-		return self.generic_set(self._db.set_sync, key, val)
-
-
-	def generic_delete(self, delf, key):
-		"del d[k]   Deletes the key k."
-		if self.autopickle:
-			key = pickle.dumps(key, protocol = -1)
-		r = delf(key)
-		if r < 0:
-			raise NetworkError
-		elif r == 0:
-			raise KeyError
-		return 1
-
-	def cache_delete(self, key):
-		return self.generic_delete(self._db.cache_delete, key)
-
-	def normal_delete(self, key):
-		return self.generic_delete(self._db.delete, key)
-
-	def delete_sync(self, key):
-		return self.generic_delete(self._db.delete_sync, key)
-
-
-	def generic_cas(self, casf, key, oldval, newval):
-		"Perform a compare-and-swap."
-		if self.autopickle:
-			key = pickle.dumps(key, protocol = -1)
-			oldval = pickle.dumps(oldval, protocol = -1)
-			newval = pickle.dumps(newval, protocol = -1)
-		r = casf(key, oldval, newval)
-		if r == 2:
-			# success
-			return 2
-		elif r == 1:
-			# no match
-			return 1
-		elif r == 0:
-			# not in
-			raise KeyError
-		else:
-			raise NetworkError
-
-	def cache_cas(self, key, oldv, newv):
-		return self.generic_cas(self._db.cache_cas, key,
-				oldval, newval)
-
-	def normal_cas(self, key, oldval, newval):
-		return self.generic_cas(self._db.cas, key,
-				oldval, newval)
-
-
-	def generic_incr(self, incrf, key, increment):
-		"""Atomically increment the value associated with the given
-		key by the given increment."""
-		if self.autopickle:
-			key = pickle.dumps(key, protocol = -1)
-		r, v = incrf(key, increment)
-		if r == 2:
-			# success
-			return v
-		elif r == 1:
-			# no match, because the value didn't have the right
-			# format
-			raise TypeError("The value must be a " + \
-					"NULL-terminated string")
-		elif r == 0:
-			# not in
-			raise KeyError
-		else:
-			raise NetworkError
-
-	def cache_incr(self, key, increment = 1):
-		return self.generic_incr(self._db.cache_incr, key, increment)
-
-	def normal_incr(self, key, increment = 1):
-		return self.generic_incr(self._db.incr, key, increment)
-
-
-	# The following functions will assume the existance of self.set,
-	# self.get, and self.delete, which are supposed to be set by our
-	# subclasses.
-
-	def __getitem__(self, key):
-		return self.get(key)
-
-	def __setitem__(self, key, val):
-		return self.set(key, val)
-
-	def __delitem__(self, key):
-		return self.delete(key)
-
-	def __contains__(self, key):
-		"Returns True if the key is in the database, False otherwise."
-		try:
-			r = self.get(key)
-		except KeyError:
-			return False
-		if not r:
-			return False
-		return True
-
-	def has_key(self, key):
-		"Returns True if the key is in the database, False otherwise."
-		return self.__contains__(key)
-
-
-
-class Cache (GenericDB):
-	get = GenericDB.cache_get
-	set = GenericDB.cache_set
-	delete = GenericDB.cache_delete
-	cas = GenericDB.cache_cas
-	incr = GenericDB.cache_incr
-
-class DB (GenericDB):
-	get = GenericDB.normal_get
-	set = GenericDB.normal_set
-	delete = GenericDB.normal_delete
-	cas = GenericDB.normal_cas
-	incr = GenericDB.normal_incr
-
-class SyncDB (GenericDB):
-	get = GenericDB.normal_get
-	set = GenericDB.set_sync
-	delete = GenericDB.delete_sync
-	cas = GenericDB.normal_cas
-	incr = GenericDB.normal_incr
-
-
diff --git a/bindings/python3/nmdb_ll.c b/bindings/python3/nmdb_ll.c
deleted file mode 100644
index a6a4ab8..0000000
--- a/bindings/python3/nmdb_ll.c
+++ /dev/null
@@ -1,452 +0,0 @@
-
-/*
- * Python 3 bindings for libnmdb
- * Alberto Bertogli (albertito@blitiri.com.ar)
- *
- * This is the low-level module, used by the python one to construct
- * friendlier objects.
- */
-
-#include <Python.h>
-#include <nmdb.h>
-
-
-/*
- * Type definitions
- */
-
-typedef struct {
-	PyObject_HEAD;
-	nmdb_t *db;
-} nmdbobject;
-static PyTypeObject nmdbType;
-
-/*
- * The nmdb object
- */
-
-/* delete */
-static void db_dealloc(nmdbobject *db)
-{
-	if (db->db) {
-		nmdb_free(db->db);
-	}
-	PyObject_Del(db);
-}
-
-
-/* add tipc server */
-static PyObject *db_add_tipc_server(nmdbobject *db, PyObject *args)
-{
-	int port;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "i:add_tipc_server", &port)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_add_tipc_server(db->db, port);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* add tcp server */
-static PyObject *db_add_tcp_server(nmdbobject *db, PyObject *args)
-{
-	int port;
-	char *addr;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "si:add_tcp_server", &addr, &port)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_add_tcp_server(db->db, addr, port);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* add udp server */
-static PyObject *db_add_udp_server(nmdbobject *db, PyObject *args)
-{
-	int port;
-	char *addr;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "si:add_udp_server", &addr, &port)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_add_udp_server(db->db, addr, port);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* cache set */
-static PyObject *db_cache_set(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *val;
-	int ksize, vsize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#s#:cache_set", &key, &ksize,
-				&val, &vsize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cache_set(db->db, key, ksize, val, vsize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* cache get */
-static PyObject *db_cache_get(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *val;
-	int ksize, vsize;
-	long rv;
-	PyObject *r;
-
-	if (!PyArg_ParseTuple(args, "s#:cache_get", &key, &ksize)) {
-		return NULL;
-	}
-
-	/* vsize is enough to hold the any value */
-	vsize = 128 * 1024;
-	val = malloc(vsize);
-	if (val == NULL)
-		return PyErr_NoMemory();
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cache_get(db->db, key, ksize, val, vsize);
-	Py_END_ALLOW_THREADS
-
-	if (rv <= -2) {
-		/* FIXME: define a better exception */
-		r = PyErr_SetFromErrno(PyExc_IOError);
-	} else if (rv == -1) {
-		/* Miss, handled in the high-level module. */
-		r = PyLong_FromLong(-1);
-	} else {
-		r = PyBytes_FromStringAndSize((char *) val, rv);
-	}
-
-	free(val);
-	return r;
-}
-
-/* cache delete */
-static PyObject *db_cache_delete(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key;
-	int ksize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#:cache_delete", &key, &ksize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cache_del(db->db, key, ksize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* cache cas */
-static PyObject *db_cache_cas(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *oldval, *newval;
-	int ksize, ovsize, nvsize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#s#s#:cache_cas", &key, &ksize,
-				&oldval, &ovsize,
-				&newval, &nvsize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cache_cas(db->db, key, ksize, oldval, ovsize,
-			newval, nvsize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* cache increment */
-static PyObject *db_cache_incr(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key;
-	int ksize;
-	int rv;
-	long long int increment;
-	int64_t newval;
-
-	if (!PyArg_ParseTuple(args, "s#L:cache_incr", &key, &ksize,
-				&increment)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cache_incr(db->db, key, ksize, increment, &newval);
-	Py_END_ALLOW_THREADS
-
-	return Py_BuildValue("LL", rv, newval);
-}
-
-
-/* db set */
-static PyObject *db_set(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *val;
-	int ksize, vsize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#s#:set", &key, &ksize,
-				&val, &vsize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_set(db->db, key, ksize, val, vsize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* db get */
-static PyObject *db_get(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *val;
-	int ksize, vsize;
-	long rv;
-	PyObject *r;
-
-	if (!PyArg_ParseTuple(args, "s#:get", &key, &ksize)) {
-		return NULL;
-	}
-
-	/* vsize is enough to hold the any value */
-	vsize = 128 * 1024;
-	val = malloc(vsize);
-	if (val == NULL)
-		return PyErr_NoMemory();
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_get(db->db, key, ksize, val, vsize);
-	Py_END_ALLOW_THREADS
-
-	if (rv <= -2) {
-		/* FIXME: define a better exception */
-		r = PyErr_SetFromErrno(PyExc_IOError);
-	} else if (rv == -1) {
-		/* Miss, handled in the high-level module. */
-		r = PyLong_FromLong(-1);
-	} else {
-		r = PyBytes_FromStringAndSize((char *) val, rv);
-	}
-
-	free(val);
-	return r;
-}
-
-/* db delete */
-static PyObject *db_delete(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key;
-	int ksize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#:delete", &key, &ksize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_del(db->db, key, ksize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* db cas */
-static PyObject *db_cas(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *oldval, *newval;
-	int ksize, ovsize, nvsize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#s#s#:cas", &key, &ksize,
-				&oldval, &ovsize,
-				&newval, &nvsize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_cas(db->db, key, ksize, oldval, ovsize, newval, nvsize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* db increment */
-static PyObject *db_incr(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key;
-	int ksize;
-	int rv;
-	long long int increment;
-	int64_t newval;
-
-	if (!PyArg_ParseTuple(args, "s#L:incr", &key, &ksize, &increment)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_incr(db->db, key, ksize, increment, &newval);
-	Py_END_ALLOW_THREADS
-
-	return Py_BuildValue("LL", rv, newval);
-}
-
-
-/* db set sync */
-static PyObject *db_set_sync(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key, *val;
-	int ksize, vsize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#s#:set_sync", &key, &ksize,
-				&val, &vsize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_set_sync(db->db, key, ksize, val, vsize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-/* db delete sync */
-static PyObject *db_delete_sync(nmdbobject *db, PyObject *args)
-{
-	unsigned char *key;
-	int ksize;
-	int rv;
-
-	if (!PyArg_ParseTuple(args, "s#:delete_sync", &key, &ksize)) {
-		return NULL;
-	}
-
-	Py_BEGIN_ALLOW_THREADS
-	rv = nmdb_del_sync(db->db, key, ksize);
-	Py_END_ALLOW_THREADS
-
-	return PyLong_FromLong(rv);
-}
-
-
-
-/* nmdb method table */
-
-static PyMethodDef nmdb_methods[] = {
-	{ "add_tipc_server", (PyCFunction) db_add_tipc_server,
-		METH_VARARGS, NULL },
-	{ "add_tcp_server", (PyCFunction) db_add_tcp_server,
-		METH_VARARGS, NULL },
-	{ "add_udp_server", (PyCFunction) db_add_udp_server,
-		METH_VARARGS, NULL },
-	{ "cache_set", (PyCFunction) db_cache_set, METH_VARARGS, NULL },
-	{ "cache_get", (PyCFunction) db_cache_get, METH_VARARGS, NULL },
-	{ "cache_delete", (PyCFunction) db_cache_delete, METH_VARARGS, NULL },
-	{ "cache_cas", (PyCFunction) db_cache_cas, METH_VARARGS, NULL },
-	{ "cache_incr", (PyCFunction) db_cache_incr, METH_VARARGS, NULL },
-	{ "set", (PyCFunction) db_set, METH_VARARGS, NULL },
-	{ "get", (PyCFunction) db_get, METH_VARARGS, NULL },
-	{ "delete", (PyCFunction) db_delete, METH_VARARGS, NULL },
-	{ "cas", (PyCFunction) db_cas, METH_VARARGS, NULL },
-	{ "incr", (PyCFunction) db_incr, METH_VARARGS, NULL },
-	{ "set_sync", (PyCFunction) db_set_sync, METH_VARARGS, NULL },
-	{ "delete_sync", (PyCFunction) db_delete_sync, METH_VARARGS, NULL },
-
-	{ NULL }
-};
-
-/* new, returns an nmdb object */
-static PyObject *db_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-	nmdbobject *db;
-
-	db = (nmdbobject *) type->tp_alloc(type, 0);
-	if (db == NULL)
-		return NULL;
-
-	if (!PyArg_ParseTuple(args, ":new")) {
-		return NULL;
-	}
-
-	db->db = nmdb_init();
-	if (db->db == NULL) {
-		return PyErr_NoMemory();
-	}
-
-	/* XXX: is this necessary? */
-	if (PyErr_Occurred()) {
-		nmdb_free(db->db);
-		return NULL;
-	}
-
-	return (PyObject *) db;
-}
-
-
-static PyTypeObject nmdbType = {
-	PyObject_HEAD_INIT(NULL)
-	.tp_name = "nmdb_ll.nmdb",
-	.tp_itemsize = sizeof(nmdbobject),
-	.tp_dealloc = (destructor) db_dealloc,
-	.tp_methods = nmdb_methods,
-	.tp_new = db_new,
-};
-
-
-
-/*
- * The module
- */
-
-static PyModuleDef nmdb_module = {
-	PyModuleDef_HEAD_INIT,
-	.m_name = "nmdb_ll",
-	.m_doc = NULL,
-	.m_size = -1,
-};
-
-
-PyMODINIT_FUNC PyInit_nmdb_ll(void)
-{
-	PyObject *m;
-
-	if (PyType_Ready(&nmdbType) < 0)
-		return NULL;
-
-	m = PyModule_Create(&nmdb_module);
-
-	Py_INCREF(&nmdbType);
-	PyModule_AddObject(m, "nmdb", (PyObject *) &nmdbType);
-
-	return m;
-}
-
-
-
diff --git a/bindings/python3/setup.py b/bindings/python3/setup.py
deleted file mode 100644
index 54c1bcd..0000000
--- a/bindings/python3/setup.py
+++ /dev/null
@@ -1,17 +0,0 @@
-
-from distutils.core import setup, Extension
-
-nmdb_ll = Extension("nmdb_ll",
-		libraries = ['nmdb'],
-		sources = ['nmdb_ll.c'])
-
-setup(
-	name = 'nmdb',
-	description = "libnmdb bindings",
-	author = "Alberto Bertogli",
-	author_email = "albertito@blitiri.com.ar",
-	url = "http://blitiri.com.ar/p/nmdb",
-	py_modules = ['nmdb'],
-	ext_modules = [nmdb_ll]
-)
-