From f8a42d366c0d20918fee579406feffe83c1f7b9a Mon Sep 17 00:00:00 2001 From: Ruby Loo Date: Wed, 20 Sep 2017 18:19:17 -0400 Subject: [PATCH] ListType preserves the order of the input The ListType class returns a list of items in a string. The list was not guaranteed to be the same order as in the string; this patch changes it so that the order is preserved. Related-Bug: #1715541 Change-Id: Iefab751d34e97f460b6d63316eb38085e4eb1154 --- ironic/api/controllers/v1/types.py | 13 ++++++++----- .../tests/unit/api/controllers/v1/test_types.py | 16 ++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ironic/api/controllers/v1/types.py b/ironic/api/controllers/v1/types.py index 7dfe12629e..a0f1cad94f 100644 --- a/ironic/api/controllers/v1/types.py +++ b/ironic/api/controllers/v1/types.py @@ -162,12 +162,15 @@ class ListType(wtypes.UserType): """Validate and convert the input to a ListType. :param value: A comma separated string of values - :returns: A list of unique values, whose order is not guaranteed. + :returns: A list of unique values (lower-cased), maintaining the + same order """ - items = [v.strip().lower() for v in six.text_type(value).split(',')] - # filter() to remove empty items - # set() to remove duplicated items - return list(set(filter(None, items))) + items = [] + for v in six.text_type(value).split(','): + v_norm = v.strip().lower() + if v_norm and v_norm not in items: + items.append(v_norm) + return items @staticmethod def frombasetype(value): diff --git a/ironic/tests/unit/api/controllers/v1/test_types.py b/ironic/tests/unit/api/controllers/v1/test_types.py index eadb67ecb6..21ceac46c2 100644 --- a/ironic/tests/unit/api/controllers/v1/test_types.py +++ b/ironic/tests/unit/api/controllers/v1/test_types.py @@ -277,14 +277,14 @@ class TestListType(base.TestCase): def test_list_type(self): v = types.ListType() - self.assertItemsEqual(['foo', 'bar'], v.validate('foo,bar')) - self.assertItemsEqual(['cat', 'meow'], v.validate("cat , meow")) - self.assertItemsEqual(['spongebob', 'squarepants'], - v.validate("SpongeBob,SquarePants")) - self.assertItemsEqual(['foo', 'bar'], - v.validate("foo, ,,bar")) - self.assertItemsEqual(['foo', 'bar'], - v.validate("foo,foo,foo,bar")) + self.assertEqual(['foo', 'bar'], v.validate('foo,bar')) + self.assertNotEqual(['bar', 'foo'], v.validate('foo,bar')) + + self.assertEqual(['cat', 'meow'], v.validate("cat , meow")) + self.assertEqual(['spongebob', 'squarepants'], + v.validate("SpongeBob,SquarePants")) + self.assertEqual(['foo', 'bar'], v.validate("foo, ,,bar")) + self.assertEqual(['foo', 'bar'], v.validate("foo,foo,foo,bar")) self.assertIsInstance(v.validate('foo,bar'), list)