[Checkins] SVN: zope.file/branches/ajung-blobs/src/zope/file/ integrated blob support

Andreas Jung andreas at andreas-jung.com
Mon Feb 26 13:20:19 EST 2007


Log message for revision 72831:
  integrated blob support
  

Changed:
  U   zope.file/branches/ajung-blobs/src/zope/file/configure.zcml
  U   zope.file/branches/ajung-blobs/src/zope/file/download.py
  U   zope.file/branches/ajung-blobs/src/zope/file/file.py

-=-
Modified: zope.file/branches/ajung-blobs/src/zope/file/configure.zcml
===================================================================
--- zope.file/branches/ajung-blobs/src/zope/file/configure.zcml	2007-02-26 18:09:37 UTC (rev 72830)
+++ zope.file/branches/ajung-blobs/src/zope/file/configure.zcml	2007-02-26 18:20:18 UTC (rev 72831)
@@ -14,6 +14,10 @@
         permission="zope.ManageContent"
         set_attributes="mimeType parameters"
         />
+    <require
+        permission="zope.ManageContent"
+        attributes="openDetached"
+        />
     <implements
         interface="
           zope.annotation.interfaces.IAttributeAnnotatable
@@ -25,23 +29,14 @@
   <adapter factory=".adapters.ReadFileAdapter" />
   <adapter factory=".adapters.WriteFileAdapter" />
 
-  <!-- set up permissions for the accessor objects -->
-
-  <class class=".file.Reader">
+  <class class="ZODB.Blobs.Blob.BlobFile">
     <require
         permission="zope.View"
-        interface=".interfaces.IFileReader"
+        attributes="read openDetached"
         />
-  </class>
-
-  <class class=".file.Writer">
     <require
-        permission="zope.View"
-        attributes="mode"
-        />
-    <require
         permission="zope.ManageContent"
-        attributes="close flush write"
+        attributes="write close"
         />
   </class>
 

Modified: zope.file/branches/ajung-blobs/src/zope/file/download.py
===================================================================
--- zope.file/branches/ajung-blobs/src/zope/file/download.py	2007-02-26 18:09:37 UTC (rev 72830)
+++ zope.file/branches/ajung-blobs/src/zope/file/download.py	2007-02-26 18:20:18 UTC (rev 72831)
@@ -21,6 +21,7 @@
 import zope.mimetype.interfaces
 import zope.publisher.browser
 import zope.publisher.http
+from zope.proxy import removeAllProxies
 
 
 class Download(zope.publisher.browser.BrowserView):
@@ -48,13 +49,7 @@
         zope.publisher.http.IResult)
 
     def getFile(self, context):
-        # This ensures that what's left has no connection to the
-        # application/database; ZODB BLOBs will provide a equivalent
-        # feature once available.
-        f = context.open('rb')
-        res = cStringIO.StringIO(f.read())
-        f.close()
-        return res
+        return removeAllProxies(context.openDetached())
 
     def __init__(self, context, contentType=None, downloadName=None,
                  contentDisposition=None, contentLength=None):

Modified: zope.file/branches/ajung-blobs/src/zope/file/file.py
===================================================================
--- zope.file/branches/ajung-blobs/src/zope/file/file.py	2007-02-26 18:09:37 UTC (rev 72830)
+++ zope.file/branches/ajung-blobs/src/zope/file/file.py	2007-02-26 18:20:18 UTC (rev 72831)
@@ -22,6 +22,7 @@
 import zope.location.interfaces
 import zope.file.interfaces
 import zope.interface
+from ZODB.Blobs.Blob import Blob
 
 
 class File(persistent.Persistent):
@@ -34,9 +35,6 @@
     __parent__ = None
     mimeType = None
 
-    _data = ""
-    size = 0
-
     def __init__(self, mimeType=None, parameters=None):
         self.mimeType = mimeType
         if parameters is None:
@@ -44,132 +42,21 @@
         else:
             parameters = dict(parameters)
         self.parameters = parameters
+        self._data = Blob()
 
     def open(self, mode="r"):
-        if mode in ("r", "rb"):
-            return Reader(self, mode)
-        if mode in ("w", "wb"):
-            return Writer(self, mode)
-        if mode in ("r+", "r+b", "rb+"):
-            return ReaderPlus(self, mode)
-        if mode in ("w+", "w+b", "wb+"):
-            return WriterPlus(self, mode)
-        raise ValueError("unsupported `mode` value")
+        return self._data.open(mode)
 
+    def openDetached(self):
+        return self._data.openDetached()
 
-class Accessor(object):
-    """Base class for the reader and writer."""
 
-    _closed = False
-    _sio = None
+    @property
+    def size(self):
+        fp = self._data.open()
+        fp.seek(0, 2)
+        size = fp.tell()
+        fp.close()
+        return size
+            
 
-    # XXX Accessor objects need to have an __parent__ to support the
-    # security machinery, but they aren't ILocation instances since
-    # they aren't addressable via URL.
-    #
-    # There needs to be an interface for this in Zope 3, but that's a
-    # large task since it affects lots of Z3 code.  __parent__ should
-    # be defined by an interface from which ILocation is derived.
-
-    def __init__(self, file, mode):
-        self.__parent__ = file
-        self.mode = mode
-
-    def close(self):
-        if not self._closed:
-            self._close()
-            self._closed = True
-            if "_sio" in self.__dict__:
-                del self._sio
-
-    def __getstate__(self):
-        """Make sure the accessors can't be stored in ZODB."""
-        cls = self.__class__
-        raise TypeError("%s.%s instance is not picklable"
-                        % (cls.__module__, cls.__name__))
-
-    _write = False
-
-    def _get_stream(self):
-        # get the right string io
-        if self._sio is None:
-            self._data = self.__parent__._data
-            # create if we don't have one yet
-            self._sio = cStringIO.StringIO() # cStringIO creates immutable
-            # instance if you pass a string, unlike StringIO :-/
-            if not self._write:
-                self._sio.write(self._data)
-                self._sio.seek(0)
-        elif self._data is not self.__parent__._data:
-            # if the data for the underlying object has changed,
-            # update our view of the data:
-            pos = self._sio.tell()
-            self._data = self.__parent__._data
-            self._sio = cStringIO.StringIO()
-            self._sio.write(self._data)
-            self._sio.seek(pos) # this may seek beyond EOF, but that appears to
-            # be how it is supposed to work, based on experiments.  Writing
-            # will insert NULLs in the previous positions.
-        return self._sio
-
-    def _close(self):
-        pass
-
-
-class Reader(Accessor):
-
-    zope.interface.implements(
-        zope.file.interfaces.IFileReader)
-
-    _data = File._data
-
-    def read(self, size=-1):
-        if self._closed:
-            raise ValueError("I/O operation on closed file")
-        return self._get_stream().read(size)
-
-    def seek(self, offset, whence=0):
-        if self._closed:
-            raise ValueError("I/O operation on closed file")
-        if whence not in (0, 1, 2):
-            raise ValueError("illegal value for `whence`")
-        self._get_stream().seek(offset, whence)
-
-    def tell(self):
-        if self._closed:
-            raise ValueError("I/O operation on closed file")
-        if self._sio is None:
-            return 0L
-        else:
-            return self._sio.tell()
-
-
-class Writer(Accessor):
-
-    zope.interface.implements(
-        zope.file.interfaces.IFileWriter)
-
-    _write = True
-
-    def flush(self):
-        if self._closed:
-            raise ValueError("I/O operation on closed file")
-        if self._sio is not None:
-            self.__parent__._data = self._sio.getvalue()
-            self.__parent__.size = len(self.__parent__._data)
-            self._data = self.__parent__._data
-
-    def write(self, data):
-        if self._closed:
-            raise ValueError("I/O operation on closed file")
-        self._get_stream().write(data)
-
-    def _close(self):
-        self.flush()
-
-class WriterPlus(Writer, Reader):
-    pass
-
-class ReaderPlus(Writer, Reader):
-
-    _write = False



More information about the Checkins mailing list