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