-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfilter.py
59 lines (52 loc) · 2.42 KB
/
filter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import re
from typing import *
class Filter:
def __init__(self, **kwargs):
# any argument matching the pattern is accepted
for attribute in kwargs:
if not (re.match(r'\w+__\w+__$', attribute) or attribute == "operator"):
raise ValueError(f"{attribute} does not match expected attribute format.")
self.__dict__.update(kwargs)
if "operator" not in self.__dir__():
self.operator = "AND"
def __eq__(self, other):
# -> tested
# check for all non hidden attributes of this class
# if they are present in another object
# and match the corresponding attributes of another object
attributes = [attr for attr in self.__dir__() if not (attr.startswith("__") or attr == "operator")]
checks = []
try:
for attr in attributes:
attribute = "__".join(attr.split("__")[0:-2])
magic_method = "__" + attr.split("__")[-2] + "__"
value = self.__getattribute__(attr)
other_value = other.__getattribute__(attribute)
checks.append(value.__getattribute__(magic_method)(other_value))
except AttributeError:
# when attribute is not present in other object, abort
return False
# return true if
# all attributes of this filter are present in the other object
# and the values match the magic method
return False not in checks
def __str__(self, logical_condition: Optional[str] = None):
# -> tested
# Returns a string to be used for sql style databases
attributes = [a for a in self.__dir__() if not (a.startswith("__") or a == "operator")]
for attr in range(len(attributes)):
a = attributes[attr] + str(self.__getattribute__(attributes[attr]))
a = a.replace("__eq__", "=")
a = a.replace("__ne__", "!=")
a = a.replace("__lt__", "<")
a = a.replace("__gt__", ">")
a = a.replace("__lte__", "<=")
a = a.replace("__gte__", ">=")
a = a.replace("__contains__", " BETWEEN ")
attributes[attr] = a
return str.join(f" {(logical_condition or self.operator).upper()} ", attributes)
def __bool__(self):
return bool(len([a for a in self.__dir__() if not (a.startswith("__") or a == "operator")]))
if __name__ == "__main__":
import tests
tests.run_tests()