def handlebars_dynamic_load(package, name): """ Dynamically compile a Handlebars template. NOTE: This will do nothing in production mode! """ if not App.is_dev_server: return None combined_name = "%s_%s" % (package, name) if combined_name in handlebars_partials: handlebars_partials[combined_name] logging.info("Dynamically loading %s-package/%s.handlebars." % (package, name)) test_file_name = ("clienttemplates/%s-package/%s.handlebars.json" % (package, name)) if not os.path.exists(test_file_name): logging.error("Attempting to call server-side template with" " no test file. Looking for: %s" % test_file_name) return None file_name = "clienttemplates/%s-package/%s.handlebars" % (package, name) in_file = open(file_name, 'r') source = unicode(in_file.read()) # HACK: Pybars doesn't handle {{else}} for some reason source = source.replace("{{else}}", "{{^}}") matches = re.search('{{>[\s]*([\w\-_]+)[\s]*}}', source) if matches: for partial in matches.groups(): (partial_package, partial_name) = partial.split("_") handlebars_dynamic_load(partial_package, partial_name) compiler = Compiler() function = compiler.compile(source) handlebars_partials[combined_name] = function return function
def compile_template_to_python(root_path, rel_path, file_name): dir_path = os.path.join(root_path, rel_path) input_path = os.path.join(dir_path, file_name) test_path = input_path + ".json" # We intentionally ignore Handlebars templates that don't have unit tests # when compiling to Python. If someday all templates have unit tests we # should emit an error here. if not os.path.exists(test_path): return None package_name = rel_path.replace("-", "_").split("_")[0] original_function_name = os.path.splitext(file_name)[0] partial_name = package_name + "_" + original_function_name function_name = original_function_name.replace("-", "_") out_dir_path = os.path.join("compiled_templates", package_name + "_package") output_path = os.path.join(out_dir_path, function_name) + ".py" init_path = os.path.join(out_dir_path, "__init__.py") compiler = Compiler() in_file = open(input_path, 'r') source = unicode(in_file.read()) # Pybars doesn't handle {{else}} for some reason source = re.sub(r'{{\s*else\s*}}', "{{^}}", source) template = compiler.compile(source) output_string = [] output_string.append("from third_party.pybars._compiler import strlist, " "_pybars_, Scope, escape, resolve, partial") output_string.append("") def write_fn(template, name, indent): output_string.append("%sdef %s(context, helpers=None, partials=None):" % (indent, name)) output_string.append("%s pybars = _pybars_" % indent) output_string.append("") output_string.append("%s # Begin constants" % indent) for name, val in template.func_globals.items(): if name.startswith("constant_"): if isinstance(val, unicode): output_string.append("%s %s = %s" % (indent, name, repr(val))) output_string.append("") for name, val in template.func_globals.items(): if name.startswith("constant_"): if isinstance(val, types.FunctionType): write_fn(val, name, indent + " ") output_string.append("%s # End constants" % indent) compiled_fn = inspect.getsource(template) fn_lines = compiled_fn.split("\n") for line in fn_lines[1:]: output_string.append("%s%s" % (indent, line)) write_fn(template, function_name, "") if not os.path.exists(out_dir_path): os.makedirs(out_dir_path) out_file = open(init_path, 'w') out_file.close() out_file = open(output_path, 'w') out_file.write("\n".join(output_string)) out_file.close() print "Compiled to %s" % output_path return (partial_name, package_name, function_name)