conf.py
changeset 0 257003279747
child 1 2223ade4f259
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conf.py	Thu Apr 02 17:47:43 2009 +0300
@@ -0,0 +1,114 @@
+"""
+    Generic configuration file output
+"""
+
+import os, tempfile, shutil
+
+class Object (object) :
+    """
+        An object that can be written to a ConfFile, as multiple lines of text.
+    """
+
+    def fmt_lines (self) :
+        """
+            Yield a series of lines to be output in the file
+        """
+        
+        abstract
+
+class File (object) :
+    """
+        A single configuration file on the filesystem.
+
+        Configuration files are 
+    """
+
+    def __init__ (self, name, path, backup_suffix='.bak', mode=0644) :
+        """
+            Initialize the config file, but don't open it yet
+
+            @param name the human-readable friendly name for the config file
+            @param path the full filesystem path for the file
+            @param backup_suffix rename the old file by adding this suffix when replacing it
+            @param mode the permission bits for the new file
+        """
+  
+        self.name = name
+        self.path = path
+        self.backup_suffix = backup_suffix
+        self.mode = mode
+    
+    def write_file (self, file, objects) :
+        """
+            Write out the given config objects into the given file
+        """
+
+        writer = Writer(file)
+        writer.write_objs(objects)
+
+    def write (self, objects) :
+        """
+            Write out a new config file with the given series of objects using the following procedure:
+                * lock the real file
+                * open a new temporary file, and write out the objects into that, closing it
+                * move the real file out of the way
+                * move the temporary file into the real file's place
+                * unlock the real file
+        """
+
+        # XXX: how to aquire the lock?
+        # XXX: this needs checking over
+
+        # open the new temporary file
+        # XXX: ensure fd is closed
+        tmp_fd, tmp_path = tempfile.mkstemp(prefix=self.name)
+
+        # ...as a file
+        tmp_file = os.fdopen(tmp_fd, "w")
+        
+        # fix the permissions
+        os.chmod(tmp_path, self.mode)
+
+        # write it
+        self.write_file(tmp_file, objects)
+
+        # close it
+        tmp_file.close()
+        del writer
+        del tmp_file
+        
+        # move the old file out of the way
+        os.rename(self.path, self.path + self.backup_suffix)
+
+        # move the new file in
+        shutil.move(tmp_path, self.path)
+
+class Writer (object) :
+    """
+        A conf.Writer is used to write out a new conf.File (as a temporary file)
+    """
+
+    def __init__ (self, file) :
+        """
+            @param file the temporary file object
+        """
+
+        self.file = file
+    
+    def write_obj (self, obj) :
+        """
+            Write a single object to the file
+        """
+        
+        # just write out all the lines
+        self.file.writelines(obj.fmt_lines())
+
+    def write_objs (self, objs) :
+        """
+            Write a series of objects to the file
+        """
+        
+        # just write each in turn
+        for obj in objs :
+            self.write_obj(obj)
+