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.capture('help commands').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.capture('help myplug')
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')
212
bzrlib.plugin.load_from_zip(zip_name)
213
self.assertTrue(plugin_name in dir(bzrlib.plugins),
214
'Plugin is not loaded')
217
if getattr(bzrlib.plugins, plugin_name, None):
218
delattr(bzrlib.plugins, plugin_name)
220
def test_load_module(self):
221
self.make_zipped_plugin('./test.zip', 'ziplug.py')
222
self.check_plugin_load('./test.zip', 'ziplug')
224
def test_load_package(self):
225
self.make_zipped_plugin('./test.zip', 'ziplug/__init__.py')
226
self.check_plugin_load('./test.zip', 'ziplug')
229
class TestSetPluginsPath(TestCase):
231
def test_set_plugins_path(self):
232
"""set_plugins_path should set the module __path__ correctly."""
233
old_path = bzrlib.plugins.__path__
235
bzrlib.plugins.__path__ = []
236
expected_path = bzrlib.plugin.set_plugins_path()
237
self.assertEqual(expected_path, bzrlib.plugins.__path__)
239
bzrlib.plugins.__path__ = old_path
242
class TestHelpIndex(tests.TestCase):
243
"""Tests for the PluginsHelpIndex class."""
245
def test_default_constructable(self):
246
index = plugin.PluginsHelpIndex()
248
def test_get_topics_None(self):
249
"""Searching for None returns an empty list."""
250
index = plugin.PluginsHelpIndex()
251
self.assertEqual([], index.get_topics(None))
253
def test_get_topics_for_plugin(self):
254
"""Searching for plugin name gets its docstring."""
255
index = plugin.PluginsHelpIndex()
256
# make a new plugin here for this test, even if we're run with
258
self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
259
demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
260
sys.modules['bzrlib.plugins.demo_module'] = demo_module
262
topics = index.get_topics('demo_module')
263
self.assertEqual(1, len(topics))
264
self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
265
self.assertEqual(demo_module, topics[0].module)
267
del sys.modules['bzrlib.plugins.demo_module']
269
def test_get_topics_no_topic(self):
270
"""Searching for something that is not a plugin returns []."""
271
# test this by using a name that cannot be a plugin - its not
272
# a valid python identifier.
273
index = plugin.PluginsHelpIndex()
274
self.assertEqual([], index.get_topics('nothing by this name'))
276
def test_prefix(self):
277
"""PluginsHelpIndex has a prefix of 'plugins/'."""
278
index = plugin.PluginsHelpIndex()
279
self.assertEqual('plugins/', index.prefix)
281
def test_get_plugin_topic_with_prefix(self):
282
"""Searching for plugins/demo_module returns help."""
283
index = plugin.PluginsHelpIndex()
284
self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
285
demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
286
sys.modules['bzrlib.plugins.demo_module'] = demo_module
288
topics = index.get_topics('plugins/demo_module')
289
self.assertEqual(1, len(topics))
290
self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
291
self.assertEqual(demo_module, topics[0].module)
293
del sys.modules['bzrlib.plugins.demo_module']
296
class FakeModule(object):
297
"""A fake module to test with."""
299
def __init__(self, doc, name):
304
class TestModuleHelpTopic(tests.TestCase):
305
"""Tests for the ModuleHelpTopic class."""
307
def test_contruct(self):
308
"""Construction takes the module to document."""
309
mod = FakeModule('foo', 'foo')
310
topic = plugin.ModuleHelpTopic(mod)
311
self.assertEqual(mod, topic.module)
313
def test_get_help_text_None(self):
314
"""A ModuleHelpTopic returns the docstring for get_help_text."""
315
mod = FakeModule(None, 'demo')
316
topic = plugin.ModuleHelpTopic(mod)
317
self.assertEqual("Plugin 'demo' has no docstring.\n",
318
topic.get_help_text())
320
def test_get_help_text_no_carriage_return(self):
321
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
322
mod = FakeModule('one line of help', 'demo')
323
topic = plugin.ModuleHelpTopic(mod)
324
self.assertEqual("one line of help\n",
325
topic.get_help_text())
327
def test_get_help_text_carriage_return(self):
328
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
329
mod = FakeModule('two lines of help\nand more\n', 'demo')
330
topic = plugin.ModuleHelpTopic(mod)
331
self.assertEqual("two lines of help\nand more\n",
332
topic.get_help_text())
334
def test_get_help_text_with_additional_see_also(self):
335
mod = FakeModule('two lines of help\nand more', 'demo')
336
topic = plugin.ModuleHelpTopic(mod)
337
self.assertEqual("two lines of help\nand more\nSee also: bar, foo\n",
338
topic.get_help_text(['foo', 'bar']))
340
def test_get_help_topic(self):
341
"""The help topic for a plugin is its module name."""
342
mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.demo')
343
topic = plugin.ModuleHelpTopic(mod)
344
self.assertEqual('demo', topic.get_help_topic())
345
mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
346
topic = plugin.ModuleHelpTopic(mod)
347
self.assertEqual('foo_bar', topic.get_help_topic())