Commits

Jeethu Rao  committed 49bc872

Created a simple cython based python extension for tinycdb

  • Participants

Comments (0)

Files changed (4)

+The MIT License
+
+Copyright (c) 2009 Jeethu Rao <jeethu@jeethurao.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+A very simple python interface to the tinycdb DBM library ( http://www.corpit.ru/mjt/tinycdb.html ).
+
+Example #1 writing :
+
+import pytinycdb
+
+db = pytinycdb.create('foo.db')
+db['foo'] = 'bar'
+db['bar'] = 'baz'
+print 'foo' in db # Prints True
+print 'moo' in db # Prints False
+db.close()
+
+Example #2 reading :
+
+import pytinycdb
+db = pytinycdb.read('foo.db')
+if 'foo' in db :
+    print "Found"
+    print db['foo']
+else :
+    print "Not found"
+
+Thats all.
+
+-- Jeethu Rao <jeethu@jeethurao.com>
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+
+setup(
+    cmdclass = {'build_ext': build_ext},
+    ext_modules = [Extension("pytinycdb", ["tinycdb.pyx"],
+                             libraries=['cdb'])]
+)
+
+
+
+'''
+A very simple interface to the tinycdb DBM.
+
+By Jeethu Rao <jeethu@jeethurao.com>
+'''
+
+cdef extern from "Python.h":
+    int PyString_AsStringAndSize(object obj, char **buffer, Py_ssize_t* length) except -1
+    object PyString_FromStringAndSize(char *v, int len)
+
+cdef extern from "stdlib.h" :
+    void *malloc(size_t size)
+    void *free(void *ptr)
+
+cdef extern from "fcntl.h" :
+    int open( char* path, int flag, int mode )
+    int O_RDWR, O_RDONLY, O_CREAT
+    int S_IRUSR, S_IWUSR
+
+cdef extern from "unistd.h" :
+    int close( int fd )
+
+cdef extern from "cdb.h" :
+    struct cdb_make :
+        pass
+    int cdb_make_start( cdb_make* m, int fd )
+    int cdb_make_add( cdb_make* m, void *k, unsigned int k_len, void* v, unsigned int v_len )
+    int cdb_make_exists( cdb_make* m, void *k, int k_len )
+    int cdb_make_finish( cdb_make* m )
+
+cdef extern from "cdb.h" :
+    int cdb_seek(int fd, void* key, unsigned int k_len, unsigned int* dlenp)
+    int cdb_bread( int fd, void* buf, int len )
+
+cdef int openFile( object file_name, int rw ) except -1 :
+    cdef char *buffer
+    cdef Py_ssize_t len
+    cdef int rez
+    rez = PyString_AsStringAndSize(file_name, &buffer, &len)
+    if rw :
+        rez = open( buffer, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR )
+    else :
+        rez = open( buffer, O_RDONLY, 0 )
+    if rez == -1 :
+        raise IOError("Can't open file: \'%s\'"%file_name)
+    return rez
+
+class CDBError( Exception ) :
+    pass
+
+cdef class create :
+    cdef int fd, finished
+    cdef cdb_make cdbm
+    def __init__( self, fname ) :
+        cdef int rez
+        self.fd = openFile( fname, 1 )
+        rez = cdb_make_start( &self.cdbm, self.fd )
+        if rez != 0 :
+            raise CDBError("Unknown Error")
+
+    def __setitem__( self, key, value ) :
+        cdef char *buffer1, *buffer2
+        cdef Py_ssize_t len1, len2
+        cdef int rez
+        rez = PyString_AsStringAndSize(key, &buffer1, &len1)
+        rez = PyString_AsStringAndSize(value, &buffer2, &len2)
+        rez = cdb_make_add( &self.cdbm, buffer1, len1, buffer2, len2 )
+        if rez != 0 :
+            raise CDBError("Unknown Error")
+    
+    def __contains__( self, key ) :
+        cdef char *buffer
+        cdef Py_ssize_t len
+        cdef int rez
+        rez = PyString_AsStringAndSize(key, &buffer, &len)
+        rez = cdb_make_exists(&self.cdbm, buffer, len)
+        if rez < 0 :
+            raise CDBError("Unknown Error")
+        if rez == 1 :
+            return True
+        return False
+
+
+    def close( self ) :
+        if not self.finished :
+            self.finished = 1
+            cdb_make_finish(&self.cdbm)
+
+    def __dealloc__( self ) :
+        if not self.finished :
+            cdb_make_finish(&self.cdbm)
+        if self.fd :
+            close( self.fd )
+
+cdef class read :
+    cdef int fd
+    def __init__( self, fname ) :
+        self.fd = openFile( fname, 0 )
+
+    def __contains__( self, key ) :
+        cdef char *buffer
+        cdef Py_ssize_t len
+        cdef int rez
+        cdef unsigned int dlen
+        rez = PyString_AsStringAndSize(key, &buffer, &len)
+        rez = cdb_seek( self.fd, buffer, len, &dlen )
+        if rez < 0 :
+            raise CDBError("Unknown Error")
+        return rez
+
+    def __getitem__( self, key ) :
+        cdef char *buffer
+        cdef Py_ssize_t len
+        cdef int rez
+        cdef unsigned int dlen
+        cdef object ret
+        rez = PyString_AsStringAndSize(key, &buffer, &len)
+        rez = cdb_seek( self.fd, buffer, len, &dlen )
+        if rez < 0 :
+            raise CDBError("Unknown Error")
+        if rez == 0 :
+            raise KeyError("Key \'%s\' not found"%key)
+        buffer = <char *>malloc(dlen)
+        if buffer == NULL :
+            raise MemoryError("malloc() failed")
+        rez = cdb_bread( self.fd, buffer, dlen )
+        if rez == 0 :
+            ret = PyString_FromStringAndSize( buffer, dlen )
+            free(buffer)
+            return ret
+        raise CDBError("Unknown Error")
+        free(buffer)
+
+    def __dealloc__( self ) :
+        if self.fd :
+            close( self.fd )