@@ -951,9 +951,12 @@ def _add_filter(self, *filter_data):
951951 self ._filters .append (self ._chain )
952952 sentence , attrs = filter_data
953953 for i , group in enumerate (self ._open_group_flag ):
954- if group is True :
955- # Open a group
956- sentence = '(' + sentence
954+ if group is True or group is None :
955+ # Open a group: None Flags a group that is negated
956+ if group is True :
957+ sentence = '(' + sentence
958+ else :
959+ sentence = 'not (' + sentence
957960 self ._open_group_flag [i ] = False # set to done
958961 self ._filters .append ([self ._attribute , sentence , attrs ])
959962 else :
@@ -1006,14 +1009,18 @@ def logical_operator(self, operation, word):
10061009 :rtype: Query
10071010 """
10081011 word = self ._parse_filter_word (word )
1012+ # consume negation
1013+ negation = self ._negation
1014+ if negation :
1015+ self ._negation = False
10091016 self ._add_filter (
1010- * self ._prepare_sentence (self ._attribute , operation , word ,
1011- self . _negation ) )
1017+ * self ._prepare_sentence (self ._attribute , operation , word , negation )
1018+ )
10121019 return self
10131020
10141021 @fluent
10151022 def equals (self , word ):
1016- """ Add a equals check
1023+ """ Add an equals check
10171024
10181025 :param word: word to compare with
10191026 :rtype: Query
@@ -1022,7 +1029,7 @@ def equals(self, word):
10221029
10231030 @fluent
10241031 def unequal (self , word ):
1025- """ Add a unequals check
1032+ """ Add an unequals check
10261033
10271034 :param word: word to compare with
10281035 :rtype: Query
@@ -1080,10 +1087,12 @@ def function(self, function_name, word):
10801087 :rtype: Query
10811088 """
10821089 word = self ._parse_filter_word (word )
1083-
1090+ # consume negation
1091+ negation = self ._negation
1092+ if negation :
1093+ self ._negation = False
10841094 self ._add_filter (
1085- * self ._prepare_function (function_name , self ._attribute , word ,
1086- self ._negation ))
1095+ * self ._prepare_function (function_name , self ._attribute , word , negation ))
10871096 return self
10881097
10891098 @fluent
@@ -1115,7 +1124,7 @@ def endswith(self, word):
11151124
11161125 @fluent
11171126 def iterable (self , iterable_name , * , collection , word , attribute = None , func = None ,
1118- operation = None , negate = False ):
1127+ operation = None , negation = False ):
11191128 """ Performs a filter with the OData 'iterable_name' keyword
11201129 on the collection
11211130
@@ -1134,7 +1143,7 @@ def iterable(self, iterable_name, *, collection, word, attribute=None, func=None
11341143 the collection
11351144 :param str operation: the logical operation to apply to the attribute
11361145 inside the collection
1137- :param bool negate : negate the funcion or operation inside the iterable
1146+ :param bool negation : negate the funcion or operation inside the iterable
11381147 :rtype: Query
11391148 """
11401149
@@ -1157,21 +1166,26 @@ def iterable(self, iterable_name, *, collection, word, attribute=None, func=None
11571166 attribute = 'a/{}' .format (attribute )
11581167
11591168 if func is not None :
1160- sentence = self ._prepare_function (func , attribute , word , negate )
1169+ sentence = self ._prepare_function (func , attribute , word , negation )
11611170 else :
1162- sentence = self ._prepare_sentence (attribute , operation , word , negate )
1171+ sentence = self ._prepare_sentence (attribute , operation , word , negation )
11631172
11641173 filter_str , attrs = sentence
11651174
1166- filter_data = '{}/{}(a:{})' .format (collection , iterable_name , filter_str ), attrs
1175+ # consume negation
1176+ negation = 'not' if self ._negation else ''
1177+ if self ._negation :
1178+ self ._negation = False
1179+
1180+ filter_data = '{} {}/{}(a:{})' .format (negation , collection , iterable_name , filter_str ).strip (), attrs
11671181 self ._add_filter (* filter_data )
11681182
11691183 self ._attribute = current_att
11701184
11711185 return self
11721186
11731187 @fluent
1174- def any (self , * , collection , word , attribute = None , func = None , operation = None , negate = False ):
1188+ def any (self , * , collection , word , attribute = None , func = None , operation = None , negation = False ):
11751189 """ Performs a filter with the OData 'any' keyword on the collection
11761190
11771191 For example:
@@ -1189,16 +1203,16 @@ def any(self, *, collection, word, attribute=None, func=None, operation=None, ne
11891203 inside the collection
11901204 :param str operation: the logical operation to apply to the
11911205 attribute inside the collection
1192- :param bool negate: negate the funcion or operation inside the iterable
1206+ :param bool negation: negates the funcion or operation inside the iterable
11931207 :rtype: Query
11941208 """
11951209
11961210 return self .iterable ('any' , collection = collection , word = word ,
11971211 attribute = attribute , func = func , operation = operation ,
1198- negate = negate )
1212+ negation = negation )
11991213
12001214 @fluent
1201- def all (self , * , collection , word , attribute = None , func = None , operation = None , negate = False ):
1215+ def all (self , * , collection , word , attribute = None , func = None , operation = None , negation = False ):
12021216 """ Performs a filter with the OData 'all' keyword on the collection
12031217
12041218 For example:
@@ -1216,13 +1230,13 @@ def all(self, *, collection, word, attribute=None, func=None, operation=None, ne
12161230 inside the collection
12171231 :param str operation: the logical operation to apply to the
12181232 attribute inside the collection
1219- :param bool negate : negate the funcion or operation inside the iterable
1233+ :param bool negation : negate the funcion or operation inside the iterable
12201234 :rtype: Query
12211235 """
12221236
12231237 return self .iterable ('all' , collection = collection , word = word ,
12241238 attribute = attribute , func = func , operation = operation ,
1225- negate = negate )
1239+ negation = negation )
12261240
12271241 @fluent
12281242 def order_by (self , attribute = None , * , ascending = True ):
@@ -1243,7 +1257,12 @@ def order_by(self, attribute=None, *, ascending=True):
12431257
12441258 def open_group (self ):
12451259 """ Applies a precedence grouping in the next filters """
1246- self ._open_group_flag .append (True )
1260+ # consume negation
1261+ if self ._negation :
1262+ self ._negation = False
1263+ self ._open_group_flag .append (None ) # flag a negated group open with None
1264+ else :
1265+ self ._open_group_flag .append (True )
12471266 return self
12481267
12491268 def close_group (self ):
0 commit comments