Пример #1
0
 def filename_to_uri(self, filename):
     """
     Given a filename, return a URI which can be used to access this
     template from the lookup.
     """
     from_dir = self.find_dir_for_path(filename)
     base_uri = TemplateLookup.filename_to_uri(self, filename)
     ret = base_uri + self.super_delimiter + from_dir
     return ret
Пример #2
0
class Renderer(object):
    '''Manages rendering templates'''
    def __init__(self, template_dir, invoking_filenames, source_files):
        self.template_dir = template_dir
        self.invoking_filenames = invoking_filenames
        self.source_files = source_files
        self.tl = TemplateLookup(directories=[template_dir])
        self.template_context = {
            'camel': camel,  # CamelCase function
            'dromedary': dromedary,  # dromeDary case function
            'EmptyTemplate': EmptyTemplate,
        }
        self.mtime_cache = {}
        self.dependency_cache = {}

    def mtime(self, filename):
        try:
            return self.mtime_cache[filename]
        except KeyError:
            mtime = os.path.getmtime(filename)
            self.mtime_cache[filename] = mtime
            return mtime

    def render(self,
               template_name,
               output_dir,
               output_name=None,
               dependencies=None,
               **kwargs):
        if output_name is None:
            output_name = template_name

        tpl = self.tl.get_template(template_name)
        output_path = output_dir + '/' + output_name

        if self.already_rendered(tpl, output_path, dependencies):
            logger.debug(" Up to date: %s", output_path)
            return

        results = self.template_context.copy()
        results.update(kwargs)
        try:
            rendered = tpl.render(**results)
        except EmptyTemplate:
            logger.debug(" Empty template: %s", output_path)
            return
        with codecs.open(output_path, "w", "utf-8") as outfile:
            logger.info("Rendering %s", output_path)
            outfile.write(
                self.autogenerated_header(
                    self.template_dir + '/' + template_name,
                    output_path,
                    self.invoking_filenames,
                ))
            outfile.write(rendered)

    def get_template_name(self, classname, directory, default):
        '''Returns the template for this class'''
        override_template = '{}/{}.java'.format(directory, classname)
        if self.tl.has_template(override_template):
            logger.debug("Found an override for %s at %s", classname,
                         override_template)
            return override_template
        else:
            return default

    def dependent_templates(self, tpl):
        '''Returns filenames for all templates that are inherited from the
        given template'''
        if tpl.filename in self.dependency_cache:
            return self.dependency_cache[tpl.filename]
        inherit_files = re.findall(r'inherit file="(.*)"', tpl.source)
        op = os.path
        dependencies = set()
        tpl_dir = op.dirname(tpl.filename)
        for parent_relpath in inherit_files:
            parent_filename = op.normpath(op.join(tpl_dir, parent_relpath))
            dependencies.add(parent_filename)
            dependencies.update(
                self.dependent_templates(
                    self.tl.get_template(
                        self.tl.filename_to_uri(parent_filename))))
        dependencies.add(tpl.filename)
        self.dependency_cache[tpl.filename] = dependencies
        return dependencies

    def already_rendered(self, tpl, output_path, dependencies):
        '''Check if rendered file is already up to date'''
        if not os.path.exists(output_path):
            logger.debug(" Rendering since %s doesn't exist", output_path)
            return False

        output_mtime = self.mtime(output_path)

        # Check if this file or the invoking file have changed
        for filename in self.invoking_filenames + self.source_files:
            if self.mtime(filename) > output_mtime:
                logger.debug(" Rendering since %s has changed", filename)
                return False
        if self.mtime(__file__) > output_mtime:
            logger.debug(" Rendering since %s has changed", __file__)
            return False

        # Check if any dependent templates have changed
        for tpl in self.dependent_templates(tpl):
            if self.mtime(tpl) > output_mtime:
                logger.debug(" Rendering since %s is newer", tpl)
                return False

        # Check if any explicitly defined dependencies have changed
        dependencies = dependencies or []
        for dep in dependencies:
            if self.mtime(dep) > output_mtime:
                logger.debug(" Rendering since %s is newer", dep)
                return False
        return True

    def autogenerated_header(self, template_path, output_path, filename):
        rel_tpl = os.path.relpath(template_path, start=output_path)
        filenames = ' and '.join(
            os.path.basename(f) for f in self.invoking_filenames)
        return ('// Autogenerated by {}.\n'
                '// Do not edit this file directly.\n'
                '// The template for this file is located at:\n'
                '// {}\n').format(filenames, rel_tpl)