[Checkins]
SVN: zope.file/branches/ajung-blobs/src/zope/file/file.py
re-added Reader/Writer classes...don't try to be smarter than
Fred :-)
Andreas Jung
andreas at andreas-jung.com
Mon Feb 26 15:06:03 EST 2007
Log message for revision 72837:
re-added Reader/Writer classes...don't try to be smarter than Fred :-)
Changed:
U zope.file/branches/ajung-blobs/src/zope/file/file.py
-=-
Modified: zope.file/branches/ajung-blobs/src/zope/file/file.py
===================================================================
--- zope.file/branches/ajung-blobs/src/zope/file/file.py 2007-02-26 20:01:06 UTC (rev 72836)
+++ zope.file/branches/ajung-blobs/src/zope/file/file.py 2007-02-26 20:06:02 UTC (rev 72837)
@@ -22,9 +22,9 @@
import zope.location.interfaces
import zope.file.interfaces
import zope.interface
+
from ZODB.Blobs.Blob import Blob
-
class File(persistent.Persistent):
zope.interface.implements(
@@ -35,6 +35,9 @@
__parent__ = None
mimeType = None
+ _data = ""
+ size = 0
+
def __init__(self, mimeType=None, parameters=None):
self.mimeType = mimeType
if parameters is None:
@@ -42,21 +45,135 @@
else:
parameters = dict(parameters)
self.parameters = parameters
- self._data = Blob()
def open(self, mode="r"):
- return self._data.open(mode)
+ if mode.startswith("r"):
+ return Reader(self, mode)
+ if mode.startswith("w"):
+ return Writer(self, mode)
+ raise ValueError("unsupported `mode` value")
def openDetached(self):
return self._data.openDetached()
-
@property
def size(self):
- fp = self._data.open()
+ fp = self._data.open('r')
fp.seek(0, 2)
- size = fp.tell()
+ size = int(fp.tell())
fp.close()
return size
-
+
+class Accessor(object):
+ """Base class for the reader and writer."""
+
+ _closed = False
+ _sio = None
+
+ # 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 = Blob() # cStringIO creates immutable
+ fp = self._sio.open('w')
+ fp.write('')
+ # instance if you pass a string, unlike StringIO :-/
+ if not self._write:
+ fp.write(self._data)
+ fp.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 = Blob()
+ fp = self._sio.open('w')
+ fp.write(self._data)
+ fp.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 fp
+
+ 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
+ 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()
+
More information about the Checkins
mailing list