]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/app/__init__.py
Make logging not retarded. Fix tests.
[wizard.git] / wizard / app / __init__.py
index 4f8448e9ae7e47c23fd5c82c75647eface50cdb7..90657630c2cb59fb2c9d946da2b514c3d86bc39d 100644 (file)
@@ -1,7 +1,15 @@
 import os.path
+import re
+
+def expand_re(val):
+    if isinstance(val, str):
+        return re.escape(val)
+    else:
+        return '(?:' + '|'.join(map(expand_re, val)) + ')'
 
 def filename_regex_extractor(f):
-    """This is a decorator to apply to functions that take a name and return
+    """
+    This is a decorator to apply to functions that take a name and return
     (filename, RegexObject) tuples.  It converts it into a function
     that takes a name and returns another function (the actual extractor)
     which takes a deployment and returns the value of the extracted variable.
@@ -10,12 +18,17 @@ def filename_regex_extractor(f):
     (with the second subgroup being the value we care about), so that we can
     reuse the regex for other things.
 
-    Its Haskell-style type signature would be:
+    Its Haskell-style type signature would be::
+
         (String -> (Filename, Regex)) -> (String -> (Deployment -> String))
 
-    It's a little bit like a transformer."""
+    For convenience purposes, we also accept [Filename], in which case
+    we use the first entry (index 0).  Passing an empty list is invalid.
+    """
     def g(var):
         file, regex = f(var)
+        if not isinstance(file, str):
+            file = file[0]
         def h(deployment):
             contents = deployment.read(file) # cached
             match = regex.search(contents)
@@ -25,3 +38,39 @@ def filename_regex_extractor(f):
         return h
     return g
 
+def filename_regex_substitution(f):
+    """
+    This is a decorator to apply to functions that take a name and return
+    (filename, RegexObject) tuples.  It converts it into a function
+    that takes a name and returns another function (that does substitution)
+    which takes a deployment and modifies its files to replace explicit
+    values with their generic WIZARD_* equivalents.  The final function returns
+    the number of replacements made.
+
+    The regular expression requires a very specific form, essentially ()()()
+    (with the second subgroup being the value to be replaced).
+
+    Its Haskell-style type signature would be::
+
+        (String -> ([Filename], Regex)) -> (String -> (Deployment -> IO Int))
+
+    For convenience purposes, we also accept Filename, in which case it is treated
+    as a single item list.
+    """
+    def g(key, var):
+        files, regex = f(var)
+        if isinstance(files, str):
+            files = (files,)
+        def h(deployment):
+            base = deployment.location
+            subs = 0
+            for file in files:
+                file = os.path.join(base, file)
+                contents = open(file, "r").read()
+                contents, n = regex.subn("\\1" + key + "\\3", contents)
+                subs += n
+                open(file, "w").write(contents)
+            return subs
+        return h
+    return g
+