mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 02:19:58 -03:30
Merge pull request #5990 from chrismeyersfsu/feature-jsonsearch
host filtering; handle unicode and python types
This commit is contained in:
commit
157ef84612
@ -323,9 +323,9 @@ unicode_spaces_other = unicode_spaces + [u'(', u')', u'=', u'"']
|
||||
|
||||
|
||||
def string_to_type(t):
|
||||
if t == 'true':
|
||||
if t == u'true':
|
||||
return True
|
||||
elif t == 'false':
|
||||
elif t == u'false':
|
||||
return False
|
||||
|
||||
if re.search('^[-+]?[0-9]+$',t):
|
||||
@ -342,7 +342,6 @@ class DynamicFilterField(models.TextField):
|
||||
|
||||
class BoolOperand(object):
|
||||
def __init__(self, t):
|
||||
#print("Got t %s" % t)
|
||||
kwargs = dict()
|
||||
k, v = self._extract_key_value(t)
|
||||
k, v = self._json_path_to_contains(k, v)
|
||||
@ -371,13 +370,13 @@ class DynamicFilterField(models.TextField):
|
||||
contains_count = 0
|
||||
for i, piece in enumerate(pieces):
|
||||
if flag_first_arr_found is False and piece.endswith('[]'):
|
||||
assembled_k += '%s__contains' % (piece[0:-2])
|
||||
assembled_k += u'%s__contains' % (piece[0:-2])
|
||||
contains_count += 1
|
||||
flag_first_arr_found = True
|
||||
elif flag_first_arr_found is False and i == len(pieces) - 1:
|
||||
assembled_k += '%s' % piece
|
||||
assembled_k += u'%s' % piece
|
||||
elif flag_first_arr_found is False:
|
||||
assembled_k += '%s__' % piece
|
||||
assembled_k += u'%s__' % piece
|
||||
elif flag_first_arr_found is True:
|
||||
new_kv = dict()
|
||||
if piece.endswith('[]'):
|
||||
@ -401,9 +400,20 @@ class DynamicFilterField(models.TextField):
|
||||
last_kv = new_kv
|
||||
contains_count += 1
|
||||
|
||||
if contains_count == 1 and isinstance(assembled_v, basestring):
|
||||
assembled_v = '"' + assembled_v + '"'
|
||||
elif contains_count > 1:
|
||||
'''
|
||||
Explicit quotes are kept up till this point.
|
||||
They will be kept if there is ONLY ONE [] in the key search.
|
||||
This is because django filter + postgres expect strings to be
|
||||
quoted "\"hello_world\"". If, instead, there are many [] in a
|
||||
filter key then we can remove the " and ".
|
||||
'''
|
||||
if contains_count != 1:
|
||||
if type(v) is unicode and v.startswith('"') and v.endswith('"'):
|
||||
v = v[1:-1]
|
||||
if contains_count == 0:
|
||||
assembled_v = v
|
||||
|
||||
if contains_count > 1:
|
||||
if type(last_v) is list:
|
||||
last_v.append(v)
|
||||
if type(last_v) is dict:
|
||||
@ -430,10 +440,11 @@ class DynamicFilterField(models.TextField):
|
||||
# value
|
||||
# ="something"
|
||||
if t_len > (v_offset + 2) and t[v_offset] == "\"" and t[v_offset + 2] == "\"":
|
||||
v = t[v_offset + 1]
|
||||
v = u'"' + unicode(t[v_offset + 1]) + u'"'
|
||||
#v = t[v_offset + 1]
|
||||
# empty ""
|
||||
elif t_len > (v_offset + 1):
|
||||
v = ""
|
||||
v = u""
|
||||
# no ""
|
||||
else:
|
||||
v = string_to_type(t[v_offset])
|
||||
@ -481,6 +492,8 @@ class DynamicFilterField(models.TextField):
|
||||
* handle optional value quoted: a.b.c=""
|
||||
|
||||
'''
|
||||
filter_string = unicode(filter_string)
|
||||
|
||||
atom = CharsNotIn(unicode_spaces_other)
|
||||
atom_inside_quotes = CharsNotIn(u'"')
|
||||
atom_quoted = Literal('"') + Optional(atom_inside_quotes) + Literal('"')
|
||||
|
||||
@ -12,20 +12,20 @@ from django.db.models import Q
|
||||
|
||||
class TestDynamicFilterFieldFilterStringToQ():
|
||||
@pytest.mark.parametrize("filter_string,q_expected", [
|
||||
('facts__facts__blank=""', Q(facts__facts__blank="")),
|
||||
('"facts__facts__ space "="f"', Q(**{ "facts__facts__ space ": "f"})),
|
||||
('"facts__facts__ e "=no_quotes_here', Q(**{ "facts__facts__ e ": "no_quotes_here"})),
|
||||
('a__b__c=3', Q(**{ "a__b__c": 3})),
|
||||
('a__b__c=3.14', Q(**{ "a__b__c": 3.14})),
|
||||
('a__b__c=true', Q(**{ "a__b__c": True})),
|
||||
('a__b__c=false', Q(**{ "a__b__c": False})),
|
||||
('a__b__c="true"', Q(**{ "a__b__c": "true"})),
|
||||
#('"a__b\"__c"="true"', Q(**{ "a__b\"__c": "true"})),
|
||||
#('a__b\"__c="true"', Q(**{ "a__b\"__c": "true"})),
|
||||
('facts__facts__blank=""', Q(**{u"facts__facts__blank": u""})),
|
||||
('"facts__facts__ space "="f"', Q(**{u"facts__facts__ space ": u"f"})),
|
||||
('"facts__facts__ e "=no_quotes_here', Q(**{u"facts__facts__ e ": u"no_quotes_here"})),
|
||||
('a__b__c=3', Q(**{u"a__b__c": 3})),
|
||||
('a__b__c=3.14', Q(**{u"a__b__c": 3.14})),
|
||||
('a__b__c=true', Q(**{u"a__b__c": True})),
|
||||
('a__b__c=false', Q(**{u"a__b__c": False})),
|
||||
('a__b__c="true"', Q(**{u"a__b__c": u"true"})),
|
||||
#('"a__b\"__c"="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
#('a__b\"__c="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
])
|
||||
def test_query_generated(self, filter_string, q_expected):
|
||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||
assert str(q) == str(q_expected)
|
||||
assert unicode(q) == unicode(q_expected)
|
||||
|
||||
@pytest.mark.parametrize("filter_string", [
|
||||
'facts__facts__blank='
|
||||
@ -40,39 +40,50 @@ class TestDynamicFilterFieldFilterStringToQ():
|
||||
])
|
||||
def test_unicode(self, filter_string, q_expected):
|
||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||
assert str(q) == str(q_expected)
|
||||
assert unicode(q) == unicode(q_expected)
|
||||
|
||||
@pytest.mark.parametrize("filter_string,q_expected", [
|
||||
('(a=b)', Q(**{"a": "b"})),
|
||||
('a=b and c=d', Q(**{"a": "b"}) & Q(**{"c": "d"})),
|
||||
('(a=b and c=d)', Q(**{"a": "b"}) & Q(**{"c": "d"})),
|
||||
('a=b or c=d', Q(**{"a": "b"}) | Q(**{"c": "d"})),
|
||||
('(a=b and c=d) or (e=f)', (Q(**{"a": "b"}) & Q(**{"c": "d"})) | (Q(**{"e": "f"}))),
|
||||
('(a=b) and (c=d or (e=f and (g=h or i=j))) or (y=z)', Q(**{"a": "b"}) & (Q(**{"c": "d"}) | (Q(**{"e": "f"}) & (Q(**{"g": "h"}) | Q(**{"i": "j"})))) | Q(**{"y": "z"}))
|
||||
('(a=b)', Q(**{u"a": u"b"})),
|
||||
('a=b and c=d', Q(**{u"a": u"b"}) & Q(**{u"c": u"d"})),
|
||||
('(a=b and c=d)', Q(**{u"a": u"b"}) & Q(**{u"c": u"d"})),
|
||||
('a=b or c=d', Q(**{u"a": u"b"}) | Q(**{u"c": u"d"})),
|
||||
('(a=b and c=d) or (e=f)', (Q(**{u"a": u"b"}) & Q(**{u"c": u"d"})) | (Q(**{u"e": u"f"}))),
|
||||
('(a=b) and (c=d or (e=f and (g=h or i=j))) or (y=z)', Q(**{u"a": u"b"}) & (Q(**{u"c": u"d"}) | (Q(**{u"e": u"f"}) & (Q(**{u"g": u"h"}) | Q(**{u"i": u"j"})))) | Q(**{u"y": u"z"}))
|
||||
])
|
||||
def test_boolean_parenthesis(self, filter_string, q_expected):
|
||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||
assert str(q) == str(q_expected)
|
||||
assert unicode(q) == unicode(q_expected)
|
||||
|
||||
@pytest.mark.parametrize("filter_string,q_expected", [
|
||||
('a__b__c[]=3', Q(**{ "a__b__c__contains": 3})),
|
||||
('a__b__c[]=3.14', Q(**{ "a__b__c__contains": 3.14})),
|
||||
('a__b__c[]=true', Q(**{ "a__b__c__contains": True})),
|
||||
('a__b__c[]=false', Q(**{ "a__b__c__contains": False})),
|
||||
('a__b__c[]="true"', Q(**{ "a__b__c__contains": "\"true\""})),
|
||||
('a__b__c[]="hello world"', Q(**{ "a__b__c__contains": "\"hello world\""})),
|
||||
('a__b__c[]__d[]="foobar"', Q(**{ "a__b__c__contains": [{"d": ["foobar"]}]})),
|
||||
('a__b__c[]__d="foobar"', Q(**{ "a__b__c__contains": [{"d": "foobar"}]})),
|
||||
('a__b__c[]__d__e="foobar"', Q(**{ "a__b__c__contains": [{"d": {"e": "foobar"}}]})),
|
||||
('a__b__c[]__d__e[]="foobar"', Q(**{ "a__b__c__contains": [{"d": {"e": ["foobar"]}}]})),
|
||||
('a__b__c[]__d__e__f[]="foobar"', Q(**{ "a__b__c__contains": [{"d": {"e": {"f": ["foobar"]}}}]})),
|
||||
('(a__b__c[]__d__e__f[]="foobar") and (a__b__c[]__d__e[]="foobar")', Q(**{ "a__b__c__contains": [{"d": {"e": {"f": ["foobar"]}}}]}) & Q(**{ "a__b__c__contains": [{"d": {"e": ["foobar"]}}]})),
|
||||
#('"a__b\"__c"="true"', Q(**{ "a__b\"__c": "true"})),
|
||||
#('a__b\"__c="true"', Q(**{ "a__b\"__c": "true"})),
|
||||
('a__b__c[]=3', Q(**{u"a__b__c__contains": 3})),
|
||||
('a__b__c[]=3.14', Q(**{u"a__b__c__contains": 3.14})),
|
||||
('a__b__c[]=true', Q(**{u"a__b__c__contains": True})),
|
||||
('a__b__c[]=false', Q(**{u"a__b__c__contains": False})),
|
||||
('a__b__c[]="true"', Q(**{u"a__b__c__contains": u"\"true\""})),
|
||||
('a__b__c[]="hello world"', Q(**{u"a__b__c__contains": u"\"hello world\""})),
|
||||
('a__b__c[]__d[]="foobar"', Q(**{u"a__b__c__contains": [{u"d": [u"foobar"]}]})),
|
||||
('a__b__c[]__d="foobar"', Q(**{u"a__b__c__contains": [{u"d": u"foobar"}]})),
|
||||
('a__b__c[]__d__e="foobar"', Q(**{u"a__b__c__contains": [{u"d": {u"e": u"foobar"}}]})),
|
||||
('a__b__c[]__d__e[]="foobar"', Q(**{u"a__b__c__contains": [{u"d": {u"e": [u"foobar"]}}]})),
|
||||
('a__b__c[]__d__e__f[]="foobar"', Q(**{u"a__b__c__contains": [{u"d": {u"e": {u"f": [u"foobar"]}}}]})),
|
||||
('(a__b__c[]__d__e__f[]="foobar") and (a__b__c[]__d__e[]="foobar")', Q(**{ u"a__b__c__contains": [{u"d": {u"e": {u"f": [u"foobar"]}}}]}) & Q(**{u"a__b__c__contains": [{u"d": {u"e": [u"foobar"]}}]})),
|
||||
#('"a__b\"__c"="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
#('a__b\"__c="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
])
|
||||
def test_contains_query_generated(self, filter_string, q_expected):
|
||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||
assert str(q) == str(q_expected)
|
||||
assert unicode(q) == unicode(q_expected)
|
||||
|
||||
@pytest.mark.parametrize("filter_string,q_expected", [
|
||||
#('a__b__c[]="true"', Q(**{u"a__b__c__contains": u"\"true\""})),
|
||||
('a__b__c="true"', Q(**{u"a__b__c": u"true"})),
|
||||
#('"a__b\"__c"="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
#('a__b\"__c="true"', Q(**{u"a__b\"__c": "true"})),
|
||||
])
|
||||
def test_contains_query_generated_unicode(self, filter_string, q_expected):
|
||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||
assert unicode(q) == unicode(q_expected)
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user