Add dict and list filters
For lists filter <list_name>=<value> returns only those artifacts that have value in the list. For dicts filter <dict_name>=<value> returns only those artifacts that have dicts with the key equal value. In both cases filters don't accept any operators. Change-Id: Iea98893b7cd975fa43f23234a78b518c96fe452c
This commit is contained in:
parent
58bf974671
commit
7b47349d02
|
@ -435,13 +435,14 @@ def _do_query_filters(filters):
|
|||
conds = [models.ArtifactProperty.name == field_name]
|
||||
if key_name is not None:
|
||||
conds.extend([models.ArtifactProperty.key_name == key_name])
|
||||
if op != 'in':
|
||||
fn = op_mappings[op]
|
||||
conds.extend([fn(getattr(models.ArtifactProperty,
|
||||
field_type + '_value'), value)])
|
||||
else:
|
||||
conds.extend([getattr(models.ArtifactProperty,
|
||||
field_type + '_value').in_(value)])
|
||||
if value is not None:
|
||||
if op != 'in':
|
||||
fn = op_mappings[op]
|
||||
conds.extend([fn(getattr(models.ArtifactProperty,
|
||||
field_type + '_value'), value)])
|
||||
else:
|
||||
conds.extend([getattr(models.ArtifactProperty,
|
||||
field_type + '_value').in_(value)])
|
||||
|
||||
prop_conds.append(conds)
|
||||
|
||||
|
|
|
@ -531,7 +531,6 @@ class BaseArtifact(base.VersionedObject):
|
|||
# (field_name, key_name, op, field_type, value)
|
||||
new_filters = []
|
||||
for filter_name, filter_value in filters:
|
||||
key_name = None
|
||||
if filter_name in ('tags-any', 'tags'):
|
||||
if ':' in filter_value:
|
||||
msg = _("Tags are filtered without operator")
|
||||
|
@ -539,28 +538,37 @@ class BaseArtifact(base.VersionedObject):
|
|||
new_filters.append(
|
||||
(filter_name, None, None, None, filter_value))
|
||||
continue
|
||||
elif '.' in filter_name:
|
||||
filter_name, key_name = filter_name.split('.', 1)
|
||||
cls._validate_filter_name(filter_name)
|
||||
op, val = utils.split_filter_op(filter_value)
|
||||
cls._validate_filter_ops(filter_name, op)
|
||||
field_type = cls.fields.get(filter_name).element_type
|
||||
else:
|
||||
cls._validate_filter_name(filter_name)
|
||||
op, val = utils.split_filter_op(filter_value)
|
||||
cls._validate_filter_ops(filter_name, op)
|
||||
field_type = cls.fields.get(filter_name)
|
||||
|
||||
key_name = None
|
||||
if '.' in filter_name:
|
||||
filter_name, key_name = filter_name.split('.', 1)
|
||||
if not isinstance(cls.fields.get(filter_name),
|
||||
glare_fields.Dict):
|
||||
msg = _("Field %s is not Dict") % filter_name
|
||||
raise exception.BadRequest(msg)
|
||||
|
||||
cls._validate_filter_name(filter_name)
|
||||
field_type = cls.fields.get(filter_name)
|
||||
|
||||
if isinstance(field_type, glare_fields.List) or isinstance(
|
||||
field_type, glare_fields.Dict) and key_name is not None:
|
||||
field_type = field_type.element_type
|
||||
try:
|
||||
if op == 'in':
|
||||
value = [field_type.coerce(cls(), filter_name, value)
|
||||
for value in
|
||||
utils.split_filter_value_for_quotes(val)]
|
||||
if isinstance(field_type, glare_fields.Dict):
|
||||
new_filters.append((
|
||||
filter_name, filter_value, None, None, None))
|
||||
else:
|
||||
value = field_type.coerce(cls(), filter_name, val)
|
||||
new_filters.append(
|
||||
(filter_name, key_name, op,
|
||||
cls._get_field_type(field_type), value))
|
||||
op, val = utils.split_filter_op(filter_value)
|
||||
cls._validate_filter_ops(filter_name, op)
|
||||
if op == 'in':
|
||||
value = [field_type.coerce(cls(), filter_name, value)
|
||||
for value in
|
||||
utils.split_filter_value_for_quotes(val)]
|
||||
else:
|
||||
value = field_type.coerce(cls(), filter_name, val)
|
||||
new_filters.append(
|
||||
(filter_name, key_name, op,
|
||||
cls._get_field_type(field_type), value))
|
||||
except ValueError:
|
||||
msg = _("Invalid filter value: %s") % str(val)
|
||||
raise exception.BadRequest(msg)
|
||||
|
|
|
@ -425,6 +425,58 @@ class TestList(TestArtifact):
|
|||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual(art_list[5:], result)
|
||||
|
||||
def test_artifact_list_dict_filters(self):
|
||||
lists_of_str = [
|
||||
['aaa', 'bbb', 'ccc'],
|
||||
['aaa', 'bbb'],
|
||||
['aaa', 'ddd'],
|
||||
['bbb'],
|
||||
['ccc']
|
||||
]
|
||||
dicts_of_str = [
|
||||
{'aaa': 'z', 'bbb': 'z', 'ccc': 'z'},
|
||||
{'aaa': 'z', 'bbb': 'z'},
|
||||
{'aaa': 'z', 'ddd': 'z'},
|
||||
{'bbb': 'z'},
|
||||
{'ccc': 'z'}
|
||||
]
|
||||
art_list = [self.create_artifact({'name': 'name%s' % i,
|
||||
'version': '1.0',
|
||||
'tags': ['tag%s' % i],
|
||||
'int1': 1024,
|
||||
'float1': 123.456,
|
||||
'str1': 'bugaga',
|
||||
'bool1': True,
|
||||
'list_of_str': lists_of_str[i],
|
||||
'dict_of_str': dicts_of_str[i]})
|
||||
for i in range(5)]
|
||||
|
||||
# test list filters
|
||||
url = '/sample_artifact?list_of_str=aaa&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual(art_list[:3], result)
|
||||
|
||||
url = '/sample_artifact?list_of_str=ccc&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual([art_list[0], art_list[4]], result)
|
||||
|
||||
url = '/sample_artifact?list_of_str=eee&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual([], result)
|
||||
|
||||
# test dict filters
|
||||
url = '/sample_artifact?dict_of_str=aaa&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual(art_list[:3], result)
|
||||
|
||||
url = '/sample_artifact?dict_of_str=ccc&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual([art_list[0], art_list[4]], result)
|
||||
|
||||
url = '/sample_artifact?dict_of_str=eee&sort=name'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual([], result)
|
||||
|
||||
def test_list_dict_prop_filters(self):
|
||||
# Create artifact
|
||||
art_list = [self.create_artifact({'name': 'name0',
|
||||
|
@ -485,11 +537,14 @@ class TestList(TestArtifact):
|
|||
self.assertEqual([], result)
|
||||
|
||||
url = '/sample_artifact?dict_of_str'
|
||||
self.get(url=url, status=400)
|
||||
self.assertEqual([], result)
|
||||
|
||||
url = '/sample_artifact?dict_of_str.pr3=blabla:val3'
|
||||
self.get(url=url, status=400)
|
||||
|
||||
url = '/sample_artifact?list_of_str.pr3=blabla:val3'
|
||||
self.get(url=url, status=400)
|
||||
|
||||
url = '/sample_artifact?dict_of_str.bla=val1'
|
||||
result = sort_results(self.get(url=url)['sample_artifact'])
|
||||
self.assertEqual([], result)
|
||||
|
|
Loading…
Reference in New Issue