]> git.phdru.name Git - m_librarian.git/blob - m_librarian/search.py
Feat(search): Использовать фильтры из файла конфигурации
[m_librarian.git] / m_librarian / search.py
1 try:
2     from configparser import NoSectionError, NoOptionError
3 except ImportError:  # Python 2
4     from ConfigParser import NoSectionError, NoOptionError
5
6 from sqlobject.sqlbuilder import AND, OR, func
7 from .config import get_config
8 from .db import Author, Book, Extension, Genre, Language
9
10 __all__ = [
11     'mk_search_conditions',
12     'search_authors', 'search_books', 'search_extensions',
13     'search_genres', 'search_languages',
14 ]
15
16
17 def _mk_search_conditions_with_operator(table, case_sensitive, comparison_op,
18                                         values, expressions):
19     if expressions is None:
20         expressions = []
21     _expressions = []
22     for column, value in values.items():
23         if column == 'id':
24             _expressions.append(table.q.id == value)
25             break
26     if case_sensitive:
27         for column, value in values.items():
28             if column == 'id':
29                 continue
30             _expressions.append(
31                 getattr(getattr(table.q, column), comparison_op)(value))
32         for expr, value in expressions:
33             _expressions.append(
34                 getattr(expr, comparison_op)(value))
35     else:
36         for column, value in values.items():
37             if column == 'id':
38                 continue
39             _expressions.append(
40                 getattr(func.lower(
41                     getattr(table.q, column)),
42                     comparison_op)(value.lower()))
43         for expr, value in expressions:
44             _expressions.append(
45                 getattr(func.lower(expr), comparison_op)(value.lower()))
46     return _expressions
47
48
49 _comparison_operators = {
50     'start': 'startswith',
51     'substring': 'contains',
52     'full': '__eq__',
53 }
54
55
56 def mk_search_conditions(table, search_type, case_sensitive, values,
57                          expressions=None, join_expressions=None):
58     if join_expressions is None:
59         join_expressions = []
60     return _mk_search_conditions_with_operator(
61         table, case_sensitive, _comparison_operators[search_type],
62         values, expressions) + join_expressions
63
64
65 def _search(table, search_type, case_sensitive, values,
66             expressions=None, join_expressions=None, orderBy=None):
67     conditions = mk_search_conditions(
68         table, search_type, case_sensitive, values, expressions=expressions,
69         join_expressions=join_expressions)
70     return table.select(AND(*conditions), orderBy=orderBy)
71
72
73 def search_authors(search_type, case_sensitive, values,
74                    expressions=None, orderBy=None):
75     return _search(Author, search_type, case_sensitive, values,
76                    expressions=expressions, orderBy=orderBy)
77
78
79 def search_books(search_type, case_sensitive, values, join_expressions=None,
80                  orderBy=None, use_filters=False):
81     if use_filters:
82         config = get_config()
83         try:
84             lang_filter = config.get('filters', 'lang')
85         except (NoSectionError, NoOptionError):
86             lang_filter = None
87         try:
88             deleted_filter = config.getint('filters', 'deleted')
89         except (NoSectionError, NoOptionError):
90             deleted_filter = None
91         if lang_filter:
92             if join_expressions is None:
93                 join_expressions = []
94             lang_conditions = []
95             for lang in lang_filter.split():
96                 lvalues = {'name': lang}
97                 conditions = mk_search_conditions(
98                     Language, search_type, case_sensitive, lvalues)
99                 lang_conditions.append(conditions)
100             join_expressions.append(Book.j.language)
101             join_expressions.append(OR(*lang_conditions))
102     conditions = mk_search_conditions(
103         Book, search_type, case_sensitive, values,
104         join_expressions=join_expressions)
105     if use_filters and not deleted_filter:
106         conditions.append(Book.q.deleted == False)  # noqa: E712
107     return Book.select(AND(*conditions), orderBy=orderBy)
108
109
110 def search_extensions(search_type, case_sensitive, values, orderBy=None):
111     return _search(Extension, search_type, case_sensitive, values,
112                    orderBy=orderBy)
113
114
115 def search_genres(search_type, case_sensitive, values, orderBy=None):
116     return _search(Genre, search_type, case_sensitive, values,
117                    orderBy=orderBy)
118
119
120 def search_languages(search_type, case_sensitive, values, orderBy=None):
121     return _search(Language, search_type, case_sensitive, values,
122                    orderBy=orderBy)