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