Mercurial > wikked
annotate tests/mock.py @ 82:9afe4a1dbd1e
Refactoring of core wiki classes:
- Use proper classes instead of dictionaries more often.
- Simplified `Page`'s public API.
- Page meta property values are now always stored in an array, even if there's
only one occurence for the given key.
- Updated unit-tests.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 19 Mar 2013 19:54:11 -0700 |
parents | 2733871775cd |
children | fd6eccb24882 |
rev | line source |
---|---|
49 | 1 import re |
2 import os.path | |
3 import types | |
4 import codecs | |
5 import logging | |
6 import StringIO | |
7 from wikked.page import Page | |
82
9afe4a1dbd1e
Refactoring of core wiki classes:
Ludovic Chabant <ludovic@chabant.com>
parents:
51
diff
changeset
|
8 from wikked.fs import PageInfo, PageNotFoundError |
49 | 9 from wikked.db import Database |
10 from wikked.indexer import WikiIndex | |
11 from wikked.scm import SourceControl | |
12 | |
13 | |
14 class MockWikiParameters(object): | |
15 def __init__(self): | |
16 self.formatters = { | |
17 self._passthrough: ['txt', 'html'] | |
18 } | |
19 | |
20 self.config_text = "" | |
21 self.special_filenames = [] | |
51 | 22 self.use_db = False |
49 | 23 |
24 self.logger_factory = lambda: logging.getLogger('wikked.tests') | |
25 self.page_factory = lambda wiki, url: MockPage(wiki, url) | |
26 self.config_factory = lambda: StringIO.StringIO(self.config_text) | |
27 self.fs_factory = lambda cfg: MockFileSystem() | |
28 self.index_factory = lambda cfg: MockWikiIndex() | |
29 self.db_factory = lambda cfg: MockDatabase() | |
30 self.scm_factory = lambda cfg: MockSourceControl() | |
31 | |
32 def getSpecialFilenames(self): | |
33 return self.special_filenames | |
34 | |
35 def _passthrough(self, text): | |
36 return text | |
37 | |
38 | |
39 class MockPage(Page): | |
40 def __init__(self, wiki, url): | |
41 Page.__init__(self, wiki, url) | |
42 | |
43 | |
44 class MockDatabase(Database): | |
45 def __init__(self, content=None, logger=None): | |
46 Database.__init__(self, logger) | |
47 self.content = content | |
51 | 48 self.conn = None |
49 | 49 self._open_count = 0 |
50 | |
51 def initDb(self): | |
52 pass | |
53 | |
54 def open(self): | |
55 self._open_count += 1 | |
51 | 56 self.conn = 'MOCK_CONNECTION' |
49 | 57 |
58 def close(self): | |
59 self._open_count -= 1 | |
60 if self._open_count < 0: | |
61 raise Exception( | |
62 "The database was closed more times than it was open.") | |
51 | 63 elif self._open_count == 0: |
64 self.conn = None | |
49 | 65 |
66 def reset(self, pages): | |
67 pass | |
68 | |
69 def update(self, pages): | |
70 pass | |
71 | |
72 def getPageUrls(self, subdir=None): | |
73 return [] | |
74 | |
75 def getPages(self, subdir=None): | |
76 return [] | |
77 | |
78 def getPage(self, url): | |
79 return None | |
80 | |
81 def pageExists(self, url): | |
82 return False | |
83 | |
84 def getLinksTo(self, url): | |
85 return [] | |
86 | |
87 | |
88 class MockFileSystem(): | |
89 def __init__(self, structure=None, slugify=Page.title_to_url, logger=None): | |
90 if not structure: | |
91 structure = [] | |
92 if not slugify: | |
93 slugify = lambda x: x | |
94 self.structure = structure | |
95 self.slugify = slugify | |
96 self.logger = logger | |
97 self.excluded = [] | |
98 | |
99 def getPageInfos(self, subdir=None): | |
100 node = self._getNode(subdir) | |
51 | 101 if node is None: |
102 raise PageNotFoundError() | |
49 | 103 for n in self._getChildren(node): |
104 yield self._getPageInfo(n) | |
105 | |
106 def getPageInfo(self, path): | |
107 node = self._getNode(path) | |
51 | 108 if node is None: |
109 raise PageNotFoundError() | |
49 | 110 return self._getPageInfo(node) |
111 | |
112 def getPage(self, url): | |
113 path = self._getPath(url, True) | |
114 node = self._getNode(path) | |
51 | 115 if node is None: |
116 raise PageNotFoundError() | |
49 | 117 return self._getPageInfo(node, True) |
118 | |
119 def setPage(self, path, content): | |
51 | 120 raise NotImplementedError() |
49 | 121 |
122 def pageExists(self, url): | |
51 | 123 try: |
124 self._getPath(url, True) | |
125 return True | |
126 except PageNotFoundError: | |
127 return False | |
49 | 128 |
129 def getPhysicalNamespacePath(self, url): | |
51 | 130 raise NotImplementedError() |
49 | 131 |
132 def _getPageInfo(self, node, with_content=False): | |
133 path_split = os.path.splitext(node['path']) | |
134 url = self.slugify(path_split[0]) | |
82
9afe4a1dbd1e
Refactoring of core wiki classes:
Ludovic Chabant <ludovic@chabant.com>
parents:
51
diff
changeset
|
135 info = PageInfo(url, node['path']) |
49 | 136 if with_content: |
82
9afe4a1dbd1e
Refactoring of core wiki classes:
Ludovic Chabant <ludovic@chabant.com>
parents:
51
diff
changeset
|
137 info.content = node['content'] |
49 | 138 return info |
139 | |
140 def _getNode(self, path): | |
141 node = self.structure | |
142 if path: | |
143 for n in path.split('/'): | |
51 | 144 if n not in node: |
145 return None | |
49 | 146 node = node[n] |
147 else: | |
148 path = '' | |
149 if isinstance(node, types.StringTypes): | |
150 return {'type': 'file', 'path': path, 'content': node} | |
151 return {'type': 'dir', 'path': path, 'content': node} | |
152 | |
153 def _getChildren(self, node): | |
154 if node['type'] != 'dir': | |
155 raise Exception("'%s' is not a directory." % node['path']) | |
156 for name in node['content']: | |
157 child_path = os.path.join(node['path'], name) | |
158 child = node['content'][name] | |
159 if isinstance(child, types.StringTypes): | |
160 yield { | |
161 'type': 'file', | |
162 'path': child_path, | |
163 'content': child | |
164 } | |
165 else: | |
166 for c in self._getChildren({ | |
167 'type': 'dir', | |
168 'path': child_path, | |
169 'content': child | |
170 }): | |
171 yield c | |
172 | |
173 def _getPath(self, url, is_file): | |
174 path = '' | |
175 current = self.structure | |
176 parts = unicode(url).lower().split('/') | |
177 for i, part in enumerate(parts): | |
178 for name in current: | |
179 name_slug = self.slugify(name) | |
180 if is_file and i == len(parts) - 1: | |
181 if re.match(r"%s\.[a-z]+" % re.escape(part), name_slug): | |
182 current = current[name] | |
183 path = os.path.join(path, name) | |
184 break | |
185 else: | |
186 if name_slug == part: | |
187 current = current[name] | |
188 path = os.path.join(path, name) | |
189 break | |
190 else: | |
191 # Failed to find a part of the URL. | |
192 raise PageNotFoundError("No such page: " + url) | |
193 return path | |
194 | |
195 @staticmethod | |
196 def save_structure(path, structure): | |
197 if not os.path.isdir(path): | |
198 os.makedirs(path) | |
199 for node in structure: | |
200 node_path = os.path.join(path, node) | |
201 if isinstance(structure[node], types.StringTypes): | |
202 with codecs.open(node_path, 'w', encoding='utf-8') as f: | |
203 f.write(structure[node]) | |
204 else: | |
205 MockFileSystem.save_structure(node_path, structure[node]) | |
206 | |
207 | |
208 class MockWikiIndex(WikiIndex): | |
209 def __init__(self, logger=None): | |
210 WikiIndex.__init__(self, logger) | |
211 | |
212 def initIndex(self): | |
213 pass | |
214 | |
215 def reset(self, pages): | |
216 pass | |
217 | |
218 def update(self, pages): | |
219 pass | |
220 | |
221 def search(self, query): | |
222 # url, title, content_highlights | |
223 return None | |
224 | |
225 | |
226 class MockSourceControl(SourceControl): | |
227 def __init__(self, logger=None): | |
228 SourceControl.__init__(self, logger) | |
229 | |
230 def initRepo(self): | |
231 pass | |
232 | |
233 def getSpecialFilenames(self): | |
234 return [] | |
235 | |
236 def getHistory(self, path=None): | |
237 return [] | |
238 | |
239 def getState(self, path): | |
240 raise NotImplementedError() | |
241 | |
242 def getRevision(self, path, rev): | |
243 raise NotImplementedError() | |
244 | |
245 def diff(self, path, rev1, rev2): | |
246 raise NotImplementedError() | |
247 | |
248 def commit(self, paths, op_meta): | |
249 raise NotImplementedError() | |
250 | |
251 def revert(self, paths=None): | |
252 raise NotImplementedError() |