Mercurial > piecrust2
comparison piecrust/data/filters.py @ 3:f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
- Serving works, with debug window.
- Baking works, multi-threading, with dependency handling.
- Various things not implemented yet.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 10 Aug 2014 23:43:16 -0700 |
parents | |
children | 474c9882decf |
comparison
equal
deleted
inserted
replaced
2:40fa08b261b9 | 3:f485ba500df3 |
---|---|
1 import logging | |
2 | |
3 | |
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(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.iteritems(): | |
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 | |
79 | |
80 | |
81 class IFilterClause(object): | |
82 def addClause(self, clause): | |
83 raise NotImplementedError() | |
84 | |
85 def pageMatches(self, page): | |
86 raise NotImplementedError() | |
87 | |
88 | |
89 class NotClause(IFilterClause): | |
90 def __init__(self): | |
91 self.child = None | |
92 | |
93 def addClause(self, clause): | |
94 if self.child is not None: | |
95 raise Exception("'NOT' filtering clauses can only have one " | |
96 "child clause.") | |
97 self.child = clause | |
98 | |
99 def pageMatches(self, page): | |
100 if self.child is None: | |
101 raise Exception("'NOT' filtering clauses must have one child " | |
102 "clause.") | |
103 return not self.child.pageMatches(page) | |
104 | |
105 | |
106 class BooleanClause(IFilterClause): | |
107 def __init__(self): | |
108 self.clauses = [] | |
109 | |
110 def addClause(self, clause): | |
111 self.clauses.append(clause) | |
112 | |
113 | |
114 class AndBooleanClause(BooleanClause): | |
115 def pageMatches(self, page): | |
116 for c in self.clauses: | |
117 if not c.pageMatches(page): | |
118 return False | |
119 return True | |
120 | |
121 | |
122 class OrBooleanClause(BooleanClause): | |
123 def pageMatches(self, page): | |
124 for c in self.clauses: | |
125 if c.pageMatches(page): | |
126 return True | |
127 return False | |
128 | |
129 | |
130 class SettingFilterClause(IFilterClause): | |
131 def __init__(self, name, value, coercer=None): | |
132 self.name = name | |
133 self.value = value | |
134 self.coercer = coercer | |
135 | |
136 def addClause(self, clause): | |
137 raise Exception("Setting filter clauses can't have child clauses. " | |
138 "Use a boolean filter clause instead.") | |
139 | |
140 | |
141 class HasFilterClause(SettingFilterClause): | |
142 def pageMatches(self, page): | |
143 actual_value = page.config.get(self.name) | |
144 if actual_value is None or not isinstance(actual_value, list): | |
145 return False | |
146 | |
147 if self.coercer: | |
148 actual_value = map(self.coercer, actual_value) | |
149 | |
150 return self.value in actual_value | |
151 | |
152 | |
153 class IsFilterClause(SettingFilterClause): | |
154 def pageMatches(self, page): | |
155 actual_value = page.config.get(self.name) | |
156 if self.coercer: | |
157 actual_value = self.coercer(actual_value) | |
158 return actual_value == self.value | |
159 |