[Zope-CVS] CVS: Products/AdaptableStorage/gateway_fs - FSConnection.py:1.6.2.1

Christian Zagrodnick cz@gocept.com
Mon, 13 Jan 2003 14:28:26 -0500


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

Modified Files:
      Tag: zagy-patches
	FSConnection.py 
Log Message:
- Merging HEAD into zagy-patches branch

- Added hidden_filenames parameter.  This string is interpreted as comma
  separated list of names to be completely ignored.


=== Products/AdaptableStorage/gateway_fs/FSConnection.py 1.6 => 1.6.2.1 ===
--- Products/AdaptableStorage/gateway_fs/FSConnection.py:1.6	Tue Dec 31 16:47:44 2002
+++ Products/AdaptableStorage/gateway_fs/FSConnection.py	Mon Jan 13 14:28:24 2003
@@ -23,23 +23,17 @@
 
 from interfaces.public import IFSConnection
 from exceptions import FSWriteError
-from mapper_public import ITPCConnection
+from mapper_public import ITPCConnection, NoStateFoundError
 
 
-# Try to decipher this one ;-)
+# Try to decipher this regular expression ;-)
 # It basically matches "\n[sectionname]...\n", where len(sectionname) > 0.
 section_re = re.compile(r'^\[([^\[\]\n]+)\][^\r\n]*(?:\r\n|\r|\n)',
                       re.MULTILINE)
 
 
-NODE_TYPE_SECTION = '@node_type'
-DATA_SECTION = '@data'
-
-
-# Write modes
-WRITE_UNCONDITIONAL = 0
-WRITE_CONDITIONAL = 1
-WRITE_PRESERVE = 2
+NODE_TYPE_SECTION = '@node_type'  # Data is 'f' (file) or 'd' (directory)
+DATA_SECTION = '@data'  # Data is a string (file) or list of names (directory)
 
 
 class FSConnection:
@@ -56,24 +50,18 @@
 
     basepath = ''
 
-    def __init__(self, basepath, hidden_filename_prefix='.'):
+    def __init__(self, basepath, hidden_filename_prefix='.', hidden_filenames=[]):
         self.basepath = basepath
         self.hidden_filename_prefix = hidden_filename_prefix
+        self.hidden_filenames = map(lambda x: x.strip(), 
+            hidden_filenames.split(','))
         self._final = 0
         # _pending holds the data to be written.
         # _pending: { subpath string -> { section_name -> data } }
         self._pending = {}
-        # _conditional holds data that will be written only if the
-        #  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):
+    def expandPath(self, subpath):
         if self.basepath:
             while subpath.startswith('/') or subpath.startswith('\\'):
                 subpath = subpath[1:]
@@ -81,8 +69,6 @@
         else:
             # unchanged.
             path = subpath
-        if check_exists:
-            assert os.path.exists(path), '%s does not exist' % path
         return path
 
 
@@ -95,7 +81,7 @@
         assert section_name != DATA_SECTION
 
 
-    def _write(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
+    def _write(self, subpath, section_name, data):
         # XXX We should be checking for '..'
         path = self.expandPath(subpath)
         # Do some early checking.
@@ -104,13 +90,12 @@
             if not v:
                 raise FSWriteError(
                     "Can't get write access to %s" % subpath)
-        self.queue(subpath, section_name, data, mode)
+        self.queue(subpath, section_name, data)
 
 
-    def writeSection(self, subpath, section_name, data,
-                     mode=WRITE_UNCONDITIONAL):
+    def writeSection(self, subpath, section_name, data):
         self.checkSectionName(section_name)
-        self._write(subpath, section_name, data, mode)
+        self._write(subpath, section_name, data)
 
 
     def writeNodeType(self, subpath, data):
@@ -130,30 +115,40 @@
 
     def readSection(self, subpath, section_name, default=None):
         self.checkSectionName(section_name)
-        path = self.expandPath(subpath, 1)
+        path = self.expandPath(subpath)
         sections = self.getPropertiesFromFile(path)
         return sections.get(section_name, default)
 
 
     def readNodeType(self, subpath):
-        path = self.expandPath(subpath, 1)
+        path = self.expandPath(subpath)
+        if not os.path.exists(path):
+            raise NoStateFoundError(subpath)
         return os.path.isdir(path) and 'd' or 'f'
 
 
-    def readData(self, subpath):
-        path = self.expandPath(subpath, 1)
+    def readData(self, subpath, allow_missing=0):
+        path = self.expandPath(subpath)
         isdir = os.path.isdir(path)
         # Read either the directory listing or the file contents.
         if isdir:
             names = []
             prefix = self.hidden_filename_prefix
             for name in os.listdir(path):
-                if not name.startswith(self.hidden_filename_prefix):
-                    names.append(name)
+                if name.startswith(self.hidden_filename_prefix):
+                    continue
+                if name in self.hidden_filenames:
+                    continue
+                names.append(name)
             # Return a sequence instead of a string.
             return names
         else:
-            f = open(path, 'rb')
+            try:
+                f = open(path, 'rb')
+            except IOError:
+                if allow_missing:
+                    return None
+                raise
             try:
                 return f.read()
             finally:
@@ -175,9 +170,11 @@
         """Read a properties file next to path."""
         props_fn = self.getPropertiesPath(path)
 
-        if not os.path.exists(props_fn):
+        try:
+            f = open(props_fn, 'rb')
+        except IOError:
+            # The file is presumably nonexistent
             return {}
-        f = open(props_fn, 'rb')
         try:
             data = f.read()
         finally:
@@ -233,10 +230,12 @@
                         finally:
                             f.close()
                 else:
-                    if not data.endswith('\n'):
-                        data = data + '\n'
-                    props_f.write('\n[%s]\n' % name)
+                    props_f.write('[%s]\n' % name)
                     props_f.write(data.replace('[', '[['))
+                    if data.endswith('\n'):
+                        props_f.write('\n')
+                    else:
+                        props_f.write('\n\n')
         finally:
             props_f.close()
 
@@ -248,7 +247,8 @@
         existing = os.listdir(path)
         prefix = self.hidden_filename_prefix
         for fn in existing:
-            if not fn.startswith(prefix) and not linked.get(fn):
+            if (not fn.startswith(prefix) and not fn in self.hidden_filenames 
+                and not linked.get(fn)):
                 item_fn = os.path.join(path, fn)
                 if os.path.isdir(item_fn):
                     rmtree(item_fn)
@@ -268,7 +268,7 @@
                 raise FSWriteError(
                     'Data or node type not specified for %s' % subpath)
             t = sections[NODE_TYPE_SECTION]
-            if t not in 'df':
+            if t not in ('d', 'f'):
                 raise FSWriteError(
                     'node type must be "d" or "f" at %s' % subpath)
             dir = os.path.dirname(subpath)
@@ -287,18 +287,10 @@
                         'Data for a directory must be a list or tuple at %s'
                         % subpath)
 
-    def queue(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
+
+    def queue(self, subpath, section_name, data):
         """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:
-            raise RuntimeError('Unknown write mode: %d' % mode)
+        m = self._pending
         sections = m.get(subpath)
         if sections is None:
             sections = {}
@@ -311,6 +303,7 @@
         else:
             sections[section_name] = data
 
+
     #
     # ITPCConnection implementation
     #
@@ -333,20 +326,6 @@
 
         This is done while the transaction can still be vetoed safely.
         """
-        for subpath, sections in self._conditional.items():
-            if self._pending.get(subpath):
-                # Add the conditional data.
-                for section_name, data in sections.items():
-                    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)
@@ -355,8 +334,6 @@
     def reset(self):
         self._final = 0
         self._pending.clear()
-        self._conditional.clear()
-        self._preserve.clear()
 
     def abort(self):
         self.reset()