Add settings for custom Jinja globals and tests (#2715)

Pelican has a setting for custom Jinja filters but not custom tests or
custom environment namespace globals. This adds both of the latter.
This commit is contained in:
Justin Mayer 2020-04-12 17:03:53 +02:00 committed by GitHub
commit 7d19bcf5d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 2 deletions

View file

@ -101,7 +101,18 @@ Basic settings
JINJA_FILTERS = {'urlencode': urlencode_filter}
See `Jinja custom filters documentation`_.
See: `Jinja custom filters documentation`_.
.. data:: JINJA_GLOBALS = {}
A dictionary of custom objects to map into the Jinja2 global environment
namespace. The dictionary should map the global name to the global
variable/function. See: `Jinja global namespace documentation`_.
.. data:: JINJA_TESTS = {}
A dictionary of custom Jinja2 tests you want to use. The dictionary should
map test names to test functions. See: `Jinja custom tests documentation`_.
.. data:: LOG_FILTER = []
@ -709,6 +720,10 @@ Time and Date
.. [#] Default is the system locale.
.. _Jinja custom filters documentation: https://jinja.palletsprojects.com/en/master/api/#custom-filters
.. _Jinja global namespace documentation: https://jinja.palletsprojects.com/en/master/api/#the-global-namespace
.. _Jinja custom tests documentation: https://jinja.palletsprojects.com/en/master/api/#custom-tests
.. _locales on Windows: https://www.microsoft.com/en-us/download/details.aspx?id=55979
.. _locale(1): https://linux.die.net/man/1/locale
@ -1357,6 +1372,5 @@ Example settings
:language: python
.. _Jinja custom filters documentation: https://jinja.palletsprojects.com/en/master/api/#custom-filters
.. _Jinja Environment documentation: https://jinja.palletsprojects.com/en/master/api/#jinja2.Environment
.. _Docutils Configuration: http://docutils.sourceforge.net/docs/user/config.html

View file

@ -78,6 +78,14 @@ class Generator(object):
custom_filters = self.settings['JINJA_FILTERS']
self.env.filters.update(custom_filters)
# get custom Jinja globals from user settings
custom_globals = self.settings['JINJA_GLOBALS']
self.env.globals.update(custom_globals)
# get custom Jinja tests from user settings
custom_tests = self.settings['JINJA_TESTS']
self.env.tests.update(custom_tests)
signals.generator_init.send(self)
def get_template(self, name):

View file

@ -120,6 +120,8 @@ DEFAULT_CONFIG = {
'output_format': 'html5',
},
'JINJA_FILTERS': {},
'JINJA_GLOBALS': {},
'JINJA_TESTS': {},
'JINJA_ENVIRONMENT': {
'trim_blocks': True,
'lstrip_blocks': True,

View file

@ -1148,3 +1148,80 @@ class TestStaticGenerator(unittest.TestCase):
self.assertTrue(
os.path.isdir(os.path.join(self.temp_output, "static")))
self.assertTrue(os.path.isfile(self.endfile))
class TestJinja2Environment(unittest.TestCase):
def setUp(self):
self.temp_content = mkdtemp(prefix='pelicantests.')
self.temp_output = mkdtemp(prefix='pelicantests.')
self.old_locale = locale.setlocale(locale.LC_ALL)
locale.setlocale(locale.LC_ALL, str('C'))
def tearDown(self):
rmtree(self.temp_content)
rmtree(self.temp_output)
locale.setlocale(locale.LC_ALL, self.old_locale)
def _test_jinja2_helper(self, additional_settings, content, expected):
settings = get_settings()
settings['STATIC_PATHS'] = ['static']
settings['TEMPLATE_PAGES'] = {
'template/source.html': 'generated/file.html'
}
settings.update(additional_settings)
generator = TemplatePagesGenerator(
context={'foo': 'foo', 'bar': 'bar'}, settings=settings,
path=self.temp_content, theme='', output_path=self.temp_output)
# create a dummy template file
template_dir = os.path.join(self.temp_content, 'template')
template_path = os.path.join(template_dir, 'source.html')
os.makedirs(template_dir)
with open(template_path, 'w') as template_file:
template_file.write(content)
writer = Writer(self.temp_output, settings=settings)
generator.generate_output(writer)
output_path = os.path.join(self.temp_output, 'generated', 'file.html')
# output file has been generated
self.assertTrue(os.path.exists(output_path))
# output content is correct
with open(output_path, 'r') as output_file:
self.assertEqual(output_file.read(), expected)
def test_jinja2_filter(self):
"""JINJA_FILTERS adds custom filters to Jinja2 environment"""
content = 'foo: {{ foo|custom_filter }}, bar: {{ bar|custom_filter }}'
settings = {'JINJA_FILTERS': {'custom_filter': lambda x: x.upper()}}
expected = 'foo: FOO, bar: BAR'
self._test_jinja2_helper(settings, content, expected)
def test_jinja2_test(self):
"""JINJA_TESTS adds custom tests to Jinja2 environment"""
content = 'foo {{ foo is custom_test }}, bar {{ bar is custom_test }}'
settings = {'JINJA_TESTS': {'custom_test': lambda x: x == 'bar'}}
expected = 'foo False, bar True'
self._test_jinja2_helper(settings, content, expected)
def test_jinja2_global(self):
"""JINJA_GLOBALS adds custom globals to Jinja2 environment"""
content = '{{ custom_global }}'
settings = {'JINJA_GLOBALS': {'custom_global': 'foobar'}}
expected = 'foobar'
self._test_jinja2_helper(settings, content, expected)
def test_jinja2_extension(self):
"""JINJA_ENVIRONMENT adds extensions to Jinja2 environment"""
content = '{% set stuff = [] %}{% do stuff.append(1) %}{{ stuff }}'
settings = {'JINJA_ENVIRONMENT': {'extensions': ['jinja2.ext.do']}}
expected = '[1]'
self._test_jinja2_helper(settings, content, expected)