[Checkins] SVN: zope.file/trunk/src/zope/file/ Add support for '+'. Change some semantics to match experiential evidence...at least on one OS (Ubuntu).

Gary Poster gary at zope.com
Sun Nov 19 11:19:32 EST 2006


Log message for revision 71185:
  Add support for '+'.  Change some semantics to match experiential evidence...at least on one OS (Ubuntu).
  

Changed:
  U   zope.file/trunk/src/zope/file/README.txt
  U   zope.file/trunk/src/zope/file/file.py
  U   zope.file/trunk/src/zope/file/interfaces.py

-=-
Modified: zope.file/trunk/src/zope/file/README.txt
===================================================================
--- zope.file/trunk/src/zope/file/README.txt	2006-11-19 16:04:44 UTC (rev 71184)
+++ zope.file/trunk/src/zope/file/README.txt	2006-11-19 16:19:31 UTC (rev 71185)
@@ -196,3 +196,38 @@
   >>> r.tell()
   Traceback (most recent call last):
   ValueError: I/O operation on closed file
+
+The file object also supports the '+' mode--both reading and writing
+simultaneously.  This can be convenient for allowing it to be used with
+tools (such as the TIFF PIL plugin as of this writing) with features
+that expect files in this mode.
+
+  >>> rw = f.open('r+')
+  >>> rw.tell()
+  0L
+  >>> rw.read()
+  'some text more text still more woohoo!'
+  >>> rw.tell()
+  38
+  >>> rw.write(' yippee!')
+  >>> rw.seek(31)
+  >>> rw.read()
+  'woohoo! yippee!'
+  >>> rw.seek(31)
+  >>> rw.write('THE END')
+  >>> rw.seek(0)
+  >>> rw.read()
+  'some text more text still more THE END yippee!'
+  >>> rw.close()
+  >>> rw = f.open('w+')
+  >>> rw.tell()
+  0L
+  >>> rw.read()
+  ''
+  >>> rw.write('hi.')
+  >>> rw.tell()
+  3
+  >>> rw.seek(0)
+  >>> rw.read()
+  'hi.'
+  >>> rw.close()

Modified: zope.file/trunk/src/zope/file/file.py
===================================================================
--- zope.file/trunk/src/zope/file/file.py	2006-11-19 16:04:44 UTC (rev 71184)
+++ zope.file/trunk/src/zope/file/file.py	2006-11-19 16:19:31 UTC (rev 71185)
@@ -50,6 +50,10 @@
             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")
 
 
@@ -84,6 +88,30 @@
         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
 
@@ -115,46 +143,33 @@
         else:
             return self._sio.tell()
 
-    def _get_stream(self):
-        # get the right string io
-        if self._sio is None:
-            # create if we don't have one yet
-            self._data = self.__parent__._data
-            self._sio = cStringIO.StringIO(self._data)
-        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
-            if pos > len(self._data):
-                # need to check if this is really right
-                pos = len(self._data)
-            self._sio = cStringIO.StringIO(self._data)
-            self._sio.seek(pos)
-        return self._sio
 
-
 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 _get_stream(self):
-        if self._sio is None:
-            self._sio = cStringIO.StringIO()
-        return self._sio
-
     def _close(self):
         self.flush()
+
+class WriterPlus(Writer, Reader):
+    pass
+
+class ReaderPlus(Writer, Reader):
+
+    _write = False

Modified: zope.file/trunk/src/zope/file/interfaces.py
===================================================================
--- zope.file/trunk/src/zope/file/interfaces.py	2006-11-19 16:04:44 UTC (rev 71184)
+++ zope.file/trunk/src/zope/file/interfaces.py	2006-11-19 16:19:31 UTC (rev 71185)
@@ -30,11 +30,13 @@
     def open(mode="r"):
         """Return an object providing access to the file data.
 
-        Allowed values for `mode` are 'r' and 'rb' (read) and 'w' and
-        'wb' (write).  Other values cause `ValueError` to be raised.
+        Allowed values for `mode` are 'r' and 'rb' (read); 'w' and
+        'wb' (write); and 'w+', 'w+b', 'wb+', 'r+', 'r+b', and 'rb+' (both).
+        Other values cause `ValueError` to be raised.
 
         If the file is opened in read mode, an `IFileReader` is
         returned; if opened in write mode, an `IFileWriter` is
+        returned; if in read/write, an object that implements both is
         returned.
 
         All readers and writers operate in 'binary' mode.



More information about the Checkins mailing list