69
# Workaround lazy import random? madness
71
self.addCleanup(cleanup)
104
72
self.create_plugin(name, source, dir,
105
73
file_name='__init__.py')
107
def promote_cache(self, directory):
108
"""Move bytecode files out of __pycache__ in given directory."""
109
cache_dir = os.path.join(directory, '__pycache__')
110
if os.path.isdir(cache_dir):
111
for name in os.listdir(cache_dir):
112
magicless_name = '.'.join(name.split('.')[0::name.count('.')])
113
rel = osutils.relpath(self.test_dir, cache_dir)
114
self.log("moving %s in %s to %s", name, rel, magicless_name)
115
os.rename(os.path.join(cache_dir, name),
116
os.path.join(directory, magicless_name))
118
def _unregister_finder(self):
119
"""Removes any test copies of _PluginsAtFinder from sys.meta_path."""
120
idx = len(sys.meta_path)
123
finder = sys.meta_path[idx]
124
if getattr(finder, "prefix", "") == self.module_prefix:
125
self.log("removed %r from sys.meta_path", finder)
126
sys.meta_path.pop(idx)
128
def _unregister_all(self):
129
"""Remove all plugins in the test namespace from sys.modules."""
130
for name in list(sys.modules):
131
if name.startswith(self.module_prefix) or name == self.module_name:
132
self.log("removed %s from sys.modules", name)
133
del sys.modules[name]
135
def assertPluginModules(self, plugin_dict):
137
dict((k[len(self.module_prefix):], sys.modules[k])
138
for k in sys.modules if k.startswith(self.module_prefix)),
75
def _unregister_plugin(self, name):
76
"""Remove the plugin from sys.modules and the brzlib namespace."""
77
py_name = 'brzlib.plugins.%s' % name
78
if py_name in sys.modules:
79
del sys.modules[py_name]
80
if getattr(brzlib.plugins, name, None) is not None:
81
delattr(brzlib.plugins, name)
83
def _unregister_plugin_submodule(self, plugin_name, submodule_name):
84
"""Remove the submodule from sys.modules and the brzlib namespace."""
85
py_name = 'brzlib.plugins.%s.%s' % (plugin_name, submodule_name)
86
if py_name in sys.modules:
87
del sys.modules[py_name]
88
plugin = getattr(brzlib.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)
141
93
def assertPluginUnknown(self, name):
142
self.assertTrue(getattr(self.module, name, None) is None)
143
self.assertFalse(self.module_prefix + name in sys.modules)
94
self.assertFalse(getattr(brzlib.plugins, name, None) is not None)
95
self.assertFalse('brzlib.plugins.%s' % name in sys.modules)
145
97
def assertPluginKnown(self, name):
146
self.assertTrue(getattr(self.module, name, None) is not None)
147
self.assertTrue(self.module_prefix + name in sys.modules)
98
self.assertTrue(getattr(brzlib.plugins, name, None) is not None)
99
self.assertTrue('brzlib.plugins.%s' % name in sys.modules)
150
102
class TestLoadingPlugins(BaseTestPlugins):
198
159
# set a place for the plugins to record their loading, and at the same
199
160
# time validate that the location the plugins should record to is
200
161
# valid and correct.
201
breezy.tests.test_plugins.TestLoadingPlugins.activeattributes[tempattribute] = [
162
brzlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
203
164
self.assertTrue(tempattribute in self.activeattributes)
204
165
# create two plugin directories
205
166
os.mkdir('first')
206
167
os.mkdir('second')
207
168
# write plugins that will record when they are loaded in the
208
169
# tempattribute list.
209
template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
170
template = ("from brzlib.tests.test_plugins import TestLoadingPlugins\n"
210
171
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
212
with open(os.path.join('first', 'pluginone.py'), 'w') as outfile:
173
outfile = open(os.path.join('first', 'pluginone.py'), 'w')
213
175
outfile.write(template % (tempattribute, 'first'))
214
176
outfile.write('\n')
216
with open(os.path.join('second', 'plugintwo.py'), 'w') as outfile:
180
outfile = open(os.path.join('second', 'plugintwo.py'), 'w')
217
182
outfile.write(template % (tempattribute, 'second'))
218
183
outfile.write('\n')
187
oldpath = brzlib.plugins.__path__
221
self.assertPluginUnknown('pluginone')
222
self.assertPluginUnknown('plugintwo')
223
self.update_module_paths(['first', 'second'])
224
exec("import %spluginone" % self.module_prefix)
189
self.assertFalse('brzlib.plugins.pluginone' in sys.modules)
190
self.assertFalse('brzlib.plugins.plugintwo' in sys.modules)
191
brzlib.plugins.__path__ = ['first', 'second']
192
exec "import brzlib.plugins.pluginone"
225
193
self.assertEqual(['first'], self.activeattributes[tempattribute])
226
exec("import %splugintwo" % self.module_prefix)
194
exec "import brzlib.plugins.plugintwo"
227
195
self.assertEqual(['first', 'second'],
228
self.activeattributes[tempattribute])
196
self.activeattributes[tempattribute])
198
# remove the plugin 'plugin'
230
199
del self.activeattributes[tempattribute]
200
self._unregister_plugin('pluginone')
201
self._unregister_plugin('plugintwo')
202
self.assertPluginUnknown('pluginone')
203
self.assertPluginUnknown('plugintwo')
232
205
def test_plugins_can_load_from_directory_with_trailing_slash(self):
233
206
# This test tests that a plugin can load from a directory when the
286
269
def test_plugin_with_bad_api_version_reports(self):
287
270
"""Try loading a plugin that requests an unsupported api.
289
272
Observe that it records the problem but doesn't complain on stderr.
291
274
See https://bugs.launchpad.net/bzr/+bug/704195
276
self.overrideAttr(plugin, 'plugin_warnings', {})
293
277
name = 'wants100.py'
294
with open(name, 'w') as f:
295
f.write("import breezy\n"
296
"from breezy.errors import IncompatibleVersion\n"
297
"raise IncompatibleVersion(breezy, [(1, 0, 0)], (0, 0, 5))\n")
280
f.write("import brzlib.api\n"
281
"brzlib.api.require_any_api(brzlib, [(1, 0, 0)])\n")
298
284
log = self.load_and_capture(name)
299
285
self.assertNotContainsRe(log,
300
r"It supports breezy version")
301
self.assertEqual({'wants100'}, self.plugin_warnings.keys())
286
r"It requested API version")
289
plugin.plugin_warnings.keys())
302
290
self.assertContainsRe(
303
self.plugin_warnings['wants100'][0],
304
r"It supports breezy version")
291
plugin.plugin_warnings['wants100'][0],
292
r"It requested API version")
306
294
def test_plugin_with_bad_name_does_not_load(self):
307
295
# The file name here invalid for a python module.
308
name = 'brz-bad plugin-name..py'
309
open(name, 'w').close()
296
name = 'bzr-bad plugin-name..py'
297
file(name, 'w').close()
310
298
log = self.load_and_capture(name)
311
299
self.assertContainsRe(log,
312
r"Unable to load 'brz-bad plugin-name\.' in '\.' as a plugin "
313
"because the file path isn't a valid module name; try renaming "
314
"it to 'bad_plugin_name_'\\.")
300
r"Unable to load 'bzr-bad plugin-name\.' in '\.' as a plugin "
301
"because the file path isn't a valid module name; try renaming "
302
"it to 'bad_plugin_name_'\.")
317
305
class TestPlugins(BaseTestPlugins):
319
307
def setup_plugin(self, source=""):
320
# This test tests a new plugin appears in breezy.plugin.plugins().
308
# This test tests a new plugin appears in brzlib.plugin.plugins().
321
309
# check the plugin is not loaded already
322
310
self.assertPluginUnknown('plugin')
323
311
# write a plugin that _cannot_ fail to load.
324
with open('plugin.py', 'w') as f:
325
f.write(source + '\n')
326
self.load_with_paths(['.'])
328
def test_plugin_loaded(self):
329
self.assertPluginUnknown('plugin')
330
self.assertIs(None, breezy.plugin.get_loaded_plugin('plugin'))
332
p = breezy.plugin.get_loaded_plugin('plugin')
333
self.assertIsInstance(p, breezy.plugin.PlugIn)
334
self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
336
def test_plugin_loaded_disabled(self):
337
self.assertPluginUnknown('plugin')
338
self.overrideEnv('BRZ_DISABLE_PLUGINS', 'plugin')
340
self.assertIs(None, breezy.plugin.get_loaded_plugin('plugin'))
312
with file('plugin.py', 'w') as f: f.write(source + '\n')
313
self.addCleanup(self.teardown_plugin)
314
plugin.load_from_path(['.'])
316
def teardown_plugin(self):
317
self._unregister_plugin('plugin')
318
self.assertPluginUnknown('plugin')
342
320
def test_plugin_appears_in_plugins(self):
343
321
self.setup_plugin()
344
322
self.assertPluginKnown('plugin')
345
p = self.plugins['plugin']
346
self.assertIsInstance(p, breezy.plugin.PlugIn)
347
self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
323
p = plugin.plugins()['plugin']
324
self.assertIsInstance(p, brzlib.plugin.PlugIn)
325
self.assertEqual(p.module, plugins.plugin)
349
327
def test_trivial_plugin_get_path(self):
350
328
self.setup_plugin()
351
p = self.plugins['plugin']
329
p = plugin.plugins()['plugin']
352
330
plugin_path = self.test_dir + '/plugin.py'
353
331
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
355
333
def test_plugin_get_path_py_not_pyc(self):
356
334
# first import creates plugin.pyc
357
335
self.setup_plugin()
358
self.promote_cache(self.test_dir)
360
self.load_with_paths(['.']) # import plugin.pyc
336
self.teardown_plugin()
337
plugin.load_from_path(['.']) # import plugin.pyc
361
338
p = plugin.plugins()['plugin']
362
339
plugin_path = self.test_dir + '/plugin.py'
363
340
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
423
402
def test_no_version_info___version__(self):
424
403
self.setup_plugin()
425
plugin = breezy.plugin.plugins()['plugin']
404
plugin = brzlib.plugin.plugins()['plugin']
426
405
self.assertEqual("unknown", plugin.__version__)
428
407
def test_str__version__with_version_info(self):
429
408
self.setup_plugin("version_info = '1.2.3'")
430
plugin = breezy.plugin.plugins()['plugin']
409
plugin = brzlib.plugin.plugins()['plugin']
431
410
self.assertEqual("1.2.3", plugin.__version__)
433
412
def test_noniterable__version__with_version_info(self):
434
413
self.setup_plugin("version_info = (1)")
435
plugin = breezy.plugin.plugins()['plugin']
414
plugin = brzlib.plugin.plugins()['plugin']
436
415
self.assertEqual("1", plugin.__version__)
438
417
def test_1__version__with_version_info(self):
439
418
self.setup_plugin("version_info = (1,)")
440
plugin = breezy.plugin.plugins()['plugin']
419
plugin = brzlib.plugin.plugins()['plugin']
441
420
self.assertEqual("1", plugin.__version__)
443
422
def test_1_2__version__with_version_info(self):
444
423
self.setup_plugin("version_info = (1, 2)")
445
plugin = breezy.plugin.plugins()['plugin']
424
plugin = brzlib.plugin.plugins()['plugin']
446
425
self.assertEqual("1.2", plugin.__version__)
448
427
def test_1_2_3__version__with_version_info(self):
449
428
self.setup_plugin("version_info = (1, 2, 3)")
450
plugin = breezy.plugin.plugins()['plugin']
429
plugin = brzlib.plugin.plugins()['plugin']
451
430
self.assertEqual("1.2.3", plugin.__version__)
453
432
def test_candidate__version__with_version_info(self):
454
433
self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
455
plugin = breezy.plugin.plugins()['plugin']
434
plugin = brzlib.plugin.plugins()['plugin']
456
435
self.assertEqual("1.2.3rc1", plugin.__version__)
458
437
def test_dev__version__with_version_info(self):
459
438
self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
460
plugin = breezy.plugin.plugins()['plugin']
439
plugin = brzlib.plugin.plugins()['plugin']
461
440
self.assertEqual("1.2.3dev", plugin.__version__)
463
442
def test_dev_fallback__version__with_version_info(self):
464
443
self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
465
plugin = breezy.plugin.plugins()['plugin']
444
plugin = brzlib.plugin.plugins()['plugin']
466
445
self.assertEqual("1.2.3dev4", plugin.__version__)
468
447
def test_final__version__with_version_info(self):
469
448
self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
470
plugin = breezy.plugin.plugins()['plugin']
449
plugin = brzlib.plugin.plugins()['plugin']
471
450
self.assertEqual("1.2.3", plugin.__version__)
473
452
def test_final_fallback__version__with_version_info(self):
474
453
self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
475
plugin = breezy.plugin.plugins()['plugin']
454
plugin = brzlib.plugin.plugins()['plugin']
476
455
self.assertEqual("1.2.3.2", plugin.__version__)
458
class TestPluginHelp(tests.TestCaseInTempDir):
460
def split_help_commands(self):
463
out, err = self.run_bzr('--no-plugins help commands')
464
for line in out.splitlines():
465
if not line.startswith(' '):
466
current = line.split()[0]
467
help[current] = help.get(current, '') + line
471
def test_plugin_help_builtins_unaffected(self):
472
# Check we don't get false positives
473
help_commands = self.split_help_commands()
474
for cmd_name in brzlib.commands.builtin_command_names():
475
if cmd_name in brzlib.commands.plugin_command_names():
478
help = brzlib.commands.get_cmd_object(cmd_name).get_help_text()
479
except NotImplementedError:
480
# some commands have no help
483
self.assertNotContainsRe(help, 'plugin "[^"]*"')
485
if cmd_name in help_commands.keys():
486
# some commands are hidden
487
help = help_commands[cmd_name]
488
self.assertNotContainsRe(help, 'plugin "[^"]*"')
490
def test_plugin_help_shows_plugin(self):
491
# Create a test plugin
492
os.mkdir('plugin_test')
493
f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
495
from brzlib import commands
496
class cmd_myplug(commands.Command):
497
__doc__ = '''Just a simple test plugin.'''
500
print 'Hello from my plugin'
508
brzlib.plugin.load_from_path(['plugin_test'])
509
brzlib.commands.register_command( brzlib.plugins.myplug.cmd_myplug)
510
help = self.run_bzr('help myplug')[0]
511
self.assertContainsRe(help, 'plugin "myplug"')
512
help = self.split_help_commands()['myplug']
513
self.assertContainsRe(help, '\[myplug\]')
516
if 'myplug' in brzlib.commands.plugin_cmds:
517
brzlib.commands.plugin_cmds.remove('myplug')
518
# remove the plugin 'myplug'
519
if getattr(brzlib.plugins, 'myplug', None):
520
delattr(brzlib.plugins, 'myplug')
479
523
class TestHelpIndex(tests.TestCase):
480
524
"""Tests for the PluginsHelpIndex class."""
552
596
mod = FakeModule(None, 'demo')
553
597
topic = plugin.ModuleHelpTopic(mod)
554
598
self.assertEqual("Plugin 'demo' has no docstring.\n",
555
topic.get_help_text())
599
topic.get_help_text())
557
601
def test_get_help_text_no_carriage_return(self):
558
602
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
559
603
mod = FakeModule('one line of help', 'demo')
560
604
topic = plugin.ModuleHelpTopic(mod)
561
605
self.assertEqual("one line of help\n",
562
topic.get_help_text())
606
topic.get_help_text())
564
608
def test_get_help_text_carriage_return(self):
565
609
"""ModuleHelpTopic.get_help_text adds a \n if needed."""
566
610
mod = FakeModule('two lines of help\nand more\n', 'demo')
567
611
topic = plugin.ModuleHelpTopic(mod)
568
612
self.assertEqual("two lines of help\nand more\n",
569
topic.get_help_text())
613
topic.get_help_text())
571
615
def test_get_help_text_with_additional_see_also(self):
572
616
mod = FakeModule('two lines of help\nand more', 'demo')
573
617
topic = plugin.ModuleHelpTopic(mod)
575
"two lines of help\nand more\n\n:See also: bar, foo\n",
576
topic.get_help_text(['foo', 'bar']))
618
self.assertEqual("two lines of help\nand more\n\n:See also: bar, foo\n",
619
topic.get_help_text(['foo', 'bar']))
578
621
def test_get_help_topic(self):
579
622
"""The help topic for a plugin is its module name."""
580
mod = FakeModule('two lines of help\nand more', 'breezy.plugins.demo')
623
mod = FakeModule('two lines of help\nand more', 'brzlib.plugins.demo')
581
624
topic = plugin.ModuleHelpTopic(mod)
582
625
self.assertEqual('demo', topic.get_help_topic())
583
626
mod = FakeModule('two lines of help\nand more',
584
'breezy.plugins.foo_bar')
627
'brzlib.plugins.foo_bar')
585
628
topic = plugin.ModuleHelpTopic(mod)
586
629
self.assertEqual('foo_bar', topic.get_help_topic())
632
class TestLoadFromPath(tests.TestCaseInTempDir):
635
super(TestLoadFromPath, self).setUp()
636
# Change brzlib.plugin to think no plugins have been loaded yet.
637
self.overrideAttr(brzlib.plugins, '__path__', [])
638
self.overrideAttr(plugin, '_loaded', False)
640
# Monkey-patch load_from_path to stop it from actually loading anything.
641
self.overrideAttr(plugin, 'load_from_path', lambda dirs: None)
643
def test_set_plugins_path_with_args(self):
644
plugin.set_plugins_path(['a', 'b'])
645
self.assertEqual(['a', 'b'], brzlib.plugins.__path__)
647
def test_set_plugins_path_defaults(self):
648
plugin.set_plugins_path()
649
self.assertEqual(plugin.get_standard_plugins_path(),
650
brzlib.plugins.__path__)
652
def test_get_standard_plugins_path(self):
653
path = plugin.get_standard_plugins_path()
654
for directory in path:
655
self.assertNotContainsRe(directory, r'\\/$')
657
from distutils.sysconfig import get_python_lib
661
if sys.platform != 'win32':
662
python_lib = get_python_lib()
663
for directory in path:
664
if directory.startswith(python_lib):
667
self.fail('No path to global plugins')
669
def test_get_standard_plugins_path_env(self):
670
self.overrideEnv('BZR_PLUGIN_PATH', 'foo/')
671
path = plugin.get_standard_plugins_path()
672
for directory in path:
673
self.assertNotContainsRe(directory, r'\\/$')
675
def test_load_plugins(self):
676
plugin.load_plugins(['.'])
677
self.assertEqual(brzlib.plugins.__path__, ['.'])
678
# subsequent loads are no-ops
679
plugin.load_plugins(['foo'])
680
self.assertEqual(brzlib.plugins.__path__, ['.'])
682
def test_load_plugins_default(self):
683
plugin.load_plugins()
684
path = plugin.get_standard_plugins_path()
685
self.assertEqual(path, brzlib.plugins.__path__)
589
688
class TestEnvPluginPath(tests.TestCase):
594
entrypoints = "ENTRYPOINTS"
691
super(TestEnvPluginPath, self).setUp()
692
self.overrideAttr(plugin, 'DEFAULT_PLUGIN_PATH', None)
694
self.user = plugin.get_user_plugin_path()
695
self.site = plugin.get_site_plugin_path()
696
self.core = plugin.get_core_plugin_path()
698
def _list2paths(self, *args):
701
plugin._append_new_path(paths, p)
704
def _set_path(self, *args):
705
path = os.pathsep.join(self._list2paths(*args))
706
self.overrideEnv('BZR_PLUGIN_PATH', path)
596
708
def check_path(self, expected_dirs, setting_dirs):
597
if setting_dirs is None:
598
del os.environ['BRZ_PLUGIN_PATH']
600
os.environ['BRZ_PLUGIN_PATH'] = os.pathsep.join(setting_dirs)
601
actual = [(p if t == 'path' else t.upper())
602
for p, t in plugin._env_plugin_path()]
603
self.assertEqual(expected_dirs, actual)
710
self._set_path(*setting_dirs)
711
actual = plugin.get_standard_plugins_path()
712
self.assertEqual(self._list2paths(*expected_dirs), actual)
605
714
def test_default(self):
606
self.check_path([self.user, self.core, self.site], None)
715
self.check_path([self.user, self.core, self.site],
608
718
def test_adhoc_policy(self):
609
719
self.check_path([self.user, self.core, self.site],
678
782
class TestDisablePlugin(BaseTestPlugins):
785
super(TestDisablePlugin, self).setUp()
786
self.create_plugin_package('test_foo')
787
# Make sure we don't pollute the plugins namespace
788
self.overrideAttr(plugins, '__path__')
789
# Be paranoid in case a test fail
790
self.addCleanup(self._unregister_plugin, 'test_foo')
680
792
def test_cannot_import(self):
681
self.create_plugin_package('works')
682
self.create_plugin_package('fails')
683
self.overrideEnv('BRZ_DISABLE_PLUGINS', 'fails')
684
self.update_module_paths(["."])
685
import breezy.testingplugins.works as works
793
self.overrideEnv('BZR_DISABLE_PLUGINS', 'test_foo')
794
plugin.set_plugins_path(['.'])
687
import breezy.testingplugins.fails as fails
796
import brzlib.plugins.test_foo
688
797
except ImportError:
691
self.fail("Loaded blocked plugin: " + repr(fails))
692
self.assertPluginModules({'fails': None, 'works': works})
694
def test_partial_imports(self):
695
self.create_plugin('good')
696
self.create_plugin('bad')
697
self.create_plugin_package('ugly')
698
self.overrideEnv('BRZ_DISABLE_PLUGINS', 'bad:ugly')
699
self.load_with_paths(['.'])
700
self.assertEqual({'good'}, self.plugins.keys())
701
self.assertPluginModules({
702
'good': self.plugins['good'].module,
706
# Ensure there are no warnings about plugins not being imported as
707
# the user has explictly requested they be disabled.
708
self.assertNotContainsRe(self.get_log(), r"Unable to load plugin")
711
class TestEnvDisablePlugins(tests.TestCase):
713
def _get_names(self, env_value):
714
os.environ['BRZ_DISABLE_PLUGINS'] = env_value
715
return plugin._env_disable_plugins()
717
def test_unset(self):
718
self.assertEqual([], plugin._env_disable_plugins())
720
def test_empty(self):
721
self.assertEqual([], self._get_names(''))
723
def test_single(self):
724
self.assertEqual(['single'], self._get_names('single'))
726
def test_multi(self):
727
expected = ['one', 'two']
728
self.assertEqual(expected, self._get_names(os.pathsep.join(expected)))
730
def test_mixed(self):
731
value = os.pathsep.join(['valid', 'in-valid'])
732
self.assertEqual(['valid'], self._get_names(value))
733
self.assertContainsRe(
735
r"Invalid name 'in-valid' in BRZ_DISABLE_PLUGINS=" + repr(value))
738
class TestEnvPluginsAt(tests.TestCase):
740
def _get_paths(self, env_value):
741
os.environ['BRZ_PLUGINS_AT'] = env_value
742
return plugin._env_plugins_at()
744
def test_empty(self):
745
self.assertEqual([], plugin._env_plugins_at())
799
self.assertPluginUnknown('test_foo')
801
def test_regular_load(self):
802
self.overrideAttr(plugin, '_loaded', False)
803
plugin.load_plugins(['.'])
804
self.assertPluginKnown('test_foo')
805
self.assertDocstring("This is the doc for test_foo",
806
brzlib.plugins.test_foo)
808
def test_not_loaded(self):
810
def captured_warning(*args, **kwargs):
811
self.warnings.append((args, kwargs))
812
self.overrideAttr(trace, 'warning', captured_warning)
813
# Reset the flag that protect against double loading
814
self.overrideAttr(plugin, '_loaded', False)
815
self.overrideEnv('BZR_DISABLE_PLUGINS', 'test_foo')
816
plugin.load_plugins(['.'])
817
self.assertPluginUnknown('test_foo')
818
# Make sure we don't warn about the plugin ImportError since this has
819
# been *requested* by the user.
820
self.assertLength(0, self.warnings)
824
class TestLoadPluginAtSyntax(tests.TestCase):
826
def _get_paths(self, paths):
827
return plugin._get_specific_plugin_paths(paths)
829
def test_empty(self):
830
self.assertEqual([], self._get_paths(None))
746
831
self.assertEqual([], self._get_paths(''))
748
833
def test_one_path(self):
749
834
self.assertEqual([('b', 'man')], self._get_paths('b@man'))
751
def test_multiple(self):
753
[('tools', 'bzr-tools'), ('p', 'play.py')],
754
self._get_paths(os.pathsep.join(('tools@bzr-tools', 'p@play.py'))))
756
def test_many_at(self):
758
[('church', 'StMichael@Plea@Norwich')],
759
self._get_paths('church@StMichael@Plea@Norwich'))
761
def test_only_py(self):
762
self.assertEqual([('test', './test.py')], self._get_paths('./test.py'))
764
def test_only_package(self):
765
self.assertEqual([('py', '/opt/b/py')], self._get_paths('/opt/b/py'))
767
def test_bad_name(self):
768
self.assertEqual([], self._get_paths('/usr/local/bzr-git'))
769
self.assertContainsRe(
771
r"Invalid name 'bzr-git' in BRZ_PLUGINS_AT='/usr/local/bzr-git'")
836
def test_bogus_path(self):
838
self.assertRaises(errors.BzrCommandError, self._get_paths, 'batman')
839
# Too much '@' isn't good either
840
self.assertRaises(errors.BzrCommandError, self._get_paths,
841
'batman@mobile@cave')
842
# An empty description probably indicates a problem
843
self.assertRaises(errors.BzrCommandError, self._get_paths,
844
os.pathsep.join(['batman@cave', '', 'robin@mobile']))
774
847
class TestLoadPluginAt(BaseTestPlugins):
777
850
super(TestLoadPluginAt, self).setUp()
851
# Make sure we don't pollute the plugins namespace
852
self.overrideAttr(plugins, '__path__')
853
# Reset the flag that protect against double loading
854
self.overrideAttr(plugin, '_loaded', False)
778
855
# Create the same plugin in two directories
779
856
self.create_plugin_package('test_foo', dir='non-standard-dir')
780
857
# The "normal" directory, we use 'standard' instead of 'plugins' to
781
858
# avoid depending on the precise naming.
782
859
self.create_plugin_package('test_foo', dir='standard/test_foo')
860
# All the tests will load the 'test_foo' plugin from various locations
861
self.addCleanup(self._unregister_plugin, 'test_foo')
862
# Unfortunately there's global cached state for the specific
864
self.addCleanup(plugin.PluginImporter.reset)
784
866
def assertTestFooLoadedFrom(self, path):
785
867
self.assertPluginKnown('test_foo')
786
868
self.assertDocstring('This is the doc for test_foo',
787
self.module.test_foo)
788
self.assertEqual(path, self.module.test_foo.dir_source)
869
brzlib.plugins.test_foo)
870
self.assertEqual(path, brzlib.plugins.test_foo.dir_source)
790
872
def test_regular_load(self):
791
self.load_with_paths(['standard'])
873
plugin.load_plugins(['standard'])
792
874
self.assertTestFooLoadedFrom('standard/test_foo')
794
876
def test_import(self):
795
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
796
self.update_module_paths(['standard'])
797
import breezy.testingplugins.test_foo
877
self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
878
plugin.set_plugins_path(['standard'])
880
import brzlib.plugins.test_foo
798
883
self.assertTestFooLoadedFrom('non-standard-dir')
800
885
def test_loading(self):
801
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
802
self.load_with_paths(['standard'])
803
self.assertTestFooLoadedFrom('non-standard-dir')
805
def test_loading_other_name(self):
806
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
807
os.rename('standard/test_foo', 'standard/test_bar')
808
self.load_with_paths(['standard'])
886
self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
887
plugin.load_plugins(['standard'])
809
888
self.assertTestFooLoadedFrom('non-standard-dir')
811
890
def test_compiled_loaded(self):
812
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
813
self.load_with_paths(['standard'])
891
self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
892
plugin.load_plugins(['standard'])
814
893
self.assertTestFooLoadedFrom('non-standard-dir')
815
894
self.assertIsSameRealPath('non-standard-dir/__init__.py',
816
self.module.test_foo.__file__)
895
brzlib.plugins.test_foo.__file__)
818
897
# Try importing again now that the source has been compiled
819
os.remove('non-standard-dir/__init__.py')
820
self.promote_cache('non-standard-dir')
822
self.load_with_paths(['standard'])
898
self._unregister_plugin('test_foo')
899
plugin._loaded = False
900
plugin.load_plugins(['standard'])
823
901
self.assertTestFooLoadedFrom('non-standard-dir')
824
suffix = plugin.COMPILED_EXT
825
self.assertIsSameRealPath('non-standard-dir/__init__' + suffix,
826
self.module.test_foo.__file__)
906
self.assertIsSameRealPath('non-standard-dir/__init__.%s' % suffix,
907
brzlib.plugins.test_foo.__file__)
828
909
def test_submodule_loading(self):
829
910
# We create an additional directory under the one for test_foo
830
911
self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
831
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
832
self.update_module_paths(['standard'])
833
import breezy.testingplugins.test_foo # noqa: F401
834
self.assertEqual(self.module_prefix + 'test_foo',
835
self.module.test_foo.__package__)
836
import breezy.testingplugins.test_foo.test_bar # noqa: F401
912
self.addCleanup(self._unregister_plugin_submodule,
913
'test_foo', 'test_bar')
914
self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
915
plugin.set_plugins_path(['standard'])
916
import brzlib.plugins.test_foo
917
self.assertEqual('brzlib.plugins.test_foo',
918
brzlib.plugins.test_foo.__package__)
919
import brzlib.plugins.test_foo.test_bar
837
920
self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
838
self.module.test_foo.test_bar.__file__)
921
brzlib.plugins.test_foo.test_bar.__file__)
840
923
def test_relative_submodule_loading(self):
841
924
self.create_plugin_package('test_foo', dir='another-dir', source='''
842
from . import test_bar
844
927
# We create an additional directory under the one for test_foo
845
928
self.create_plugin_package('test_bar', dir='another-dir/test_bar')
846
self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@another-dir')
847
self.update_module_paths(['standard'])
848
import breezy.testingplugins.test_foo # noqa: F401
849
self.assertEqual(self.module_prefix + 'test_foo',
850
self.module.test_foo.__package__)
929
self.addCleanup(self._unregister_plugin_submodule,
930
'test_foo', 'test_bar')
931
self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@another-dir')
932
plugin.set_plugins_path(['standard'])
933
import brzlib.plugins.test_foo
934
self.assertEqual('brzlib.plugins.test_foo',
935
brzlib.plugins.test_foo.__package__)
851
936
self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
852
self.module.test_foo.test_bar.__file__)
937
brzlib.plugins.test_foo.test_bar.__file__)
854
939
def test_loading_from___init__only(self):
855
940
# We rename the existing __init__.py file to ensure that we don't load