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.
(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)
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
+