Mercurial > hg > MakeItSo
view makeitso/template.py @ 64:c20277dbf8fa
closer to substitution
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Thu, 06 Jan 2011 18:04:58 -0800 |
parents | b91133e3b02d |
children | 0152741621c1 |
line wrap: on
line source
""" basic API template class """ import os import sys from makeitso import ContentTemplate from makeitso import PolyTemplate class Undefined(object): """marker class for variables""" def __int__(self): return 0 Undefined = Undefined() # singleton class Variable(object): """variable object for MakeItSo templates""" def __init__(self, name, description=None, default=Undefined, cast=None): self.name = name self.default = default self.description = description # TODO (maybe): get cast from default variable type if not None self.cast = cast self._set = False def set(self, value): if self.cast: self.value = self.cast(value) else: self.value = value self._set = True def read(self, fd=sys.stdout): """prompt and read the variable from stdin""" fd.write(self.display()) self.set(raw_input()) def display(self): description = self.description or self.name if self.default: return 'Enter %s [DEFAULT: %s]:' % (description, repr(self.default)) else: return 'Enter %s:' % description class MakeItSoTemplate(ContentTemplate): """API template for MakeItSo""" # name of the template name = '' # description of the template description = '' # templates to interpolate # paths are relative to __file__ unless absolute or URIs templates = [] # variables vars = [] # inspect the templates for more variables look = False def __init__(self, output=None, interactive=True, usedefaults=True, variables=None): """ - output : output file or directory - interactive : whether tointeractively get variables - usedefaults : try to use the default values if not specified """ # boilerplate assert self.templates self.output = output self.interactive = interactive self.location = os.path.dirname(os.path.abspath(__file__)) self.defaults = variables.copy() self.usedefaults = usedefaults # make a dictionary of the variables for lookup convenience self.vardict = {} for i in self.vars: self.vardict[i.name] = i # ensure all of these templates exist for template in self.templates: if template.startswith('http://') or template.startswith('https://'): continue if os.path.isabs(template): path = template else: path = os.path.join(self.location, template) assert os.path.exists(template) def get_variables(self, **variables): # XXX could do this in the ctor vars = ContentTemplate.get_variables(self, **variables) if self.usedefaults: for variable in self.vars: if variable.name in vars: continue if variable.default is not Undefined: vars[variable.name] = variable.default return vars def missing(self, **variables): vars = self.get_variables(**variables) missing = set([]) # get known needed variables for var in self.vars: if var.name not in vars: missing.add(var) if self.look: # scan templates for other variables raise NotImplementedError return missing def pre(self, **variables): """do stuff before interpolation""" def substitute(self, **variables): """do the substitution""" vars = self.get_variables(**variables) self.pre(**vars) self.check_missing(vars) # do the substitution PolyTemplate(self.templates, output=self.output, interactive=self.interactive, variables = vars self.post(**variables) def post(self, **variables): """do stuff after interpolation""" def read_variables(self, variables): """read variables from stdin""" retval = {} for i in variables: if i in self.vardict: self.vardict[i].read() else: retval.update(ContentTemplate.read_variables(self, (i,))) return retval class PasteScriptTemplate(MakeItSoTemplate): """template for backwards compatability with PasteScript"""