@@ -951,9 +951,12 @@ def _add_filter(self, *filter_data):
951
951
self ._filters .append (self ._chain )
952
952
sentence , attrs = filter_data
953
953
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
957
960
self ._open_group_flag [i ] = False # set to done
958
961
self ._filters .append ([self ._attribute , sentence , attrs ])
959
962
else :
@@ -1006,14 +1009,18 @@ def logical_operator(self, operation, word):
1006
1009
:rtype: Query
1007
1010
"""
1008
1011
word = self ._parse_filter_word (word )
1012
+ # consume negation
1013
+ negation = self ._negation
1014
+ if negation :
1015
+ self ._negation = False
1009
1016
self ._add_filter (
1010
- * self ._prepare_sentence (self ._attribute , operation , word ,
1011
- self . _negation ) )
1017
+ * self ._prepare_sentence (self ._attribute , operation , word , negation )
1018
+ )
1012
1019
return self
1013
1020
1014
1021
@fluent
1015
1022
def equals (self , word ):
1016
- """ Add a equals check
1023
+ """ Add an equals check
1017
1024
1018
1025
:param word: word to compare with
1019
1026
:rtype: Query
@@ -1022,7 +1029,7 @@ def equals(self, word):
1022
1029
1023
1030
@fluent
1024
1031
def unequal (self , word ):
1025
- """ Add a unequals check
1032
+ """ Add an unequals check
1026
1033
1027
1034
:param word: word to compare with
1028
1035
:rtype: Query
@@ -1080,10 +1087,12 @@ def function(self, function_name, word):
1080
1087
:rtype: Query
1081
1088
"""
1082
1089
word = self ._parse_filter_word (word )
1083
-
1090
+ # consume negation
1091
+ negation = self ._negation
1092
+ if negation :
1093
+ self ._negation = False
1084
1094
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 ))
1087
1096
return self
1088
1097
1089
1098
@fluent
@@ -1115,7 +1124,7 @@ def endswith(self, word):
1115
1124
1116
1125
@fluent
1117
1126
def iterable (self , iterable_name , * , collection , word , attribute = None , func = None ,
1118
- operation = None , negate = False ):
1127
+ operation = None , negation = False ):
1119
1128
""" Performs a filter with the OData 'iterable_name' keyword
1120
1129
on the collection
1121
1130
@@ -1134,7 +1143,7 @@ def iterable(self, iterable_name, *, collection, word, attribute=None, func=None
1134
1143
the collection
1135
1144
:param str operation: the logical operation to apply to the attribute
1136
1145
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
1138
1147
:rtype: Query
1139
1148
"""
1140
1149
@@ -1157,21 +1166,26 @@ def iterable(self, iterable_name, *, collection, word, attribute=None, func=None
1157
1166
attribute = 'a/{}' .format (attribute )
1158
1167
1159
1168
if func is not None :
1160
- sentence = self ._prepare_function (func , attribute , word , negate )
1169
+ sentence = self ._prepare_function (func , attribute , word , negation )
1161
1170
else :
1162
- sentence = self ._prepare_sentence (attribute , operation , word , negate )
1171
+ sentence = self ._prepare_sentence (attribute , operation , word , negation )
1163
1172
1164
1173
filter_str , attrs = sentence
1165
1174
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
1167
1181
self ._add_filter (* filter_data )
1168
1182
1169
1183
self ._attribute = current_att
1170
1184
1171
1185
return self
1172
1186
1173
1187
@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 ):
1175
1189
""" Performs a filter with the OData 'any' keyword on the collection
1176
1190
1177
1191
For example:
@@ -1189,16 +1203,16 @@ def any(self, *, collection, word, attribute=None, func=None, operation=None, ne
1189
1203
inside the collection
1190
1204
:param str operation: the logical operation to apply to the
1191
1205
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
1193
1207
:rtype: Query
1194
1208
"""
1195
1209
1196
1210
return self .iterable ('any' , collection = collection , word = word ,
1197
1211
attribute = attribute , func = func , operation = operation ,
1198
- negate = negate )
1212
+ negation = negation )
1199
1213
1200
1214
@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 ):
1202
1216
""" Performs a filter with the OData 'all' keyword on the collection
1203
1217
1204
1218
For example:
@@ -1216,13 +1230,13 @@ def all(self, *, collection, word, attribute=None, func=None, operation=None, ne
1216
1230
inside the collection
1217
1231
:param str operation: the logical operation to apply to the
1218
1232
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
1220
1234
:rtype: Query
1221
1235
"""
1222
1236
1223
1237
return self .iterable ('all' , collection = collection , word = word ,
1224
1238
attribute = attribute , func = func , operation = operation ,
1225
- negate = negate )
1239
+ negation = negation )
1226
1240
1227
1241
@fluent
1228
1242
def order_by (self , attribute = None , * , ascending = True ):
@@ -1243,7 +1257,12 @@ def order_by(self, attribute=None, *, ascending=True):
1243
1257
1244
1258
def open_group (self ):
1245
1259
""" 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 )
1247
1266
return self
1248
1267
1249
1268
def close_group (self ):
0 commit comments