-
Notifications
You must be signed in to change notification settings - Fork 331
Expand file tree
/
Copy pathoperators.py
More file actions
69 lines (57 loc) · 1.86 KB
/
Copy pathoperators.py
File metadata and controls
69 lines (57 loc) · 1.86 KB
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
60
61
62
63
64
65
66
67
68
69
import sqlalchemy as sa
def inspect_type(mixed):
if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute):
return mixed.property.columns[0].type
elif isinstance(mixed, sa.orm.ColumnProperty):
return mixed.columns[0].type
elif isinstance(mixed, sa.Column):
return mixed.type
def is_case_insensitive(mixed):
try:
return isinstance(inspect_type(mixed).comparator, CaseInsensitiveComparator)
except AttributeError:
try:
return issubclass(
inspect_type(mixed).comparator_factory, CaseInsensitiveComparator
)
except AttributeError:
return False
class CaseInsensitiveComparator(sa.Unicode.Comparator):
@classmethod
def lowercase_arg(cls, func):
def operation(self, other, **kwargs):
operator = getattr(sa.Unicode.Comparator, func)
if other is None:
return operator(self, other, **kwargs)
if not is_case_insensitive(other):
other = sa.func.lower(other)
return operator(self, other, **kwargs)
return operation
def in_(self, other):
if isinstance(other, list) or isinstance(other, tuple):
other = map(sa.func.lower, other)
return sa.Unicode.Comparator.in_(self, other)
def notin_(self, other):
if isinstance(other, list) or isinstance(other, tuple):
other = map(sa.func.lower, other)
return sa.Unicode.Comparator.notin_(self, other)
string_operator_funcs = [
'__eq__',
'__ne__',
'__lt__',
'__le__',
'__gt__',
'__ge__',
'concat',
'contains',
'ilike',
'like',
'notlike',
'notilike',
'startswith',
'endswith',
]
for func in string_operator_funcs:
setattr(
CaseInsensitiveComparator, func, CaseInsensitiveComparator.lowercase_arg(func)
)