]> scripts.mit.edu Git - wizard.git/blob - wizard/app/__init__.py
Make logging not retarded. Fix tests.
[wizard.git] / wizard / app / __init__.py
1 import os.path
2 import re
3
4 def expand_re(val):
5     if isinstance(val, str):
6         return re.escape(val)
7     else:
8         return '(?:' + '|'.join(map(expand_re, val)) + ')'
9
10 def filename_regex_extractor(f):
11     """
12     This is a decorator to apply to functions that take a name and return
13     (filename, RegexObject) tuples.  It converts it into a function
14     that takes a name and returns another function (the actual extractor)
15     which takes a deployment and returns the value of the extracted variable.
16
17     The regular expression requires a very specific form, essentially ()()()
18     (with the second subgroup being the value we care about), so that we can
19     reuse the regex for other things.
20
21     Its Haskell-style type signature would be::
22
23         (String -> (Filename, Regex)) -> (String -> (Deployment -> String))
24
25     For convenience purposes, we also accept [Filename], in which case
26     we use the first entry (index 0).  Passing an empty list is invalid.
27     """
28     def g(var):
29         file, regex = f(var)
30         if not isinstance(file, str):
31             file = file[0]
32         def h(deployment):
33             contents = deployment.read(file) # cached
34             match = regex.search(contents)
35             if not match: return None
36             # assumes that the second match is the one we want.
37             return match.group(2)
38         return h
39     return g
40
41 def filename_regex_substitution(f):
42     """
43     This is a decorator to apply to functions that take a name and return
44     (filename, RegexObject) tuples.  It converts it into a function
45     that takes a name and returns another function (that does substitution)
46     which takes a deployment and modifies its files to replace explicit
47     values with their generic WIZARD_* equivalents.  The final function returns
48     the number of replacements made.
49
50     The regular expression requires a very specific form, essentially ()()()
51     (with the second subgroup being the value to be replaced).
52
53     Its Haskell-style type signature would be::
54
55         (String -> ([Filename], Regex)) -> (String -> (Deployment -> IO Int))
56
57     For convenience purposes, we also accept Filename, in which case it is treated
58     as a single item list.
59     """
60     def g(key, var):
61         files, regex = f(var)
62         if isinstance(files, str):
63             files = (files,)
64         def h(deployment):
65             base = deployment.location
66             subs = 0
67             for file in files:
68                 file = os.path.join(base, file)
69                 contents = open(file, "r").read()
70                 contents, n = regex.subn("\\1" + key + "\\3", contents)
71                 subs += n
72                 open(file, "w").write(contents)
73             return subs
74         return h
75     return g
76