2052.3.6
by John Arbash Meinel
[merge] bzr.dev 2078 |
1 |
# Copyright (C) 2006 Canonical Ltd
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
17 |
"""Tests for the Registry classes"""
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
18 |
|
19 |
import os |
|
20 |
import sys |
|
21 |
||
22 |
from bzrlib import ( |
|
23 |
errors, |
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
24 |
registry, |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
25 |
osutils, |
26 |
)
|
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
27 |
from bzrlib.tests import TestCase, TestCaseInTempDir |
28 |
||
29 |
||
30 |
class TestRegistry(TestCase): |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
31 |
|
32 |
def register_stuff(self, a_registry): |
|
33 |
a_registry.register('one', 1) |
|
34 |
a_registry.register('two', 2) |
|
35 |
a_registry.register('four', 4) |
|
36 |
a_registry.register('five', 5) |
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
37 |
|
38 |
def test_registry(self): |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
39 |
a_registry = registry.Registry() |
40 |
self.register_stuff(a_registry) |
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
41 |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
42 |
self.failUnless(a_registry.default_key is None) |
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
43 |
|
44 |
# test get() (self.default_key == None)
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
45 |
self.assertRaises(KeyError, a_registry.get) |
46 |
self.assertRaises(KeyError, a_registry.get, None) |
|
47 |
self.assertEqual(2, a_registry.get('two')) |
|
48 |
self.assertRaises(KeyError, a_registry.get, 'three') |
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
49 |
|
50 |
# test _set_default_key
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
51 |
a_registry.default_key = 'five' |
52 |
self.failUnless(a_registry.default_key == 'five') |
|
53 |
self.assertEqual(5, a_registry.get()) |
|
54 |
self.assertEqual(5, a_registry.get(None)) |
|
55 |
# If they ask for a specific entry, they should get KeyError
|
|
56 |
# not the default value. They can always pass None if they prefer
|
|
57 |
self.assertRaises(KeyError, a_registry.get, 'six') |
|
58 |
self.assertRaises(KeyError, a_registry._set_default_key, 'six') |
|
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
59 |
|
60 |
# test keys()
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
61 |
self.assertEqual(['five', 'four', 'one', 'two'], a_registry.keys()) |
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
62 |
|
1911.4.11
by John Arbash Meinel
Remove extra dict-like members, simplfying the api |
63 |
def test_registry_funcs(self): |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
64 |
a_registry = registry.Registry() |
65 |
self.register_stuff(a_registry) |
|
66 |
||
67 |
self.failUnless('one' in a_registry) |
|
1911.4.11
by John Arbash Meinel
Remove extra dict-like members, simplfying the api |
68 |
a_registry.remove('one') |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
69 |
self.failIf('one' in a_registry) |
70 |
self.assertRaises(KeyError, a_registry.get, 'one') |
|
71 |
||
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
72 |
a_registry.register('one', 'one') |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
73 |
|
74 |
self.assertEqual(['five', 'four', 'one', 'two'], |
|
1911.4.11
by John Arbash Meinel
Remove extra dict-like members, simplfying the api |
75 |
sorted(a_registry.keys())) |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
76 |
self.assertEqual([('five', 5), ('four', 4), |
77 |
('one', 'one'), ('two', 2)], |
|
78 |
sorted(a_registry.iteritems())) |
|
79 |
||
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
80 |
def test_register_override(self): |
81 |
a_registry = registry.Registry() |
|
82 |
a_registry.register('one', 'one') |
|
83 |
self.assertRaises(KeyError, a_registry.register, 'one', 'two') |
|
84 |
self.assertRaises(KeyError, a_registry.register, 'one', 'two', |
|
85 |
override_existing=False) |
|
86 |
||
87 |
a_registry.register('one', 'two', override_existing=True) |
|
88 |
self.assertEqual('two', a_registry.get('one')) |
|
89 |
||
90 |
self.assertRaises(KeyError, a_registry.register_lazy, |
|
91 |
'one', 'three', 'four') |
|
92 |
||
93 |
a_registry.register_lazy('one', 'module', 'member', |
|
94 |
override_existing=True) |
|
95 |
||
96 |
def test_registry_help(self): |
|
97 |
a_registry = registry.Registry() |
|
98 |
a_registry.register('one', 1, help='help text for one') |
|
99 |
# We should not have to import the module to return the help
|
|
100 |
# information
|
|
101 |
a_registry.register_lazy('two', 'nonexistent_module', 'member', |
|
102 |
help='help text for two') |
|
103 |
||
104 |
# We should be able to handle a callable to get information
|
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
105 |
help_calls = [] |
1911.4.9
by John Arbash Meinel
A help callable should take the registry as the first parameter |
106 |
def generic_help(reg, key): |
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
107 |
help_calls.append(key) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
108 |
return 'generic help for %s' % (key,) |
109 |
a_registry.register('three', 3, help=generic_help) |
|
110 |
a_registry.register_lazy('four', 'nonexistent_module', 'member2', |
|
111 |
help=generic_help) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
112 |
a_registry.register('five', 5) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
113 |
|
1911.4.10
by John Arbash Meinel
A test which uses the callback to return information from the object. |
114 |
def help_from_object(reg, key): |
115 |
obj = reg.get(key) |
|
116 |
return obj.help() |
|
117 |
||
118 |
class SimpleObj(object): |
|
119 |
def help(self): |
|
120 |
return 'this is my help' |
|
121 |
a_registry.register('six', SimpleObj(), help=help_from_object) |
|
122 |
||
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
123 |
self.assertEqual('help text for one', a_registry.get_help('one')) |
124 |
self.assertEqual('help text for two', a_registry.get_help('two')) |
|
125 |
self.assertEqual('generic help for three', |
|
126 |
a_registry.get_help('three')) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
127 |
self.assertEqual(['three'], help_calls) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
128 |
self.assertEqual('generic help for four', |
129 |
a_registry.get_help('four')) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
130 |
self.assertEqual(['three', 'four'], help_calls) |
131 |
self.assertEqual(None, a_registry.get_help('five')) |
|
1911.4.10
by John Arbash Meinel
A test which uses the callback to return information from the object. |
132 |
self.assertEqual('this is my help', a_registry.get_help('six')) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
133 |
|
134 |
self.assertRaises(KeyError, a_registry.get_help, None) |
|
1911.4.10
by John Arbash Meinel
A test which uses the callback to return information from the object. |
135 |
self.assertRaises(KeyError, a_registry.get_help, 'seven') |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
136 |
|
137 |
a_registry.default_key = 'one' |
|
138 |
self.assertEqual('help text for one', a_registry.get_help(None)) |
|
1911.4.10
by John Arbash Meinel
A test which uses the callback to return information from the object. |
139 |
self.assertRaises(KeyError, a_registry.get_help, 'seven') |
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
140 |
|
141 |
self.assertEqual([('five', None), |
|
142 |
('four', 'generic help for four'), |
|
143 |
('one', 'help text for one'), |
|
1911.4.10
by John Arbash Meinel
A test which uses the callback to return information from the object. |
144 |
('six', 'this is my help'), |
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
145 |
('three', 'generic help for three'), |
146 |
('two', 'help text for two'), |
|
1911.4.11
by John Arbash Meinel
Remove extra dict-like members, simplfying the api |
147 |
], sorted((key, a_registry.get_help(key)) |
148 |
for key in a_registry.keys())) |
|
149 |
||
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
150 |
# We don't know what order it was called in, but we should get
|
151 |
# 2 more calls to three and four
|
|
152 |
self.assertEqual(['four', 'four', 'three', 'three'], |
|
153 |
sorted(help_calls)) |
|
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
154 |
|
155 |
def test_registry_info(self): |
|
156 |
a_registry = registry.Registry() |
|
157 |
a_registry.register('one', 1, info='string info') |
|
158 |
# We should not have to import the module to return the info
|
|
159 |
a_registry.register_lazy('two', 'nonexistent_module', 'member', |
|
160 |
info=2) |
|
161 |
||
162 |
# We should be able to handle a callable to get information
|
|
163 |
a_registry.register('three', 3, info=['a', 'list']) |
|
164 |
obj = object() |
|
165 |
a_registry.register_lazy('four', 'nonexistent_module', 'member2', |
|
166 |
info=obj) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
167 |
a_registry.register('five', 5) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
168 |
|
169 |
self.assertEqual('string info', a_registry.get_info('one')) |
|
170 |
self.assertEqual(2, a_registry.get_info('two')) |
|
171 |
self.assertEqual(['a', 'list'], a_registry.get_info('three')) |
|
172 |
self.assertIs(obj, a_registry.get_info('four')) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
173 |
self.assertIs(None, a_registry.get_info('five')) |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
174 |
|
175 |
self.assertRaises(KeyError, a_registry.get_info, None) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
176 |
self.assertRaises(KeyError, a_registry.get_info, 'six') |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
177 |
|
178 |
a_registry.default_key = 'one' |
|
179 |
self.assertEqual('string info', a_registry.get_info(None)) |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
180 |
self.assertRaises(KeyError, a_registry.get_info, 'six') |
1911.4.7
by John Arbash Meinel
Add help and info parameters, and tests for them |
181 |
|
1911.4.8
by John Arbash Meinel
Add Registry.iterhelp and Registry.iterinfo |
182 |
self.assertEqual([('five', None), |
183 |
('four', obj), |
|
184 |
('one', 'string info'), |
|
185 |
('three', ['a', 'list']), |
|
186 |
('two', 2), |
|
1911.4.11
by John Arbash Meinel
Remove extra dict-like members, simplfying the api |
187 |
], sorted((key, a_registry.get_info(key)) |
188 |
for key in a_registry.keys())) |
|
189 |
||
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
190 |
|
191 |
class TestRegistryWithDirs(TestCaseInTempDir): |
|
192 |
"""Registry tests that require temporary dirs"""
|
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
193 |
|
194 |
def create_plugin_file(self, contents): |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
195 |
"""Create a file to be used as a plugin.
|
196 |
||
197 |
This is created in a temporary directory, so that we
|
|
198 |
are sure that it doesn't start in the plugin path.
|
|
199 |
"""
|
|
200 |
os.mkdir('tmp') |
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
201 |
plugin_name = 'bzr_plugin_a_%s' % (osutils.rand_chars(4),) |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
202 |
open('tmp/'+plugin_name+'.py', 'wb').write(contents) |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
203 |
return plugin_name |
204 |
||
205 |
def create_simple_plugin(self): |
|
206 |
return self.create_plugin_file( |
|
207 |
'object1 = "foo"\n' |
|
208 |
'\n\n' |
|
209 |
'def function(a,b,c):\n' |
|
210 |
' return a,b,c\n' |
|
211 |
'\n\n' |
|
212 |
'class MyClass(object):\n' |
|
213 |
' def __init__(self, a):\n' |
|
214 |
' self.a = a\n' |
|
215 |
'\n\n' |
|
216 |
)
|
|
217 |
||
1912.5.2
by Adeodato Simó
Morph John's LazyFactory into a generalized Registry class, and |
218 |
def test_lazy_import_registry(self): |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
219 |
plugin_name = self.create_simple_plugin() |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
220 |
a_registry = registry.Registry() |
221 |
a_registry.register_lazy('obj', plugin_name, 'object1') |
|
222 |
a_registry.register_lazy('function', plugin_name, 'function') |
|
223 |
a_registry.register_lazy('klass', plugin_name, 'MyClass') |
|
224 |
a_registry.register_lazy('module', plugin_name, None) |
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
225 |
|
226 |
self.assertEqual(['function', 'klass', 'module', 'obj'], |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
227 |
sorted(a_registry.keys())) |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
228 |
# The plugin should not be loaded until we grab the first object
|
229 |
self.failIf(plugin_name in sys.modules) |
|
230 |
||
231 |
# By default the plugin won't be in the search path
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
232 |
self.assertRaises(ImportError, a_registry.get, 'obj') |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
233 |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
234 |
plugin_path = os.getcwd() + '/tmp' |
235 |
sys.path.append(plugin_path) |
|
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
236 |
try: |
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
237 |
obj = a_registry.get('obj') |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
238 |
self.assertEqual('foo', obj) |
239 |
self.failUnless(plugin_name in sys.modules) |
|
240 |
||
241 |
# Now grab another object
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
242 |
func = a_registry.get('function') |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
243 |
self.assertEqual(plugin_name, func.__module__) |
244 |
self.assertEqual('function', func.__name__) |
|
245 |
self.assertEqual((1, [], '3'), func(1, [], '3')) |
|
246 |
||
247 |
# And finally a class
|
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
248 |
klass = a_registry.get('klass') |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
249 |
self.assertEqual(plugin_name, klass.__module__) |
250 |
self.assertEqual('MyClass', klass.__name__) |
|
251 |
||
252 |
inst = klass(1) |
|
253 |
self.assertIsInstance(inst, klass) |
|
254 |
self.assertEqual(1, inst.a) |
|
255 |
||
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
256 |
module = a_registry.get('module') |
1911.4.1
by John Arbash Meinel
Creating a factory that can load modules on demand. |
257 |
self.assertIs(obj, module.object1) |
258 |
self.assertIs(func, module.function) |
|
259 |
self.assertIs(klass, module.MyClass) |
|
260 |
finally: |
|
1911.4.5
by John Arbash Meinel
Make a Registry look more like a dict, and allow anyone to register stuff lazily. |
261 |
sys.path.remove(plugin_path) |
262 |