Caffe2 - Python API
A deep learning, cross platform ML framework
code_template.py
1 import re
2 
3 # match $identifier or ${identifier} and replace with value in env
4 # If this identifier is at the beginning of whitespace on a line
5 # and its value is a list then it is treated as
6 # block subsitution by indenting to that depth and putting each element
7 # of the list on its own line
8 # if the identifier is on a line starting with non-whitespace and a list
9 # then it is comma separated ${,foo} will insert a comma before the list
10 # if this list is not empty and ${foo,} will insert one after.
11 
12 
13 class CodeTemplate(object):
14  substitution_str = r'(^[^\n\S]*)?\$([^\d\W]\w*|\{,?[^\d\W]\w*\,?})'
15 
16  # older versions of Python have a bug where \w* does not work,
17  # so we need to replace with the non-shortened version [a-zA-Z0-9_]*
18  # https://bugs.python.org/issue18647
19 
20  substitution_str = substitution_str.replace(r'\w', r'[a-zA-Z0-9_]')
21 
22  subtitution = re.compile(substitution_str, re.MULTILINE)
23 
24  @staticmethod
25  def from_file(filename):
26  with open(filename, 'r') as f:
27  return CodeTemplate(f.read(), filename)
28 
29  def __init__(self, pattern, filename=""):
30  self.pattern = pattern
31  self.filename = filename
32 
33  def substitute(self, env={}, **kwargs):
34  def lookup(v):
35  return kwargs[v] if v in kwargs else env[v]
36 
37  def indent_lines(indent, v):
38  return "".join([indent + l + "\n" for e in v for l in str(e).splitlines()]).rstrip()
39 
40  def replace(match):
41  indent = match.group(1)
42  key = match.group(2)
43  comma_before = ''
44  comma_after = ''
45  if key[0] == "{":
46  key = key[1:-1]
47  if key[0] == ",":
48  comma_before = ', '
49  key = key[1:]
50  if key[-1] == ',':
51  comma_after = ', '
52  key = key[:-1]
53  v = lookup(key)
54  if indent is not None:
55  if not isinstance(v, list):
56  v = [v]
57  return indent_lines(indent, v)
58  elif isinstance(v, list):
59  middle = ', '.join([str(x) for x in v])
60  if len(v) == 0:
61  return middle
62  return comma_before + middle + comma_after
63  else:
64  return str(v)
65  return self.subtitution.sub(replace, self.pattern)
66 
67 
68 if __name__ == "__main__":
69  c = CodeTemplate("""\
70  int foo($args) {
71 
72  $bar
73  $bar
74  $a+$b
75  }
76  int commatest(int a${,stuff})
77  int notest(int a${,empty,})
78  """)
79  print(c.substitute(args=["hi", 8], bar=["what", 7],
80  a=3, b=4, stuff=["things...", "others"], empty=[]))