mirror of
https://github.com/ansible/awx.git
synced 2026-03-03 17:51:06 -03:30
add not logic to json search
* Also fix up single contains [] logic. Values with a single contains should be wrapped in [] and not, like I thought before, \"\"
This commit is contained in:
@@ -401,19 +401,18 @@ class DynamicFilterField(models.TextField):
|
|||||||
contains_count += 1
|
contains_count += 1
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Explicit quotes are kept up till this point.
|
Explicit quotes are kept until this point.
|
||||||
They will be kept if there is ONLY ONE [] in the key search.
|
Note: we could have totally "ripped" them off earlier when we decided
|
||||||
This is because django filter + postgres expect strings to be
|
what type to convert the token to.
|
||||||
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('"'):
|
||||||
if type(v) is unicode and v.startswith('"') and v.endswith('"'):
|
v = v[1:-1]
|
||||||
v = v[1:-1]
|
|
||||||
if contains_count == 0:
|
|
||||||
assembled_v = v
|
|
||||||
|
|
||||||
if contains_count > 1:
|
if contains_count == 0:
|
||||||
|
assembled_v = v
|
||||||
|
elif contains_count == 1:
|
||||||
|
assembled_v = [v]
|
||||||
|
elif contains_count > 1:
|
||||||
if type(last_v) is list:
|
if type(last_v) is list:
|
||||||
last_v.append(v)
|
last_v.append(v)
|
||||||
if type(last_v) is dict:
|
if type(last_v) is dict:
|
||||||
@@ -471,9 +470,13 @@ class DynamicFilterField(models.TextField):
|
|||||||
|
|
||||||
|
|
||||||
class BoolNot(object):
|
class BoolNot(object):
|
||||||
def __init__(self,t):
|
def __init__(self, t):
|
||||||
self.right = t[0][1]
|
self.right = t[0][1].result
|
||||||
self.result = ~self.right
|
|
||||||
|
self.result = self.execute_logic(self.right)
|
||||||
|
|
||||||
|
def execute_logic(self, right):
|
||||||
|
return ~right
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -503,7 +506,7 @@ class DynamicFilterField(models.TextField):
|
|||||||
grammar.setParseAction(cls.BoolOperand)
|
grammar.setParseAction(cls.BoolOperand)
|
||||||
|
|
||||||
boolExpr = infixNotation(grammar, [
|
boolExpr = infixNotation(grammar, [
|
||||||
#("not", 1, opAssoc.RIGHT, cls.BoolNot),
|
("not", 1, opAssoc.RIGHT, cls.BoolNot),
|
||||||
("and", 2, opAssoc.LEFT, cls.BoolAnd),
|
("and", 2, opAssoc.LEFT, cls.BoolAnd),
|
||||||
("or", 2, opAssoc.LEFT, cls.BoolOr),
|
("or", 2, opAssoc.LEFT, cls.BoolOr),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -48,19 +48,20 @@ class TestDynamicFilterFieldFilterStringToQ():
|
|||||||
('(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 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)', (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"}))
|
('(a=b and not c=d) or not (e=f)', (Q(**{u"a": u"b"}) & ~Q(**{u"c": u"d"})) | (~Q(**{u"e": u"f"}))),
|
||||||
|
('(a=b) and not (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):
|
def test_boolean_parenthesis(self, filter_string, q_expected):
|
||||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||||
assert unicode(q) == unicode(q_expected)
|
assert unicode(q) == unicode(q_expected)
|
||||||
|
|
||||||
@pytest.mark.parametrize("filter_string,q_expected", [
|
@pytest.mark.parametrize("filter_string,q_expected", [
|
||||||
('a__b__c[]=3', Q(**{u"a__b__c__contains": 3})),
|
('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[]=3.14', Q(**{u"a__b__c__contains": [3.14]})),
|
||||||
('a__b__c[]=true', Q(**{u"a__b__c__contains": True})),
|
('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[]=false', Q(**{u"a__b__c__contains": [False]})),
|
||||||
('a__b__c[]="true"', Q(**{u"a__b__c__contains": u"\"true\""})),
|
('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[]="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="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"}}]})),
|
||||||
@@ -84,8 +85,6 @@ class TestDynamicFilterFieldFilterStringToQ():
|
|||||||
q = DynamicFilterField.filter_string_to_q(filter_string)
|
q = DynamicFilterField.filter_string_to_q(filter_string)
|
||||||
assert unicode(q) == unicode(q_expected)
|
assert unicode(q) == unicode(q_expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
#('"facts__quoted_val"="f\"oo"', 1),
|
#('"facts__quoted_val"="f\"oo"', 1),
|
||||||
#('facts__facts__arr[]="foo"', 1),
|
#('facts__facts__arr[]="foo"', 1),
|
||||||
|
|||||||
Reference in New Issue
Block a user