From e3fe08e204bd1df2d91552911b008ac33997b34a Mon Sep 17 00:00:00 2001
From: Louis <spalax@gresille.org>
Date: Fri, 5 Feb 2016 23:23:10 +0100
Subject: [PATCH 1/3] [WIP] Try to get template options in a more robust way

---
 patacrep/templates.py | 89 +++++++++++++++++++------------------------
 1 file changed, 39 insertions(+), 50 deletions(-)

diff --git a/patacrep/templates.py b/patacrep/templates.py
index f745a58e..f9b91b24 100644
--- a/patacrep/templates.py
+++ b/patacrep/templates.py
@@ -8,7 +8,7 @@ import yaml
 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, \
         TemplateNotFound, nodes
 from jinja2.ext import Extension
-from jinja2.meta import find_referenced_templates as find_templates
+from jinja2.meta import find_referenced_templates
 
 from patacrep import errors, files, utils
 from patacrep.latex import lang2babel, UnknownLanguage
@@ -162,12 +162,16 @@ class TexBookRenderer(Renderer):
                 )
 
     def get_all_variables(self, user_config):
-        '''
-        Validate template variables (and set defaults when needed)
+        '''Validate template variables (and set defaults when needed)
         '''
         data = self.get_template_variables(self.template)
         variables = dict()
         for name, param in data.items():
+            print("*"*30, "DEBUG", "*"*30) # TODO DELETE THIS
+            from pprint import pprint
+            print("Data:"); pprint(data)
+            print("Name:", name)
+            print("Param:", param)
             template_config = user_config.get(name, {})
             variables[name] = self._get_variables(param, template_config)
         return variables
@@ -181,63 +185,31 @@ class TexBookRenderer(Renderer):
         data = utils.DictOfDict(parameter.get('default', {}))
         data.update(user_config)
 
+        print("*"*30, "DEBUG", "*"*30) # TODO DELETE THIS
+        from pprint import pprint
+        print("Parameter", parameter)
+        print("Data"); pprint(data)
+        print("Schema"); pprint(schema)
         utils.validate_yaml_schema(data, schema)
         return data
 
-    def get_template_variables(self, template, skip=None):
+    def get_template_variables(self, templatename):
         """Parse the template to extract the variables as a dictionary.
 
         If the template includes or extends other templates, load them as well.
 
         Arguments:
-        - template: the name of the template, as a string.
-        - skip: a list of templates (as strings) to skip: if they are included
+        - templatename: the name of the template, as a string.
           in 'template' (or one of its subtemplates), it is not parsed.
         """
-        if not skip:
-            skip = []
         variables = {}
-        (current, templates) = self.parse_template(template)
-        if current:
-            variables[template.name] = current
-
-        for subtemplate in templates:
-            if subtemplate in skip:
+        for template in self._iter_template_content(templatename):
+            match = re.findall(_VARIABLE_REGEXP, template)
+            if not match:
                 continue
-            subtemplate = self.jinjaenv.get_template(subtemplate)
-            variables.update(
-                self.get_template_variables(
-                    subtemplate,
-                    skip + templates
-                    )
-                )
-        return variables
-
-    def parse_template(self, template):
-        """Return (variables, templates).
-
-        Argument:
-        - template: name of the template to parse.
-
-        Return values:
-        - variables: a dictionary of variables contained in 'template', NOT
-          recursively (included templates are not parsed).
-        - templates: list of included temlates, NOT recursively.
-        """
-
-        subvariables = {}
-        templatename = self.jinjaenv.get_template(template).filename
-        with patacrep.encoding.open_read(
-            templatename,
-            encoding=self.encoding
-            ) as template_file:
-            content = template_file.read()
-        subtemplates = list(find_templates(self.jinjaenv.parse(content)))
-        match = re.findall(_VARIABLE_REGEXP, content)
-        if match:
-            for var in match:
+            for variables_string in match:
                 try:
-                    subvariables.update(yaml.load(var))
+                    variables.update(yaml.load(variables_string))
                 except ValueError as exception:
                     raise errors.TemplateError(
                         exception,
@@ -246,12 +218,29 @@ class TexBookRenderer(Renderer):
                             "{filename}. The yaml string was:"
                             "\n'''\n{yamlstring}\n'''"
                         ).format(
-                            filename=templatename,
-                            yamlstring=var,
+                            filename=template.filename,
+                            yamlstring=variables_string,
                             )
                         )
+        return variables
 
-        return (subvariables, subtemplates)
+    def _iter_template_content(self, templatename, *, skip=None):
+        """Iterate over template (and subtemplate) content."""
+        if skip is None:
+            skip = []
+        template = self.jinjaenv.get_template(templatename)
+        with patacrep.encoding.open_read(
+            template.filename,
+            encoding=self.encoding
+            ) as contentfile:
+            content = contentfile.read()
+            for subtemplatename in find_referenced_templates(self.jinjaenv.parse(content)):
+                if subtemplatename not in skip:
+                    yield from self._iter_template_content(
+                        subtemplatename,
+                        skip=skip + [templatename],
+                        )
+            yield content
 
     def render_tex(self, output, context):
         '''Render a template into a .tex file

From 67d53f894fbf4a72746f9db9db4d12c6c445698a Mon Sep 17 00:00:00 2001
From: Oliverpool <oliverpool@hotmail.fr>
Date: Tue, 9 Feb 2016 16:15:19 +0100
Subject: [PATCH 2/3] Include the template name as key of the template
 variables

---
 patacrep/templates.py | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/patacrep/templates.py b/patacrep/templates.py
index f9b91b24..325d581e 100644
--- a/patacrep/templates.py
+++ b/patacrep/templates.py
@@ -193,23 +193,25 @@ class TexBookRenderer(Renderer):
         utils.validate_yaml_schema(data, schema)
         return data
 
-    def get_template_variables(self, templatename):
+    def get_template_variables(self, basetemplate):
         """Parse the template to extract the variables as a dictionary.
 
         If the template includes or extends other templates, load them as well.
 
         Arguments:
-        - templatename: the name of the template, as a string.
+        - basetemplate: the name of the template, as a string.
           in 'template' (or one of its subtemplates), it is not parsed.
         """
         variables = {}
-        for template in self._iter_template_content(templatename):
+        for templatename, template in self._iter_template_content(basetemplate):
             match = re.findall(_VARIABLE_REGEXP, template)
             if not match:
                 continue
+            if templatename not in variables:
+                variables[templatename] = {}
             for variables_string in match:
                 try:
-                    variables.update(yaml.load(variables_string))
+                    variables[templatename].update(yaml.load(variables_string))
                 except ValueError as exception:
                     raise errors.TemplateError(
                         exception,
@@ -240,7 +242,7 @@ class TexBookRenderer(Renderer):
                         subtemplatename,
                         skip=skip + [templatename],
                         )
-            yield content
+            yield template.name, content
 
     def render_tex(self, output, context):
         '''Render a template into a .tex file

From 1bb623ab0d4bc414b543ae7872cf2749faaa46a9 Mon Sep 17 00:00:00 2001
From: Oliverpool <oliverpool@hotmail.fr>
Date: Tue, 9 Feb 2016 16:17:33 +0100
Subject: [PATCH 3/3] Clean debug and reorder

---
 patacrep/templates.py | 22 +++++++---------------
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/patacrep/templates.py b/patacrep/templates.py
index 325d581e..0e96cab0 100644
--- a/patacrep/templates.py
+++ b/patacrep/templates.py
@@ -166,31 +166,23 @@ class TexBookRenderer(Renderer):
         '''
         data = self.get_template_variables(self.template)
         variables = dict()
-        for name, param in data.items():
-            print("*"*30, "DEBUG", "*"*30) # TODO DELETE THIS
-            from pprint import pprint
-            print("Data:"); pprint(data)
-            print("Name:", name)
-            print("Param:", param)
-            template_config = user_config.get(name, {})
-            variables[name] = self._get_variables(param, template_config)
+        for templatename, param in data.items():
+            template_config = user_config.get(templatename, {})
+            variables[templatename] = self._get_variables(param, template_config)
         return variables
 
     @staticmethod
     def _get_variables(parameter, user_config):
         '''Get the default value for the parameter, according to the language.
-        '''
-        schema = parameter.get('schema', {})
 
+        May raise an errors.SBFileError if the data does not respect the schema
+        '''
         data = utils.DictOfDict(parameter.get('default', {}))
         data.update(user_config)
 
-        print("*"*30, "DEBUG", "*"*30) # TODO DELETE THIS
-        from pprint import pprint
-        print("Parameter", parameter)
-        print("Data"); pprint(data)
-        print("Schema"); pprint(schema)
+        schema = parameter.get('schema', {})
         utils.validate_yaml_schema(data, schema)
+
         return data
 
     def get_template_variables(self, basetemplate):