git » nmdb » commit 75322af

Bring the python module up to date.

author Alberto Bertogli
2007-01-07 06:25:05 UTC
committer Alberto Bertogli
2007-01-07 06:25:05 UTC
parent 1fe50a3a1a55ffc733b130fc5ca25b3b597e9f01

Bring the python module up to date.
This patch updates the python bindings to support multiple servers; allow the
use of python object both as keys and as values, as long as they can be hashed
and pickled (respectively); and document everything a bit.

python/nmdb.py +76 -13
python/nmdb_ll.c +18 -0

diff --git a/python/nmdb.py b/python/nmdb.py
index 8f14b58..7cea957 100644
--- a/python/nmdb.py
+++ b/python/nmdb.py
@@ -1,38 +1,98 @@
 
-#
-# libnmdb python wrapper
-# Alberto Bertogli (albertito@gmail.com)
-#
-
+"""
+libnmdb python 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()
+>>> import nmdb
+>>> db = nmdb.DB()
+>>> 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/lib64/python2.5/site-packages/nmdb.py", line 74, in __getitem__
+    raise KeyError
+KeyError
+"""
+
+import cPickle
 import nmdb_ll
 
+
 class NetworkError (Exception):
 	pass
 
+
 class _nmdbDict (object):
 	def __init__(self, db, op_get, op_set, op_delete):
 		self.db = db
-		self.op_get = op_get
-		self.op_set = op_set
-		self.op_delete = op_delete
+		self.get = op_get
+		self.set = op_set
+		self.delete = op_delete
+		self.autopickle = True
+
+	def add_server(self, port):
+		"Adds a server to the server pool."
+		rv = self.db.add_server(port)
+		if not rv:
+			raise NetworkError
+		return rv
 
 	def __getitem__(self, key):
+		"d[k]   Returns the value associated with the key k."
+		if self.autopickle:
+			key = str(hash(key))
 		try:
-			r = self.op_get(key)
+			r = self.get(key)
 		except:
 			raise NetworkError
 		if not r:
 			raise KeyError
+		if self.autopickle:
+			r = cPickle.loads(r)
 		return r
 
 	def __setitem__(self, key, val):
-		r = self.op_set(key, val)
+		"d[k] = v   Associates the value v to the key k."
+		if self.autopickle:
+			key = str(hash(key))
+			val = cPickle.dumps(val, protocol = -1)
+		r = self.set(key, val)
 		if r <= 0:
 			raise NetworkError
 		return 1
 
 	def __delitem__(self, key):
-		r = self.op_delete(key)
+		"del d[k]   Deletes the key k."
+		if self.autopickle:
+			key = str(hash(key))
+		r = self.delete(key)
 		if r < 0:
 			raise NetworkError
 		elif r == 0:
@@ -40,8 +100,11 @@ class _nmdbDict (object):
 		return 1
 
 	def __contains__(self, key):
+		"Returns True if the key is in the database, False otherwise."
+		if self.autopickle:
+			key = hash(key)
 		try:
-			r = self.op_get(key)
+			r = self.get(key)
 		except:
 			raise NetworkError
 		if not r:
@@ -49,6 +112,7 @@ class _nmdbDict (object):
 		return True
 
 	def has_key(self, key):
+		"Returns True if the key is in the database, False otherwise."
 		return self.__contains__(key)
 
 
@@ -63,7 +127,6 @@ class DB (_nmdbDict):
 		db = nmdb_ll.connect(port)
 		_nmdbDict.__init__(self, db, db.get, db.set, db.delete)
 
-
 class SyncDB (_nmdbDict):
 	def __init__(self, port = -1):
 		db = nmdb_ll.connect(port)
diff --git a/python/nmdb_ll.c b/python/nmdb_ll.c
index aa1c196..47f5b2c 100644
--- a/python/nmdb_ll.c
+++ b/python/nmdb_ll.c
@@ -35,6 +35,23 @@ static void db_dealloc(nmdbobject *db)
 }
 
 
+/* add server */
+static PyObject *db_add_server(nmdbobject *db, PyObject *args)
+{
+	int port;
+	int rv;
+
+	if (!PyArg_ParseTuple(args, "i:add_server", &port)) {
+		return NULL;
+	}
+
+	Py_BEGIN_ALLOW_THREADS
+	rv = nmdb_add_server(db->db, port);
+	Py_END_ALLOW_THREADS
+
+	return PyLong_FromLong(rv);
+}
+
 /* cache set */
 static PyObject *db_cache_set(nmdbobject *db, PyObject *args)
 {
@@ -222,6 +239,7 @@ static PyObject *db_delete_sync(nmdbobject *db, PyObject *args)
 /* nmdb method table */
 
 static PyMethodDef nmdb_methods[] = {
+	{ "add_server", (PyCFunction) db_add_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 },