Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport tojson filter from #48309 to 2018.3 #48339

Merged
merged 7 commits into from
Jul 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions doc/topics/jinja/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,10 @@ Example:
encoding (usually a ``unicode`` type). This filter was incorrectly-named
when it was added. ``json_decode_list`` will be supported until the Neon
release.
.. deprecated:: 2018.3.3,Fluorine
The :jinja_ref:`tojson` filter accomplishes what this filter was designed
to do, making this filter redundant.


Recursively encodes all string elements of the list to bytes.

Expand Down Expand Up @@ -915,6 +919,9 @@ Returns:
encoding (usually a ``unicode`` type). This filter was incorrectly-named
when it was added. ``json_decode_dict`` will be supported until the Neon
release.
.. deprecated:: 2018.3.3,Fluorine
The :jinja_ref:`tojson` filter accomplishes what this filter was designed
to do, making this filter redundant.

Recursively encodes all string items in the dictionary to bytes.

Expand All @@ -934,6 +941,22 @@ Returns:
{'a': '\xd0\x94'}


.. jinja_ref:: tojson

``tojson``
----------

.. versionadded:: 2018.3.3,Fluorine

Dumps a data structure to JSON.

This filter was added to provide this functionality to hosts which have a
Jinja release older than version 2.9 installed. If Jinja 2.9 or newer is
installed, then the upstream version of the filter will be used. See the
`upstream docs`__ for more information.

.. __: http://jinja.pocoo.org/docs/2.10/templates/#tojson

.. jinja_ref:: random_hash

``random_hash``
Expand Down
17 changes: 17 additions & 0 deletions doc/topics/releases/2018.3.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,20 @@ Improves timezone detection by using the pytz module.

Adds ``timezone.list`` to list supported timezones in either Windows or Unix
format.

New Jinja Filter
================

The :jinja_ref:`tojson` filter (from Jinja 2.9 and later) has been ported to
Salt, and will be used when this filter is not available. This allows older LTS
releases such as CentOS 7 and Ubuntu 14.04 to use this filter.

You should use this filter any time you wish to dump a list or dictionary into
an SLS file, to ensure that the result is able to be loaded by the YAML
renderer. For example:

.. code-block:: jinja

foo:
bar.baz:
- some_arg: {{ mydict|tojson }}
4 changes: 2 additions & 2 deletions salt/utils/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def encode(data, encoding=None, errors='strict', keep=False,


@jinja_filter('json_decode_dict') # Remove this for Neon
@jinja_filter('json_encode_dict')
@jinja_filter('json_encode_dict') # Remove this for Neon
def encode_dict(data, encoding=None, errors='strict', keep=False,
preserve_dict_class=False, preserve_tuples=False):
'''
Expand Down Expand Up @@ -327,7 +327,7 @@ def encode_dict(data, encoding=None, errors='strict', keep=False,


@jinja_filter('json_decode_list') # Remove this for Neon
@jinja_filter('json_encode_list')
@jinja_filter('json_encode_list') # Remove this for Neon
def encode_list(data, encoding=None, errors='strict', keep=False,
preserve_dict_class=False, preserve_tuples=False):
'''
Expand Down
20 changes: 20 additions & 0 deletions salt/utils/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,26 @@ def to_bool(val):
return False


@jinja_filter('tojson')
def tojson(val, indent=None):
'''
Implementation of tojson filter (only present in Jinja 2.9 and later). If
Jinja 2.9 or later is installed, then the upstream version of this filter
will be used.
'''
options = {'ensure_ascii': True}
if indent is not None:
options['indent'] = indent
return (
salt.utils.json.dumps(
val, **options
).replace('<', '\\u003c')
.replace('>', '\\u003e')
.replace('&', '\\u0026')
.replace("'", '\\u0027')
)


@jinja_filter('quote')
def quote(txt):
'''
Expand Down
4 changes: 4 additions & 0 deletions salt/utils/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,12 @@ def opt_jinja_env_helper(opts, optname):
jinja_env = jinja2.Environment(undefined=jinja2.StrictUndefined,
**env_args)

tojson_filter = jinja_env.filters.get('tojson')
jinja_env.tests.update(JinjaTest.salt_jinja_tests)
jinja_env.filters.update(JinjaFilter.salt_jinja_filters)
if tojson_filter is not None:
# Use the existing tojson filter, if present (jinja2 >= 2.9)
jinja_env.filters['tojson'] = tojson_filter
jinja_env.globals.update(JinjaGlobal.salt_jinja_globals)

# globals
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/utils/test_jinja.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
'''
Tests for salt.utils.jinja
'''
# Import Python libs
from __future__ import absolute_import, unicode_literals, print_function

# Import Salt libs
import salt.utils.jinja
from tests.support.unit import TestCase


class JinjaTestCase(TestCase):
def test_tojson(self):
'''
Test the tojson filter for those using Jinja < 2.9. Non-ascii unicode
content should be dumped with ensure_ascii=True.
'''
data = {'Non-ascii words': ['süß', 'спам', 'яйца']}
result = salt.utils.jinja.tojson(data)
expected = '{"Non-ascii words": ["s\\u00fc\\u00df", "\\u0441\\u043f\\u0430\\u043c", "\\u044f\\u0439\\u0446\\u0430"]}'
assert result == expected, result