diff --git a/TODO b/TODO index 46988f586345bba1a8bf23921d0255e0de082308..7fb50004fb82e26e70a83ca1fe31500d8cea7063 100644 --- a/TODO +++ b/TODO @@ -14,8 +14,6 @@ - Don't store current flow session in cookie, ever. -- [JINJA]/[/JINJA] in yaml files - - Redo permissions system - Custom matcher classes diff --git a/course/content.py b/course/content.py index ddb0b2779dc4e03933717b11b1e727eded4a5ce1..6536593b186e550f165017bb6681d4a31a61aff0 100644 --- a/course/content.py +++ b/course/content.py @@ -30,7 +30,7 @@ import re import datetime from django.utils.timezone import now -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured from markdown.extensions import Extension from markdown.treeprocessors import Treeprocessor @@ -95,9 +95,13 @@ def get_repo_blob(repo, full_name, commit_sha): def get_repo_blob_data_cached(repo, full_name, commit_sha): - cache_key = "%%%1".join((repo.controldir(), full_name, commit_sha)) + cache_key = "%%%1".join((repo.controldir(), full_name, str(commit_sha))) + + try: + import django.core.cache as cache + except ImproperlyConfigured: + return get_repo_blob(repo, full_name, commit_sha).data - import django.core.cache as cache def_cache = cache.caches["default"] result = def_cache.get(cache_key) if result is not None: @@ -109,6 +113,24 @@ def get_repo_blob_data_cached(repo, full_name, commit_sha): return result +JINJA_YAML_RE = re.compile( + r"^\[JINJA\]\s*$(.*?)^\[\/JINJA\]\s*$", + re.MULTILINE | re.DOTALL) + + +def expand_yaml_macros(repo, commit_sha, yaml_str): + def compute_replacement(match): + jinja_src = match.group(1) + + from jinja2 import Environment + env = Environment(loader=GitTemplateLoader(repo, commit_sha)) + template = env.from_string(jinja_src) + return template.render() + + result, _ = JINJA_YAML_RE.subn(compute_replacement, yaml_str) + return result + + def get_raw_yaml_from_repo(repo, full_name, commit_sha): """Return decoded YAML data structure from the given file in *repo* at *commit_sha*. @@ -122,7 +144,10 @@ def get_raw_yaml_from_repo(repo, full_name, commit_sha): if result is not None: return result - result = load_yaml(get_repo_blob(repo, full_name, commit_sha).data) + result = load_yaml( + expand_yaml_macros( + repo, commit_sha, + get_repo_blob(repo, full_name, commit_sha).data)) def_cache.add(cache_key, result, None) @@ -147,7 +172,10 @@ def get_yaml_from_repo(repo, full_name, commit_sha, cached=True): return result result = dict_to_struct( - load_yaml(get_repo_blob(repo, full_name, commit_sha).data)) + load_yaml( + expand_yaml_macros( + repo, commit_sha, + get_repo_blob(repo, full_name, commit_sha).data))) if cached: def_cache.add(cache_key, result, None) @@ -314,7 +342,7 @@ class GitTemplateLoader(BaseTemplateLoader): def get_source(self, environment, template): try: - data = get_repo_blob(self.repo, template, self.commit_sha).data + data = get_repo_blob_data_cached(self.repo, template, self.commit_sha) except ObjectDoesNotExist: raise TemplateNotFound(template) diff --git a/course/validation.py b/course/validation.py index c2fe515b908195acdd7e5a3089fc94e07aaab16c..1ec6181754a365d91c9c7593ceed2f9e5110f2e3 100644 --- a/course/validation.py +++ b/course/validation.py @@ -562,9 +562,15 @@ class FileSystemFakeRepo(object): def __init__(self, root): self.root = root + def controldir(self): + return self.root + def __getitem__(self, sha): return sha + def __str__(self): + return "" % self.root + @property def tree(self): return FileSystemFakeRepoTree(self.root) diff --git a/doc/content.rst b/doc/content.rst index d52cadb591b6becf6cfdd9d968318e04fbe1e347..59b00b851c072e2a5c4bc19b5459970d0c87b6f9 100644 --- a/doc/content.rst +++ b/doc/content.rst @@ -71,6 +71,8 @@ Here's an example:: ... +TODO: Macro expansion in YAML + On system lock-in -----------------