1from __future__ import absolute_import
2import hashlib
3
4from django.template.base import Template
5try:
6    from django.template.exceptions import TemplateDoesNotExist
7except ImportError:  # Django < 1.9
8    from django.template.base import TemplateDoesNotExist
9
10from django.template.loader import BaseLoader
11try:
12    from django.template.engine import Engine
13except ImportError:  # Django < 1.8
14    pass
15import os
16
17from django.conf import settings
18from .compiler import Compiler
19
20from pyjade.utils import process
21# from django.template.loaders.cached import Loader
22
23
24try:
25    from django.template.loader import make_origin
26except ImportError:  # Django >= 1.9
27    try:
28        from django.template import Origin
29
30        def make_origin(display_name, loader, name, dirs):
31            return Origin(
32                name=display_name,
33                template_name=name,
34                loader=loader,
35            )
36    except ImportError:  # Django 1.8.x
37        make_origin = Engine.get_default().make_origin
38
39
40class Loader(BaseLoader):
41    is_usable = True
42
43    def __init__(self, loaders):
44        self.template_cache = {}
45        self._loaders = loaders
46        self._cached_loaders = []
47
48        try:
49            from django.template.loader import find_template_loader as _find_template_loader
50        except:
51            _find_template_loader = Engine.get_default().find_template_loader
52        self._find_template_loader = _find_template_loader
53
54    @property
55    def loaders(self):
56        # Resolve loaders on demand to avoid circular imports
57        if not self._cached_loaders:
58            # Set self._cached_loaders atomically. Otherwise, another thread
59            # could see an incomplete list. See #17303.
60            cached_loaders = []
61            for loader in self._loaders:
62                cached_loaders.append(self._find_template_loader(loader))
63            self._cached_loaders = cached_loaders
64        return self._cached_loaders
65
66    def find_template(self, name, dirs=None):
67        for loader in self.loaders:
68            try:
69                template, display_name = loader(name, dirs)
70                return (template, make_origin(display_name, loader,
71                                              name, dirs))
72            except TemplateDoesNotExist:
73                pass
74        raise TemplateDoesNotExist(name)
75
76    def load_template_source(self, template_name, template_dirs=None):
77        for loader in self.loaders:
78            try:
79                return loader.load_template_source(template_name,
80                                                   template_dirs)
81            except TemplateDoesNotExist:
82                pass
83        raise TemplateDoesNotExist(template_name)
84
85    def load_template(self, template_name, template_dirs=None):
86        key = template_name
87        if template_dirs:
88            # If template directories were specified, use a hash to differentiate
89            key = '-'.join([template_name, hashlib.sha1('|'.join(template_dirs)).hexdigest()])
90
91        if settings.DEBUG or key not in self.template_cache:
92
93            if os.path.splitext(template_name)[1] in ('.jade',):
94                try:
95                    source, display_name = self.load_template_source(template_name, template_dirs)
96                    source = process(source,filename=template_name,compiler=Compiler)
97                    origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
98                    template = Template(source, origin, template_name)
99                except NotImplementedError:
100                    template, origin = self.find_template(template_name, template_dirs)
101            else:
102                template, origin = self.find_template(template_name, template_dirs)
103            if not hasattr(template, 'render'):
104                try:
105                    template = Template(process(source,filename=template_name,compiler=Compiler), origin, template_name)
106                except (TemplateDoesNotExist, UnboundLocalError):
107                    # If compiling the template we found raises TemplateDoesNotExist,
108                    # back off to returning he source and display name for the template
109                    # we were asked to load. This allows for correct identification (later)
110                    # of the actual template that does not exist.
111                    return template, origin
112            self.template_cache[key] = template
113        return self.template_cache[key], None
114
115    # def _preprocess(self, source, name, filename=None):
116    #     parser = Parser(source,filename=filename)
117    #     block = parser.parse()
118    #     compiler = Compiler(block)
119    #     return compiler.compile().strip()
120
121    def reset(self):
122        "Empty the template cache."
123        self.template_cache.clear()
124