~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_plugins.py

  • Committer: Matthäus G. Chajdas
  • Date: 2010-10-12 01:18:01 UTC
  • mto: (5484.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 5485.
  • Revision ID: dev@anteru.net-20101012011801-thahmhfxdzz0j6d4
Remove spaces.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
20
20
# affects the global state of the process.  See bzrlib/plugins.py for more
21
21
# comments.
22
22
 
 
23
from cStringIO import StringIO
23
24
import logging
24
25
import os
25
 
from StringIO import StringIO
26
26
import sys
27
 
import zipfile
28
27
 
 
28
import bzrlib
29
29
from bzrlib import (
 
30
    errors,
30
31
    osutils,
31
32
    plugin,
 
33
    plugins,
32
34
    tests,
33
 
    )
34
 
import bzrlib.plugin
35
 
import bzrlib.plugins
36
 
import bzrlib.commands
37
 
import bzrlib.help
38
 
from bzrlib.tests import (
39
 
    TestCase,
40
 
    TestCaseInTempDir,
41
 
    TestUtil,
42
 
    )
43
 
from bzrlib.osutils import pathjoin, abspath, normpath
44
 
 
45
 
 
46
 
PLUGIN_TEXT = """\
47
 
import bzrlib.commands
48
 
class cmd_myplug(bzrlib.commands.Command):
49
 
    '''Just a simple test plugin.'''
50
 
    aliases = ['mplg']
51
 
    def run(self):
52
 
        print 'Hello from my plugin'
53
 
"""
 
35
    trace,
 
36
    )
 
37
 
54
38
 
55
39
# TODO: Write a test for plugin decoration of commands.
56
40
 
57
 
class TestLoadingPlugins(TestCaseInTempDir):
 
41
class TestPluginMixin(object):
 
42
 
 
43
    def create_plugin(self, name, source=None, dir='.', file_name=None):
 
44
        if source is None:
 
45
            source = '''\
 
46
"""This is the doc for %s"""
 
47
''' % (name)
 
48
        if file_name is None:
 
49
            file_name = name + '.py'
 
50
        # 'source' must not fail to load
 
51
        path = osutils.pathjoin(dir, file_name)
 
52
        f = open(path, 'w')
 
53
        self.addCleanup(os.unlink, path)
 
54
        try:
 
55
            f.write(source + '\n')
 
56
        finally:
 
57
            f.close()
 
58
 
 
59
    def create_plugin_package(self, name, dir=None, source=None):
 
60
        if dir is None:
 
61
            dir = name
 
62
        if source is None:
 
63
            source = '''\
 
64
"""This is the doc for %s"""
 
65
dir_source = '%s'
 
66
''' % (name, dir)
 
67
        os.makedirs(dir)
 
68
        def cleanup():
 
69
            # Workaround lazy import random? madness
 
70
            osutils.rmtree(dir)
 
71
        self.addCleanup(cleanup)
 
72
        self.create_plugin(name, source, dir,
 
73
                           file_name='__init__.py')
 
74
 
 
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)
 
82
 
 
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)
 
92
 
 
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)
 
96
 
 
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)
 
100
 
 
101
 
 
102
class TestLoadingPlugins(tests.TestCaseInTempDir, TestPluginMixin):
58
103
 
59
104
    activeattributes = {}
60
105
 
68
113
        # set a place for the plugins to record their loading, and at the same
69
114
        # time validate that the location the plugins should record to is
70
115
        # valid and correct.
71
 
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
72
 
            [tempattribute] = []
 
116
        self.__class__.activeattributes [tempattribute] = []
73
117
        self.failUnless(tempattribute in self.activeattributes)
74
118
        # create two plugin directories
75
119
        os.mkdir('first')
99
143
        finally:
100
144
            # remove the plugin 'plugin'
101
145
            del self.activeattributes[tempattribute]
102
 
            if 'bzrlib.plugins.plugin' in sys.modules:
103
 
                del sys.modules['bzrlib.plugins.plugin']
104
 
            if getattr(bzrlib.plugins, 'plugin', None):
105
 
                del bzrlib.plugins.plugin
106
 
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
 
146
            self._unregister_plugin('plugin')
 
147
        self.assertPluginUnknown('plugin')
107
148
 
108
149
    def test_plugins_from_different_dirs_can_demand_load(self):
 
150
        self.failIf('bzrlib.plugins.pluginone' in sys.modules)
 
151
        self.failIf('bzrlib.plugins.plugintwo' in sys.modules)
109
152
        # This test tests that having two plugins in different
110
153
        # directories with different names allows them both to be loaded, when
111
154
        # we do a direct import statement.
143
186
 
144
187
        oldpath = bzrlib.plugins.__path__
145
188
        try:
 
189
            self.failIf('bzrlib.plugins.pluginone' in sys.modules)
 
190
            self.failIf('bzrlib.plugins.plugintwo' in sys.modules)
146
191
            bzrlib.plugins.__path__ = ['first', 'second']
147
192
            exec "import bzrlib.plugins.pluginone"
148
193
            self.assertEqual(['first'], self.activeattributes[tempattribute])
152
197
        finally:
153
198
            # remove the plugin 'plugin'
154
199
            del self.activeattributes[tempattribute]
155
 
            if getattr(bzrlib.plugins, 'pluginone', None):
156
 
                del bzrlib.plugins.pluginone
157
 
            if getattr(bzrlib.plugins, 'plugintwo', None):
158
 
                del bzrlib.plugins.plugintwo
159
 
        self.failIf(getattr(bzrlib.plugins, 'pluginone', None))
160
 
        self.failIf(getattr(bzrlib.plugins, 'plugintwo', None))
 
200
            self._unregister_plugin('pluginone')
 
201
            self._unregister_plugin('plugintwo')
 
202
        self.assertPluginUnknown('pluginone')
 
203
        self.assertPluginUnknown('plugintwo')
161
204
 
162
205
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
163
206
        # This test tests that a plugin can load from a directory when the
164
207
        # directory in the path has a trailing slash.
165
208
        # check the plugin is not loaded already
166
 
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
 
209
        self.assertPluginUnknown('ts_plugin')
167
210
        tempattribute = "trailing-slash"
168
211
        self.failIf(tempattribute in self.activeattributes)
169
212
        # set a place for the plugin to record its loading, and at the same
190
233
            bzrlib.plugin.load_from_path(['plugin_test'+os.sep])
191
234
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
192
235
        finally:
193
 
            # remove the plugin 'plugin'
194
236
            del self.activeattributes[tempattribute]
195
 
            if getattr(bzrlib.plugins, 'ts_plugin', None):
196
 
                del bzrlib.plugins.ts_plugin
197
 
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
 
237
            self._unregister_plugin('ts_plugin')
 
238
        self.assertPluginUnknown('ts_plugin')
198
239
 
199
240
    def load_and_capture(self, name):
200
241
        """Load plugins from '.' capturing the output.
251
292
            "it to 'bad_plugin_name_'\.")
252
293
 
253
294
 
254
 
class TestPlugins(TestCaseInTempDir):
 
295
class TestPlugins(tests.TestCaseInTempDir, TestPluginMixin):
255
296
 
256
297
    def setup_plugin(self, source=""):
257
298
        # This test tests a new plugin appears in bzrlib.plugin.plugins().
258
299
        # check the plugin is not loaded already
259
 
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
 
300
        self.assertPluginUnknown('plugin')
260
301
        # write a plugin that _cannot_ fail to load.
261
302
        file('plugin.py', 'w').write(source + '\n')
262
303
        self.addCleanup(self.teardown_plugin)
263
 
        bzrlib.plugin.load_from_path(['.'])
 
304
        plugin.load_from_path(['.'])
264
305
 
265
306
    def teardown_plugin(self):
266
 
        # remove the plugin 'plugin'
267
 
        if 'bzrlib.plugins.plugin' in sys.modules:
268
 
            del sys.modules['bzrlib.plugins.plugin']
269
 
        if getattr(bzrlib.plugins, 'plugin', None):
270
 
            del bzrlib.plugins.plugin
271
 
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
 
307
        self._unregister_plugin('plugin')
 
308
        self.assertPluginUnknown('plugin')
272
309
 
273
310
    def test_plugin_appears_in_plugins(self):
274
311
        self.setup_plugin()
275
 
        self.failUnless('plugin' in bzrlib.plugin.plugins())
276
 
        self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
277
 
        plugins = bzrlib.plugin.plugins()
278
 
        plugin = plugins['plugin']
279
 
        self.assertIsInstance(plugin, bzrlib.plugin.PlugIn)
280
 
        self.assertEqual(bzrlib.plugins.plugin, plugin.module)
 
312
        self.assertPluginKnown('plugin')
 
313
        p = plugin.plugins()['plugin']
 
314
        self.assertIsInstance(p, bzrlib.plugin.PlugIn)
 
315
        self.assertEqual(p.module, plugins.plugin)
281
316
 
282
317
    def test_trivial_plugin_get_path(self):
283
318
        self.setup_plugin()
284
 
        plugins = bzrlib.plugin.plugins()
285
 
        plugin = plugins['plugin']
 
319
        p = plugin.plugins()['plugin']
286
320
        plugin_path = self.test_dir + '/plugin.py'
287
 
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
321
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
288
322
 
289
323
    def test_plugin_get_path_py_not_pyc(self):
290
 
        self.setup_plugin()         # after first import there will be plugin.pyc
 
324
        # first import creates plugin.pyc
 
325
        self.setup_plugin()
291
326
        self.teardown_plugin()
292
 
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
293
 
        plugins = bzrlib.plugin.plugins()
294
 
        plugin = plugins['plugin']
 
327
        plugin.load_from_path(['.']) # import plugin.pyc
 
328
        p = plugin.plugins()['plugin']
295
329
        plugin_path = self.test_dir + '/plugin.py'
296
 
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
330
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
297
331
 
298
332
    def test_plugin_get_path_pyc_only(self):
299
 
        self.setup_plugin()         # after first import there will be plugin.pyc
 
333
        # first import creates plugin.pyc (or plugin.pyo depending on __debug__)
 
334
        self.setup_plugin()
300
335
        self.teardown_plugin()
301
336
        os.unlink(self.test_dir + '/plugin.py')
302
 
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
303
 
        plugins = bzrlib.plugin.plugins()
304
 
        plugin = plugins['plugin']
 
337
        plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
 
338
        p = plugin.plugins()['plugin']
305
339
        if __debug__:
306
340
            plugin_path = self.test_dir + '/plugin.pyc'
307
341
        else:
308
342
            plugin_path = self.test_dir + '/plugin.pyo'
309
 
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
343
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
310
344
 
311
345
    def test_no_test_suite_gives_None_for_test_suite(self):
312
346
        self.setup_plugin()
313
 
        plugin = bzrlib.plugin.plugins()['plugin']
314
 
        self.assertEqual(None, plugin.test_suite())
 
347
        p = plugin.plugins()['plugin']
 
348
        self.assertEqual(None, p.test_suite())
315
349
 
316
350
    def test_test_suite_gives_test_suite_result(self):
317
351
        source = """def test_suite(): return 'foo'"""
318
352
        self.setup_plugin(source)
319
 
        plugin = bzrlib.plugin.plugins()['plugin']
320
 
        self.assertEqual('foo', plugin.test_suite())
 
353
        p = plugin.plugins()['plugin']
 
354
        self.assertEqual('foo', p.test_suite())
321
355
 
322
356
    def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
323
357
        self.setup_plugin()
324
 
        loader = TestUtil.TestLoader()
325
 
        plugin = bzrlib.plugin.plugins()['plugin']
326
 
        self.assertEqual(None, plugin.load_plugin_tests(loader))
 
358
        loader = tests.TestUtil.TestLoader()
 
359
        p = plugin.plugins()['plugin']
 
360
        self.assertEqual(None, p.load_plugin_tests(loader))
327
361
 
328
362
    def test_load_plugin_tests_gives_load_plugin_tests_result(self):
329
363
        source = """
330
364
def load_tests(standard_tests, module, loader):
331
365
    return 'foo'"""
332
366
        self.setup_plugin(source)
333
 
        loader = TestUtil.TestLoader()
334
 
        plugin = bzrlib.plugin.plugins()['plugin']
335
 
        self.assertEqual('foo', plugin.load_plugin_tests(loader))
 
367
        loader = tests.TestUtil.TestLoader()
 
368
        p = plugin.plugins()['plugin']
 
369
        self.assertEqual('foo', p.load_plugin_tests(loader))
 
370
 
 
371
    def check_version_info(self, expected, source='', name='plugin'):
 
372
        self.setup_plugin(source)
 
373
        self.assertEqual(expected, plugin.plugins()[name].version_info())
336
374
 
337
375
    def test_no_version_info(self):
338
 
        self.setup_plugin()
339
 
        plugin = bzrlib.plugin.plugins()['plugin']
340
 
        self.assertEqual(None, plugin.version_info())
 
376
        self.check_version_info(None)
341
377
 
342
378
    def test_with_version_info(self):
343
 
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
344
 
        plugin = bzrlib.plugin.plugins()['plugin']
345
 
        self.assertEqual((1, 2, 3, 'dev', 4), plugin.version_info())
 
379
        self.check_version_info((1, 2, 3, 'dev', 4),
 
380
                                "version_info = (1, 2, 3, 'dev', 4)")
346
381
 
347
382
    def test_short_version_info_gets_padded(self):
348
383
        # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
349
384
        # so we adapt it
350
 
        self.setup_plugin("version_info = (1, 2, 3)")
351
 
        plugin = bzrlib.plugin.plugins()['plugin']
352
 
        self.assertEqual((1, 2, 3, 'final', 0), plugin.version_info())
 
385
        self.check_version_info((1, 2, 3, 'final', 0),
 
386
                                "version_info = (1, 2, 3)")
 
387
 
 
388
    def check_version(self, expected, source=None, name='plugin'):
 
389
        self.setup_plugin(source)
 
390
        self.assertEqual(expected, plugins[name].__version__)
353
391
 
354
392
    def test_no_version_info___version__(self):
355
393
        self.setup_plugin()
407
445
        self.assertEqual("1.2.3.final.2", plugin.__version__)
408
446
 
409
447
 
410
 
class TestPluginHelp(TestCaseInTempDir):
 
448
class TestPluginHelp(tests.TestCaseInTempDir):
411
449
 
412
450
    def split_help_commands(self):
413
451
        help = {}
442
480
    def test_plugin_help_shows_plugin(self):
443
481
        # Create a test plugin
444
482
        os.mkdir('plugin_test')
445
 
        f = open(pathjoin('plugin_test', 'myplug.py'), 'w')
446
 
        f.write(PLUGIN_TEXT)
 
483
        f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
 
484
        f.write("""\
 
485
from bzrlib import commands
 
486
class cmd_myplug(commands.Command):
 
487
    __doc__ = '''Just a simple test plugin.'''
 
488
    aliases = ['mplg']
 
489
    def run(self):
 
490
        print 'Hello from my plugin'
 
491
 
 
492
"""
 
493
)
447
494
        f.close()
448
495
 
449
496
        try:
627
674
        self.assertEqual(path, bzrlib.plugins.__path__)
628
675
 
629
676
 
630
 
class TestEnvPluginPath(tests.TestCaseInTempDir):
 
677
class TestEnvPluginPath(tests.TestCase):
631
678
 
632
679
    def setUp(self):
633
680
        super(TestEnvPluginPath, self).setUp()
680
727
        self.check_path([self.user, self.core, self.site],
681
728
                        ['+user', '+user'])
682
729
        # And only the first reference is kept (since the later references will
683
 
        # onnly produce <plugin> already loaded mutters)
 
730
        # only produce '<plugin> already loaded' mutters)
684
731
        self.check_path([self.user, self.core, self.site],
685
732
                        ['+user', '+user', '+core',
686
733
                         '+user', '+site', '+site',
687
734
                         '+core'])
688
735
 
689
 
    def test_disable_overrides_disable(self):
 
736
    def test_disable_overrides_enable(self):
690
737
        self.check_path([self.core, self.site], ['-user', '+user'])
691
738
 
692
739
    def test_disable_core(self):
719
766
    def test_bogus_references(self):
720
767
        self.check_path(['+foo', '-bar', self.core, self.site],
721
768
                        ['+foo', '-bar'])
 
769
 
 
770
 
 
771
class TestDisablePlugin(tests.TestCaseInTempDir, TestPluginMixin):
 
772
 
 
773
    def setUp(self):
 
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')
 
780
 
 
781
    def test_cannot_import(self):
 
782
        osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
 
783
        plugin.set_plugins_path(['.'])
 
784
        try:
 
785
            import bzrlib.plugins.test_foo
 
786
        except ImportError:
 
787
            pass
 
788
        self.assertPluginUnknown('test_foo')
 
789
 
 
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)
 
796
 
 
797
    def test_not_loaded(self):
 
798
        self.warnings = []
 
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)
 
810
 
 
811
 
 
812
class TestLoadPluginAtSyntax(tests.TestCase):
 
813
 
 
814
    def _get_paths(self, paths):
 
815
        return plugin._get_specific_plugin_paths(paths)
 
816
 
 
817
    def test_empty(self):
 
818
        self.assertEquals([], self._get_paths(None))
 
819
        self.assertEquals([], self._get_paths(''))
 
820
 
 
821
    def test_one_path(self):
 
822
        self.assertEquals([('b', 'man')], self._get_paths('b@man'))
 
823
 
 
824
    def test_bogus_path(self):
 
825
        # We need a '@'
 
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']))
 
833
 
 
834
 
 
835
class TestLoadPluginAt(tests.TestCaseInTempDir, TestPluginMixin):
 
836
 
 
837
    def setUp(self):
 
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')
 
850
 
 
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)
 
856
 
 
857
    def test_regular_load(self):
 
858
        plugin.load_plugins(['standard'])
 
859
        self.assertTestFooLoadedFrom('standard/test_foo')
 
860
 
 
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'])
 
864
        try:
 
865
            import bzrlib.plugins.test_foo
 
866
        except ImportError:
 
867
            pass
 
868
        self.assertTestFooLoadedFrom('non-standard-dir')
 
869
 
 
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')
 
874
 
 
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__)
 
881
 
 
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')
 
887
        if __debug__:
 
888
            suffix = 'pyc'
 
889
        else:
 
890
            suffix = 'pyo'
 
891
        self.assertIsSameRealPath('non-standard-dir/__init__.%s' % suffix,
 
892
                                  bzrlib.plugins.test_foo.__file__)
 
893
 
 
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__)
 
907
 
 
908
    def test_relative_submodule_loading(self):
 
909
        self.create_plugin_package('test_foo', dir='another-dir', source='''
 
910
import test_bar
 
911
''')
 
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__)
 
923
 
 
924
    def test_loading_from___init__only(self):
 
925
        # We rename the existing __init__.py file to ensure that we don't load
 
926
        # a random file
 
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')
 
934
 
 
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)
 
939
        source = '''\
 
940
"""This is the doc for %s"""
 
941
dir_source = '%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)