diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/couch.py | 49 | ||||
| -rw-r--r-- | backends/leap_backend.py | 8 | ||||
| -rw-r--r-- | backends/objectstore.py | 22 | ||||
| -rw-r--r-- | backends/openstack.py | 14 | ||||
| -rw-r--r-- | backends/sqlcipher.py | 16 | 
5 files changed, 52 insertions, 57 deletions
| diff --git a/backends/couch.py b/backends/couch.py index 78026af8..8ba42d78 100644 --- a/backends/couch.py +++ b/backends/couch.py @@ -1,7 +1,5 @@ -import sys  import uuid  from base64 import b64encode, b64decode -from u1db import errors  from u1db.sync import LocalSyncTarget  from couchdb.client import Server, Document as CouchDocument  from couchdb.http import ResourceNotFound @@ -17,7 +15,8 @@ except ImportError:  class CouchDatabase(ObjectStore):      """A U1DB implementation that uses Couch as its persistence layer.""" -    def __init__(self, url, database, replica_uid=None, full_commit=True, session=None):  +    def __init__(self, url, database, replica_uid=None, full_commit=True, +                 session=None):          """Create a new Couch data container."""          self._url = url          self._full_commit = full_commit @@ -54,8 +53,9 @@ class CouchDatabase(ObjectStore):              doc_id=doc_id,              rev=cdoc['u1db_rev'],              has_conflicts=has_conflicts) -        if cdoc['u1db_json'] is not None: -            doc.content = json.loads(cdoc['u1db_json']) +        contents = self._database.get_attachment(cdoc, 'u1db_json') +        if contents: +            doc.content = json.loads(contents.getvalue())          else:              doc.make_tombstone()          return doc @@ -83,13 +83,14 @@ class CouchDatabase(ObjectStore):              cdoc['_rev'] = old_cdoc['_rev']          # store u1db's rev          cdoc['u1db_rev'] = doc.rev +        # save doc in db +        self._database.save(cdoc)          # store u1db's content as json string          if not doc.is_tombstone(): -            cdoc['u1db_json'] = doc.get_json() +            self._database.put_attachment(cdoc, doc.get_json(), +                                          filename='u1db_json')          else: -            cdoc['u1db_json'] = None -        # save doc in db -        self._database.save(cdoc) +            self._database.delete_attachment(cdoc, 'u1db_json')      def get_sync_target(self):          return CouchSyncTarget(self) @@ -103,7 +104,6 @@ class CouchDatabase(ObjectStore):          #self._server = None          self._database = None          return True -              def sync(self, url, creds=None, autocreate=True):          from u1db.sync import Synchronizer @@ -114,15 +114,16 @@ class CouchDatabase(ObjectStore):          if self._replica_uid is None:              self._replica_uid = uuid.uuid4().hex          doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) -        doc.content = { 'sync_log' : [], -                        'transaction_log' : [], -                        'conflict_log' : b64encode(json.dumps([])), -                        'replica_uid' : self._replica_uid } +        doc.content = {'sync_log': [], +                       'transaction_log': [], +                       'conflict_log': b64encode(json.dumps([])), +                       'replica_uid': self._replica_uid}          self._put_doc(doc)      def _get_u1db_data(self):          cdoc = self._database.get(self.U1DB_DATA_DOC_ID) -        content = json.loads(cdoc['u1db_json']) +        jsonstr = self._database.get_attachment(cdoc, 'u1db_json').getvalue() +        content = json.loads(jsonstr)          self._sync_log.log = content['sync_log']          self._transaction_log.log = content['transaction_log']          self._conflict_log.log = json.loads(b64decode(content['conflict_log'])) @@ -131,14 +132,15 @@ class CouchDatabase(ObjectStore):      def _set_u1db_data(self):          doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) -        doc.content = { 'sync_log'        : self._sync_log.log, -                        'transaction_log' : self._transaction_log.log, -                        # Here, the b64 encode ensures that document content -                        # does not cause strange behaviour in couchdb because -                        # of encoding. -                        'conflict_log'    : b64encode(json.dumps(self._conflict_log.log)), -                        'replica_uid'     : self._replica_uid, -                        '_rev'            : self._couch_rev} +        doc.content = { +            'sync_log': self._sync_log.log, +            'transaction_log': self._transaction_log.log, +            # Here, the b64 encode ensures that document content +            # does not cause strange behaviour in couchdb because +            # of encoding. +            'conflict_log': b64encode(json.dumps(self._conflict_log.log)), +            'replica_uid': self._replica_uid, +            '_rev': self._couch_rev}          self._put_doc(doc)      #------------------------------------------------------------------------- @@ -166,4 +168,3 @@ class CouchSyncTarget(LocalSyncTarget):          self._db._set_replica_gen_and_trans_id(              source_replica_uid, source_replica_generation,              source_replica_transaction_id) - diff --git a/backends/leap_backend.py b/backends/leap_backend.py index 3e859f7c..7e98dd45 100644 --- a/backends/leap_backend.py +++ b/backends/leap_backend.py @@ -41,8 +41,9 @@ class LeapDocument(Document):          """          if not self._soledad:              raise NoSoledadInstance() -        ciphertext = self._soledad.encrypt_symmetric(self.doc_id, self.get_json()) -        return json.dumps({'_encrypted_json' : ciphertext}) +        ciphertext = self._soledad.encrypt_symmetric(self.doc_id, +                                                     self.get_json()) +        return json.dumps({'_encrypted_json': ciphertext})      def set_encrypted_json(self, encrypted_json):          """ @@ -89,7 +90,8 @@ class LeapDatabase(HTTPDatabase):              doc_id = self._allocate_doc_id()          res, headers = self._request_json('PUT', ['doc', doc_id], {},                                            content, 'application/json') -        new_doc = self._factory(doc_id, res['rev'], content, soledad=self._soledad) +        new_doc = self._factory(doc_id, res['rev'], content, +                                soledad=self._soledad)          return new_doc diff --git a/backends/objectstore.py b/backends/objectstore.py index b6523336..d72a2ecc 100644 --- a/backends/objectstore.py +++ b/backends/objectstore.py @@ -1,6 +1,7 @@  from u1db.backends import CommonBackend  from u1db import errors, Document, vectorclock +  class ObjectStore(CommonBackend):      """      A backend for storing u1db data in an object store. @@ -139,12 +140,13 @@ class ObjectStore(CommonBackend):      def _set_replica_gen_and_trans_id(self, other_replica_uid,                                        other_generation, other_transaction_id):          return self._do_set_replica_gen_and_trans_id( -                 other_replica_uid, -                 other_generation, -                 other_transaction_id) +            other_replica_uid, +            other_generation, +            other_transaction_id)      def _do_set_replica_gen_and_trans_id(self, other_replica_uid, -                                         other_generation, other_transaction_id): +                                         other_generation, +                                         other_transaction_id):          self._sync_log.set_replica_gen_and_trans_id(other_replica_uid,                                                      other_generation,                                                      other_transaction_id) @@ -201,7 +203,6 @@ class ObjectStore(CommonBackend):          """          Verify if u1db data exists in store.          """ -        doc = self._get_doc(self.U1DB_DATA_DOC_ID)          if not self._get_doc(self.U1DB_DATA_DOC_ID):              return False          return True @@ -234,7 +235,6 @@ class ObjectStore(CommonBackend):      replica_uid = property(          _get_replica_uid, _set_replica_uid, doc="Replica UID of the database") -      #-------------------------------------------------------------------------      # The methods below were cloned from u1db sqlite backend. They should at      # least exist and raise a NotImplementedError exception in CommonBackend @@ -387,12 +387,12 @@ class TransactionLog(SimpleLog):          return cur_gen, newest_trans_id, changes -      def get_transaction_log(self):          """          Return only a list of (doc_id, transaction_id)          """ -        return map(lambda x: (x[1], x[2]), sorted(self._get_log(reverse=False))) +        return map(lambda x: (x[1], x[2]), +                   sorted(self._get_log(reverse=False)))  class SyncLog(SimpleLog): @@ -416,7 +416,7 @@ class SyncLog(SimpleLog):          return (info[1], info[2])      def set_replica_gen_and_trans_id(self, other_replica_uid, -                                      other_generation, other_transaction_id): +                                     other_generation, other_transaction_id):          """          Set the last-known generation and transaction id for the other          database replica. @@ -425,6 +425,7 @@ class SyncLog(SimpleLog):          self.append((other_replica_uid, other_generation,                       other_transaction_id)) +  class ConflictLog(SimpleLog):      """      A list of (doc_id, my_doc_rev, my_content) tuples. @@ -433,7 +434,7 @@ class ConflictLog(SimpleLog):      def __init__(self, factory):          super(ConflictLog, self).__init__()          self._factory = factory -     +      def delete_conflicts(self, conflicts):          for conflict in conflicts:              self._set_log(self.filter(lambda x: @@ -448,4 +449,3 @@ class ConflictLog(SimpleLog):      def has_conflicts(self, doc_id):          return bool(self.filter(lambda x: x[0] == doc_id)) - diff --git a/backends/openstack.py b/backends/openstack.py index c027231c..a9615736 100644 --- a/backends/openstack.py +++ b/backends/openstack.py @@ -1,6 +1,6 @@ -from u1db import errors +# TODO: this backend is not tested yet.  from u1db.remote.http_target import HTTPSyncTarget -from swiftclient import client +import swiftclient  from soledad.backends.objectstore import ObjectStore @@ -25,12 +25,13 @@ class OpenStackDatabase(ObjectStore):      def _get_doc(self, doc_id, check_for_conflicts=False):          """Get just the document content, without fancy handling. -         +          Conflicts do not happen on server side, so there's no need to check          for them.          """          try: -            response, contents = self._connection.get_object(self._container, doc_id) +            response, contents = self._connection.get_object(self._container, +                                                             doc_id)              # TODO: change revision to be a dictionary element?              rev = response['x-object-meta-rev']              return self._factory(doc_id, rev, contents) @@ -53,7 +54,7 @@ class OpenStackDatabase(ObjectStore):      def _put_doc(self, doc, new_rev):          new_rev = self._allocate_doc_rev(doc.rev)          # TODO: change revision to be a dictionary element? -        headers = { 'X-Object-Meta-Rev' : new_rev } +        headers = {'X-Object-Meta-Rev': new_rev}          self._connection.put_object(self._container, doc_id, doc.get_json(),                                      headers=headers) @@ -77,6 +78,7 @@ class OpenStackDatabase(ObjectStore):          self._url, self._auth_token = self._connection.get_auth()          return self._url, self.auth_token +  class OpenStackSyncTarget(HTTPSyncTarget):      def get_sync_info(self, source_replica_uid): @@ -94,5 +96,3 @@ class OpenStackSyncTarget(HTTPSyncTarget):          self._db._set_replica_gen_and_trans_id(              source_replica_uid, source_replica_generation,              source_replica_transaction_id) - - diff --git a/backends/sqlcipher.py b/backends/sqlcipher.py index 3d03449e..08b4df43 100644 --- a/backends/sqlcipher.py +++ b/backends/sqlcipher.py @@ -59,11 +59,9 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):      _index_storage_value = 'expand referenced encrypted' -      @classmethod      def set_pragma_key(cls, db_handle, key): -       db_handle.cursor().execute("PRAGMA key = '%s'" % key) - +        db_handle.cursor().execute("PRAGMA key = '%s'" % key)      def __init__(self, sqlite_file, password, document_factory=None):          """Create a new sqlcipher file.""" @@ -74,20 +72,18 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):          self._ensure_schema()          self._factory = document_factory or Document -      def _check_if_db_is_encrypted(self, sqlite_file):          if not os.path.exists(sqlite_file):              return          else:              try: -                # try to open an encrypted database with the regular u1db backend -                # should raise a DatabaseError exception. +                # try to open an encrypted database with the regular u1db +                # backend should raise a DatabaseError exception.                  SQLitePartialExpandDatabase(sqlite_file)                  raise DatabaseIsNotEncrypted()              except DatabaseError:                  pass -      @classmethod      def _open_database(cls, sqlite_file, password, document_factory=None):          if not os.path.isfile(sqlite_file): @@ -113,7 +109,6 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):          return SQLCipherDatabase._sqlite_registry[v](              sqlite_file, password, document_factory=document_factory) -      @classmethod      def open_database(cls, sqlite_file, password, create, backend_cls=None,                        document_factory=None): @@ -129,7 +124,6 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):              return backend_cls(sqlite_file, password,                                 document_factory=document_factory) -      def sync(self, url, creds=None, autocreate=True, soledad=None):          """          Synchronize encrypted documents with remote replica exposed at url. @@ -137,9 +131,7 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):          from u1db.sync import Synchronizer          from leap.soledad.backends.leap_backend import LeapSyncTarget          return Synchronizer(self, LeapSyncTarget(url, creds=creds), -                            soledad=self._soledad).sync( -            autocreate=autocreate) +                            soledad=self._soledad).sync(autocreate=autocreate)  SQLiteDatabase.register_implementation(SQLCipherDatabase) - | 
