56
56
'rmod' : lambda column : column .__rmod__ ,
57
57
}
58
58
59
+ _DYNAMIC_OPERATORS = [
60
+ 'concat' ,
61
+ 'add' ,
62
+ 'radd' ,
63
+ 'sub' ,
64
+ 'rsub' ,
65
+ 'mul' ,
66
+ 'rmul' ,
67
+ 'truediv' ,
68
+ 'rtruediv' ,
69
+ 'floordiv' ,
70
+ 'rfloordiv' ,
71
+ 'mod' ,
72
+ 'rmod' ,
73
+ ]
74
+
59
75
60
76
def get_sqlalchemy_filter (operator : str , value : Any , allow_arithmetic : bool = True ) -> Callable [[str ], Callable ] | None :
61
77
if operator in ['in' , 'not_in' , 'between' ]:
62
78
if not isinstance (value , (tuple , list , set )):
63
79
raise SelectOperatorError (f'The value of the <{ operator } > filter must be tuple, list or set' )
64
80
65
- if (
66
- operator
67
- in ['add' , 'radd' , 'sub' , 'rsub' , 'mul' , 'rmul' , 'truediv' , 'rtruediv' , 'floordiv' , 'rfloordiv' , 'mod' , 'rmod' ]
68
- and not allow_arithmetic
69
- ):
81
+ if operator in _DYNAMIC_OPERATORS and not allow_arithmetic :
70
82
raise SelectOperatorError (f'Nested arithmetic operations are not allowed: { operator } ' )
71
83
72
84
sqlalchemy_filter = _SUPPORTED_FILTERS .get (operator )
73
- if sqlalchemy_filter is None and operator not in [ 'or' , 'mor' , '__gor' ] :
85
+ if sqlalchemy_filter is None and operator != 'or' :
74
86
warnings .warn (
75
87
f'The operator <{ operator } > is not yet supported, only { ", " .join (_SUPPORTED_FILTERS .keys ())} .' ,
76
88
SyntaxWarning ,
@@ -94,12 +106,6 @@ def _create_or_filters(column: str, op: str, value: Any) -> list[ColumnElement |
94
106
sqlalchemy_filter = get_sqlalchemy_filter (or_op , or_value )
95
107
if sqlalchemy_filter is not None :
96
108
or_filters .append (sqlalchemy_filter (column )(or_value ))
97
- elif op == 'mor' :
98
- for or_op , or_values in value .items ():
99
- for or_value in or_values :
100
- sqlalchemy_filter = get_sqlalchemy_filter (or_op , or_value )
101
- if sqlalchemy_filter is not None :
102
- or_filters .append (sqlalchemy_filter (column )(or_value ))
103
109
return or_filters
104
110
105
111
@@ -131,43 +137,50 @@ def _create_and_filters(column: str, op: str, value: Any) -> list[ColumnElement
131
137
def parse_filters (model : Type [Model ] | AliasedClass , ** kwargs ) -> list [ColumnElement ]:
132
138
filters = []
133
139
134
- def process_filters (target_column : str , target_op : str , target_value : Any ):
135
- # OR / MOR
136
- or_filters = _create_or_filters (target_column , target_op , target_value )
137
- if or_filters :
138
- filters .append (or_ (* or_filters ))
139
-
140
- # ARITHMETIC
141
- arithmetic_filters = _create_arithmetic_filters (target_column , target_op , target_value )
142
- if arithmetic_filters :
143
- filters .append (and_ (* arithmetic_filters ))
144
- else :
145
- # AND
146
- and_filters = _create_and_filters (target_column , target_op , target_value )
147
- if and_filters :
148
- filters .append (* and_filters )
149
-
150
140
for key , value in kwargs .items ():
151
- if '__' in key :
152
- field_name , op = key .rsplit ('__' , 1 )
153
-
154
- # OR GROUP
155
- if field_name == '__gor' and op == '' :
156
- _or_filters = []
157
- for field_or in value :
158
- for _key , _value in field_or .items ():
159
- _field_name , _op = _key .rsplit ('__' , 1 )
160
- _column = get_column (model , _field_name )
161
- process_filters (_column , _op , _value )
162
- if _or_filters :
163
- filters .append (or_ (* _or_filters ))
164
- else :
165
- column = get_column (model , field_name )
166
- process_filters (column , op , value )
167
- else :
168
- # NON FILTER
141
+ if '__' not in key :
142
+ # NO FILTER
169
143
column = get_column (model , key )
170
144
filters .append (column == value )
145
+ continue
146
+
147
+ field_name , op = key .rsplit ('__' , 1 )
148
+
149
+ # OR GROUP
150
+ if field_name == '__or' and op == '' :
151
+ __or__filters = []
152
+
153
+ for field_or in value :
154
+ for _key , _value in field_or .items ():
155
+ _field_name , _op = _key .rsplit ('__' , 1 )
156
+ _column = get_column (model , _field_name )
157
+
158
+ if '__' not in key :
159
+ __or__filters .append (_column == _value )
160
+
161
+ if _op == 'or' :
162
+ __or__filters .append (* _create_or_filters (_column , _op , _value ))
163
+ continue
164
+
165
+ if _op in _DYNAMIC_OPERATORS :
166
+ __or__filters .append (* _create_arithmetic_filters (_column , _op , _value ))
167
+ continue
168
+
169
+ __or__filters .append (* _create_and_filters (_column , _op , _value ))
170
+
171
+ filters .append (or_ (* __or__filters ))
172
+ else :
173
+ column = get_column (model , field_name )
174
+
175
+ if op == 'or' :
176
+ filters .append (or_ (* _create_or_filters (column , op , value )))
177
+ continue
178
+
179
+ if op in _DYNAMIC_OPERATORS :
180
+ filters .append (and_ (* _create_arithmetic_filters (column , op , value )))
181
+ continue
182
+
183
+ filters .append (* _create_and_filters (column , op , value ))
171
184
172
185
return filters
173
186
0 commit comments