diff options
| author | drebs <drebs@leap.se> | 2012-12-10 18:39:56 -0200 | 
|---|---|---|
| committer | drebs <drebs@leap.se> | 2012-12-10 18:39:56 -0200 | 
| commit | 64347825e57076560fa32b24df0ed2b310d4e052 (patch) | |
| tree | cbe88e64d129ec0a7b8a70cba5467a6fb8cce0a1 | |
| parent | e21b1cbe95dd3c424e0fe83f27ef439d7ab8cc76 (diff) | |
CouchDB backend can put and get objects.
| -rw-r--r-- | backends/couch.py (renamed from backends/couchdb.py) | 52 | ||||
| -rw-r--r-- | backends/leap.py | 1 | ||||
| -rw-r--r-- | backends/objectstore.py | 43 | ||||
| -rw-r--r-- | backends/openstack.py | 2 | ||||
| -rw-r--r-- | tests/test_couchdb.py | 19 | 
5 files changed, 80 insertions, 37 deletions
diff --git a/backends/couchdb.py b/backends/couch.py index 89b713f9..5586ea9c 100644 --- a/backends/couchdb.py +++ b/backends/couch.py @@ -1,7 +1,9 @@  from u1db import errors  from u1db.remote.http_target import HTTPSyncTarget -from couchdb import * +from couchdb.client import Server, Document +from couchdb.http import ResourceNotFound  from soledad.backends.objectstore import ObjectStore +from soledad.backends.leap import LeapDocument  class CouchDatabase(ObjectStore): @@ -12,13 +14,18 @@ class CouchDatabase(ObjectStore):          self._url = url          self._full_commit = full_commit          self._session = session -        self._server = couchdb.Server(url=self._url, -                                      full_commit=self._full_commit, -                                      session=self._session) +        self._server = Server(url=self._url, +                              full_commit=self._full_commit, +                              session=self._session)          # this will ensure that transaction and sync logs exist and are          # up-to-date. -        super(CouchDatabase, self) -        self._database = self._server[database] +        self.set_document_factory(LeapDocument) +        try: +            self._database = self._server[database] +        except ResourceNotFound: +            self._server.create(database) +            self._database = self._server[database] +        super(CouchDatabase, self).__init__()      #-------------------------------------------------------------------------      # implemented methods from Database @@ -31,13 +38,14 @@ class CouchDatabase(ObjectStore):          for them.          """          cdoc = self._database.get(doc_id) -        if cdoc is not None: -            content = {} -            for key, value in content: -                if not key in ['_id', '_rev', '_u1db_rev']: -                    content[key] = value -            doc = self._factory(doc_id=doc_id, rev=cdoc['_u1db_rev']) -            doc.content = content +        if cdoc is None: +            return None +        content = {} +        for (key, value) in cdoc.items(): +            if key not in ['_id', '_rev', 'u1db_rev']: +                content[key] = value +        doc = self._factory(doc_id=doc_id, rev=cdoc['u1db_rev']) +        doc.content = content          return doc      def get_all_docs(self, include_deleted=False): @@ -51,12 +59,15 @@ class CouchDatabase(ObjectStore):              results.append(doc)          return (generation, results) -    def _put_doc(self, doc, new_rev): +    def _put_doc(self, doc):          # map u1db metadata to couch          content = doc.content -        content['_id'] = doc.doc_id -        content['_u1db_rev'] = new_rev -        self._database.save(doc.content) +        cdoc = Document() +        cdoc['_id'] = doc.doc_id +        cdoc['u1db_rev'] = doc.rev +        for (key, value) in content.items(): +            cdoc[key] = value +        self._database.save(cdoc)      def get_sync_target(self):          return CouchSyncTarget(self) @@ -70,6 +81,13 @@ class CouchDatabase(ObjectStore):          return Synchronizer(self, CouchSyncTarget(url, creds=creds)).sync(              autocreate=autocreate) +    def _get_u1db_data(self): +        cdoc = self._database.get(self.U1DB_DATA_DOC_ID) +        self._sync_log.log = cdoc['sync_log'] +        self._transaction_log.log = cdoc['transaction_log'] +        self._replica_uid = cdoc['replica_uid'] +        self._couch_rev = cdoc['_rev'] +      #-------------------------------------------------------------------------      # Couch specific methods      #------------------------------------------------------------------------- diff --git a/backends/leap.py b/backends/leap.py index 2c815632..ce00c8f3 100644 --- a/backends/leap.py +++ b/backends/leap.py @@ -7,6 +7,7 @@ from u1db import Document  from u1db.remote.http_target import HTTPSyncTarget  from u1db.remote.http_database import HTTPDatabase  import base64 +from soledad import GPGWrapper  class NoDefaultKey(Exception): diff --git a/backends/objectstore.py b/backends/objectstore.py index d9ab7cbd..5bd864c8 100644 --- a/backends/objectstore.py +++ b/backends/objectstore.py @@ -1,5 +1,7 @@ +import uuid  from u1db.backends import CommonBackend  from soledad import SyncLog, TransactionLog +from soledad.backends.leap import LeapDocument  class ObjectStore(CommonBackend): @@ -45,15 +47,14 @@ class ObjectStore(CommonBackend):          self._check_doc_id(doc.doc_id)          self._check_doc_size(doc)          # put the document -        new_rev = self._allocate_doc_rev(doc.rev) -        self._put_doc(doc, new_rev) -        doc.rev = new_rev +        doc.rev = self._allocate_doc_rev(doc.rev) +        self._put_doc(doc)          # update u1db generation and logs          new_gen = self._get_generation() + 1          trans_id = self._allocate_transaction_id()          self._transaction_log.append((new_gen, doc.doc_id, trans_id))          self._set_u1db_data() -        return new_rev +        return doc.rev      def delete_doc(self, doc):          old_doc = self._get_doc(doc.doc_id, check_for_conflicts=True) @@ -145,15 +146,16 @@ class ObjectStore(CommonBackend):          """          if not self._is_initialized():              self._initialize() -        u1db_data = self._get_doc('u1db_data') -        self._sync_log.log = u1db_data.content['sync_log'] -        self._transaction_log.log = u1db_data.content['transaction_log'] +        self._get_u1db_data() + +    U1DB_DATA_DOC_ID = 'u1db_data'      def _is_initialized(self):          """          Verify if u1db data exists in store.          """ -        if not self._get_doc('u1db_data'): +        doc = self._get_doc(self.U1DB_DATA_DOC_ID) +        if not self._get_doc(self.U1DB_DATA_DOC_ID):              return False          return True @@ -161,19 +163,22 @@ class ObjectStore(CommonBackend):          """          Create u1db data object in store.          """ -        content = { 'transaction_log' : [], -                    'sync_log' : [] } -        doc = self.create_doc('u1db_data', content) +        self._replica_uid = uuid.uuid4().hex +        doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) +        doc.content = { 'transaction_log' : [], +                        'sync_log' : [], +                        'replica_uid' : self._replica_uid } +        self._put_doc(doc) -    def _get_u1db_data(self): -        data = self.get_doc('u1db_data').content -        self._transaction_log = data['transaction_log'] -        self._sync_log = data['sync_log'] +    def _get_u1db_data(self, u1db_data_doc_id): +        NotImplementedError(self._get_u1db_data)      def _set_u1db_data(self): -        doc = self._factory('u1db_data') -        doc.content = { 'transaction_log' : self._transaction_log, -                        'sync_log'        : self._sync_log } -        self.put_doc(doc) +        doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) +        doc.content = { 'transaction_log' : self._transaction_log.log, +                        'sync_log'        : self._sync_log.log, +                        'replica_uid'     : self._replica_uid, +                        '_rev'            : self._couch_rev} +        self._put_doc(doc) diff --git a/backends/openstack.py b/backends/openstack.py index 5f2a2771..c027231c 100644 --- a/backends/openstack.py +++ b/backends/openstack.py @@ -17,7 +17,7 @@ class OpenStackDatabase(ObjectStore):                                                    self._auth_key)          self._get_auth()          # this will ensure transaction and sync logs exist and are up-to-date. -        super(OpenStackDatabase, self) +        super(OpenStackDatabase, self).__init__()      #-------------------------------------------------------------------------      # implemented methods from Database diff --git a/tests/test_couchdb.py b/tests/test_couchdb.py new file mode 100644 index 00000000..58285086 --- /dev/null +++ b/tests/test_couchdb.py @@ -0,0 +1,19 @@ +import unittest +from soledad.backends.couch import CouchDatabase + +class CouchTestCase(unittest.TestCase): + +    def setUp(self): +        self._db = CouchDatabase('http://localhost:5984', 'u1db_tests') + +    def test_create_get(self): +        doc1 = self._db.create_doc({"key": "value"}, doc_id="testdoc") +        doc2 = self._db.get_doc('testdoc') +        self.assertEqual(doc1, doc2, 'error storing/retrieving document.') +        self.assertEqual(self._db._get_generation(), 1) + +    def tearDown(self): +        self._db._server.delete('u1db_tests') + +if __name__ == '__main__': +    unittest.main()  | 
