Source code for pyramid.scaffolds.template

# (c) 2005 Ian Bicking and contributors; written for Paste
# (http://pythonpaste.org) Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license.php

import re
import sys
import os

from pyramid._compat import native_, bytes_

from pyramid.scaffolds import copydir

fsenc = sys.getfilesystemencoding()


[docs] class Template(object): """Inherit from this base class and override methods to use the Pyramid scaffolding system.""" copydir = copydir # for testing _template_dir = None def __init__(self, name): self.name = name
[docs] def render_template(self, content, vars, filename=None): """Return a bytestring representing a templated file based on the input (content) and the variable names defined (vars). ``filename`` is used for exception reporting.""" # this method must not be named "template_renderer" fbo of extension # scaffolds that need to work under pyramid 1.2 and 1.3, and which # need to do "template_renderer = # staticmethod(paste_script_template_renderer)" content = native_(content, fsenc) try: return bytes_( substitute_escaped_double_braces( substitute_double_braces(content, TypeMapper(vars)) ), fsenc, ) except Exception as e: _add_except(e, ' in file %s' % filename) raise
def module_dir(self): mod = sys.modules[self.__class__.__module__] return os.path.dirname(mod.__file__)
[docs] def template_dir(self): """Return the template directory of the scaffold. By default, it returns the value of ``os.path.join(self.module_dir(), self._template_dir)`` (``self.module_dir()`` returns the module in which your subclass has been defined). If ``self._template_dir`` is a tuple this method just returns the value instead of trying to construct a path. If _template_dir is a tuple, it should be a 2-element tuple: ``(package_name, package_relative_path)``.""" assert self._template_dir is not None, ( "Template %r didn't set _template_dir" % self ) if isinstance(self._template_dir, tuple): return self._template_dir else: return os.path.join(self.module_dir(), self._template_dir)
def run(self, command, output_dir, vars): self.pre(command, output_dir, vars) self.write_files(command, output_dir, vars) self.post(command, output_dir, vars)
[docs] def pre(self, command, output_dir, vars): # pragma: no cover """ Called before template is applied. """ pass
[docs] def post(self, command, output_dir, vars): # pragma: no cover """ Called after template is applied. """ pass
def write_files(self, command, output_dir, vars): template_dir = self.template_dir() if not self.exists(output_dir): self.out("Creating directory %s" % output_dir) if not command.args.simulate: # Don't let copydir create this top-level directory, # since copydir will svn add it sometimes: self.makedirs(output_dir) self.copydir.copy_dir( template_dir, output_dir, vars, verbosity=command.verbosity, simulate=command.args.simulate, interactive=command.args.interactive, overwrite=command.args.overwrite, indent=1, template_renderer=self.render_template, ) def makedirs(self, dir): # pragma: no cover return os.makedirs(dir) def exists(self, path): # pragma: no cover return os.path.exists(path) def out(self, msg): # pragma: no cover print(msg) # hair for exit with usage when paster create is used under 1.3 instead # of pcreate for extension scaffolds which need to support multiple # versions of pyramid; the check_vars method is called by pastescript # only as the result of "paster create"; pyramid doesn't use it. the # required_templates tuple is required to allow it to get as far as # calling check_vars. required_templates = () def check_vars(self, vars, other): raise RuntimeError( 'Under Pyramid 1.3, you should use the "pcreate" command rather ' 'than "paster create"' )
class TypeMapper(dict): def __getitem__(self, item): options = item.split('|') for op in options[:-1]: try: value = eval_with_catch(op, dict(self.items())) break except (NameError, KeyError): pass else: value = eval(options[-1], dict(self.items())) if value is None: return '' else: return str(value) def eval_with_catch(expr, vars): try: return eval(expr, vars) except Exception as e: _add_except(e, 'in expression %r' % expr) raise double_brace_pattern = re.compile(r'{{(?P<braced>.*?)}}') def substitute_double_braces(content, values): def double_bracerepl(match): value = match.group('braced').strip() return values[value] return double_brace_pattern.sub(double_bracerepl, content) escaped_double_brace_pattern = re.compile( r'\\{\\{(?P<escape_braced>[^\\]*?)\\}\\}' ) def substitute_escaped_double_braces(content): def escaped_double_bracerepl(match): value = match.group('escape_braced').strip() return "{{%(value)s}}" % locals() return escaped_double_brace_pattern.sub(escaped_double_bracerepl, content) def _add_except(exc, info): # pragma: no cover if not hasattr(exc, 'args') or exc.args is None: return args = list(exc.args) if args: args[0] += ' ' + info else: args = [info] exc.args = tuple(args) return