1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
import os
import warnings
from django import dispatch
from jinja2 import Environment, loaders
__all__ = ('env', 'need_env')
env = None
_JINJA_I18N_EXTENSION_NAME = 'jinja2.ext.i18n'
# TODO: This should be documented (as even I'm not sure where it's use-case is)
need_env = dispatch.Signal(providing_args=['arguments', 'loaders',
'filters', 'extensions',
'globals', 'tests'])
class CoffinEnvironment(Environment):
def __init__(self, filters={}, globals={}, tests={}, loader=None, extensions=[], **kwargs):
if not loader:
loader = loaders.ChoiceLoader(self._get_loaders())
all_ext = self._get_all_extensions()
extensions.extend(all_ext['extensions'])
super(CoffinEnvironment, self).__init__(extensions=extensions, loader=loader, **kwargs)
self.filters.update(filters)
self.filters.update(all_ext['filters'])
self.globals.update(globals)
self.globals.update(all_ext['globals'])
self.tests.update(tests)
self.tests.update(all_ext['tests'])
from coffin.template import Template as CoffinTemplate
self.template_class = CoffinTemplate
def _get_loaders(self):
"""Tries to translate each template loader given in the Django settings
(:mod:`django.settings`) to a similarly-behaving Jinja loader.
Warns if a similar loader cannot be found.
Allows for Jinja2 loader instances to be placed in the template loader
settings.
"""
loaders = []
from coffin.template.loaders import jinja_loader_from_django_loader
from django.conf import settings
for loader in settings.TEMPLATE_LOADERS:
if isinstance(loader, basestring):
loader_obj = jinja_loader_from_django_loader(loader)
if loader_obj:
loaders.append(loader_obj)
else:
warnings.warn('Cannot translate loader: %s' % loader)
else: # It's assumed to be a Jinja2 loader instance.
loaders.append(loader)
return loaders
def _get_templatelibs(self):
"""Return an iterable of template ``Library`` instances.
Since we cannot support the {% load %} tag in Jinja, we have to
register all libraries globally.
"""
from django.conf import settings
from django.template import get_library, InvalidTemplateLibrary
libs = []
for a in settings.INSTALLED_APPS:
try:
path = __import__(a + '.templatetags', {}, {}, ['__file__']).__file__
path = os.path.dirname(path) # we now have the templatetags/ directory
except ImportError:
pass
else:
for f in os.listdir(path):
if f == '__init__.py':
continue
if f.endswith('.py'):
try:
# TODO: will need updating when #6587 lands
libs.append(get_library(
"django.templatetags.%s" % os.path.splitext(f)[0]))
except InvalidTemplateLibrary:
pass
return libs
def _get_all_extensions(self):
from django.conf import settings
from coffin.template import builtins
from django.core.urlresolvers import get_callable
extensions, filters, globals, tests = [], {}, {}, {}
# start with our builtins
for lib in builtins:
extensions.extend(getattr(lib, 'jinja2_extensions', []))
filters.update(getattr(lib, 'jinja2_filters', {}))
globals.update(getattr(lib, 'jinja2_globals', {}))
tests.update(getattr(lib, 'jinja2_tests', {}))
if settings.USE_I18N:
extensions.append(_JINJA_I18N_EXTENSION_NAME)
# add the globally defined extension list
extensions.extend(list(getattr(settings, 'JINJA2_EXTENSIONS', [])))
def from_setting(setting):
retval = {}
setting = getattr(settings, setting, {})
if isinstance(setting, dict):
for key, value in setting.iteritems():
retval[user] = callable(value) and value or get_callable(value)
else:
for value in setting:
value = callable(value) and value or get_callable(value)
retval[value.__name__] = value
return retval
filters.update(from_setting('JINJA2_FILTERS'))
globals.update(from_setting('JINJA2_GLOBALS'))
tests.update(from_setting('JINJA2_TESTS'))
# add extensions defined in application's templatetag libraries
for lib in self._get_templatelibs():
extensions.extend(getattr(lib, 'jinja2_extensions', []))
filters.update(getattr(lib, 'jinja2_filters', {}))
globals.update(getattr(lib, 'jinja2_globals', {}))
tests.update(getattr(lib, 'jinja2_tests', {}))
return dict(
extensions=extensions,
filters=filters,
globals=globals,
tests=tests,
)
def get_env():
"""
:return: A Jinja2 environment singleton.
"""
# need_env.send(sender=Environment, arguments=arguments,
# loaders=loaders_, extensions=extensions,
# filters=filters, tests=tests, globals=globals)
return CoffinEnvironment(autoescape=True)
env = get_env()
|