20
20
# affects the global state of the process. See bzrlib/plugins.py for more
23
from cStringIO import StringIO
24
from StringIO import StringIO
28
from bzrlib import plugin, tests
31
import bzrlib.commands
33
from bzrlib.tests import TestCase, TestCaseInTempDir
34
from bzrlib.osutils import pathjoin, abspath
38
import bzrlib.commands
39
class cmd_myplug(bzrlib.commands.Command):
40
'''Just a simple test plugin.'''
43
print 'Hello from my plugin'
46
39
# TODO: Write a test for plugin decoration of commands.
48
class TestLoadingPlugins(TestCaseInTempDir):
41
class TestPluginMixin(object):
43
def create_plugin(self, name, source=None, dir='.', file_name=None):
46
"""This is the doc for %s"""
49
file_name = name + '.py'
50
# 'source' must not fail to load
51
path = osutils.pathjoin(dir, file_name)
53
self.addCleanup(os.unlink, path)
55
f.write(source + '\n')
59
def create_plugin_package(self, name, dir=None, source=None):
64
"""This is the doc for %s"""
69
# Workaround lazy import random? madness
71
self.addCleanup(cleanup)
72
self.create_plugin(name, source, dir,
73
file_name='__init__.py')
75
def _unregister_plugin(self, name):
76
"""Remove the plugin from sys.modules and the bzrlib namespace."""
77
py_name = 'bzrlib.plugins.%s' % name
78
if py_name in sys.modules:
79
del sys.modules[py_name]
80
if getattr(bzrlib.plugins, name, None) is not None:
81
delattr(bzrlib.plugins, name)
83
def _unregister_plugin_submodule(self, plugin_name, submodule_name):
84
"""Remove the submodule from sys.modules and the bzrlib namespace."""
85
py_name = 'bzrlib.plugins.%s.%s' % (plugin_name, submodule_name)
86
if py_name in sys.modules:
87
del sys.modules[py_name]
88
plugin = getattr(bzrlib.plugins, plugin_name, None)
89
if plugin is not None:
90
if getattr(plugin, submodule_name, None) is not None:
91
delattr(plugin, submodule_name)
93
def assertPluginUnknown(self, name):
94
self.failIf(getattr(bzrlib.plugins, name, None) is not None)
95
self.failIf('bzrlib.plugins.%s' % name in sys.modules)
97
def assertPluginKnown(self, name):
98
self.failUnless(getattr(bzrlib.plugins, name, None) is not None)
99
self.failUnless('bzrlib.plugins.%s' % name in sys.modules)
102
class TestLoadingPlugins(tests.TestCaseInTempDir, TestPluginMixin):
50
104
activeattributes = {}
116
198
# remove the plugin 'plugin'
117
199
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))
200
self._unregister_plugin('pluginone')
201
self._unregister_plugin('plugintwo')
202
self.assertPluginUnknown('pluginone')
203
self.assertPluginUnknown('plugintwo')
205
def test_plugins_can_load_from_directory_with_trailing_slash(self):
206
# This test tests that a plugin can load from a directory when the
207
# directory in the path has a trailing slash.
208
# check the plugin is not loaded already
209
self.assertPluginUnknown('ts_plugin')
210
tempattribute = "trailing-slash"
211
self.failIf(tempattribute in self.activeattributes)
212
# set a place for the plugin to record its loading, and at the same
213
# time validate that the location the plugin should record to is
215
bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
217
self.failUnless(tempattribute in self.activeattributes)
218
# create a directory for the plugin
219
os.mkdir('plugin_test')
220
# write a plugin that will record when its loaded in the
221
# tempattribute list.
222
template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
223
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
225
outfile = open(os.path.join('plugin_test', 'ts_plugin.py'), 'w')
227
outfile.write(template % (tempattribute, 'plugin'))
233
bzrlib.plugin.load_from_path(['plugin_test'+os.sep])
234
self.assertEqual(['plugin'], self.activeattributes[tempattribute])
236
del self.activeattributes[tempattribute]
237
self._unregister_plugin('ts_plugin')
238
self.assertPluginUnknown('ts_plugin')
240
def load_and_capture(self, name):
241
"""Load plugins from '.' capturing the output.
243
:param name: The name of the plugin.
244
:return: A string with the log from the plugin loading call.
249
handler = logging.StreamHandler(stream)
250
log = logging.getLogger('bzr')
251
log.addHandler(handler)
254
bzrlib.plugin.load_from_path(['.'])
256
if 'bzrlib.plugins.%s' % name in sys.modules:
257
del sys.modules['bzrlib.plugins.%s' % name]
258
if getattr(bzrlib.plugins, name, None):
259
delattr(bzrlib.plugins, name)
261
# Stop capturing output
264
log.removeHandler(handler)
265
return stream.getvalue()
269
def test_plugin_with_bad_api_version_reports(self):
270
# This plugin asks for bzrlib api version 1.0.0, which is not supported
275
f.write("import bzrlib.api\n"
276
"bzrlib.api.require_any_api(bzrlib, [(1, 0, 0)])\n")
280
log = self.load_and_capture(name)
281
self.assertContainsRe(log,
282
r"It requested API version")
284
def test_plugin_with_bad_name_does_not_load(self):
285
# The file name here invalid for a python module.
286
name = 'bzr-bad plugin-name..py'
287
file(name, 'w').close()
288
log = self.load_and_capture(name)
289
self.assertContainsRe(log,
290
r"Unable to load 'bzr-bad plugin-name\.' in '\.' as a plugin "
291
"because the file path isn't a valid module name; try renaming "
292
"it to 'bad_plugin_name_'\.")
295
class TestPlugins(tests.TestCaseInTempDir, TestPluginMixin):
297
def setup_plugin(self, source=""):
298
# This test tests a new plugin appears in bzrlib.plugin.plugins().
299
# check the plugin is not loaded already
300
self.assertPluginUnknown('plugin')
129
301
# 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):
302
file('plugin.py', 'w').write(source + '\n')
303
self.addCleanup(self.teardown_plugin)
304
plugin.load_from_path(['.'])
306
def teardown_plugin(self):
307
self._unregister_plugin('plugin')
308
self.assertPluginUnknown('plugin')
310
def test_plugin_appears_in_plugins(self):
312
self.assertPluginKnown('plugin')
313
p = plugin.plugins()['plugin']
314
self.assertIsInstance(p, bzrlib.plugin.PlugIn)
315
self.assertEqual(p.module, plugins.plugin)
317
def test_trivial_plugin_get_path(self):
319
p = plugin.plugins()['plugin']
320
plugin_path = self.test_dir + '/plugin.py'
321
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
323
def test_plugin_get_path_py_not_pyc(self):
324
# first import creates plugin.pyc
326
self.teardown_plugin()
327
plugin.load_from_path(['.']) # import plugin.pyc
328
p = plugin.plugins()['plugin']
329
plugin_path = self.test_dir + '/plugin.py'
330
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
332
def test_plugin_get_path_pyc_only(self):
333
# first import creates plugin.pyc (or plugin.pyo depending on __debug__)
335
self.teardown_plugin()
336
os.unlink(self.test_dir + '/plugin.py')
337
plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
338
p = plugin.plugins()['plugin']
340
plugin_path = self.test_dir + '/plugin.pyc'
342
plugin_path = self.test_dir + '/plugin.pyo'
343
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
345
def test_no_test_suite_gives_None_for_test_suite(self):
347
p = plugin.plugins()['plugin']
348
self.assertEqual(None, p.test_suite())
350
def test_test_suite_gives_test_suite_result(self):
351
source = """def test_suite(): return 'foo'"""
352
self.setup_plugin(source)
353
p = plugin.plugins()['plugin']
354
self.assertEqual('foo', p.test_suite())
356
def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
358
loader = tests.TestUtil.TestLoader()
359
p = plugin.plugins()['plugin']
360
self.assertEqual(None, p.load_plugin_tests(loader))
362
def test_load_plugin_tests_gives_load_plugin_tests_result(self):
364
def load_tests(standard_tests, module, loader):
366
self.setup_plugin(source)
367
loader = tests.TestUtil.TestLoader()
368
p = plugin.plugins()['plugin']
369
self.assertEqual('foo', p.load_plugin_tests(loader))
371
def check_version_info(self, expected, source='', name='plugin'):
372
self.setup_plugin(source)
373
self.assertEqual(expected, plugin.plugins()[name].version_info())
375
def test_no_version_info(self):
376
self.check_version_info(None)
378
def test_with_version_info(self):
379
self.check_version_info((1, 2, 3, 'dev', 4),
380
"version_info = (1, 2, 3, 'dev', 4)")
382
def test_short_version_info_gets_padded(self):
383
# the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
385
self.check_version_info((1, 2, 3, 'final', 0),
386
"version_info = (1, 2, 3)")
388
def check_version(self, expected, source=None, name='plugin'):
389
self.setup_plugin(source)
390
self.assertEqual(expected, plugins[name].__version__)
392
def test_no_version_info___version__(self):
394
plugin = bzrlib.plugin.plugins()['plugin']
395
self.assertEqual("unknown", plugin.__version__)
397
def test_str__version__with_version_info(self):
398
self.setup_plugin("version_info = '1.2.3'")
399
plugin = bzrlib.plugin.plugins()['plugin']
400
self.assertEqual("1.2.3", plugin.__version__)
402
def test_noniterable__version__with_version_info(self):
403
self.setup_plugin("version_info = (1)")
404
plugin = bzrlib.plugin.plugins()['plugin']
405
self.assertEqual("1", plugin.__version__)
407
def test_1__version__with_version_info(self):
408
self.setup_plugin("version_info = (1,)")
409
plugin = bzrlib.plugin.plugins()['plugin']
410
self.assertEqual("1", plugin.__version__)
412
def test_1_2__version__with_version_info(self):
413
self.setup_plugin("version_info = (1, 2)")
414
plugin = bzrlib.plugin.plugins()['plugin']
415
self.assertEqual("1.2", plugin.__version__)
417
def test_1_2_3__version__with_version_info(self):
418
self.setup_plugin("version_info = (1, 2, 3)")
419
plugin = bzrlib.plugin.plugins()['plugin']
420
self.assertEqual("1.2.3", plugin.__version__)
422
def test_candidate__version__with_version_info(self):
423
self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
424
plugin = bzrlib.plugin.plugins()['plugin']
425
self.assertEqual("1.2.3rc1", plugin.__version__)
427
def test_dev__version__with_version_info(self):
428
self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
429
plugin = bzrlib.plugin.plugins()['plugin']
430
self.assertEqual("1.2.3dev", plugin.__version__)
432
def test_dev_fallback__version__with_version_info(self):
433
self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
434
plugin = bzrlib.plugin.plugins()['plugin']
435
self.assertEqual("1.2.3dev4", plugin.__version__)
437
def test_final__version__with_version_info(self):
438
self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
439
plugin = bzrlib.plugin.plugins()['plugin']
440
self.assertEqual("1.2.3", plugin.__version__)
442
def test_final_fallback__version__with_version_info(self):
443
self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
444
plugin = bzrlib.plugin.plugins()['plugin']
445
self.assertEqual("1.2.3.final.2", plugin.__version__)
448
class TestPluginHelp(tests.TestCaseInTempDir):
148
450
def split_help_commands(self):
151
for line in self.capture('help commands').splitlines():
453
out, err = self.run_bzr('--no-plugins help commands')
454
for line in out.splitlines():
152
455
if not line.startswith(' '):
153
456
current = line.split()[0]
154
457
help[current] = help.get(current, '') + line
167
470
# some commands have no help
170
self.assertNotContainsRe(help, 'From plugin "[^"]*"')
473
self.assertNotContainsRe(help, 'plugin "[^"]*"')
172
475
if cmd_name in help_commands.keys():
173
476
# some commands are hidden
174
477
help = help_commands[cmd_name]
175
self.assertNotContainsRe(help, 'From plugin "[^"]*"')
478
self.assertNotContainsRe(help, 'plugin "[^"]*"')
177
480
def test_plugin_help_shows_plugin(self):
178
481
# Create a test plugin
179
482
os.mkdir('plugin_test')
180
f = open(pathjoin('plugin_test', 'myplug.py'), 'w')
483
f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
485
from bzrlib import commands
486
class cmd_myplug(commands.Command):
487
__doc__ = '''Just a simple test plugin.'''
490
print 'Hello from my plugin'
186
498
bzrlib.plugin.load_from_path(['plugin_test'])
187
499
bzrlib.commands.register_command( bzrlib.plugins.myplug.cmd_myplug)
188
help = self.capture('help myplug')
189
self.assertContainsRe(help, 'From plugin "myplug"')
500
help = self.run_bzr('help myplug')[0]
501
self.assertContainsRe(help, 'plugin "myplug"')
190
502
help = self.split_help_commands()['myplug']
191
503
self.assertContainsRe(help, '\[myplug\]')
193
505
# unregister command
194
if bzrlib.commands.plugin_cmds.get('myplug', None):
195
del bzrlib.commands.plugin_cmds['myplug']
506
if 'myplug' in bzrlib.commands.plugin_cmds:
507
bzrlib.commands.plugin_cmds.remove('myplug')
196
508
# remove the plugin 'myplug'
197
509
if getattr(bzrlib.plugins, 'myplug', None):
198
510
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
513
class TestHelpIndex(tests.TestCase):
243
514
"""Tests for the PluginsHelpIndex class."""
345
616
mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
346
617
topic = plugin.ModuleHelpTopic(mod)
347
618
self.assertEqual('foo_bar', topic.get_help_topic())
621
class TestLoadFromPath(tests.TestCaseInTempDir):
624
super(TestLoadFromPath, self).setUp()
625
# Change bzrlib.plugin to think no plugins have been loaded yet.
626
self.overrideAttr(bzrlib.plugins, '__path__', [])
627
self.overrideAttr(plugin, '_loaded', False)
629
# Monkey-patch load_from_path to stop it from actually loading anything.
630
self.overrideAttr(plugin, 'load_from_path', lambda dirs: None)
632
def test_set_plugins_path_with_args(self):
633
plugin.set_plugins_path(['a', 'b'])
634
self.assertEqual(['a', 'b'], bzrlib.plugins.__path__)
636
def test_set_plugins_path_defaults(self):
637
plugin.set_plugins_path()
638
self.assertEqual(plugin.get_standard_plugins_path(),
639
bzrlib.plugins.__path__)
641
def test_get_standard_plugins_path(self):
642
path = plugin.get_standard_plugins_path()
643
for directory in path:
644
self.assertNotContainsRe(directory, r'\\/$')
646
from distutils.sysconfig import get_python_lib
650
if sys.platform != 'win32':
651
python_lib = get_python_lib()
652
for directory in path:
653
if directory.startswith(python_lib):
656
self.fail('No path to global plugins')
658
def test_get_standard_plugins_path_env(self):
659
os.environ['BZR_PLUGIN_PATH'] = 'foo/'
660
path = plugin.get_standard_plugins_path()
661
for directory in path:
662
self.assertNotContainsRe(directory, r'\\/$')
664
def test_load_plugins(self):
665
plugin.load_plugins(['.'])
666
self.assertEqual(bzrlib.plugins.__path__, ['.'])
667
# subsequent loads are no-ops
668
plugin.load_plugins(['foo'])
669
self.assertEqual(bzrlib.plugins.__path__, ['.'])
671
def test_load_plugins_default(self):
672
plugin.load_plugins()
673
path = plugin.get_standard_plugins_path()
674
self.assertEqual(path, bzrlib.plugins.__path__)
677
class TestEnvPluginPath(tests.TestCase):
680
super(TestEnvPluginPath, self).setUp()
681
self.overrideAttr(plugin, 'DEFAULT_PLUGIN_PATH', None)
683
self.user = plugin.get_user_plugin_path()
684
self.site = plugin.get_site_plugin_path()
685
self.core = plugin.get_core_plugin_path()
687
def _list2paths(self, *args):
690
plugin._append_new_path(paths, p)
693
def _set_path(self, *args):
694
path = os.pathsep.join(self._list2paths(*args))
695
osutils.set_or_unset_env('BZR_PLUGIN_PATH', path)
697
def check_path(self, expected_dirs, setting_dirs):
699
self._set_path(*setting_dirs)
700
actual = plugin.get_standard_plugins_path()
701
self.assertEquals(self._list2paths(*expected_dirs), actual)
703
def test_default(self):
704
self.check_path([self.user, self.core, self.site],
707
def test_adhoc_policy(self):
708
self.check_path([self.user, self.core, self.site],
709
['+user', '+core', '+site'])
711
def test_fallback_policy(self):
712
self.check_path([self.core, self.site, self.user],
713
['+core', '+site', '+user'])
715
def test_override_policy(self):
716
self.check_path([self.user, self.site, self.core],
717
['+user', '+site', '+core'])
719
def test_disable_user(self):
720
self.check_path([self.core, self.site], ['-user'])
722
def test_disable_user_twice(self):
723
# Ensures multiple removals don't left cruft
724
self.check_path([self.core, self.site], ['-user', '-user'])
726
def test_duplicates_are_removed(self):
727
self.check_path([self.user, self.core, self.site],
729
# And only the first reference is kept (since the later references will
730
# only produce '<plugin> already loaded' mutters)
731
self.check_path([self.user, self.core, self.site],
732
['+user', '+user', '+core',
733
'+user', '+site', '+site',
736
def test_disable_overrides_enable(self):
737
self.check_path([self.core, self.site], ['-user', '+user'])
739
def test_disable_core(self):
740
self.check_path([self.site], ['-core'])
741
self.check_path([self.user, self.site], ['+user', '-core'])
743
def test_disable_site(self):
744
self.check_path([self.core], ['-site'])
745
self.check_path([self.user, self.core], ['-site', '+user'])
747
def test_override_site(self):
748
self.check_path(['mysite', self.user, self.core],
749
['mysite', '-site', '+user'])
750
self.check_path(['mysite', self.core],
753
def test_override_core(self):
754
self.check_path(['mycore', self.user, self.site],
755
['mycore', '-core', '+user', '+site'])
756
self.check_path(['mycore', self.site],
759
def test_my_plugin_only(self):
760
self.check_path(['myplugin'], ['myplugin', '-user', '-core', '-site'])
762
def test_my_plugin_first(self):
763
self.check_path(['myplugin', self.core, self.site, self.user],
764
['myplugin', '+core', '+site', '+user'])
766
def test_bogus_references(self):
767
self.check_path(['+foo', '-bar', self.core, self.site],
771
class TestDisablePlugin(tests.TestCaseInTempDir, TestPluginMixin):
774
super(TestDisablePlugin, self).setUp()
775
self.create_plugin_package('test_foo')
776
# Make sure we don't pollute the plugins namespace
777
self.overrideAttr(plugins, '__path__')
778
# Be paranoid in case a test fail
779
self.addCleanup(self._unregister_plugin, 'test_foo')
781
def test_cannot_import(self):
782
osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
783
plugin.set_plugins_path(['.'])
785
import bzrlib.plugins.test_foo
788
self.assertPluginUnknown('test_foo')
790
def test_regular_load(self):
791
self.overrideAttr(plugin, '_loaded', False)
792
plugin.load_plugins(['.'])
793
self.assertPluginKnown('test_foo')
794
self.assertDocstring("This is the doc for test_foo",
795
bzrlib.plugins.test_foo)
797
def test_not_loaded(self):
799
def captured_warning(*args, **kwargs):
800
self.warnings.append((args, kwargs))
801
self.overrideAttr(trace, 'warning', captured_warning)
802
# Reset the flag that protect against double loading
803
self.overrideAttr(plugin, '_loaded', False)
804
osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
805
plugin.load_plugins(['.'])
806
self.assertPluginUnknown('test_foo')
807
# Make sure we don't warn about the plugin ImportError since this has
808
# been *requested* by the user.
809
self.assertLength(0, self.warnings)
812
class TestLoadPluginAtSyntax(tests.TestCase):
814
def _get_paths(self, paths):
815
return plugin._get_specific_plugin_paths(paths)
817
def test_empty(self):
818
self.assertEquals([], self._get_paths(None))
819
self.assertEquals([], self._get_paths(''))
821
def test_one_path(self):
822
self.assertEquals([('b', 'man')], self._get_paths('b@man'))
824
def test_bogus_path(self):
826
self.assertRaises(errors.BzrCommandError, self._get_paths, 'batman')
827
# Too much '@' isn't good either
828
self.assertRaises(errors.BzrCommandError, self._get_paths,
829
'batman@mobile@cave')
830
# An empty description probably indicates a problem
831
self.assertRaises(errors.BzrCommandError, self._get_paths,
832
os.pathsep.join(['batman@cave', '', 'robin@mobile']))
835
class TestLoadPluginAt(tests.TestCaseInTempDir, TestPluginMixin):
838
super(TestLoadPluginAt, self).setUp()
839
# Make sure we don't pollute the plugins namespace
840
self.overrideAttr(plugins, '__path__')
841
# Reset the flag that protect against double loading
842
self.overrideAttr(plugin, '_loaded', False)
843
# Create the same plugin in two directories
844
self.create_plugin_package('test_foo', dir='non-standard-dir')
845
# The "normal" directory, we use 'standard' instead of 'plugins' to
846
# avoid depending on the precise naming.
847
self.create_plugin_package('test_foo', dir='standard/test_foo')
848
# All the tests will load the 'test_foo' plugin from various locations
849
self.addCleanup(self._unregister_plugin, 'test_foo')
851
def assertTestFooLoadedFrom(self, path):
852
self.assertPluginKnown('test_foo')
853
self.assertDocstring('This is the doc for test_foo',
854
bzrlib.plugins.test_foo)
855
self.assertEqual(path, bzrlib.plugins.test_foo.dir_source)
857
def test_regular_load(self):
858
plugin.load_plugins(['standard'])
859
self.assertTestFooLoadedFrom('standard/test_foo')
861
def test_import(self):
862
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
863
plugin.set_plugins_path(['standard'])
865
import bzrlib.plugins.test_foo
868
self.assertTestFooLoadedFrom('non-standard-dir')
870
def test_loading(self):
871
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
872
plugin.load_plugins(['standard'])
873
self.assertTestFooLoadedFrom('non-standard-dir')
875
def test_compiled_loaded(self):
876
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
877
plugin.load_plugins(['standard'])
878
self.assertTestFooLoadedFrom('non-standard-dir')
879
self.assertIsSameRealPath('non-standard-dir/__init__.py',
880
bzrlib.plugins.test_foo.__file__)
882
# Try importing again now that the source has been compiled
883
self._unregister_plugin('test_foo')
884
plugin._loaded = False
885
plugin.load_plugins(['standard'])
886
self.assertTestFooLoadedFrom('non-standard-dir')
891
self.assertIsSameRealPath('non-standard-dir/__init__.%s' % suffix,
892
bzrlib.plugins.test_foo.__file__)
894
def test_submodule_loading(self):
895
# We create an additional directory under the one for test_foo
896
self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
897
self.addCleanup(self._unregister_plugin_submodule,
898
'test_foo', 'test_bar')
899
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
900
plugin.set_plugins_path(['standard'])
901
import bzrlib.plugins.test_foo
902
self.assertEqual('bzrlib.plugins.test_foo',
903
bzrlib.plugins.test_foo.__package__)
904
import bzrlib.plugins.test_foo.test_bar
905
self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
906
bzrlib.plugins.test_foo.test_bar.__file__)
908
def test_relative_submodule_loading(self):
909
self.create_plugin_package('test_foo', dir='another-dir', source='''
912
# We create an additional directory under the one for test_foo
913
self.create_plugin_package('test_bar', dir='another-dir/test_bar')
914
self.addCleanup(self._unregister_plugin_submodule,
915
'test_foo', 'test_bar')
916
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@another-dir')
917
plugin.set_plugins_path(['standard'])
918
import bzrlib.plugins.test_foo
919
self.assertEqual('bzrlib.plugins.test_foo',
920
bzrlib.plugins.test_foo.__package__)
921
self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
922
bzrlib.plugins.test_foo.test_bar.__file__)
924
def test_loading_from___init__only(self):
925
# We rename the existing __init__.py file to ensure that we don't load
927
init = 'non-standard-dir/__init__.py'
928
random = 'non-standard-dir/setup.py'
929
os.rename(init, random)
930
self.addCleanup(os.rename, random, init)
931
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
932
plugin.load_plugins(['standard'])
933
self.assertPluginUnknown('test_foo')
935
def test_loading_from_specific_file(self):
936
plugin_dir = 'non-standard-dir'
937
plugin_file_name = 'iamtestfoo.py'
938
plugin_path = osutils.pathjoin(plugin_dir, plugin_file_name)
940
"""This is the doc for %s"""
942
''' % ('test_foo', plugin_path)
943
self.create_plugin('test_foo', source=source,
944
dir=plugin_dir, file_name=plugin_file_name)
945
osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@%s' % plugin_path)
946
plugin.load_plugins(['standard'])
947
self.assertTestFooLoadedFrom(plugin_path)