Ensure Ansible's unique filter preserves order (#67856)

Fixes #63417
This commit is contained in:
Martin Krizek 2020-11-23 08:55:18 +01:00 committed by GitHub
parent 35022e13a8
commit ae08c6a639
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 18 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- Ensure Ansible's unique filter preserves order (https://github.com/ansible/ansible/issues/63417)

View file

@ -62,11 +62,7 @@ def unique(environment, a, case_sensitive=False, attribute=None):
error = e = None error = e = None
try: try:
if HAS_UNIQUE: if HAS_UNIQUE:
c = do_unique(environment, a, case_sensitive=case_sensitive, attribute=attribute) c = list(do_unique(environment, a, case_sensitive=case_sensitive, attribute=attribute))
if isinstance(a, Hashable):
c = set(c)
else:
c = list(c)
except TypeError as e: except TypeError as e:
error = e error = e
_do_fail(e) _do_fail(e)
@ -82,13 +78,11 @@ def unique(environment, a, case_sensitive=False, attribute=None):
raise AnsibleFilterError("Ansible's unique filter does not support case_sensitive nor attribute parameters, " raise AnsibleFilterError("Ansible's unique filter does not support case_sensitive nor attribute parameters, "
"you need a newer version of Jinja2 that provides their version of the filter.") "you need a newer version of Jinja2 that provides their version of the filter.")
if isinstance(a, Hashable):
c = set(a)
else:
c = [] c = []
for x in a: for x in a:
if x not in c: if x not in c:
c.append(x) c.append(x)
return c return c

View file

@ -12,10 +12,10 @@ import ansible.plugins.filter.mathstuff as ms
from ansible.errors import AnsibleFilterError, AnsibleFilterTypeError from ansible.errors import AnsibleFilterError, AnsibleFilterTypeError
UNIQUE_DATA = (([1, 3, 4, 2], sorted([1, 2, 3, 4])), UNIQUE_DATA = (([1, 3, 4, 2], [1, 3, 4, 2]),
([1, 3, 2, 4, 2, 3], sorted([1, 2, 3, 4])), ([1, 3, 2, 4, 2, 3], [1, 3, 2, 4]),
(['a', 'b', 'c', 'd'], sorted(['a', 'b', 'c', 'd'])), (['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']),
(['a', 'a', 'd', 'b', 'a', 'd', 'c', 'b'], sorted(['a', 'b', 'c', 'd'])), (['a', 'a', 'd', 'b', 'a', 'd', 'c', 'b'], ['a', 'd', 'b', 'c']),
) )
TWO_SETS_DATA = (([1, 2], [3, 4], ([], sorted([1, 2]), sorted([1, 2, 3, 4]), sorted([1, 2, 3, 4]))), TWO_SETS_DATA = (([1, 2], [3, 4], ([], sorted([1, 2]), sorted([1, 2, 3, 4]), sorted([1, 2, 3, 4]))),
@ -29,10 +29,10 @@ env = Environment()
@pytest.mark.parametrize('data, expected', UNIQUE_DATA) @pytest.mark.parametrize('data, expected', UNIQUE_DATA)
class TestUnique: class TestUnique:
def test_unhashable(self, data, expected): def test_unhashable(self, data, expected):
assert sorted(ms.unique(env, list(data))) == expected assert ms.unique(env, list(data)) == expected
def test_hashable(self, data, expected): def test_hashable(self, data, expected):
assert sorted(ms.unique(env, tuple(data))) == expected assert ms.unique(env, tuple(data)) == expected
@pytest.mark.parametrize('dataset1, dataset2, expected', TWO_SETS_DATA) @pytest.mark.parametrize('dataset1, dataset2, expected', TWO_SETS_DATA)