operators.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import sqlalchemy as sa
  2. def inspect_type(mixed):
  3. if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute):
  4. return mixed.property.columns[0].type
  5. elif isinstance(mixed, sa.orm.ColumnProperty):
  6. return mixed.columns[0].type
  7. elif isinstance(mixed, sa.Column):
  8. return mixed.type
  9. def is_case_insensitive(mixed):
  10. try:
  11. return isinstance(
  12. inspect_type(mixed).comparator,
  13. CaseInsensitiveComparator
  14. )
  15. except AttributeError:
  16. try:
  17. return issubclass(
  18. inspect_type(mixed).comparator_factory,
  19. CaseInsensitiveComparator
  20. )
  21. except AttributeError:
  22. return False
  23. class CaseInsensitiveComparator(sa.Unicode.Comparator):
  24. @classmethod
  25. def lowercase_arg(cls, func):
  26. def operation(self, other, **kwargs):
  27. operator = getattr(sa.Unicode.Comparator, func)
  28. if other is None:
  29. return operator(self, other, **kwargs)
  30. if not is_case_insensitive(other):
  31. other = sa.func.lower(other)
  32. return operator(self, other, **kwargs)
  33. return operation
  34. def in_(self, other):
  35. if isinstance(other, list) or isinstance(other, tuple):
  36. other = map(sa.func.lower, other)
  37. return sa.Unicode.Comparator.in_(self, other)
  38. def notin_(self, other):
  39. if isinstance(other, list) or isinstance(other, tuple):
  40. other = map(sa.func.lower, other)
  41. return sa.Unicode.Comparator.notin_(self, other)
  42. string_operator_funcs = [
  43. '__eq__',
  44. '__ne__',
  45. '__lt__',
  46. '__le__',
  47. '__gt__',
  48. '__ge__',
  49. 'concat',
  50. 'contains',
  51. 'ilike',
  52. 'like',
  53. 'notlike',
  54. 'notilike',
  55. 'startswith',
  56. 'endswith',
  57. ]
  58. for func in string_operator_funcs:
  59. setattr(
  60. CaseInsensitiveComparator,
  61. func,
  62. CaseInsensitiveComparator.lowercase_arg(func)
  63. )