comparison makeitso/makeitso.py @ 5:f064be514e53

choose a better filename and remove some stuff from shebang
author Jeff Hammel <jhammel@mozilla.com>
date Wed, 10 Nov 2010 18:01:07 -0800
parents
children ac78e26cd568
comparison
equal deleted inserted replaced
4:08a50935e941 5:f064be514e53
1 #!/usr/bin/env python
2 """
3 filesystem template interpreter
4 """
5
6 import os
7 import re
8 import subprocess
9 import sys
10
11 from optparse import OptionParser
12 from tempita import Template
13
14 shebang_re = '#!.*makeitso.*'
15 shebang_re = re.compile(shebang_re)
16
17 def call(command, *args, **kw):
18 code = subprocess.call(command, *args, **kw)
19 if code:
20 if isinstance(command, basestring):
21 cmdstr = command
22 else:
23 cmdstr = ' '.join(command)
24 raise SystemExit("Command `%s` exited with code %d" % (cmdstr, code))
25
26 def get_missing(name_error):
27 """
28 This is a horrible hack because python doesn't do the proper thing
29 via eval and return the name of the variable; instead, it just gives
30 you a message:
31 >>> try:
32 ... eval('2*foo')
33 ... except Exception, e:
34 ... pass
35 """
36 message = name_error.args[0]
37 varname = message.split("'")[1]
38 return varname
39
40 def missing_variables(template, variables):
41 """return additional variables needed"""
42 vars = variables.copy()
43 missing = set([])
44 while True:
45 try:
46 template.substitute(**vars)
47 return missing
48 except NameError, e:
49 missed = get_missing(e)
50 missing.add(missed)
51 vars[missed] = ''
52 return missing
53
54 def template_variables(template):
55 """return the variables needed for a template"""
56 return missing_variables(template, {})
57
58 def read_variables(variables):
59 retval = {}
60 for i in variables:
61 print 'Enter %s: ' % i,
62 retval[i] = raw_input()
63 return retval
64
65 def substitute(content, fp=sys.stdout, variables=None):
66
67 # remove makeitso shebang if it has one
68 if shebang_re.match(content):
69 content = os.linesep.join(content.splitlines()[1:])
70
71 variables = variables or {}
72 template = Template(content)
73 missing = missing_variables(template, variables)
74 if missing:
75 # TODO: add a switch for interactive or not
76 variables.update(read_variables(missing))
77 print >> fp, template.substitute(**variables)
78
79
80 def main(args=sys.argv[1:]):
81
82 # create option parser
83 usage = '%prog [options]'
84 parser = OptionParser(usage, description=__doc__)
85 parser.add_option('--variables', dest='variables', action='store_true',
86 help='print the variables in a template')
87 options, args = parser.parse_args(args)
88
89 if options.variables:
90 variables = template_variables() # TODO: pass template
91 return
92
93 # template variables
94 variables = {}
95 _vars = []
96 _args = []
97 for arg in args:
98 if '=' in arg:
99 key, value = arg.split('=')
100 variables[key] = value
101 else:
102 _args.append(arg)
103 args = _args
104
105 # get the content
106 if args:
107 for arg in args:
108 content = file(arg).read()
109 substitute(content, variables=variables)
110 else:
111 content = sys.stdin.read()
112 substitute(content, variables=variables)
113
114 if __name__ == '__main__':
115 main()