/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_plugins.py

  • Committer: Jelmer Vernooij
  • Date: 2017-08-27 13:57:26 UTC
  • mto: This revision was merged to the branch mainline in revision 6773.
  • Revision ID: jelmer@jelmer.uk-20170827135726-o6k0a4j205zdh8k0
Fix some tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd, 2017 Breezy developers
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
16
16
 
17
17
"""Tests for plugins"""
18
18
 
19
 
# XXX: There are no plugin tests at the moment because the plugin module
20
 
# affects the global state of the process.  See bzrlib/plugins.py for more
21
 
# comments.
22
 
 
23
 
from cStringIO import StringIO
 
19
import imp
 
20
import importlib
24
21
import logging
25
22
import os
26
23
import sys
27
24
 
28
 
import bzrlib
29
 
from bzrlib import (
 
25
import breezy
 
26
from .. import (
 
27
    errors,
30
28
    osutils,
31
29
    plugin,
32
 
    plugins,
33
30
    tests,
34
31
    trace,
35
32
    )
 
33
from ..sixish import (
 
34
    PY3,
 
35
    StringIO,
 
36
    viewkeys,
 
37
    )
36
38
 
37
39
 
38
40
# TODO: Write a test for plugin decoration of commands.
39
41
 
40
 
class TestPluginMixin(object):
 
42
invalidate_caches = getattr(importlib, "invalidate_caches", lambda: None)
 
43
 
 
44
 
 
45
class BaseTestPlugins(tests.TestCaseInTempDir):
 
46
    """TestCase that isolates plugin imports and cleans up on completion."""
 
47
 
 
48
    def setUp(self):
 
49
        super(BaseTestPlugins, self).setUp()
 
50
        self.module_name = "breezy.testingplugins"
 
51
        self.module_prefix = self.module_name + "."
 
52
        self.module = imp.new_module(self.module_name)
 
53
 
 
54
        self.overrideAttr(plugin, "_MODULE_PREFIX", self.module_prefix)
 
55
        self.overrideAttr(breezy, "testingplugins", self.module)
 
56
 
 
57
        sys.modules[self.module_name] = self.module
 
58
        self.addCleanup(self._unregister_all)
 
59
        self.addCleanup(self._unregister_finder)
 
60
 
 
61
        invalidate_caches()
 
62
 
 
63
    def reset(self):
 
64
        """Remove all global testing state and clean up module."""
 
65
        # GZ 2017-06-02: Ideally don't do this, write new test or generate
 
66
        # bytecode by other mechanism.
 
67
        self.log("resetting plugin testing context")
 
68
        self._unregister_all()
 
69
        self._unregister_finder()
 
70
        sys.modules[self.module_name] = self.module
 
71
        for name in list(self.module.__dict__):
 
72
            if name[:2] != '__':
 
73
                delattr(self.module, name)
 
74
        invalidate_caches()
 
75
        self.plugins = None
 
76
 
 
77
    def update_module_paths(self, paths):
 
78
        paths = plugin.extend_path(paths, self.module_name)
 
79
        self.module.__path__ = paths
 
80
        self.log("using %r", paths)
 
81
        return paths
 
82
 
 
83
    def load_with_paths(self, paths):
 
84
        self.log("loading plugins!")
 
85
        plugin.load_plugins(self.update_module_paths(paths), state=self)
41
86
 
42
87
    def create_plugin(self, name, source=None, dir='.', file_name=None):
43
88
        if source is None:
48
93
            file_name = name + '.py'
49
94
        # 'source' must not fail to load
50
95
        path = osutils.pathjoin(dir, file_name)
51
 
        f = open(path, 'w')
52
 
        self.addCleanup(os.unlink, path)
53
 
        try:
 
96
        with open(path, 'w') as f:
54
97
            f.write(source + '\n')
55
 
        finally:
56
 
            f.close()
57
98
 
58
99
    def create_plugin_package(self, name, dir=None, source=None):
59
100
        if dir is None:
64
105
dir_source = '%s'
65
106
''' % (name, dir)
66
107
        os.makedirs(dir)
67
 
        def cleanup():
68
 
            # Workaround lazy import random? madness
69
 
            osutils.rmtree(dir)
70
 
        self.addCleanup(cleanup)
71
108
        self.create_plugin(name, source, dir,
72
109
                           file_name='__init__.py')
73
110
 
74
 
    def _unregister_plugin(self, name):
75
 
        """Remove the plugin from sys.modules and the bzrlib namespace."""
76
 
        py_name = 'bzrlib.plugins.%s' % name
77
 
        if py_name in sys.modules:
78
 
            del sys.modules[py_name]
79
 
        if getattr(bzrlib.plugins, name, None) is not None:
80
 
            delattr(bzrlib.plugins, name)
 
111
    def promote_cache(self, directory):
 
112
        """Move bytecode files out of __pycache__ in given directory."""
 
113
        cache_dir = os.path.join(directory, '__pycache__')
 
114
        if os.path.isdir(cache_dir):
 
115
            for name in os.listdir(cache_dir):
 
116
                magicless_name = '.'.join(name.split('.')[0::name.count('.')])
 
117
                rel = osutils.relpath(self.test_dir, cache_dir)
 
118
                self.log("moving %s in %s to %s", name, rel, magicless_name)
 
119
                os.rename(os.path.join(cache_dir, name),
 
120
                    os.path.join(directory, magicless_name))
 
121
 
 
122
    def _unregister_finder(self):
 
123
        """Removes any test copies of _PluginsAtFinder from sys.meta_path."""
 
124
        idx = len(sys.meta_path)
 
125
        while idx:
 
126
            idx -= 1
 
127
            finder = sys.meta_path[idx]
 
128
            if getattr(finder, "prefix", "") == self.module_prefix:
 
129
                self.log("removed %r from sys.meta_path", finder)
 
130
                sys.meta_path.pop(idx)
 
131
 
 
132
    def _unregister_all(self):
 
133
        """Remove all plugins in the test namespace from sys.modules."""
 
134
        for name in list(sys.modules):
 
135
            if name.startswith(self.module_prefix) or name == self.module_name:
 
136
                self.log("removed %s from sys.modules", name)
 
137
                del sys.modules[name]
 
138
 
 
139
    def assertPluginModules(self, plugin_dict):
 
140
        self.assertEqual(
 
141
            dict((k[len(self.module_prefix):], sys.modules[k])
 
142
                for k in sys.modules if k.startswith(self.module_prefix)),
 
143
            plugin_dict)
81
144
 
82
145
    def assertPluginUnknown(self, name):
83
 
        self.failIf(getattr(bzrlib.plugins, name, None) is not None)
84
 
        self.failIf('bzrlib.plugins.%s' % name in sys.modules)
 
146
        self.assertTrue(getattr(self.module, name, None) is None)
 
147
        self.assertFalse(self.module_prefix + name in sys.modules)
85
148
 
86
149
    def assertPluginKnown(self, name):
87
 
        self.failUnless(getattr(bzrlib.plugins, name, None) is not None)
88
 
        self.failUnless('bzrlib.plugins.%s' % name in sys.modules)
89
 
 
90
 
 
91
 
class TestLoadingPlugins(tests.TestCaseInTempDir, TestPluginMixin):
 
150
        self.assertTrue(getattr(self.module, name, None) is not None)
 
151
        self.assertTrue(self.module_prefix + name in sys.modules)
 
152
 
 
153
 
 
154
class TestLoadingPlugins(BaseTestPlugins):
92
155
 
93
156
    activeattributes = {}
94
157
 
98
161
        # file name we can use which is also a valid attribute for accessing in
99
162
        # activeattributes. - we cannot give import parameters.
100
163
        tempattribute = "0"
101
 
        self.failIf(tempattribute in self.activeattributes)
 
164
        self.assertFalse(tempattribute in self.activeattributes)
102
165
        # set a place for the plugins to record their loading, and at the same
103
166
        # time validate that the location the plugins should record to is
104
167
        # valid and correct.
105
168
        self.__class__.activeattributes [tempattribute] = []
106
 
        self.failUnless(tempattribute in self.activeattributes)
 
169
        self.assertTrue(tempattribute in self.activeattributes)
107
170
        # create two plugin directories
108
171
        os.mkdir('first')
109
172
        os.mkdir('second')
110
173
        # write a plugin that will record when its loaded in the
111
174
        # tempattribute list.
112
 
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
 
175
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
113
176
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
114
177
 
115
 
        outfile = open(os.path.join('first', 'plugin.py'), 'w')
116
 
        try:
 
178
        with open(os.path.join('first', 'plugin.py'), 'w') as outfile:
117
179
            outfile.write(template % (tempattribute, 'first'))
118
180
            outfile.write('\n')
119
 
        finally:
120
 
            outfile.close()
121
181
 
122
 
        outfile = open(os.path.join('second', 'plugin.py'), 'w')
123
 
        try:
 
182
        with open(os.path.join('second', 'plugin.py'), 'w') as outfile:
124
183
            outfile.write(template % (tempattribute, 'second'))
125
184
            outfile.write('\n')
126
 
        finally:
127
 
            outfile.close()
128
185
 
129
186
        try:
130
 
            bzrlib.plugin.load_from_path(['first', 'second'])
 
187
            self.load_with_paths(['first', 'second'])
131
188
            self.assertEqual(['first'], self.activeattributes[tempattribute])
132
189
        finally:
133
 
            # remove the plugin 'plugin'
134
190
            del self.activeattributes[tempattribute]
135
 
            self._unregister_plugin('plugin')
136
 
        self.assertPluginUnknown('plugin')
137
191
 
138
192
    def test_plugins_from_different_dirs_can_demand_load(self):
139
 
        self.failIf('bzrlib.plugins.pluginone' in sys.modules)
140
 
        self.failIf('bzrlib.plugins.plugintwo' in sys.modules)
 
193
        self.assertFalse('breezy.plugins.pluginone' in sys.modules)
 
194
        self.assertFalse('breezy.plugins.plugintwo' in sys.modules)
141
195
        # This test tests that having two plugins in different
142
196
        # directories with different names allows them both to be loaded, when
143
197
        # we do a direct import statement.
144
198
        # Determine a file name we can use which is also a valid attribute
145
199
        # for accessing in activeattributes. - we cannot give import parameters.
146
200
        tempattribute = "different-dirs"
147
 
        self.failIf(tempattribute in self.activeattributes)
 
201
        self.assertFalse(tempattribute in self.activeattributes)
148
202
        # set a place for the plugins to record their loading, and at the same
149
203
        # time validate that the location the plugins should record to is
150
204
        # valid and correct.
151
 
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
 
205
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes \
152
206
            [tempattribute] = []
153
 
        self.failUnless(tempattribute in self.activeattributes)
 
207
        self.assertTrue(tempattribute in self.activeattributes)
154
208
        # create two plugin directories
155
209
        os.mkdir('first')
156
210
        os.mkdir('second')
157
211
        # write plugins that will record when they are loaded in the
158
212
        # tempattribute list.
159
 
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
 
213
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
160
214
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
161
215
 
162
 
        outfile = open(os.path.join('first', 'pluginone.py'), 'w')
163
 
        try:
 
216
        with open(os.path.join('first', 'pluginone.py'), 'w') as outfile:
164
217
            outfile.write(template % (tempattribute, 'first'))
165
218
            outfile.write('\n')
166
 
        finally:
167
 
            outfile.close()
168
219
 
169
 
        outfile = open(os.path.join('second', 'plugintwo.py'), 'w')
170
 
        try:
 
220
        with open(os.path.join('second', 'plugintwo.py'), 'w') as outfile:
171
221
            outfile.write(template % (tempattribute, 'second'))
172
222
            outfile.write('\n')
173
 
        finally:
174
 
            outfile.close()
175
223
 
176
 
        oldpath = bzrlib.plugins.__path__
177
224
        try:
178
 
            self.failIf('bzrlib.plugins.pluginone' in sys.modules)
179
 
            self.failIf('bzrlib.plugins.plugintwo' in sys.modules)
180
 
            bzrlib.plugins.__path__ = ['first', 'second']
181
 
            exec "import bzrlib.plugins.pluginone"
 
225
            self.assertPluginUnknown('pluginone')
 
226
            self.assertPluginUnknown('plugintwo')
 
227
            self.update_module_paths(['first', 'second'])
 
228
            exec("import %spluginone" % self.module_prefix)
182
229
            self.assertEqual(['first'], self.activeattributes[tempattribute])
183
 
            exec "import bzrlib.plugins.plugintwo"
 
230
            exec("import %splugintwo" % self.module_prefix)
184
231
            self.assertEqual(['first', 'second'],
185
232
                self.activeattributes[tempattribute])
186
233
        finally:
187
 
            # remove the plugin 'plugin'
188
234
            del self.activeattributes[tempattribute]
189
 
            self._unregister_plugin('pluginone')
190
 
            self._unregister_plugin('plugintwo')
191
 
        self.assertPluginUnknown('pluginone')
192
 
        self.assertPluginUnknown('plugintwo')
193
235
 
194
236
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
195
237
        # This test tests that a plugin can load from a directory when the
197
239
        # check the plugin is not loaded already
198
240
        self.assertPluginUnknown('ts_plugin')
199
241
        tempattribute = "trailing-slash"
200
 
        self.failIf(tempattribute in self.activeattributes)
 
242
        self.assertFalse(tempattribute in self.activeattributes)
201
243
        # set a place for the plugin to record its loading, and at the same
202
244
        # time validate that the location the plugin should record to is
203
245
        # valid and correct.
204
 
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
 
246
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes \
205
247
            [tempattribute] = []
206
 
        self.failUnless(tempattribute in self.activeattributes)
 
248
        self.assertTrue(tempattribute in self.activeattributes)
207
249
        # create a directory for the plugin
208
250
        os.mkdir('plugin_test')
209
251
        # write a plugin that will record when its loaded in the
210
252
        # tempattribute list.
211
 
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
 
253
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
212
254
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
213
255
 
214
 
        outfile = open(os.path.join('plugin_test', 'ts_plugin.py'), 'w')
215
 
        try:
 
256
        with open(os.path.join('plugin_test', 'ts_plugin.py'), 'w') as outfile:
216
257
            outfile.write(template % (tempattribute, 'plugin'))
217
258
            outfile.write('\n')
218
 
        finally:
219
 
            outfile.close()
220
259
 
221
260
        try:
222
 
            bzrlib.plugin.load_from_path(['plugin_test'+os.sep])
 
261
            self.load_with_paths(['plugin_test'+os.sep])
223
262
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
 
263
            self.assertPluginKnown('ts_plugin')
224
264
        finally:
225
265
            del self.activeattributes[tempattribute]
226
 
            self._unregister_plugin('ts_plugin')
227
 
        self.assertPluginUnknown('ts_plugin')
228
266
 
229
267
    def load_and_capture(self, name):
230
268
        """Load plugins from '.' capturing the output.
236
274
        stream = StringIO()
237
275
        try:
238
276
            handler = logging.StreamHandler(stream)
239
 
            log = logging.getLogger('bzr')
 
277
            log = logging.getLogger('brz')
240
278
            log.addHandler(handler)
241
279
            try:
242
 
                try:
243
 
                    bzrlib.plugin.load_from_path(['.'])
244
 
                finally:
245
 
                    if 'bzrlib.plugins.%s' % name in sys.modules:
246
 
                        del sys.modules['bzrlib.plugins.%s' % name]
247
 
                    if getattr(bzrlib.plugins, name, None):
248
 
                        delattr(bzrlib.plugins, name)
 
280
                self.load_with_paths(['.'])
249
281
            finally:
250
282
                # Stop capturing output
251
283
                handler.flush()
256
288
            stream.close()
257
289
 
258
290
    def test_plugin_with_bad_api_version_reports(self):
259
 
        # This plugin asks for bzrlib api version 1.0.0, which is not supported
260
 
        # anymore.
 
291
        """Try loading a plugin that requests an unsupported api.
 
292
 
 
293
        Observe that it records the problem but doesn't complain on stderr.
 
294
 
 
295
        See https://bugs.launchpad.net/bzr/+bug/704195
 
296
        """
261
297
        name = 'wants100.py'
262
 
        f = file(name, 'w')
263
 
        try:
264
 
            f.write("import bzrlib.api\n"
265
 
                "bzrlib.api.require_any_api(bzrlib, [(1, 0, 0)])\n")
266
 
        finally:
267
 
            f.close()
268
 
 
 
298
        with open(name, 'w') as f:
 
299
            f.write("import breezy\n"
 
300
                "from breezy.errors import IncompatibleVersion\n"
 
301
                "raise IncompatibleVersion(breezy, [(1, 0, 0)], (0, 0, 5))\n")
269
302
        log = self.load_and_capture(name)
270
 
        self.assertContainsRe(log,
271
 
            r"It requested API version")
 
303
        self.assertNotContainsRe(log,
 
304
            r"It supports breezy version")
 
305
        self.assertEqual({'wants100'}, viewkeys(self.plugin_warnings))
 
306
        self.assertContainsRe(
 
307
            self.plugin_warnings['wants100'][0],
 
308
            r"It supports breezy version")
272
309
 
273
310
    def test_plugin_with_bad_name_does_not_load(self):
274
311
        # The file name here invalid for a python module.
275
 
        name = 'bzr-bad plugin-name..py'
276
 
        file(name, 'w').close()
 
312
        name = 'brz-bad plugin-name..py'
 
313
        open(name, 'w').close()
277
314
        log = self.load_and_capture(name)
278
315
        self.assertContainsRe(log,
279
 
            r"Unable to load 'bzr-bad plugin-name\.' in '\.' as a plugin "
 
316
            r"Unable to load 'brz-bad plugin-name\.' in '\.' as a plugin "
280
317
            "because the file path isn't a valid module name; try renaming "
281
318
            "it to 'bad_plugin_name_'\.")
282
319
 
283
320
 
284
 
class TestPlugins(tests.TestCaseInTempDir, TestPluginMixin):
 
321
class TestPlugins(BaseTestPlugins):
285
322
 
286
323
    def setup_plugin(self, source=""):
287
 
        # This test tests a new plugin appears in bzrlib.plugin.plugins().
 
324
        # This test tests a new plugin appears in breezy.plugin.plugins().
288
325
        # check the plugin is not loaded already
289
326
        self.assertPluginUnknown('plugin')
290
327
        # write a plugin that _cannot_ fail to load.
291
 
        file('plugin.py', 'w').write(source + '\n')
292
 
        self.addCleanup(self.teardown_plugin)
293
 
        plugin.load_from_path(['.'])
 
328
        with open('plugin.py', 'w') as f: f.write(source + '\n')
 
329
        self.load_with_paths(['.'])
294
330
 
295
 
    def teardown_plugin(self):
296
 
        self._unregister_plugin('plugin')
 
331
    def test_plugin_loaded(self):
297
332
        self.assertPluginUnknown('plugin')
 
333
        self.assertIs(None, breezy.plugin.get_loaded_plugin('plugin'))
 
334
        self.setup_plugin()
 
335
        p = breezy.plugin.get_loaded_plugin('plugin')
 
336
        self.assertIsInstance(p, breezy.plugin.PlugIn)
 
337
        self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
298
338
 
299
339
    def test_plugin_appears_in_plugins(self):
300
340
        self.setup_plugin()
301
341
        self.assertPluginKnown('plugin')
302
 
        p = plugin.plugins()['plugin']
303
 
        self.assertIsInstance(p, bzrlib.plugin.PlugIn)
304
 
        self.assertEqual(p.module, plugins.plugin)
 
342
        p = self.plugins['plugin']
 
343
        self.assertIsInstance(p, breezy.plugin.PlugIn)
 
344
        self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
305
345
 
306
346
    def test_trivial_plugin_get_path(self):
307
347
        self.setup_plugin()
308
 
        p = plugin.plugins()['plugin']
 
348
        p = self.plugins['plugin']
309
349
        plugin_path = self.test_dir + '/plugin.py'
310
350
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
311
351
 
312
352
    def test_plugin_get_path_py_not_pyc(self):
313
353
        # first import creates plugin.pyc
314
354
        self.setup_plugin()
315
 
        self.teardown_plugin()
316
 
        plugin.load_from_path(['.']) # import plugin.pyc
 
355
        self.promote_cache(self.test_dir)
 
356
        self.reset()
 
357
        self.load_with_paths(['.']) # import plugin.pyc
317
358
        p = plugin.plugins()['plugin']
318
359
        plugin_path = self.test_dir + '/plugin.py'
319
360
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
321
362
    def test_plugin_get_path_pyc_only(self):
322
363
        # first import creates plugin.pyc (or plugin.pyo depending on __debug__)
323
364
        self.setup_plugin()
324
 
        self.teardown_plugin()
325
365
        os.unlink(self.test_dir + '/plugin.py')
326
 
        plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
 
366
        self.promote_cache(self.test_dir)
 
367
        self.reset()
 
368
        self.load_with_paths(['.']) # import plugin.pyc (or .pyo)
327
369
        p = plugin.plugins()['plugin']
328
 
        if __debug__:
329
 
            plugin_path = self.test_dir + '/plugin.pyc'
330
 
        else:
331
 
            plugin_path = self.test_dir + '/plugin.pyo'
 
370
        plugin_path = self.test_dir + '/plugin' + plugin.COMPILED_EXT
332
371
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
333
372
 
334
373
    def test_no_test_suite_gives_None_for_test_suite(self):
350
389
 
351
390
    def test_load_plugin_tests_gives_load_plugin_tests_result(self):
352
391
        source = """
353
 
def load_tests(standard_tests, module, loader):
 
392
def load_tests(loader, standard_tests, pattern):
354
393
    return 'foo'"""
355
394
        self.setup_plugin(source)
356
395
        loader = tests.TestUtil.TestLoader()
380
419
 
381
420
    def test_no_version_info___version__(self):
382
421
        self.setup_plugin()
383
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
422
        plugin = breezy.plugin.plugins()['plugin']
384
423
        self.assertEqual("unknown", plugin.__version__)
385
424
 
386
425
    def test_str__version__with_version_info(self):
387
426
        self.setup_plugin("version_info = '1.2.3'")
388
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
427
        plugin = breezy.plugin.plugins()['plugin']
389
428
        self.assertEqual("1.2.3", plugin.__version__)
390
429
 
391
430
    def test_noniterable__version__with_version_info(self):
392
431
        self.setup_plugin("version_info = (1)")
393
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
432
        plugin = breezy.plugin.plugins()['plugin']
394
433
        self.assertEqual("1", plugin.__version__)
395
434
 
396
435
    def test_1__version__with_version_info(self):
397
436
        self.setup_plugin("version_info = (1,)")
398
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
437
        plugin = breezy.plugin.plugins()['plugin']
399
438
        self.assertEqual("1", plugin.__version__)
400
439
 
401
440
    def test_1_2__version__with_version_info(self):
402
441
        self.setup_plugin("version_info = (1, 2)")
403
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
442
        plugin = breezy.plugin.plugins()['plugin']
404
443
        self.assertEqual("1.2", plugin.__version__)
405
444
 
406
445
    def test_1_2_3__version__with_version_info(self):
407
446
        self.setup_plugin("version_info = (1, 2, 3)")
408
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
447
        plugin = breezy.plugin.plugins()['plugin']
409
448
        self.assertEqual("1.2.3", plugin.__version__)
410
449
 
411
450
    def test_candidate__version__with_version_info(self):
412
451
        self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
413
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
452
        plugin = breezy.plugin.plugins()['plugin']
414
453
        self.assertEqual("1.2.3rc1", plugin.__version__)
415
454
 
416
455
    def test_dev__version__with_version_info(self):
417
456
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
418
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
457
        plugin = breezy.plugin.plugins()['plugin']
419
458
        self.assertEqual("1.2.3dev", plugin.__version__)
420
459
 
421
460
    def test_dev_fallback__version__with_version_info(self):
422
461
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
423
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
462
        plugin = breezy.plugin.plugins()['plugin']
424
463
        self.assertEqual("1.2.3dev4", plugin.__version__)
425
464
 
426
465
    def test_final__version__with_version_info(self):
427
466
        self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
428
 
        plugin = bzrlib.plugin.plugins()['plugin']
 
467
        plugin = breezy.plugin.plugins()['plugin']
429
468
        self.assertEqual("1.2.3", plugin.__version__)
430
469
 
431
470
    def test_final_fallback__version__with_version_info(self):
432
471
        self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
433
 
        plugin = bzrlib.plugin.plugins()['plugin']
434
 
        self.assertEqual("1.2.3.final.2", plugin.__version__)
435
 
 
436
 
 
437
 
class TestPluginHelp(tests.TestCaseInTempDir):
 
472
        plugin = breezy.plugin.plugins()['plugin']
 
473
        self.assertEqual("1.2.3.2", plugin.__version__)
 
474
 
 
475
 
 
476
# GZ 2017-06-02: Move this suite to blackbox, as it's what it actually is.
 
477
class TestPluginHelp(BaseTestPlugins):
438
478
 
439
479
    def split_help_commands(self):
440
480
        help = {}
450
490
    def test_plugin_help_builtins_unaffected(self):
451
491
        # Check we don't get false positives
452
492
        help_commands = self.split_help_commands()
453
 
        for cmd_name in bzrlib.commands.builtin_command_names():
454
 
            if cmd_name in bzrlib.commands.plugin_command_names():
 
493
        for cmd_name in breezy.commands.builtin_command_names():
 
494
            if cmd_name in breezy.commands.plugin_command_names():
455
495
                continue
456
496
            try:
457
 
                help = bzrlib.commands.get_cmd_object(cmd_name).get_help_text()
 
497
                help = breezy.commands.get_cmd_object(cmd_name).get_help_text()
458
498
            except NotImplementedError:
459
499
                # some commands have no help
460
500
                pass
461
501
            else:
462
502
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
463
503
 
464
 
            if cmd_name in help_commands.keys():
 
504
            if cmd_name in help_commands:
465
505
                # some commands are hidden
466
506
                help = help_commands[cmd_name]
467
507
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
469
509
    def test_plugin_help_shows_plugin(self):
470
510
        # Create a test plugin
471
511
        os.mkdir('plugin_test')
472
 
        f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
473
 
        f.write("""\
474
 
from bzrlib import commands
475
 
class cmd_myplug(commands.Command):
476
 
    __doc__ = '''Just a simple test plugin.'''
477
 
    aliases = ['mplg']
478
 
    def run(self):
479
 
        print 'Hello from my plugin'
480
 
 
481
 
"""
482
 
)
483
 
        f.close()
484
 
 
485
 
        try:
486
 
            # Check its help
487
 
            bzrlib.plugin.load_from_path(['plugin_test'])
488
 
            bzrlib.commands.register_command( bzrlib.plugins.myplug.cmd_myplug)
489
 
            help = self.run_bzr('help myplug')[0]
490
 
            self.assertContainsRe(help, 'plugin "myplug"')
491
 
            help = self.split_help_commands()['myplug']
492
 
            self.assertContainsRe(help, '\[myplug\]')
493
 
        finally:
494
 
            # unregister command
495
 
            if 'myplug' in bzrlib.commands.plugin_cmds:
496
 
                bzrlib.commands.plugin_cmds.remove('myplug')
497
 
            # remove the plugin 'myplug'
498
 
            if getattr(bzrlib.plugins, 'myplug', None):
499
 
                delattr(bzrlib.plugins, 'myplug')
 
512
        source = (
 
513
            "from breezy import commands\n"
 
514
            "class cmd_myplug(commands.Command):\n"
 
515
            "    __doc__ = '''Just a simple test plugin.'''\n"
 
516
            "    aliases = ['mplg']\n"
 
517
            "    def run(self):\n"
 
518
            "        print ('Hello from my plugin')\n"
 
519
        )
 
520
        self.create_plugin('myplug', source, 'plugin_test')
 
521
 
 
522
        # Check its help
 
523
        self.load_with_paths(['plugin_test'])
 
524
        myplug = self.plugins['myplug'].module
 
525
        breezy.commands.register_command(myplug.cmd_myplug)
 
526
        self.addCleanup(breezy.commands.plugin_cmds.remove, 'myplug')
 
527
        help = self.run_bzr('help myplug')[0]
 
528
        self.assertContainsRe(help, 'plugin "myplug"')
 
529
        help = self.split_help_commands()['myplug']
 
530
        self.assertContainsRe(help, '\[myplug\]')
500
531
 
501
532
 
502
533
class TestHelpIndex(tests.TestCase):
515
546
        index = plugin.PluginsHelpIndex()
516
547
        # make a new plugin here for this test, even if we're run with
517
548
        # --no-plugins
518
 
        self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
519
 
        demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
520
 
        sys.modules['bzrlib.plugins.demo_module'] = demo_module
 
549
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
 
550
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
 
551
        sys.modules['breezy.plugins.demo_module'] = demo_module
521
552
        try:
522
553
            topics = index.get_topics('demo_module')
523
554
            self.assertEqual(1, len(topics))
524
555
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
525
556
            self.assertEqual(demo_module, topics[0].module)
526
557
        finally:
527
 
            del sys.modules['bzrlib.plugins.demo_module']
 
558
            del sys.modules['breezy.plugins.demo_module']
528
559
 
529
560
    def test_get_topics_no_topic(self):
530
561
        """Searching for something that is not a plugin returns []."""
541
572
    def test_get_plugin_topic_with_prefix(self):
542
573
        """Searching for plugins/demo_module returns help."""
543
574
        index = plugin.PluginsHelpIndex()
544
 
        self.assertFalse(sys.modules.has_key('bzrlib.plugins.demo_module'))
545
 
        demo_module = FakeModule('', 'bzrlib.plugins.demo_module')
546
 
        sys.modules['bzrlib.plugins.demo_module'] = demo_module
 
575
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
 
576
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
 
577
        sys.modules['breezy.plugins.demo_module'] = demo_module
547
578
        try:
548
579
            topics = index.get_topics('plugins/demo_module')
549
580
            self.assertEqual(1, len(topics))
550
581
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
551
582
            self.assertEqual(demo_module, topics[0].module)
552
583
        finally:
553
 
            del sys.modules['bzrlib.plugins.demo_module']
 
584
            del sys.modules['breezy.plugins.demo_module']
554
585
 
555
586
 
556
587
class FakeModule(object):
594
625
    def test_get_help_text_with_additional_see_also(self):
595
626
        mod = FakeModule('two lines of help\nand more', 'demo')
596
627
        topic = plugin.ModuleHelpTopic(mod)
597
 
        self.assertEqual("two lines of help\nand more\nSee also: bar, foo\n",
598
 
            topic.get_help_text(['foo', 'bar']))
 
628
        self.assertEqual("two lines of help\nand more\n\n:See also: bar, foo\n",
 
629
                         topic.get_help_text(['foo', 'bar']))
599
630
 
600
631
    def test_get_help_topic(self):
601
632
        """The help topic for a plugin is its module name."""
602
 
        mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.demo')
 
633
        mod = FakeModule('two lines of help\nand more', 'breezy.plugins.demo')
603
634
        topic = plugin.ModuleHelpTopic(mod)
604
635
        self.assertEqual('demo', topic.get_help_topic())
605
 
        mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
 
636
        mod = FakeModule('two lines of help\nand more',
 
637
                         'breezy.plugins.foo_bar')
606
638
        topic = plugin.ModuleHelpTopic(mod)
607
639
        self.assertEqual('foo_bar', topic.get_help_topic())
608
640
 
609
641
 
610
 
class TestLoadFromPath(tests.TestCaseInTempDir):
611
 
 
612
 
    def setUp(self):
613
 
        super(TestLoadFromPath, self).setUp()
614
 
        # Change bzrlib.plugin to think no plugins have been loaded yet.
615
 
        self.overrideAttr(bzrlib.plugins, '__path__', [])
616
 
        self.overrideAttr(plugin, '_loaded', False)
617
 
 
618
 
        # Monkey-patch load_from_path to stop it from actually loading anything.
619
 
        self.overrideAttr(plugin, 'load_from_path', lambda dirs: None)
620
 
 
621
 
    def test_set_plugins_path_with_args(self):
622
 
        plugin.set_plugins_path(['a', 'b'])
623
 
        self.assertEqual(['a', 'b'], bzrlib.plugins.__path__)
624
 
 
625
 
    def test_set_plugins_path_defaults(self):
626
 
        plugin.set_plugins_path()
627
 
        self.assertEqual(plugin.get_standard_plugins_path(),
628
 
                         bzrlib.plugins.__path__)
629
 
 
630
 
    def test_get_standard_plugins_path(self):
631
 
        path = plugin.get_standard_plugins_path()
632
 
        for directory in path:
633
 
            self.assertNotContainsRe(directory, r'\\/$')
634
 
        try:
635
 
            from distutils.sysconfig import get_python_lib
636
 
        except ImportError:
637
 
            pass
638
 
        else:
639
 
            if sys.platform != 'win32':
640
 
                python_lib = get_python_lib()
641
 
                for directory in path:
642
 
                    if directory.startswith(python_lib):
643
 
                        break
644
 
                else:
645
 
                    self.fail('No path to global plugins')
646
 
 
647
 
    def test_get_standard_plugins_path_env(self):
648
 
        os.environ['BZR_PLUGIN_PATH'] = 'foo/'
649
 
        path = plugin.get_standard_plugins_path()
650
 
        for directory in path:
651
 
            self.assertNotContainsRe(directory, r'\\/$')
652
 
 
653
 
    def test_load_plugins(self):
654
 
        plugin.load_plugins(['.'])
655
 
        self.assertEqual(bzrlib.plugins.__path__, ['.'])
656
 
        # subsequent loads are no-ops
657
 
        plugin.load_plugins(['foo'])
658
 
        self.assertEqual(bzrlib.plugins.__path__, ['.'])
659
 
 
660
 
    def test_load_plugins_default(self):
661
 
        plugin.load_plugins()
662
 
        path = plugin.get_standard_plugins_path()
663
 
        self.assertEqual(path, bzrlib.plugins.__path__)
664
 
 
665
 
 
666
642
class TestEnvPluginPath(tests.TestCase):
667
643
 
668
 
    def setUp(self):
669
 
        super(TestEnvPluginPath, self).setUp()
670
 
        self.overrideAttr(plugin, 'DEFAULT_PLUGIN_PATH', None)
671
 
 
672
 
        self.user = plugin.get_user_plugin_path()
673
 
        self.site = plugin.get_site_plugin_path()
674
 
        self.core = plugin.get_core_plugin_path()
675
 
 
676
 
    def _list2paths(self, *args):
677
 
        paths = []
678
 
        for p in args:
679
 
            plugin._append_new_path(paths, p)
680
 
        return paths
681
 
 
682
 
    def _set_path(self, *args):
683
 
        path = os.pathsep.join(self._list2paths(*args))
684
 
        osutils.set_or_unset_env('BZR_PLUGIN_PATH', path)
 
644
    user = "USER"
 
645
    core = "CORE"
 
646
    site = "SITE"
685
647
 
686
648
    def check_path(self, expected_dirs, setting_dirs):
687
 
        if setting_dirs:
688
 
            self._set_path(*setting_dirs)
689
 
        actual = plugin.get_standard_plugins_path()
690
 
        self.assertEquals(self._list2paths(*expected_dirs), actual)
 
649
        if setting_dirs is None:
 
650
            del os.environ['BRZ_PLUGIN_PATH']
 
651
        else:
 
652
            os.environ['BRZ_PLUGIN_PATH'] = os.pathsep.join(setting_dirs)
 
653
        actual = [(p if t == 'path' else t.upper())
 
654
            for p, t in plugin._env_plugin_path()]
 
655
        self.assertEqual(expected_dirs, actual)
691
656
 
692
657
    def test_default(self):
693
658
        self.check_path([self.user, self.core, self.site],
757
722
                        ['+foo', '-bar'])
758
723
 
759
724
 
760
 
class TestDisablePlugin(tests.TestCaseInTempDir, TestPluginMixin):
761
 
 
762
 
    def setUp(self):
763
 
        super(TestDisablePlugin, self).setUp()
764
 
        self.create_plugin_package('test_foo')
765
 
        # Make sure we don't pollute the plugins namespace
766
 
        self.overrideAttr(plugins, '__path__')
767
 
        # Be paranoid in case a test fail
768
 
        self.addCleanup(self._unregister_plugin, 'test_foo')
 
725
class TestDisablePlugin(BaseTestPlugins):
769
726
 
770
727
    def test_cannot_import(self):
771
 
        osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
772
 
        plugin.set_plugins_path(['.'])
 
728
        self.create_plugin_package('works')
 
729
        self.create_plugin_package('fails')
 
730
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'fails')
 
731
        self.update_module_paths(["."])
 
732
        import breezy.testingplugins.works as works
773
733
        try:
774
 
            import bzrlib.plugins.test_foo
 
734
            import breezy.testingplugins.fails as fails
775
735
        except ImportError:
776
736
            pass
777
 
        self.assertPluginUnknown('test_foo')
778
 
 
779
 
    def test_regular_load(self):
780
 
        self.overrideAttr(plugin, '_loaded', False)
781
 
        plugin.load_plugins(['.'])
782
 
        self.assertPluginKnown('test_foo')
783
 
        self.assertDocstring("This is the doc for test_foo",
784
 
                             bzrlib.plugins.test_foo)
785
 
 
786
 
    def test_not_loaded(self):
787
 
        self.warnings = []
788
 
        def captured_warning(*args, **kwargs):
789
 
            self.warnings.append((args, kwargs))
790
 
        self.overrideAttr(trace, 'warning', captured_warning)
791
 
        # Reset the flag that protect against double loading
792
 
        self.overrideAttr(plugin, '_loaded', False)
793
 
        osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
794
 
        plugin.load_plugins(['.'])
795
 
        self.assertPluginUnknown('test_foo')
796
 
        # Make sure we don't warn about the plugin ImportError since this has
797
 
        # been *requested* by the user.
798
 
        self.assertLength(0, self.warnings)
799
 
 
800
 
 
801
 
class TestLoadPluginAt(tests.TestCaseInTempDir, TestPluginMixin):
 
737
        else:
 
738
            self.fail("Loaded blocked plugin: " + repr(fails))
 
739
        self.assertPluginModules({'fails': None, 'works': works})
 
740
 
 
741
    def test_partial_imports(self):
 
742
        self.create_plugin('good')
 
743
        self.create_plugin('bad')
 
744
        self.create_plugin_package('ugly')
 
745
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'bad:ugly')
 
746
        self.load_with_paths(['.'])
 
747
        self.assertEqual({'good'}, viewkeys(self.plugins))
 
748
        self.assertPluginModules({
 
749
            'good': self.plugins['good'].module,
 
750
            'bad': None,
 
751
            'ugly': None,
 
752
        })
 
753
        # Ensure there are no warnings about plugins not being imported as
 
754
        # the user has explictly requested they be disabled.
 
755
        self.assertNotContainsRe(self.get_log(), r"Unable to load plugin")
 
756
 
 
757
 
 
758
class TestEnvDisablePlugins(tests.TestCase):
 
759
 
 
760
    def _get_names(self, env_value):
 
761
        os.environ['BRZ_DISABLE_PLUGINS'] = env_value
 
762
        return plugin._env_disable_plugins()
 
763
 
 
764
    def test_unset(self):
 
765
        self.assertEqual([], plugin._env_disable_plugins())
 
766
 
 
767
    def test_empty(self):
 
768
        self.assertEqual([], self._get_names(''))
 
769
 
 
770
    def test_single(self):
 
771
        self.assertEqual(['single'], self._get_names('single'))
 
772
 
 
773
    def test_multi(self):
 
774
        expected = ['one', 'two']
 
775
        self.assertEqual(expected, self._get_names(os.pathsep.join(expected)))
 
776
 
 
777
    def test_mixed(self):
 
778
        value = os.pathsep.join(['valid', 'in-valid'])
 
779
        self.assertEqual(['valid'], self._get_names(value))
 
780
        self.assertContainsRe(self.get_log(),
 
781
            r"Invalid name 'in-valid' in BRZ_DISABLE_PLUGINS=" + repr(value))
 
782
 
 
783
 
 
784
class TestEnvPluginsAt(tests.TestCase):
 
785
 
 
786
    def _get_paths(self, env_value):
 
787
        os.environ['BRZ_PLUGINS_AT'] = env_value
 
788
        return plugin._env_plugins_at()
 
789
 
 
790
    def test_empty(self):
 
791
        self.assertEqual([], plugin._env_plugins_at())
 
792
        self.assertEqual([], self._get_paths(''))
 
793
 
 
794
    def test_one_path(self):
 
795
        self.assertEqual([('b', 'man')], self._get_paths('b@man'))
 
796
 
 
797
    def test_multiple(self):
 
798
        self.assertEqual(
 
799
            [('tools', 'bzr-tools'), ('p', 'play.py')],
 
800
            self._get_paths(os.pathsep.join(('tools@bzr-tools', 'p@play.py'))))
 
801
 
 
802
    def test_many_at(self):
 
803
        self.assertEqual(
 
804
            [('church', 'StMichael@Plea@Norwich')],
 
805
            self._get_paths('church@StMichael@Plea@Norwich'))
 
806
 
 
807
    def test_only_py(self):
 
808
        self.assertEqual([('test', './test.py')], self._get_paths('./test.py'))
 
809
 
 
810
    def test_only_package(self):
 
811
        self.assertEqual([('py', '/opt/b/py')], self._get_paths('/opt/b/py'))
 
812
 
 
813
    def test_bad_name(self):
 
814
        self.assertEqual([], self._get_paths('/usr/local/bzr-git'))
 
815
        self.assertContainsRe(self.get_log(),
 
816
            r"Invalid name 'bzr-git' in BRZ_PLUGINS_AT='/usr/local/bzr-git'")
 
817
 
 
818
 
 
819
class TestLoadPluginAt(BaseTestPlugins):
802
820
 
803
821
    def setUp(self):
804
822
        super(TestLoadPluginAt, self).setUp()
805
 
        # Make sure we don't pollute the plugins namespace
806
 
        self.overrideAttr(plugins, '__path__')
807
 
        # Be paranoid in case a test fail
808
 
        self.addCleanup(self._unregister_plugin, 'test_foo')
809
 
        # Reset the flag that protect against double loading
810
 
        self.overrideAttr(plugin, '_loaded', False)
811
823
        # Create the same plugin in two directories
812
824
        self.create_plugin_package('test_foo', dir='non-standard-dir')
813
825
        # The "normal" directory, we use 'standard' instead of 'plugins' to
817
829
    def assertTestFooLoadedFrom(self, path):
818
830
        self.assertPluginKnown('test_foo')
819
831
        self.assertDocstring('This is the doc for test_foo',
820
 
                             bzrlib.plugins.test_foo)
821
 
        self.assertEqual(path, bzrlib.plugins.test_foo.dir_source)
 
832
                             self.module.test_foo)
 
833
        self.assertEqual(path, self.module.test_foo.dir_source)
822
834
 
823
835
    def test_regular_load(self):
824
 
        plugin.load_plugins(['standard'])
 
836
        self.load_with_paths(['standard'])
825
837
        self.assertTestFooLoadedFrom('standard/test_foo')
826
838
 
827
839
    def test_import(self):
828
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
829
 
        plugin.set_plugins_path(['standard'])
830
 
        try:
831
 
            import bzrlib.plugins.test_foo
832
 
        except ImportError:
833
 
            pass
 
840
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
841
        self.update_module_paths(['standard'])
 
842
        import breezy.testingplugins.test_foo
834
843
        self.assertTestFooLoadedFrom('non-standard-dir')
835
844
 
836
845
    def test_loading(self):
837
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
838
 
        plugin.load_plugins(['standard'])
 
846
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
847
        self.load_with_paths(['standard'])
 
848
        self.assertTestFooLoadedFrom('non-standard-dir')
 
849
 
 
850
    def test_loading_other_name(self):
 
851
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
852
        os.rename('standard/test_foo', 'standard/test_bar')
 
853
        self.load_with_paths(['standard'])
839
854
        self.assertTestFooLoadedFrom('non-standard-dir')
840
855
 
841
856
    def test_compiled_loaded(self):
842
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
843
 
        plugin.load_plugins(['standard'])
 
857
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
858
        self.load_with_paths(['standard'])
844
859
        self.assertTestFooLoadedFrom('non-standard-dir')
845
 
        self.assertEqual('non-standard-dir/__init__.py',
846
 
                         bzrlib.plugins.test_foo.__file__)
 
860
        self.assertIsSameRealPath('non-standard-dir/__init__.py',
 
861
                                  self.module.test_foo.__file__)
847
862
 
848
863
        # Try importing again now that the source has been compiled
849
 
        self._unregister_plugin('test_foo')
850
 
        plugin._loaded = False
851
 
        plugin.load_plugins(['standard'])
 
864
        os.remove('non-standard-dir/__init__.py')
 
865
        self.promote_cache('non-standard-dir')
 
866
        self.reset()
 
867
        self.load_with_paths(['standard'])
852
868
        self.assertTestFooLoadedFrom('non-standard-dir')
853
 
        if __debug__:
854
 
            suffix = 'pyc'
855
 
        else:
856
 
            suffix = 'pyo'
857
 
        self.assertEqual('non-standard-dir/__init__.%s' % suffix,
858
 
                         bzrlib.plugins.test_foo.__file__)
 
869
        suffix = plugin.COMPILED_EXT
 
870
        self.assertIsSameRealPath('non-standard-dir/__init__' + suffix,
 
871
                                  self.module.test_foo.__file__)
859
872
 
860
873
    def test_submodule_loading(self):
861
874
        # We create an additional directory under the one for test_foo
862
875
        self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
863
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
864
 
        plugin.set_plugins_path(['standard'])
865
 
        import bzrlib.plugins.test_foo
866
 
        self.assertEqual('bzrlib.plugins.test_foo',
867
 
                         bzrlib.plugins.test_foo.__package__)
868
 
        import bzrlib.plugins.test_foo.test_bar
869
 
        self.assertEqual('non-standard-dir/test_bar/__init__.py',
870
 
                         bzrlib.plugins.test_foo.test_bar.__file__)
 
876
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
877
        self.update_module_paths(['standard'])
 
878
        import breezy.testingplugins.test_foo
 
879
        self.assertEqual(self.module_prefix + 'test_foo',
 
880
                         self.module.test_foo.__package__)
 
881
        import breezy.testingplugins.test_foo.test_bar
 
882
        self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
 
883
                                  self.module.test_foo.test_bar.__file__)
 
884
 
 
885
    def test_relative_submodule_loading(self):
 
886
        self.create_plugin_package('test_foo', dir='another-dir', source='''
 
887
from . import test_bar
 
888
''')
 
889
        # We create an additional directory under the one for test_foo
 
890
        self.create_plugin_package('test_bar', dir='another-dir/test_bar')
 
891
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@another-dir')
 
892
        self.update_module_paths(['standard'])
 
893
        import breezy.testingplugins.test_foo
 
894
        self.assertEqual(self.module_prefix + 'test_foo',
 
895
                         self.module.test_foo.__package__)
 
896
        self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
 
897
                                  self.module.test_foo.test_bar.__file__)
871
898
 
872
899
    def test_loading_from___init__only(self):
873
900
        # We rename the existing __init__.py file to ensure that we don't load
875
902
        init = 'non-standard-dir/__init__.py'
876
903
        random = 'non-standard-dir/setup.py'
877
904
        os.rename(init, random)
878
 
        self.addCleanup(os.rename, random, init)
879
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
880
 
        plugin.load_plugins(['standard'])
 
905
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
 
906
        self.load_with_paths(['standard'])
881
907
        self.assertPluginUnknown('test_foo')
882
908
 
883
909
    def test_loading_from_specific_file(self):
890
916
''' % ('test_foo', plugin_path)
891
917
        self.create_plugin('test_foo', source=source,
892
918
                           dir=plugin_dir, file_name=plugin_file_name)
893
 
        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo@%s' % plugin_path)
894
 
        plugin.load_plugins(['standard'])
 
919
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@%s' % plugin_path)
 
920
        self.load_with_paths(['standard'])
895
921
        self.assertTestFooLoadedFrom(plugin_path)
 
922
 
 
923
 
 
924
class TestDescribePlugins(BaseTestPlugins):
 
925
 
 
926
    def test_describe_plugins(self):
 
927
        class DummyModule(object):
 
928
            __doc__ = 'Hi there'
 
929
        class DummyPlugin(object):
 
930
            __version__ = '0.1.0'
 
931
            module = DummyModule()
 
932
        self.plugin_warnings = {'bad': ['Failed to load (just testing)']}
 
933
        self.plugins = {'good': DummyPlugin()}
 
934
        self.assertEqual("""\
 
935
bad (failed to load)
 
936
  ** Failed to load (just testing)
 
937
 
 
938
good 0.1.0
 
939
  Hi there
 
940
 
 
941
""", ''.join(plugin.describe_plugins(state=self)))