Commits

Thomas Waldmann committed 16ea00a

create mixin classes that transform bytes <-> file stores

often (but maybe not always), the underlying storage system just offers either
a bytes- or files-oriented interface, not both.

but on the backend layer, we need a BytesStore for the metadata and a
FileStore for the data.

Comments (0)

Files changed (7)

MoinMoin/storage/stores/__init__.py

         """
 
 
+class BytesMutableStoreMixin(object):
+    """
+    mix this into a FileMutableStore to get a BytesMutableStore, like shown here:
+
+    class BytesStore(BytesMutableStoreMixin, FileStore, BytesMutableStoreBase):
+        # that's all, nothing more needed
+    """
+    def __getitem__(self, key):
+        with super(BytesMutableStoreMixin, self).__getitem__(key) as stream:
+            return stream.read()
+
+    def __setitem__(self, key, value):
+        with StringIO(value) as stream:
+            super(BytesMutableStoreMixin, self).__setitem__(key, stream)
+
+
 class FileMutableStoreBase(MutableStoreBase):
     @abstractmethod
     def __setitem__(self, key, stream):
               closing that file later. caller must not rely on some specific
               file pointer position after we return.
         """
+
+class FileMutableStoreMixin(object):
+    """
+    mix this into a BytesMutableStore to get a FileMutableStore, like shown here:
+
+    class FileStore(FileMutableStoreMixin, BytesStore, FileMutableStoreBase)
+        # that's all, nothing more needed
+    """
+    def __getitem__(self, key):
+        value = super(FileMutableStoreMixin, self).__getitem__(key)
+        return StringIO(value)
+
+    def __setitem__(self, key, stream):
+        value = stream.read()
+        super(FileMutableStoreMixin, self).__setitem__(key, value)

MoinMoin/storage/stores/fs.py

 import errno
 import shutil
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase
+from . import (BytesMutableStoreBase, FileMutableStoreBase,
+               BytesMutableStoreMixin, FileMutableStoreMixin)
 
 
-class _Store(MutableStoreBase):
+class FileStore(FileMutableStoreBase):
     """
     A simple filesystem-based store.
 
     def __delitem__(self, key):
         os.remove(self._mkpath(key))
 
-
-class BytesStore(_Store, BytesMutableStoreBase):
-    def __getitem__(self, key):
-        try:
-            with open(self._mkpath(key), 'rb') as f:
-                return f.read() # better use get_file() and read smaller blocks for big files
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                raise KeyError(key)
-            raise
-
-    def __setitem__(self, key, value):
-        with open(self._mkpath(key), "wb") as f:
-            f.write(value)
-
-
-class FileStore(_Store, FileMutableStoreBase):
     def __getitem__(self, key):
         try:
             return open(self._mkpath(key), 'rb')
         with open(self._mkpath(key), "wb") as f:
             blocksize = 64 * 1024
             shutil.copyfileobj(stream, f, blocksize)
+
+
+class BytesStore(BytesMutableStoreMixin, FileStore, BytesMutableStoreBase):
+    """filesystem BytesStore"""

MoinMoin/storage/stores/kc.py

 
 from kyotocabinet import *
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase, StringIO
+from . import (BytesMutableStoreBase, FileMutableStoreBase,
+               BytesMutableStoreMixin, FileMutableStoreMixin)
 
 
-class _Store(MutableStoreBase):
+class BytesStore(BytesMutableStoreBase):
     """
     Kyoto cabinet based store.
     """
     def __delitem__(self, key):
         self._db.remove(key)
 
-
-class BytesStore(_Store, BytesMutableStoreBase):
     def __getitem__(self, key):
         value = self._db.get(key)
         if value is None:
             raise KeyError("set error: " + str(self._db.error()))
 
 
-class FileStore(_Store, FileMutableStoreBase):
-    def __getitem__(self, key):
-        value = self._db.get(key)
-        if value is None:
-            raise KeyError("get error: " + str(self._db.error()))
-        return StringIO(value)
-
-    def __setitem__(self, key, stream):
-        if not self._db.set(key, stream.read()):
-            raise KeyError("set error: " + str(self._db.error()))
+class FileStore(FileMutableStoreMixin, BytesStore, FileMutableStoreBase):
+    """Kyoto Cabinet FileStore"""

MoinMoin/storage/stores/kt.py

 import urllib
 from httplib import HTTPConnection
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase, StringIO
+from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase
 
 
 class _Store(MutableStoreBase):

MoinMoin/storage/stores/memory.py

 
 from __future__ import absolute_import, division
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase, StringIO
+from . import (BytesMutableStoreBase, FileMutableStoreBase,
+               BytesMutableStoreMixin, FileMutableStoreMixin)
 
 
-class _Store(MutableStoreBase):
+class BytesStore(BytesMutableStoreBase):
     """
     A simple dict-based in-memory store. No persistence!
     """
     def __delitem__(self, key):
         del self._st[key]
 
-
-class BytesStore(_Store, BytesMutableStoreBase):
     def __getitem__(self, key):
         return self._st[key]
 
         self._st[key] = value
 
 
-class FileStore(_Store, FileMutableStoreBase):
-    def __getitem__(self, key):
-        return StringIO(self._st[key])
-
-    def __setitem__(self, key, stream):
-        self._st[key] = stream.read()
+class FileStore(FileMutableStoreMixin, BytesStore, FileMutableStoreBase):
+    """memory FileStore"""

MoinMoin/storage/stores/sqla.py

 from sqlalchemy import create_engine, select, MetaData, Table, Column, String, Binary
 from sqlalchemy.pool import StaticPool
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase, StringIO
+from . import (BytesMutableStoreBase, FileMutableStoreBase,
+               BytesMutableStoreMixin, FileMutableStoreMixin)
 
 KEY_LEN = 128
 VALUE_LEN = 1024 * 1024 # 1MB binary data
 
 
-class _Store(MutableStoreBase):
+class BytesStore(BytesMutableStoreBase):
     """
     A simple dict-based in-memory store. No persistence!
     """
     def __delitem__(self, key):
         self.table.delete().where(self.table.c.key == key).execute()
 
-
-class BytesStore(_Store, BytesMutableStoreBase):
     def __getitem__(self, key):
         value = select([self.table.c.value], self.table.c.key == key).execute().fetchone()
         if value is not None:
         self.table.insert().execute(key=key, value=value)
 
 
-class FileStore(_Store, FileMutableStoreBase):
-    def __getitem__(self, key):
-        value = select([self.table.c.value], self.table.c.key == key).execute().fetchone()
-        if value is not None:
-            return StringIO(value[0])
-        else:
-            raise KeyError(key)
-
-    def __setitem__(self, key, stream):
-        self.table.insert().execute(key=key, value=stream.read())
+class FileStore(FileMutableStoreMixin, BytesStore, FileMutableStoreBase):
+    """sqlalchemy FileStore"""

MoinMoin/storage/stores/sqlite.py

 import zlib
 from sqlite3 import *
 
-from . import MutableStoreBase, BytesMutableStoreBase, FileMutableStoreBase, StringIO
+from . import (BytesMutableStoreBase, FileMutableStoreBase,
+               BytesMutableStoreMixin, FileMutableStoreMixin)
 
 
-class _Store(MutableStoreBase):
+class BytesStore(BytesMutableStoreBase):
     """
     A simple sqlite3 based store.
     """
             value = zlib.decompress(value)
         return value
 
-
-class BytesStore(_Store, BytesMutableStoreBase):
     def __getitem__(self, key):
         rows = list(self.conn.execute("select value from {0} where key=?".format(self.table_name), (key, )))
         if not rows:
             self.conn.execute('insert into {0} values (?, ?)'.format(self.table_name), (key, buffer(value)))
 
 
-class FileStore(_Store, FileMutableStoreBase):
-    def __getitem__(self, key):
-        rows = list(self.conn.execute("select value from {0} where key=?".format(self.table_name), (key, )))
-        if not rows:
-            raise KeyError(key)
-        value = str(rows[0]['value'])
-        return StringIO(self._decompress(value))
-
-    def __setitem__(self, key, stream):
-        value = stream.read()
-        value = self._compress(value)
-        with self.conn:
-            self.conn.execute('insert into {0} values (?, ?)'.format(self.table_name), (key, buffer(value)))
+class FileStore(FileMutableStoreMixin, BytesStore, FileMutableStoreBase):
+    """sqlite FileStore"""