46
79
# TODO: Write a test for plugin decoration of commands.
48
class TestLoadingPlugins(TestCaseInTempDir):
52
def test_plugins_with_the_same_name_are_not_loaded(self):
53
# This test tests that having two plugins in different directories does
54
# not result in both being loaded when they have the same name. get a
55
# file name we can use which is also a valid attribute for accessing in
56
# activeattributes. - we cannot give import parameters.
58
self.failIf(tempattribute in self.activeattributes)
59
# set a place for the plugins to record their loading, and at the same
60
# time validate that the location the plugins should record to is
62
bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
64
self.failUnless(tempattribute in self.activeattributes)
65
# create two plugin directories
68
# write a plugin that will record when its loaded in the
70
template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
71
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
72
print >> file(os.path.join('first', 'plugin.py'), 'w'), template % (tempattribute, 'first')
73
print >> file(os.path.join('second', 'plugin.py'), 'w'), template % (tempattribute, 'second')
75
bzrlib.plugin.load_from_path(['first', 'second'])
76
self.assertEqual(['first'], self.activeattributes[tempattribute])
78
# remove the plugin 'plugin'
79
del self.activeattributes[tempattribute]
80
if getattr(bzrlib.plugins, 'plugin', None):
81
del bzrlib.plugins.plugin
82
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
84
def test_plugins_from_different_dirs_can_demand_load(self):
85
# This test tests that having two plugins in different
86
# directories with different names allows them both to be loaded, when
87
# we do a direct import statement.
88
# Determine a file name we can use which is also a valid attribute
89
# for accessing in activeattributes. - we cannot give import parameters.
90
tempattribute = "different-dirs"
91
self.failIf(tempattribute in self.activeattributes)
92
# set a place for the plugins to record their loading, and at the same
93
# time validate that the location the plugins should record to is
95
bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
97
self.failUnless(tempattribute in self.activeattributes)
98
# create two plugin directories
101
# write plugins that will record when they are loaded in the
102
# tempattribute list.
103
template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
104
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
105
print >> file(os.path.join('first', 'pluginone.py'), 'w'), template % (tempattribute, 'first')
106
print >> file(os.path.join('second', 'plugintwo.py'), 'w'), template % (tempattribute, 'second')
107
oldpath = bzrlib.plugins.__path__
109
bzrlib.plugins.__path__ = ['first', 'second']
110
exec "import bzrlib.plugins.pluginone"
111
self.assertEqual(['first'], self.activeattributes[tempattribute])
112
exec "import bzrlib.plugins.plugintwo"
113
self.assertEqual(['first', 'second'],
114
self.activeattributes[tempattribute])
116
# remove the plugin 'plugin'
117
del self.activeattributes[tempattribute]
118
if getattr(bzrlib.plugins, 'plugin', None):
119
del bzrlib.plugins.plugin
120
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
123
class TestAllPlugins(TestCaseInTempDir):
125
def test_plugin_appears_in_all_plugins(self):
126
# This test tests a new plugin appears in bzrlib.plugin.all_plugins().
127
# check the plugin is not loaded already
128
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
129
# write a plugin that _cannot_ fail to load.
130
print >> file('plugin.py', 'w'), ""
132
bzrlib.plugin.load_from_path(['.'])
133
self.failUnless('plugin' in bzrlib.plugin.all_plugins())
134
self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
135
self.assertEqual(bzrlib.plugin.all_plugins()['plugin'],
136
bzrlib.plugins.plugin)
138
# remove the plugin 'plugin'
139
if 'bzrlib.plugins.plugin' in sys.modules:
140
del sys.modules['bzrlib.plugins.plugin']
141
if getattr(bzrlib.plugins, 'plugin', None):
142
del bzrlib.plugins.plugin
143
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
146
class TestPluginHelp(TestCaseInTempDir):
148
def split_help_commands(self):
151
for line in self.run_bzr('help commands')[0].splitlines():
152
if not line.startswith(' '):
153
current = line.split()[0]
154
help[current] = help.get(current, '') + line
158
def test_plugin_help_builtins_unaffected(self):
159
# Check we don't get false positives
160
help_commands = self.split_help_commands()
161
for cmd_name in bzrlib.commands.builtin_command_names():
162
if cmd_name in bzrlib.commands.plugin_command_names():
165
help = bzrlib.commands.get_cmd_object(cmd_name).get_help_text()
166
except NotImplementedError:
167
# some commands have no help
170
self.assertNotContainsRe(help, 'From plugin "[^"]*"')
172
if cmd_name in help_commands.keys():
173
# some commands are hidden
174
help = help_commands[cmd_name]
175
self.assertNotContainsRe(help, 'From plugin "[^"]*"')
177
def test_plugin_help_shows_plugin(self):
178
# Create a test plugin
179
os.mkdir('plugin_test')
180
f = open(pathjoin('plugin_test', 'myplug.py'), 'w')
186
bzrlib.plugin.load_from_path(['plugin_test'])
187
bzrlib.commands.register_command( bzrlib.plugins.myplug.cmd_myplug)
188
help = self.run_bzr('help myplug')[0]
189
self.assertContainsRe(help, 'From plugin "myplug"')
190
help = self.split_help_commands()['myplug']
191
self.assertContainsRe(help, '\[myplug\]')
194
if bzrlib.commands.plugin_cmds.get('myplug', None):
195
del bzrlib.commands.plugin_cmds['myplug']
196
# remove the plugin 'myplug'
197
if getattr(bzrlib.plugins, 'myplug', None):
198
delattr(bzrlib.plugins, 'myplug')
201
class TestPluginFromZip(TestCaseInTempDir):
203
def make_zipped_plugin(self, zip_name, filename):
204
z = zipfile.ZipFile(zip_name, 'w')
205
z.writestr(filename, PLUGIN_TEXT)
208
def check_plugin_load(self, zip_name, plugin_name):
209
self.assertFalse(plugin_name in dir(bzrlib.plugins),
210
'Plugin already loaded')
211
old_path = bzrlib.plugins.__path__
213
# this is normally done by load_plugins -> set_plugins_path
214
bzrlib.plugins.__path__ = [zip_name]
215
bzrlib.plugin.load_from_zip(zip_name)
216
self.assertTrue(plugin_name in dir(bzrlib.plugins),
217
'Plugin is not loaded')
220
if getattr(bzrlib.plugins, plugin_name, None):
221
delattr(bzrlib.plugins, plugin_name)
222
del sys.modules['bzrlib.plugins.' + plugin_name]
223
bzrlib.plugins.__path__ = old_path
225
def test_load_module(self):
226
self.make_zipped_plugin('./test.zip', 'ziplug.py')
227
self.check_plugin_load('./test.zip', 'ziplug')
229
def test_load_package(self):
230
self.make_zipped_plugin('./test.zip', 'ziplug/__init__.py')
231
self.check_plugin_load('./test.zip', 'ziplug')
234
class TestSetPluginsPath(TestCase):
236
def test_set_plugins_path(self):
237
"""set_plugins_path should set the module __path__ correctly."""
238
old_path = bzrlib.plugins.__path__
240
bzrlib.plugins.__path__ = []
241
expected_path = bzrlib.plugin.set_plugins_path()
242
self.assertEqual(expected_path, bzrlib.plugins.__path__)
244
bzrlib.plugins.__path__ = old_path
247
class TestHelpIndex(tests.TestCase):
248
"""Tests for the PluginsHelpIndex class."""
250
def test_default_constructable(self):
251
index = plugin.PluginsHelpIndex()
253
def test_get_topics_None(self):
254
"""Searching for None returns an empty list."""
255
index = plugin.PluginsHelpIndex()
256
self.assertEqual([], index.get_topics(None))
258
def test_get_topics_for_plugin(self):
259
"""Searching for plugin name gets its docstring."""
260
index = plugin.PluginsHelpIndex()
261
# make a new plugin here for this test, even if we're run with
263
self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
264
demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
265
sys.modules['bzrlib.plugins.demo_module'] = demo_module
267
topics = index.get_topics('demo_module')
268
self.assertEqual(1, len(topics))
269
self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
270
self.assertEqual(demo_module, topics[0].module)
272
del sys.modules['bzrlib.plugins.demo_module']
274
def test_get_topics_no_topic(self):
275
"""Searching for something that is not a plugin returns []."""
276
# test this by using a name that cannot be a plugin - its not
277
# a valid python identifier.
278
index = plugin.PluginsHelpIndex()
279
self.assertEqual([], index.get_topics('nothing by this name'))
281
def test_prefix(self):
282
"""PluginsHelpIndex has a prefix of 'plugins/'."""
283
index = plugin.PluginsHelpIndex()
284
self.assertEqual('plugins/', index.prefix)
286
def test_get_plugin_topic_with_prefix(self):
287
"""Searching for plugins/demo_module returns help."""
288
index = plugin.PluginsHelpIndex()
289
self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
290
demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
291
sys.modules['bzrlib.plugins.demo_module'] = demo_module
293
topics = index.get_topics('plugins/demo_module')
294
self.assertEqual(1, len(topics))
295
self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
296
self.assertEqual(demo_module, topics[0].module)
298
del sys.modules['bzrlib.plugins.demo_module']
301
class FakeModule(object):
302
"""A fake module to test with."""
304
def __init__(self, doc, name):
309
class TestModuleHelpTopic(tests.TestCase):
310
"""Tests for the ModuleHelpTopic class."""
312
def test_contruct(self):
313
"""Construction takes the module to document."""
314
mod = FakeModule('foo', 'foo')
315
topic = plugin.ModuleHelpTopic(mod)
316
self.assertEqual(mod, topic.module)
318
def test_get_help_text_None(self):
319
"""A ModuleHelpTopic returns the docstring for get_help_text."""
320
mod = FakeModule(None, 'demo')
321
topic = plugin.ModuleHelpTopic(mod)
322
self.assertEqual("Plugin 'demo' has no docstring.\n",
323
topic.get_help_text())
325
def test_get_help_text_no_carriage_return(self):
326
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
327
mod = FakeModule('one line of help', 'demo')
328
topic = plugin.ModuleHelpTopic(mod)
329
self.assertEqual("one line of help\n",
330
topic.get_help_text())
332
def test_get_help_text_carriage_return(self):
333
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
334
mod = FakeModule('two lines of help\nand more\n', 'demo')
335
topic = plugin.ModuleHelpTopic(mod)
336
self.assertEqual("two lines of help\nand more\n",
337
topic.get_help_text())
339
def test_get_help_text_with_additional_see_also(self):
340
mod = FakeModule('two lines of help\nand more', 'demo')
341
topic = plugin.ModuleHelpTopic(mod)
342
self.assertEqual("two lines of help\nand more\nSee also: bar, foo\n",
343
topic.get_help_text(['foo', 'bar']))
345
def test_get_help_topic(self):
346
"""The help topic for a plugin is its module name."""
347
mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.demo')
348
topic = plugin.ModuleHelpTopic(mod)
349
self.assertEqual('demo', topic.get_help_topic())
350
mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
351
topic = plugin.ModuleHelpTopic(mod)
352
self.assertEqual('foo_bar', topic.get_help_topic())