Use unicode match for name_or_id

The name_or_id field might be a unicode string.  Make sure we don't
run into problems comparing it by converting all comparison objects.

This is a follow-on to Id89bbf6306adebe96c1db417a4b8b5ae51023af0 based
on/as an alternative to I546b1fbd3375861173f411a7cfdb9e1baa5e6250

Closes-Bug: 1668849
Change-Id: I4e7fa49bd8525148961f02b0e0d7b567145a68b6
Co-Authored-By: Liu Qing <liuqing@chinac.com>
This commit is contained in:
Ian Wienand 2017-03-03 15:10:31 +11:00
parent 0ecbb22547
commit 7883171eca
2 changed files with 42 additions and 4 deletions

View File

@ -75,6 +75,25 @@ def _iterate_timeout(timeout, message, wait=2):
raise exc.OpenStackCloudTimeout(message) raise exc.OpenStackCloudTimeout(message)
def _make_unicode(input):
"""Turn an input into unicode unconditionally
:param input:
A unicode, string or other object
"""
try:
if isinstance(input, unicode):
return input
if isinstance(input, str):
return input.decode('utf-8')
else:
# int, for example
return unicode(input)
except NameError:
# python3!
return str(input)
def _filter_list(data, name_or_id, filters): def _filter_list(data, name_or_id, filters):
"""Filter a list by name/ID and arbitrary meta data. """Filter a list by name/ID and arbitrary meta data.
@ -98,12 +117,14 @@ def _filter_list(data, name_or_id, filters):
A string containing a jmespath expression for further filtering. A string containing a jmespath expression for further filtering.
""" """
if name_or_id: if name_or_id:
# name_or_id might already be unicode
name_or_id = _make_unicode(name_or_id)
identifier_matches = [] identifier_matches = []
for e in data: for e in data:
e_id = e.get('id', None) e_id = _make_unicode(e.get('id', None))
e_name = e.get('name', None) e_name = _make_unicode(e.get('name', None))
if ((e_id and str(e_id) == str(name_or_id)) or if ((e_id and e_id == name_or_id) or
(e_name and str(e_name) == str(name_or_id))): (e_name and e_name == name_or_id)):
identifier_matches.append(e) identifier_matches.append(e)
data = identifier_matches data = identifier_matches

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
@ -47,6 +49,21 @@ class TestUtils(base.TestCase):
ret = _utils._filter_list(data, 'pluto[2017-01-10]', None) ret = _utils._filter_list(data, 'pluto[2017-01-10]', None)
self.assertEqual([el2], ret) self.assertEqual([el2], ret)
def test__filter_list_unicode(self):
el1 = dict(id=100, name=u'中文', last='duck',
other=dict(category='duck', financial=dict(status='poor')))
el2 = dict(id=200, name=u'中文', last='trump',
other=dict(category='human', financial=dict(status='rich')))
el3 = dict(id=300, name='donald', last='ronald mac',
other=dict(category='clown', financial=dict(status='rich')))
data = [el1, el2, el3]
ret = _utils._filter_list(
data, u'中文',
{'other': {
'financial': {'status': 'rich'}
}})
self.assertEqual([el2], ret)
def test__filter_list_filter(self): def test__filter_list_filter(self):
el1 = dict(id=100, name='donald', other='duck') el1 = dict(id=100, name='donald', other='duck')
el2 = dict(id=200, name='donald', other='trump') el2 = dict(id=200, name='donald', other='trump')