~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_plugins.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-10-20 05:12:09 UTC
  • mfrom: (4744.2.9 2.1-peak-mem-tweak)
  • Revision ID: pqm@pqm.ubuntu.com-20091020051209-telne1xq2bq6cp7m
(jam) In GCCHKStreamSource clear caches after we fetch from a VF

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2007 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
24
23
import logging
25
24
import os
 
25
from StringIO import StringIO
26
26
import sys
 
27
import zipfile
27
28
 
28
 
import bzrlib
29
29
from bzrlib import (
30
 
    errors,
31
30
    osutils,
32
31
    plugin,
33
 
    plugins,
34
32
    tests,
35
 
    trace,
36
 
    )
37
 
 
 
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
"""
38
54
 
39
55
# TODO: Write a test for plugin decoration of commands.
40
56
 
41
 
class BaseTestPlugins(tests.TestCaseInTempDir):
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.assertFalse(getattr(bzrlib.plugins, name, None) is not None)
95
 
        self.assertFalse('bzrlib.plugins.%s' % name in sys.modules)
96
 
 
97
 
    def assertPluginKnown(self, name):
98
 
        self.assertTrue(getattr(bzrlib.plugins, name, None) is not None)
99
 
        self.assertTrue('bzrlib.plugins.%s' % name in sys.modules)
100
 
 
101
 
 
102
 
class TestLoadingPlugins(BaseTestPlugins):
 
57
class TestLoadingPlugins(TestCaseInTempDir):
103
58
 
104
59
    activeattributes = {}
105
60
 
109
64
        # file name we can use which is also a valid attribute for accessing in
110
65
        # activeattributes. - we cannot give import parameters.
111
66
        tempattribute = "0"
112
 
        self.assertFalse(tempattribute in self.activeattributes)
 
67
        self.failIf(tempattribute in self.activeattributes)
113
68
        # set a place for the plugins to record their loading, and at the same
114
69
        # time validate that the location the plugins should record to is
115
70
        # valid and correct.
116
 
        self.__class__.activeattributes [tempattribute] = []
117
 
        self.assertTrue(tempattribute in self.activeattributes)
 
71
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
 
72
            [tempattribute] = []
 
73
        self.failUnless(tempattribute in self.activeattributes)
118
74
        # create two plugin directories
119
75
        os.mkdir('first')
120
76
        os.mkdir('second')
143
99
        finally:
144
100
            # remove the plugin 'plugin'
145
101
            del self.activeattributes[tempattribute]
146
 
            self._unregister_plugin('plugin')
147
 
        self.assertPluginUnknown('plugin')
 
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))
148
107
 
149
108
    def test_plugins_from_different_dirs_can_demand_load(self):
150
 
        self.assertFalse('bzrlib.plugins.pluginone' in sys.modules)
151
 
        self.assertFalse('bzrlib.plugins.plugintwo' in sys.modules)
152
109
        # This test tests that having two plugins in different
153
110
        # directories with different names allows them both to be loaded, when
154
111
        # we do a direct import statement.
155
112
        # Determine a file name we can use which is also a valid attribute
156
113
        # for accessing in activeattributes. - we cannot give import parameters.
157
114
        tempattribute = "different-dirs"
158
 
        self.assertFalse(tempattribute in self.activeattributes)
 
115
        self.failIf(tempattribute in self.activeattributes)
159
116
        # set a place for the plugins to record their loading, and at the same
160
117
        # time validate that the location the plugins should record to is
161
118
        # valid and correct.
162
119
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
163
120
            [tempattribute] = []
164
 
        self.assertTrue(tempattribute in self.activeattributes)
 
121
        self.failUnless(tempattribute in self.activeattributes)
165
122
        # create two plugin directories
166
123
        os.mkdir('first')
167
124
        os.mkdir('second')
186
143
 
187
144
        oldpath = bzrlib.plugins.__path__
188
145
        try:
189
 
            self.assertFalse('bzrlib.plugins.pluginone' in sys.modules)
190
 
            self.assertFalse('bzrlib.plugins.plugintwo' in sys.modules)
191
146
            bzrlib.plugins.__path__ = ['first', 'second']
192
147
            exec "import bzrlib.plugins.pluginone"
193
148
            self.assertEqual(['first'], self.activeattributes[tempattribute])
197
152
        finally:
198
153
            # remove the plugin 'plugin'
199
154
            del self.activeattributes[tempattribute]
200
 
            self._unregister_plugin('pluginone')
201
 
            self._unregister_plugin('plugintwo')
202
 
        self.assertPluginUnknown('pluginone')
203
 
        self.assertPluginUnknown('plugintwo')
 
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))
204
161
 
205
162
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
206
163
        # This test tests that a plugin can load from a directory when the
207
164
        # directory in the path has a trailing slash.
208
165
        # check the plugin is not loaded already
209
 
        self.assertPluginUnknown('ts_plugin')
 
166
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
210
167
        tempattribute = "trailing-slash"
211
 
        self.assertFalse(tempattribute in self.activeattributes)
 
168
        self.failIf(tempattribute in self.activeattributes)
212
169
        # set a place for the plugin to record its loading, and at the same
213
170
        # time validate that the location the plugin should record to is
214
171
        # valid and correct.
215
172
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
216
173
            [tempattribute] = []
217
 
        self.assertTrue(tempattribute in self.activeattributes)
 
174
        self.failUnless(tempattribute in self.activeattributes)
218
175
        # create a directory for the plugin
219
176
        os.mkdir('plugin_test')
220
177
        # write a plugin that will record when its loaded in the
233
190
            bzrlib.plugin.load_from_path(['plugin_test'+os.sep])
234
191
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
235
192
        finally:
 
193
            # remove the plugin 'plugin'
236
194
            del self.activeattributes[tempattribute]
237
 
            self._unregister_plugin('ts_plugin')
238
 
        self.assertPluginUnknown('ts_plugin')
 
195
            if getattr(bzrlib.plugins, 'ts_plugin', None):
 
196
                del bzrlib.plugins.ts_plugin
 
197
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
239
198
 
240
199
    def load_and_capture(self, name):
241
200
        """Load plugins from '.' capturing the output.
267
226
            stream.close()
268
227
 
269
228
    def test_plugin_with_bad_api_version_reports(self):
270
 
        """Try loading a plugin that requests an unsupported api.
271
 
        
272
 
        Observe that it records the problem but doesn't complain on stderr.
273
 
 
274
 
        See https://bugs.launchpad.net/bzr/+bug/704195
275
 
        """
276
 
        self.overrideAttr(plugin, 'plugin_warnings', {})
 
229
        # This plugin asks for bzrlib api version 1.0.0, which is not supported
 
230
        # anymore.
277
231
        name = 'wants100.py'
278
232
        f = file(name, 'w')
279
233
        try:
281
235
                "bzrlib.api.require_any_api(bzrlib, [(1, 0, 0)])\n")
282
236
        finally:
283
237
            f.close()
 
238
 
284
239
        log = self.load_and_capture(name)
285
 
        self.assertNotContainsRe(log,
286
 
            r"It requested API version")
287
 
        self.assertEquals(
288
 
            ['wants100'],
289
 
            plugin.plugin_warnings.keys())
290
 
        self.assertContainsRe(
291
 
            plugin.plugin_warnings['wants100'][0],
 
240
        self.assertContainsRe(log,
292
241
            r"It requested API version")
293
242
 
294
243
    def test_plugin_with_bad_name_does_not_load(self):
302
251
            "it to 'bad_plugin_name_'\.")
303
252
 
304
253
 
305
 
class TestPlugins(BaseTestPlugins):
 
254
class TestPlugins(TestCaseInTempDir):
306
255
 
307
256
    def setup_plugin(self, source=""):
308
257
        # This test tests a new plugin appears in bzrlib.plugin.plugins().
309
258
        # check the plugin is not loaded already
310
 
        self.assertPluginUnknown('plugin')
 
259
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
311
260
        # write a plugin that _cannot_ fail to load.
312
 
        with file('plugin.py', 'w') as f: f.write(source + '\n')
 
261
        file('plugin.py', 'w').write(source + '\n')
313
262
        self.addCleanup(self.teardown_plugin)
314
 
        plugin.load_from_path(['.'])
 
263
        bzrlib.plugin.load_from_path(['.'])
315
264
 
316
265
    def teardown_plugin(self):
317
 
        self._unregister_plugin('plugin')
318
 
        self.assertPluginUnknown('plugin')
 
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))
319
272
 
320
273
    def test_plugin_appears_in_plugins(self):
321
274
        self.setup_plugin()
322
 
        self.assertPluginKnown('plugin')
323
 
        p = plugin.plugins()['plugin']
324
 
        self.assertIsInstance(p, bzrlib.plugin.PlugIn)
325
 
        self.assertEqual(p.module, plugins.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)
326
281
 
327
282
    def test_trivial_plugin_get_path(self):
328
283
        self.setup_plugin()
329
 
        p = plugin.plugins()['plugin']
 
284
        plugins = bzrlib.plugin.plugins()
 
285
        plugin = plugins['plugin']
330
286
        plugin_path = self.test_dir + '/plugin.py'
331
 
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
 
287
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
332
288
 
333
289
    def test_plugin_get_path_py_not_pyc(self):
334
 
        # first import creates plugin.pyc
335
 
        self.setup_plugin()
 
290
        self.setup_plugin()         # after first import there will be plugin.pyc
336
291
        self.teardown_plugin()
337
 
        plugin.load_from_path(['.']) # import plugin.pyc
338
 
        p = plugin.plugins()['plugin']
 
292
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
 
293
        plugins = bzrlib.plugin.plugins()
 
294
        plugin = plugins['plugin']
339
295
        plugin_path = self.test_dir + '/plugin.py'
340
 
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
 
296
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
341
297
 
342
298
    def test_plugin_get_path_pyc_only(self):
343
 
        # first import creates plugin.pyc (or plugin.pyo depending on __debug__)
344
 
        self.setup_plugin()
 
299
        self.setup_plugin()         # after first import there will be plugin.pyc
345
300
        self.teardown_plugin()
346
301
        os.unlink(self.test_dir + '/plugin.py')
347
 
        plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
348
 
        p = plugin.plugins()['plugin']
 
302
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
 
303
        plugins = bzrlib.plugin.plugins()
 
304
        plugin = plugins['plugin']
349
305
        if __debug__:
350
306
            plugin_path = self.test_dir + '/plugin.pyc'
351
307
        else:
352
308
            plugin_path = self.test_dir + '/plugin.pyo'
353
 
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
 
309
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
354
310
 
355
311
    def test_no_test_suite_gives_None_for_test_suite(self):
356
312
        self.setup_plugin()
357
 
        p = plugin.plugins()['plugin']
358
 
        self.assertEqual(None, p.test_suite())
 
313
        plugin = bzrlib.plugin.plugins()['plugin']
 
314
        self.assertEqual(None, plugin.test_suite())
359
315
 
360
316
    def test_test_suite_gives_test_suite_result(self):
361
317
        source = """def test_suite(): return 'foo'"""
362
318
        self.setup_plugin(source)
363
 
        p = plugin.plugins()['plugin']
364
 
        self.assertEqual('foo', p.test_suite())
 
319
        plugin = bzrlib.plugin.plugins()['plugin']
 
320
        self.assertEqual('foo', plugin.test_suite())
365
321
 
366
322
    def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
367
323
        self.setup_plugin()
368
 
        loader = tests.TestUtil.TestLoader()
369
 
        p = plugin.plugins()['plugin']
370
 
        self.assertEqual(None, p.load_plugin_tests(loader))
 
324
        loader = TestUtil.TestLoader()
 
325
        plugin = bzrlib.plugin.plugins()['plugin']
 
326
        self.assertEqual(None, plugin.load_plugin_tests(loader))
371
327
 
372
328
    def test_load_plugin_tests_gives_load_plugin_tests_result(self):
373
329
        source = """
374
330
def load_tests(standard_tests, module, loader):
375
331
    return 'foo'"""
376
332
        self.setup_plugin(source)
377
 
        loader = tests.TestUtil.TestLoader()
378
 
        p = plugin.plugins()['plugin']
379
 
        self.assertEqual('foo', p.load_plugin_tests(loader))
380
 
 
381
 
    def check_version_info(self, expected, source='', name='plugin'):
382
 
        self.setup_plugin(source)
383
 
        self.assertEqual(expected, plugin.plugins()[name].version_info())
 
333
        loader = TestUtil.TestLoader()
 
334
        plugin = bzrlib.plugin.plugins()['plugin']
 
335
        self.assertEqual('foo', plugin.load_plugin_tests(loader))
384
336
 
385
337
    def test_no_version_info(self):
386
 
        self.check_version_info(None)
 
338
        self.setup_plugin()
 
339
        plugin = bzrlib.plugin.plugins()['plugin']
 
340
        self.assertEqual(None, plugin.version_info())
387
341
 
388
342
    def test_with_version_info(self):
389
 
        self.check_version_info((1, 2, 3, 'dev', 4),
390
 
                                "version_info = (1, 2, 3, 'dev', 4)")
 
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())
391
346
 
392
347
    def test_short_version_info_gets_padded(self):
393
348
        # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
394
349
        # so we adapt it
395
 
        self.check_version_info((1, 2, 3, 'final', 0),
396
 
                                "version_info = (1, 2, 3)")
397
 
 
398
 
    def check_version(self, expected, source=None, name='plugin'):
399
 
        self.setup_plugin(source)
400
 
        self.assertEqual(expected, plugins[name].__version__)
 
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())
401
353
 
402
354
    def test_no_version_info___version__(self):
403
355
        self.setup_plugin()
452
404
    def test_final_fallback__version__with_version_info(self):
453
405
        self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
454
406
        plugin = bzrlib.plugin.plugins()['plugin']
455
 
        self.assertEqual("1.2.3.2", plugin.__version__)
456
 
 
457
 
 
458
 
class TestPluginHelp(tests.TestCaseInTempDir):
 
407
        self.assertEqual("1.2.3.final.2", plugin.__version__)
 
408
 
 
409
 
 
410
class TestPluginHelp(TestCaseInTempDir):
459
411
 
460
412
    def split_help_commands(self):
461
413
        help = {}
490
442
    def test_plugin_help_shows_plugin(self):
491
443
        # Create a test plugin
492
444
        os.mkdir('plugin_test')
493
 
        f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
494
 
        f.write("""\
495
 
from bzrlib import commands
496
 
class cmd_myplug(commands.Command):
497
 
    __doc__ = '''Just a simple test plugin.'''
498
 
    aliases = ['mplg']
499
 
    def run(self):
500
 
        print 'Hello from my plugin'
501
 
 
502
 
"""
503
 
)
 
445
        f = open(pathjoin('plugin_test', 'myplug.py'), 'w')
 
446
        f.write(PLUGIN_TEXT)
504
447
        f.close()
505
448
 
506
449
        try:
615
558
    def test_get_help_text_with_additional_see_also(self):
616
559
        mod = FakeModule('two lines of help\nand more', 'demo')
617
560
        topic = plugin.ModuleHelpTopic(mod)
618
 
        self.assertEqual("two lines of help\nand more\n\n:See also: bar, foo\n",
619
 
                         topic.get_help_text(['foo', 'bar']))
 
561
        self.assertEqual("two lines of help\nand more\nSee also: bar, foo\n",
 
562
            topic.get_help_text(['foo', 'bar']))
620
563
 
621
564
    def test_get_help_topic(self):
622
565
        """The help topic for a plugin is its module name."""
623
566
        mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.demo')
624
567
        topic = plugin.ModuleHelpTopic(mod)
625
568
        self.assertEqual('demo', topic.get_help_topic())
626
 
        mod = FakeModule('two lines of help\nand more',
627
 
                         'bzrlib.plugins.foo_bar')
 
569
        mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
628
570
        topic = plugin.ModuleHelpTopic(mod)
629
571
        self.assertEqual('foo_bar', topic.get_help_topic())
630
572
 
633
575
 
634
576
    def setUp(self):
635
577
        super(TestLoadFromPath, self).setUp()
 
578
        # Save the attributes that we're about to monkey-patch.
 
579
        old_plugins_path = bzrlib.plugins.__path__
 
580
        old_loaded = plugin._loaded
 
581
        old_load_from_path = plugin.load_from_path
 
582
 
 
583
        def restore():
 
584
            bzrlib.plugins.__path__ = old_plugins_path
 
585
            plugin._loaded = old_loaded
 
586
            plugin.load_from_path = old_load_from_path
 
587
 
 
588
        self.addCleanup(restore)
 
589
 
636
590
        # Change bzrlib.plugin to think no plugins have been loaded yet.
637
 
        self.overrideAttr(bzrlib.plugins, '__path__', [])
638
 
        self.overrideAttr(plugin, '_loaded', False)
 
591
        bzrlib.plugins.__path__ = []
 
592
        plugin._loaded = False
639
593
 
640
594
        # Monkey-patch load_from_path to stop it from actually loading anything.
641
 
        self.overrideAttr(plugin, 'load_from_path', lambda dirs: None)
 
595
        def load_from_path(dirs):
 
596
            pass
 
597
        plugin.load_from_path = load_from_path
642
598
 
643
599
    def test_set_plugins_path_with_args(self):
644
600
        plugin.set_plugins_path(['a', 'b'])
667
623
                    self.fail('No path to global plugins')
668
624
 
669
625
    def test_get_standard_plugins_path_env(self):
670
 
        self.overrideEnv('BZR_PLUGIN_PATH', 'foo/')
 
626
        os.environ['BZR_PLUGIN_PATH'] = 'foo/'
671
627
        path = plugin.get_standard_plugins_path()
672
628
        for directory in path:
673
629
            self.assertNotContainsRe(directory, r'\\/$')
685
641
        self.assertEqual(path, bzrlib.plugins.__path__)
686
642
 
687
643
 
688
 
class TestEnvPluginPath(tests.TestCase):
 
644
class TestEnvPluginPath(tests.TestCaseInTempDir):
689
645
 
690
646
    def setUp(self):
691
647
        super(TestEnvPluginPath, self).setUp()
692
 
        self.overrideAttr(plugin, 'DEFAULT_PLUGIN_PATH', None)
 
648
        old_default = plugin.DEFAULT_PLUGIN_PATH
 
649
 
 
650
        def restore():
 
651
            plugin.DEFAULT_PLUGIN_PATH = old_default
 
652
 
 
653
        self.addCleanup(restore)
 
654
 
 
655
        plugin.DEFAULT_PLUGIN_PATH = None
693
656
 
694
657
        self.user = plugin.get_user_plugin_path()
695
658
        self.site = plugin.get_site_plugin_path()
703
666
 
704
667
    def _set_path(self, *args):
705
668
        path = os.pathsep.join(self._list2paths(*args))
706
 
        self.overrideEnv('BZR_PLUGIN_PATH', path)
 
669
        osutils.set_or_unset_env('BZR_PLUGIN_PATH', path)
707
670
 
708
671
    def check_path(self, expected_dirs, setting_dirs):
709
672
        if setting_dirs:
738
701
        self.check_path([self.user, self.core, self.site],
739
702
                        ['+user', '+user'])
740
703
        # And only the first reference is kept (since the later references will
741
 
        # only produce '<plugin> already loaded' mutters)
 
704
        # onnly produce <plugin> already loaded mutters)
742
705
        self.check_path([self.user, self.core, self.site],
743
706
                        ['+user', '+user', '+core',
744
707
                         '+user', '+site', '+site',
745
708
                         '+core'])
746
709
 
747
 
    def test_disable_overrides_enable(self):
 
710
    def test_disable_overrides_disable(self):
748
711
        self.check_path([self.core, self.site], ['-user', '+user'])
749
712
 
750
713
    def test_disable_core(self):
777
740
    def test_bogus_references(self):
778
741
        self.check_path(['+foo', '-bar', self.core, self.site],
779
742
                        ['+foo', '-bar'])
780
 
 
781
 
 
782
 
class TestDisablePlugin(BaseTestPlugins):
783
 
 
784
 
    def setUp(self):
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')
791
 
 
792
 
    def test_cannot_import(self):
793
 
        self.overrideEnv('BZR_DISABLE_PLUGINS', 'test_foo')
794
 
        plugin.set_plugins_path(['.'])
795
 
        try:
796
 
            import bzrlib.plugins.test_foo
797
 
        except ImportError:
798
 
            pass
799
 
        self.assertPluginUnknown('test_foo')
800
 
 
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
 
                             bzrlib.plugins.test_foo)
807
 
 
808
 
    def test_not_loaded(self):
809
 
        self.warnings = []
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)
821
 
 
822
 
 
823
 
 
824
 
class TestLoadPluginAtSyntax(tests.TestCase):
825
 
 
826
 
    def _get_paths(self, paths):
827
 
        return plugin._get_specific_plugin_paths(paths)
828
 
 
829
 
    def test_empty(self):
830
 
        self.assertEquals([], self._get_paths(None))
831
 
        self.assertEquals([], self._get_paths(''))
832
 
 
833
 
    def test_one_path(self):
834
 
        self.assertEquals([('b', 'man')], self._get_paths('b@man'))
835
 
 
836
 
    def test_bogus_path(self):
837
 
        # We need a '@'
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']))
845
 
 
846
 
 
847
 
class TestLoadPluginAt(BaseTestPlugins):
848
 
 
849
 
    def setUp(self):
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)
855
 
        # Create the same plugin in two directories
856
 
        self.create_plugin_package('test_foo', dir='non-standard-dir')
857
 
        # The "normal" directory, we use 'standard' instead of 'plugins' to
858
 
        # avoid depending on the precise naming.
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
863
 
        # registered paths.
864
 
        self.addCleanup(plugin.PluginImporter.reset)
865
 
 
866
 
    def assertTestFooLoadedFrom(self, path):
867
 
        self.assertPluginKnown('test_foo')
868
 
        self.assertDocstring('This is the doc for test_foo',
869
 
                             bzrlib.plugins.test_foo)
870
 
        self.assertEqual(path, bzrlib.plugins.test_foo.dir_source)
871
 
 
872
 
    def test_regular_load(self):
873
 
        plugin.load_plugins(['standard'])
874
 
        self.assertTestFooLoadedFrom('standard/test_foo')
875
 
 
876
 
    def test_import(self):
877
 
        self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
878
 
        plugin.set_plugins_path(['standard'])
879
 
        try:
880
 
            import bzrlib.plugins.test_foo
881
 
        except ImportError:
882
 
            pass
883
 
        self.assertTestFooLoadedFrom('non-standard-dir')
884
 
 
885
 
    def test_loading(self):
886
 
        self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
887
 
        plugin.load_plugins(['standard'])
888
 
        self.assertTestFooLoadedFrom('non-standard-dir')
889
 
 
890
 
    def test_compiled_loaded(self):
891
 
        self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
892
 
        plugin.load_plugins(['standard'])
893
 
        self.assertTestFooLoadedFrom('non-standard-dir')
894
 
        self.assertIsSameRealPath('non-standard-dir/__init__.py',
895
 
                                  bzrlib.plugins.test_foo.__file__)
896
 
 
897
 
        # Try importing again now that the source has been compiled
898
 
        self._unregister_plugin('test_foo')
899
 
        plugin._loaded = False
900
 
        plugin.load_plugins(['standard'])
901
 
        self.assertTestFooLoadedFrom('non-standard-dir')
902
 
        if __debug__:
903
 
            suffix = 'pyc'
904
 
        else:
905
 
            suffix = 'pyo'
906
 
        self.assertIsSameRealPath('non-standard-dir/__init__.%s' % suffix,
907
 
                                  bzrlib.plugins.test_foo.__file__)
908
 
 
909
 
    def test_submodule_loading(self):
910
 
        # We create an additional directory under the one for test_foo
911
 
        self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
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 bzrlib.plugins.test_foo
917
 
        self.assertEqual('bzrlib.plugins.test_foo',
918
 
                         bzrlib.plugins.test_foo.__package__)
919
 
        import bzrlib.plugins.test_foo.test_bar
920
 
        self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
921
 
                                  bzrlib.plugins.test_foo.test_bar.__file__)
922
 
 
923
 
    def test_relative_submodule_loading(self):
924
 
        self.create_plugin_package('test_foo', dir='another-dir', source='''
925
 
import test_bar
926
 
''')
927
 
        # We create an additional directory under the one for test_foo
928
 
        self.create_plugin_package('test_bar', dir='another-dir/test_bar')
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 bzrlib.plugins.test_foo
934
 
        self.assertEqual('bzrlib.plugins.test_foo',
935
 
                         bzrlib.plugins.test_foo.__package__)
936
 
        self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
937
 
                                  bzrlib.plugins.test_foo.test_bar.__file__)
938
 
 
939
 
    def test_loading_from___init__only(self):
940
 
        # We rename the existing __init__.py file to ensure that we don't load
941
 
        # a random file
942
 
        init = 'non-standard-dir/__init__.py'
943
 
        random = 'non-standard-dir/setup.py'
944
 
        os.rename(init, random)
945
 
        self.addCleanup(os.rename, random, init)
946
 
        self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@non-standard-dir')
947
 
        plugin.load_plugins(['standard'])
948
 
        self.assertPluginUnknown('test_foo')
949
 
 
950
 
    def test_loading_from_specific_file(self):
951
 
        plugin_dir = 'non-standard-dir'
952
 
        plugin_file_name = 'iamtestfoo.py'
953
 
        plugin_path = osutils.pathjoin(plugin_dir, plugin_file_name)
954
 
        source = '''\
955
 
"""This is the doc for %s"""
956
 
dir_source = '%s'
957
 
''' % ('test_foo', plugin_path)
958
 
        self.create_plugin('test_foo', source=source,
959
 
                           dir=plugin_dir, file_name=plugin_file_name)
960
 
        self.overrideEnv('BZR_PLUGINS_AT', 'test_foo@%s' % plugin_path)
961
 
        plugin.load_plugins(['standard'])
962
 
        self.assertTestFooLoadedFrom(plugin_path)
963
 
 
964
 
 
965
 
class TestDescribePlugins(BaseTestPlugins):
966
 
 
967
 
    def test_describe_plugins(self):
968
 
        class DummyModule(object):
969
 
            __doc__ = 'Hi there'
970
 
        class DummyPlugin(object):
971
 
            __version__ = '0.1.0'
972
 
            module = DummyModule()
973
 
        def dummy_plugins():
974
 
            return { 'good': DummyPlugin() }
975
 
        self.overrideAttr(plugin, 'plugin_warnings',
976
 
            {'bad': ['Failed to load (just testing)']})
977
 
        self.overrideAttr(plugin, 'plugins', dummy_plugins)
978
 
        self.assertEquals("""\
979
 
bad (failed to load)
980
 
  ** Failed to load (just testing)
981
 
 
982
 
good 0.1.0
983
 
  Hi there
984
 
 
985
 
""", ''.join(plugin.describe_plugins()))