# Path: knights/compiler.py
# def kompile(src, raw=False, filename='<compiler>', loader=None, **kwargs):
#     '''
#     Creates a new class based on the supplied template, and returnsit.
# 
#     class Template(object):
#         def __call__(self, context):
#             return ''.join(self._iterator(context))
# 
#         def _iterator(self, context):
#             return map(str, self._root(context)
# 
#         def _root(self, context):
#             yield ''
#             yield ...
#             yield from self.head(context)
# 
#     Blocks create new methods, and add a 'yield from self.{block}(context)' to
#     the current function
# 
#     '''
# 
#     parser = Parser(src, loader=loader)
#     parser.load_library('knights.tags')
#     parser.load_library('knights.helpers')
# 
#     parser.build_method('_root')
# 
#     if parser.parent:
#         # Remove _root from the method list
#         parser.methods = [
#             method for method in parser.methods if method.name != '_root'
#         ]
# 
#     klass = parser.build_class()
# 
#     # Wrap it in a module
#     inst = ast.Module(body=[klass])
# 
#     ast.fix_missing_locations(inst)
# 
#     if kwargs.get('astor', False):
#         import astor
#         print(astor.to_source(inst))
# 
#     # Compile code to create class
#     code = compile(inst, filename=filename, mode='exec', optimize=2)
# 
#     # Execute it and return the instance
#     g = {
#         '_': Helpers(parser.helpers),
#         'parent': parser.parent,
#         'ContextScope': ContextScope,
#     }
#     eval(code, g)
# 
#     klass = g['Template']
#     if raw:
#         return klass
#     return klass()
# 
# Path: knights/loader.py
# class TemplateLoader(dict):
#     def __init__(self, paths):
#         self.paths = [
#             (pathlib.Path.cwd() / path).resolve()
#             for path in paths
#         ]
# 
#     def load(self, name, raw=False):
#         for path in self.paths:
#             full_path = path / name
#             try:
#                 full_path.relative_to(path)
#             except ValueError:
#                 # XXX Raise Suspicious Op?
#                 continue
#             if full_path.exists() and full_path.is_file():
#                 with full_path.open(encoding='utf-8') as fin:
#                     src = fin.read()
# 
#                 return kompile(src, raw=raw, filename=str(full_path), loader=self)
#         raise TemplateNotFound(name)
# 
#     def __missing__(self, key):
#         self[key] = tmpl = self.load(key)
#         return tmpl
# 
# class TemplateNotFound(Exception):
#     pass


from collections import defaultdict
from django.template.backends.base import BaseEngine
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
from django.template.base import (TemplateDoesNotExist,  # NOQA
                                  TemplateSyntaxError)
from .compiler import kompile
from .loader import TemplateLoader, TemplateNotFound

class KnightsTemplater(BaseEngine):

    def __init__(self, params):
        params = params.copy()

        super(KnightsTemplater, self).__init__(params)

        self.loader = TemplateLoader(self.template_dirs)

    def from_string(self, template_code):
        tmpl = kompile(template_code, loader=self.loader)
        return Template(tmpl)

    def get_template(self, template_name):
        try:
            tmpl = self.loader[template_name]
        except TemplateNotFound:
            raise TemplateDoesNotExist(template_name)
        except Exception as e:
            raise TemplateSyntaxError(e).with_traceback(e.__traceback__)
        return Template(tmpl)


class Template(object):

    def __init__(self, template):
        self.template = template

    def render(self, context=None, request=None):

# Path: knights/compiler.py
# def kompile(src, raw=False, filename='<compiler>', loader=None, **kwargs):
#     '''
#     Creates a new class based on the supplied template, and returnsit.
# 
#     class Template(object):
#         def __call__(self, context):
#             return ''.join(self._iterator(context))
# 
#         def _iterator(self, context):
#             return map(str, self._root(context)
# 
#         def _root(self, context):
#             yield ''
#             yield ...
#             yield from self.head(context)
# 
#     Blocks create new methods, and add a 'yield from self.{block}(context)' to
#     the current function
# 
#     '''
# 
#     parser = Parser(src, loader=loader)
#     parser.load_library('knights.tags')
#     parser.load_library('knights.helpers')
# 
#     parser.build_method('_root')
# 
#     if parser.parent:
#         # Remove _root from the method list
#         parser.methods = [
#             method for method in parser.methods if method.name != '_root'
#         ]
# 
#     klass = parser.build_class()
# 
#     # Wrap it in a module
#     inst = ast.Module(body=[klass])
# 
#     ast.fix_missing_locations(inst)
# 
#     if kwargs.get('astor', False):
#         import astor
#         print(astor.to_source(inst))
# 
#     # Compile code to create class
#     code = compile(inst, filename=filename, mode='exec', optimize=2)
# 
#     # Execute it and return the instance
#     g = {
#         '_': Helpers(parser.helpers),
#         'parent': parser.parent,
#         'ContextScope': ContextScope,
#     }
#     eval(code, g)
# 
#     klass = g['Template']
#     if raw:
#         return klass
#     return klass()
# 
# Path: knights/loader.py
# class TemplateLoader(dict):
#     def __init__(self, paths):
#         self.paths = [
#             (pathlib.Path.cwd() / path).resolve()
#             for path in paths
#         ]
# 
#     def load(self, name, raw=False):
#         for path in self.paths:
#             full_path = path / name
#             try:
#                 full_path.relative_to(path)
#             except ValueError:
#                 # XXX Raise Suspicious Op?
#                 continue
#             if full_path.exists() and full_path.is_file():
#                 with full_path.open(encoding='utf-8') as fin:
#                     src = fin.read()
# 
#                 return kompile(src, raw=raw, filename=str(full_path), loader=self)
#         raise TemplateNotFound(name)
# 
#     def __missing__(self, key):
#         self[key] = tmpl = self.load(key)
#         return tmpl
# 
# class TemplateNotFound(Exception):
#     pass


# Path: knights/dj.py
from collections import defaultdict
from django.template.backends.base import BaseEngine
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
from django.template.base import (TemplateDoesNotExist,  # NOQA
                                  TemplateSyntaxError)
from .compiler import kompile
from .loader import TemplateLoader, TemplateNotFound


class KnightsTemplater(BaseEngine):

    def __init__(self, params):
        params = params.copy()

        super(KnightsTemplater, self).__init__(params)

        self.loader = TemplateLoader(self.template_dirs)

    def from_string(self, template_code):
        tmpl = kompile(template_code, loader=self.loader)
        return Template(tmpl)

    def get_template(self, template_name):
        try:
            tmpl = self.loader[template_name]
        except TemplateNotFound:
            raise TemplateDoesNotExist(template_name)
        except Exception as e:
            raise TemplateSyntaxError(e).with_traceback(e.__traceback__)
        return Template(tmpl)


class Template(object):

    def __init__(self, template):
        self.template = template

    def render(self, context=None, request=None):

        if context is None: