[Zope-CVS] CVS: Products/AdaptableStorage/gateway_fs - FSClassificationSection.py:1.2 FSConnection.py:1.3 FSDirectoryItems.py:1.3

Shane Hathaway shane@zope.com
Thu, 5 Dec 2002 12:39:18 -0500


Update of /cvs-repository/Products/AdaptableStorage/gateway_fs
In directory cvs.zope.org:/tmp/cvs-serv16479/gateway_fs

Modified Files:
	FSClassificationSection.py FSConnection.py FSDirectoryItems.py 
Log Message:
The following comments might not make sense to anyone but me right now,
but someday it might be useful for historical purposes.

- Removed ClassificationAspect.  This strategy simply can't work correctly.
  The load() method of FSClassificationSection was using the wrong object
  mapper to classify filenames (it was using the child's rather than the
  container's object mapper), revealing that classification should be
  known only to the container, not the object.

- Added a "preserve" write mode to FSConnection, enabling classification to
  be preserved even though other sections get changed.

- Simplified FSClassificationSection using the new preserve write mode.

- Since ClassificationAspect no longer exists, nothing will ever delegate
  aspect loading/storing to MetaTypeClassifier.  Removed the methods that
  implemented the IAspectSerializer interface.

- Now gateways can return None as the serial, making them invisible to the
  hash computation.

- Added tests that verify that classifications get stored in preserve mode.

- Turned the debug flag back off :-)



=== Products/AdaptableStorage/gateway_fs/FSClassificationSection.py 1.1 => 1.2 ===
--- Products/AdaptableStorage/gateway_fs/FSClassificationSection.py:1.1	Wed Dec  4 23:18:07 2002
+++ Products/AdaptableStorage/gateway_fs/FSClassificationSection.py	Thu Dec  5 12:38:46 2002
@@ -11,62 +11,35 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Gateway of object classification data.
+"""Gateway for storing classification data.
+
+The classification info is designed to be used by the container
+of an object, not the object itself.  But frequently an object gets
+stored without its container being stored.  So this gateway does nothing
+other than preserve classification information for an object.
 
 $Id$
 """
 
-from serial_public import IGateway, RecordSchema
+from serial_public import IGateway
+
+from FSConnection import WRITE_PRESERVE
+
 
 class FSClassificationSection:
 
     __implements__ = IGateway
 
-    schema = RecordSchema()
-    schema.addColumn('classification', 'classification')
-
     def __init__(self, fs_conn):
         self.fs_conn = fs_conn
 
     def getSchema(self):
-        return self.schema
-
-    def getIdFrom(self, key):
-        pos = key.rfind('/')
-        if pos >= 0:
-            return key[pos + 1:]
-        else:
-            return key
+        return None
 
     def load(self, object_mapper, key):
-        classification = {}
-        text = self.fs_conn.readSection(key, 'classification', '')
-        if text:
-            lines = text.split('\n')
-            for line in lines:
-                if '=' in line:
-                    k, v = line.split('=', 1)
-                    classification[k.strip()] = v.strip()
-        if not classification:
-            name = self.getIdFrom(key)
-            classifier = object_mapper.getClassifier()
-            isdir = (self.fs_conn.readNodeType(key) == 'd')
-            classification, mapper_name = classifier.classifyFilename(
-                name, isdir)
-        items = classification.items()
-        items.sort()
-        return ((classification,),), tuple(items)
-
-    def store(self, object_mapper, key, state, required=1):
-        assert len(state) == 1
-        assert len(state[0]) == 1
-        classification = state[0][0]
-        items = classification.items()
-        items.sort()
-        lines = []
-        for k, v in items:
-            lines.append('%s=%s' % (k.strip(), v.strip()))
-        text = '\n'.join(lines)
-        self.fs_conn.writeSection(key, 'classification', text, required)
-        return tuple(items)
+        return None, None
+
+    def store(self, object_mapper, key, state):
+        self.fs_conn.writeSection(key, 'classification', '', WRITE_PRESERVE)
+        return None
 


=== Products/AdaptableStorage/gateway_fs/FSConnection.py 1.2 => 1.3 ===
--- Products/AdaptableStorage/gateway_fs/FSConnection.py:1.2	Tue Dec  3 18:10:52 2002
+++ Products/AdaptableStorage/gateway_fs/FSConnection.py	Thu Dec  5 12:38:46 2002
@@ -35,6 +35,12 @@
 DATA_SECTION = '@data'
 
 
+# Write modes
+WRITE_UNCONDITIONAL = 0
+WRITE_CONDITIONAL = 1
+WRITE_PRESERVE = 2
+
+
 class FSConnection:
     """Reads / writes files with 'sections'.
 
@@ -59,6 +65,10 @@
         #  rest of the data for a subpath is in _pending.
         # _conditional: { subpath string -> { section_name -> data } }
         self._conditional = {}
+        # _preserve holds the name of sections that will either be
+        #  copied or changed by another write operation.
+        # _preserve: { subpath string -> { section_name -> 1 } }
+        self._preserve = {}
 
 
     def expandPath(self, subpath, check_exists=0):
@@ -83,7 +93,7 @@
         assert section_name != DATA_SECTION
 
 
-    def _write(self, subpath, section_name, data, conditional=0):
+    def _write(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
         # XXX We should be checking for '..'
         path = self.expandPath(subpath)
         # Do some early checking.
@@ -92,12 +102,13 @@
             if not v:
                 raise FSWriteError(
                     "Can't get write access to %s" % subpath)
-        self.record(subpath, section_name, data, conditional)
+        self.queue(subpath, section_name, data, mode)
 
 
-    def writeSection(self, subpath, section_name, data, conditional=0):
+    def writeSection(self, subpath, section_name, data,
+                     mode=WRITE_UNCONDITIONAL):
         self.checkSectionName(section_name)
-        self._write(subpath, section_name, data, conditional)
+        self._write(subpath, section_name, data, mode)
 
 
     def writeNodeType(self, subpath, data):
@@ -108,7 +119,7 @@
             if (want_dir != (not not os.path.isdir(path))):
                 raise FSWriteError(
                     "Can't mix file and directory at %s" % subpath)
-        self.record(subpath, NODE_TYPE_SECTION, data, 0)
+        self.queue(subpath, NODE_TYPE_SECTION, data)
 
 
     def writeData(self, subpath, data):
@@ -280,12 +291,18 @@
     def getName(self):
         return self.basepath
 
-    def record(self, subpath, section_name, data, conditional=0):
-        """Records data to be written at commit time"""
-        if conditional:
+    def queue(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
+        """Queues data to be written at commit time"""
+        if mode == WRITE_UNCONDITIONAL:
+            m = self._pending
+        elif mode == WRITE_CONDITIONAL:
             m = self._conditional
+        elif mode == WRITE_PRESERVE:
+            m = self._preserve
+            # The data doesn't matter in this case.
+            data = 1
         else:
-            m = self._pending
+            raise RuntimeError('Unknown write mode: %d' % mode)
         sections = m.get(subpath)
         if sections is None:
             sections = {}
@@ -310,27 +327,37 @@
             if self._pending.get(subpath):
                 # Add the conditional data.
                 for section_name, data in sections.items():
-                    self.record(subpath, section_name, data)
+                    self.queue(subpath, section_name, data)
+        for subpath, sections in self._preserve.items():
+            psections = self._pending.get(subpath)
+            for section_name, data in sections.items():
+                if not psections or not psections.has_key(section_name):
+                    # Preserve the existing data.
+                    data = self.readSection(subpath, section_name, '')
+                    if data:
+                        self.queue(subpath, section_name, data)
         self._conditional.clear()
         items = self._pending.items()
         items.sort()  # Ensure that base directories come first.
         self.beforeWrite(items)
         self._final = 1
 
-    def abort(self):
+    def reset(self):
         self._final = 0
         self._pending.clear()
         self._conditional.clear()
+        self._preserve.clear()
+
+    def abort(self):
+        self.reset()
 
     def finish(self):
         if self._final:
-            self._final = 0
             try:
                 items = self._pending.items()
                 items.sort()  # Ensure that base directories come first.
                 for subpath, sections in items:
                     self.writeFinal(subpath, sections)
             finally:
-                self._pending.clear()
-                self._conditional.clear()
+                self.reset()
 


=== Products/AdaptableStorage/gateway_fs/FSDirectoryItems.py 1.2 => 1.3 ===
--- Products/AdaptableStorage/gateway_fs/FSDirectoryItems.py:1.2	Tue Dec  3 18:10:52 2002
+++ Products/AdaptableStorage/gateway_fs/FSDirectoryItems.py	Thu Dec  5 12:38:46 2002
@@ -19,6 +19,8 @@
 
 from serial_public import IGateway, RecordSchema
 
+from FSConnection import WRITE_CONDITIONAL
+
 
 class FSDirectoryItems:
 
@@ -81,7 +83,8 @@
             for k, v in items:
                 text.append('%s=%s' % (k, v))
             text = '\n'.join(text)
-            c.writeSection(subkey, 'classification', text, 1)
+            # Write it only if the rest of the subobject is also stored
+            c.writeSection(subkey, 'classification', text, WRITE_CONDITIONAL)
         names.sort()
         serial.sort()
         c.writeData(key, names)