Mercurial > piecrust2
comparison piecrust/data/filters.py @ 967:afd230972167
data: Improve pagination filters code, add `defined` and `not_empty`.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 08 Oct 2017 09:30:59 -0700 |
parents | 08e02c2a2a1a |
children |
comparison
equal
deleted
inserted
replaced
966:cc55740860de | 967:afd230972167 |
---|---|
1 import logging | 1 import logging |
2 | 2 |
3 | 3 |
4 logger = logging.getLogger(__name__) | 4 logger = logging.getLogger(__name__) |
5 | |
6 | |
7 class PaginationFilter(object): | |
8 def __init__(self): | |
9 self.root_clause = None | |
10 | |
11 @property | |
12 def is_empty(self): | |
13 return self.root_clause is None | |
14 | |
15 def addClause(self, clause): | |
16 self._ensureRootClause() | |
17 self.root_clause.addClause(clause) | |
18 | |
19 def addClausesFromConfig(self, config): | |
20 self._ensureRootClause() | |
21 self._addClausesFromConfigRecursive(config, self.root_clause) | |
22 | |
23 def pageMatches(self, page): | |
24 if self.root_clause is None: | |
25 return True | |
26 return self.root_clause.pageMatches(self, page) | |
27 | |
28 def _ensureRootClause(self): | |
29 if self.root_clause is None: | |
30 self.root_clause = AndBooleanClause() | |
31 | |
32 def _addClausesFromConfigRecursive(self, config, parent_clause): | |
33 for key, val in config.items(): | |
34 if key == 'and': | |
35 if not isinstance(val, list) or len(val) == 0: | |
36 raise Exception("The given boolean 'AND' filter clause " | |
37 "doesn't have an array of child clauses.") | |
38 subcl = AndBooleanClause() | |
39 parent_clause.addClause(subcl) | |
40 for c in val: | |
41 self._addClausesFromConfigRecursive(c, subcl) | |
42 | |
43 elif key == 'or': | |
44 if not isinstance(val, list) or len(val) == 0: | |
45 raise Exception("The given boolean 'OR' filter clause " | |
46 "doesn't have an array of child clauses.") | |
47 subcl = OrBooleanClause() | |
48 parent_clause.addClause(subcl) | |
49 for c in val: | |
50 self._addClausesFromConfigRecursive(c, subcl) | |
51 | |
52 elif key == 'not': | |
53 if isinstance(val, list): | |
54 if len(val) != 1: | |
55 raise Exception("'NOT' filter clauses must have " | |
56 "exactly one child clause.") | |
57 val = val[0] | |
58 subcl = NotClause() | |
59 parent_clause.addClause(subcl) | |
60 self._addClausesFromConfigRecursive(val, subcl) | |
61 | |
62 elif key[:4] == 'has_': | |
63 setting_name = key[4:] | |
64 if isinstance(val, list): | |
65 wrappercl = AndBooleanClause() | |
66 for c in val: | |
67 wrappercl.addClause(HasFilterClause(setting_name, c)) | |
68 parent_clause.addClause(wrappercl) | |
69 else: | |
70 parent_clause.addClause(HasFilterClause(setting_name, val)) | |
71 | |
72 elif key[:3] == 'is_': | |
73 setting_name = key[3:] | |
74 parent_clause.addClause(IsFilterClause(setting_name, val)) | |
75 | |
76 else: | |
77 raise Exception("Unknown filter clause: %s" % key) | |
78 | 5 |
79 | 6 |
80 class IFilterClause(object): | 7 class IFilterClause(object): |
81 def addClause(self, clause): | 8 def addClause(self, clause): |
82 raise NotImplementedError() | 9 raise NotImplementedError() |
124 if c.pageMatches(fil, page): | 51 if c.pageMatches(fil, page): |
125 return True | 52 return True |
126 return False | 53 return False |
127 | 54 |
128 | 55 |
56 class IsDefinedFilterClause(IFilterClause): | |
57 def __init__(self, name): | |
58 self.name = name | |
59 | |
60 def pageMatches(self, fil, page): | |
61 return self.name in page.config | |
62 | |
63 | |
64 class IsNotEmptyFilterClause(IFilterClause): | |
65 def __init__(self, name): | |
66 self.name = name | |
67 | |
68 def pageMatches(self, fil, page): | |
69 return bool(page.config.get(self.name)) | |
70 | |
71 | |
129 class SettingFilterClause(IFilterClause): | 72 class SettingFilterClause(IFilterClause): |
130 def __init__(self, name, value, coercer=None): | 73 def __init__(self, name, value, coercer=None): |
131 self.name = name | 74 self.name = name |
132 self.value = value | 75 self.value = value |
133 self.coercer = coercer | 76 self.coercer = coercer |
154 actual_value = page.config.get(self.name) | 97 actual_value = page.config.get(self.name) |
155 if self.coercer: | 98 if self.coercer: |
156 actual_value = self.coercer(actual_value) | 99 actual_value = self.coercer(actual_value) |
157 return actual_value == self.value | 100 return actual_value == self.value |
158 | 101 |
102 | |
103 unary_ops = {'not': NotClause} | |
104 binary_ops = { | |
105 'and': AndBooleanClause, | |
106 'or': OrBooleanClause} | |
107 misc_ops = { | |
108 'defined': IsDefinedFilterClause, | |
109 'not_empty': IsNotEmptyFilterClause} | |
110 | |
111 | |
112 class PaginationFilter(object): | |
113 def __init__(self): | |
114 self.root_clause = None | |
115 | |
116 @property | |
117 def is_empty(self): | |
118 return self.root_clause is None | |
119 | |
120 def addClause(self, clause): | |
121 self._ensureRootClause() | |
122 self.root_clause.addClause(clause) | |
123 | |
124 def addClausesFromConfig(self, config): | |
125 self._ensureRootClause() | |
126 self._addClausesFromConfigRecursive(config, self.root_clause) | |
127 | |
128 def pageMatches(self, page): | |
129 if self.root_clause is None: | |
130 return True | |
131 return self.root_clause.pageMatches(self, page) | |
132 | |
133 def _ensureRootClause(self): | |
134 if self.root_clause is None: | |
135 self.root_clause = AndBooleanClause() | |
136 | |
137 def _addClausesFromConfigRecursive(self, config, parent_clause): | |
138 for key, val in config.items(): | |
139 clause_class = unary_ops.get(key) | |
140 if clause_class: | |
141 if isinstance(val, list): | |
142 if len(val) != 1: | |
143 raise Exception( | |
144 "Unary filter '%s' must have exactly one child " | |
145 "clause." % key) | |
146 val = val[0] | |
147 subcl = clause_class() | |
148 parent_clause.addClause(subcl) | |
149 self._addClausesFromConfigRecursive(val, subcl) | |
150 continue | |
151 | |
152 clause_class = binary_ops.get(key) | |
153 if clause_class: | |
154 if not isinstance(val, list) or len(val) == 0: | |
155 raise Exception( | |
156 "Binary filter clause '%s' doesn't have an array " | |
157 "of child clauses." % key) | |
158 subcl = clause_class() | |
159 parent_clause.addClause(subcl) | |
160 for c in val: | |
161 self._addClausesFromConfigRecursive(c, subcl) | |
162 continue | |
163 | |
164 clause_class = misc_ops.get(key) | |
165 if clause_class: | |
166 if isinstance(val, list): | |
167 wrappercl = AndBooleanClause() | |
168 for c in val: | |
169 wrappercl.addClause(clause_class(c)) | |
170 parent_clause.addClause(wrappercl) | |
171 else: | |
172 parent_clause.addClause(clause_class(val)) | |
173 continue | |
174 | |
175 if key[:4] == 'has_': | |
176 setting_name = key[4:] | |
177 if isinstance(val, list): | |
178 wrappercl = AndBooleanClause() | |
179 for c in val: | |
180 wrappercl.addClause(HasFilterClause(setting_name, c)) | |
181 parent_clause.addClause(wrappercl) | |
182 else: | |
183 parent_clause.addClause(HasFilterClause(setting_name, val)) | |
184 continue | |
185 | |
186 if key[:3] == 'is_': | |
187 setting_name = key[3:] | |
188 parent_clause.addClause(IsFilterClause(setting_name, val)) | |
189 continue | |
190 | |
191 raise Exception("Unknown filter clause: %s" % key) |