Mercurial > hg > MakeItSo
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() |
