kadischi/lib shvar.py,1.2,1.3

Jasper O'neal Hartline (autopsy) fedora-extras-commits at redhat.com
Tue Jun 20 21:37:52 UTC 2006


Author: autopsy

Update of /cvs/devel/kadischi/lib
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv13790/kadischi/lib

Added Files:
	shvar.py 
Log Message:
Re-addition of shvar.py at mode 664


Index: shvar.py
===================================================================
RCS file: shvar.py
diff -N shvar.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ shvar.py	20 Jun 2006 21:37:50 -0000	1.3
@@ -0,0 +1,205 @@
+#
+# Handle files with only shell variable declarations and full-line comments
+# 
+# This is based on the shvar.c from Red Hat's C configuration tools, and
+# has similar functions, but differs in various aspects:
+#
+#  - It doesn't do inheritance
+#  - Empty variables aren't treated the same as missing variables
+#  - The shell unquoting is closer to correct
+#
+# This functionality is *not* safe to use for writing files in
+# world-writable directories such as /tmp.
+#
+import os
+import re
+import string
+
+def escape(val):
+    escapes = "[\"\\\\$`]"   # Must be escaped
+    spaces = "[ \t'~]"         # Only require quotes
+
+    if not re.search (escapes, val) and not re.search (spaces, val):
+        return val
+    return '"' + re.sub ("(%s)" % escapes, "\\\\\\1", val) + '"'
+
+def unescape_double(str):
+    return re.sub("\\\\([$`\"\\\\])", "\\1", str)
+
+def unescape_unquoted(str):
+    return re.sub("\\\\(.)", "\\1", str)
+
+def unescape_partial(match):
+    s = match.group()
+    if s[0] == '"':
+        return unescape_double(s[1:-1])
+    elif s[0] == "'":
+        return s[1:-1]
+    else:
+        return unescape_unquoted(s)
+
+# This is not exactly right; one thing that is definitely wrong is
+# the handling of newlines (but the splitting into lines doesn't handle
+# that correctly,anyways). Also, we don't guard against unmatched
+# quotes; they'll just get passed through verbatim
+def unescape(val):
+    return re.sub("[^'\"]+|'[^']*'|\"([^\\\\\\\"]+|\\\\.)*\"", unescape_partial, val)
+
+class shvarFile:
+    def __init__(self,filename,mustExist = False):
+        self.filename = filename
+        self.lines = []
+        self.modified = False
+
+        try:
+            f = file(filename, "r")
+        except IOError:
+            if mustExist:
+                raise
+            else:
+                return
+
+        while True:
+            l = f.readline()
+            if l == "":
+                break
+            self.lines.append (l.rstrip())
+            
+        f.close()
+
+    def findValue(self, key):
+        prefix = key + "="
+        prefixlen = len(prefix)
+        i = 0
+        for l in self.lines:
+            l = self.lines[i]
+            if l[:prefixlen] == prefix:
+                value = unescape(l[prefixlen:])
+                if value != None and value != "":
+                    return (value, i)
+            i = i + 1
+                
+        return (None, -1)
+
+    # Get the value associated with the key. An empty value
+    # is treated the same as a missing value; in both cases None is returned
+    def __getitem__(self, key):
+        (value, i) = self.findValue(key)
+        return value
+
+    # return 1 if <key> resolves to any truth value (e.g. "yes", "y", "true")
+    # return 0 if <key> resolves to any non-truth value (e.g. "no", "n", "false")
+    # return <default> otherwise
+    def trueValue(self, key, default=None):
+        tmp = self[key]
+        if tmp == None:
+            return default
+        tmp = string.lower (tmp)
+        if tmp == "yes" or tmp == "true" or tmp == "y" or tmp == "t":
+            return 1
+        elif tmp == "no" or tmp == "false" or tmp == "f" or tmp == "n":
+            return 0
+        else:
+            return default
+
+    # Set the variable <key> equal to the value <value>.
+    # If <key> does not exist, append the pair to the end of the file.
+    def __setitem__(self, key, value):
+        (oldValue, i) = self.findValue(key)
+        if (oldValue == value):
+            return
+
+        self.modified = True
+        if value != None:
+            newline = "%s=%s" % (key, escape (value))
+            if i != -1:
+                self.lines[i] = newline
+            else:
+                self.lines.append (newline)
+        else:
+            if i != -1:
+                del self.lines[i]
+
+    def write(self, mask = None):
+        # We try first to write it using a temporary file in
+        # the same directory and moving it over the original
+        # If we can't create a temporary, we try just writing
+        # over the original
+        #
+        if mask != None:
+            old_mask = os.umask (mask)
+        
+        temp = self.filename + ".new"
+        try:
+            f = file (temp, "w")
+        except:
+            temp = None
+            f = file (self.filename, "w")
+
+        try:
+            for l in self.lines:
+                f.write(l)
+                f.write("\n")
+            f.close()
+        except:
+            if temp != None:
+                os.remove(temp)
+            raise
+        
+        os.rename(temp, self.filename)
+
+        if mask != None:
+            os.umask (old_mask)
+
+#
+# Test cases. Note that there is a big tempfile raise in this
+# test case since the temporary file name used when rewriting
+# the file (<filename>.new) is predictable.
+#
+if __name__ == '__main__':
+    import tempfile
+
+    (fd, filename) = tempfile.mkstemp(".sh")
+    f = os.fdopen(fd, "w")
+
+    f.write("""
+# Temporary file for testing shvar
+
+var1=""
+
+# Comment about va2
+var2='abcd'"cdef"
+
+var3=true
+var4=f
+"""
+            )
+    f.close()
+    
+    shf = shvarFile (filename)
+
+    assert shf["var1"] == ""
+    assert shf["var2"] == "abcdcdef"
+    assert shf["var5"] == None
+    assert shf.trueValue ("var1") == None
+    assert shf.trueValue ("var1", True)
+    assert shf.trueValue ("var5", True)
+    assert not shf.trueValue ("var4")
+    assert not shf.trueValue ("var4")
+
+    shf["var1"] = "abcd"
+    shf["var2"] = "a\"bcd\"$a"
+    shf["var4"] = None
+    shf["var5"] = "blahblah"
+
+    shf.write()
+
+    shf = shvarFile (filename, True)
+
+    assert shf["var1"] == "abcd"
+    assert shf["var2"] == "a\"bcd\"$a"
+    assert shf["var3"] == "true"
+    assert shf["var4"] == None
+    assert shf["var5"] == "blahblah"
+
+    os.remove (filename)




More information about the fedora-extras-commits mailing list