~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugin.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
When load_plugins() is invoked, any python module in any directory in
21
21
$BZR_PLUGIN_PATH will be imported.  The module will be imported as
22
22
'bzrlib.plugins.$BASENAME(PLUGIN)'.  In the plugin's main body, it should
23
 
update any bzrlib registries it wants to extend; for example, to add new
24
 
commands, import bzrlib.commands and add your new command to the plugin_cmds
25
 
variable.
 
23
update any bzrlib registries it wants to extend.
 
24
 
 
25
See the plugin-api developer documentation for information about writing
 
26
plugins.
26
27
 
27
28
BZR_PLUGIN_PATH is also honoured for any plugins imported via
28
29
'import bzrlib.plugins.PLUGINNAME', as long as set_plugins_path has been 
41
42
 
42
43
from bzrlib import (
43
44
    config,
 
45
    debug,
44
46
    osutils,
 
47
    trace,
45
48
    )
46
49
from bzrlib import plugins as _mod_plugins
47
50
""")
48
51
 
49
 
from bzrlib.symbol_versioning import deprecated_function, zero_ninetyone
 
52
from bzrlib.symbol_versioning import deprecated_function, one_three
50
53
from bzrlib.trace import mutter, warning, log_exception_quietly
51
54
 
52
55
 
61
64
    return DEFAULT_PLUGIN_PATH
62
65
 
63
66
 
64
 
@deprecated_function(zero_ninetyone)
65
 
def all_plugins():
66
 
    """Return a dictionary of the plugins."""
67
 
    return dict((name, plugin.module) for name, plugin in plugins().items())
68
 
 
69
 
 
70
67
def disable_plugins():
71
68
    """Disable loading plugins.
72
69
 
77
74
    global _loaded
78
75
    _loaded = True
79
76
 
 
77
 
80
78
def _strip_trailing_sep(path):
81
79
    return path.rstrip("\\/")
82
80
 
 
81
 
83
82
def set_plugins_path():
84
83
    """Set the path for plugins to be loaded from."""
85
84
    path = os.environ.get('BZR_PLUGIN_PATH',
86
85
                          get_default_plugin_path()).split(os.pathsep)
 
86
    bzr_exe = bool(getattr(sys, 'frozen', None))
 
87
    if bzr_exe:    # expand path for bzr.exe
 
88
        # We need to use relative path to system-wide plugin
 
89
        # directory because bzrlib from standalone bzr.exe
 
90
        # could be imported by another standalone program
 
91
        # (e.g. bzr-config; or TortoiseBzr/Olive if/when they
 
92
        # will become standalone exe). [bialix 20071123]
 
93
        # __file__ typically is
 
94
        # C:\Program Files\Bazaar\lib\library.zip\bzrlib\plugin.pyc
 
95
        # then plugins directory is
 
96
        # C:\Program Files\Bazaar\plugins
 
97
        # so relative path is ../../../plugins
 
98
        path.append(osutils.abspath(osutils.pathjoin(
 
99
            osutils.dirname(__file__), '../../../plugins')))
87
100
    # Get rid of trailing slashes, since Python can't handle them when
88
101
    # it tries to import modules.
89
102
    path = map(_strip_trailing_sep, path)
90
 
    # search the plugin path before the bzrlib installed dir
91
 
    path.append(os.path.dirname(_mod_plugins.__file__))
 
103
    if not bzr_exe:     # don't look inside library.zip
 
104
        # search the plugin path before the bzrlib installed dir
 
105
        path.append(os.path.dirname(_mod_plugins.__file__))
 
106
    # search the arch independent path if we can determine that and
 
107
    # the plugin is found nowhere else
 
108
    if sys.platform != 'win32':
 
109
        try:
 
110
            from distutils.sysconfig import get_python_lib
 
111
        except ImportError:
 
112
            # If distutuils is not available, we just won't add that path
 
113
            pass
 
114
        else:
 
115
            archless_path = osutils.pathjoin(get_python_lib(), 'bzrlib',
 
116
                    'plugins')
 
117
            if archless_path not in path:
 
118
                path.append(archless_path)
92
119
    _mod_plugins.__path__ = path
93
120
    return path
94
121
 
138
165
        mutter('looking for plugins in %s', d)
139
166
        if os.path.isdir(d):
140
167
            load_from_dir(d)
141
 
        else:
142
 
            # it might be a zip: try loading from the zip.
143
 
            load_from_zip(d)
144
 
            continue
145
168
 
146
169
 
147
170
# backwards compatability: load_from_dirs was the old name
191
214
        except Exception, e:
192
215
            ## import pdb; pdb.set_trace()
193
216
            if re.search('\.|-| ', name):
194
 
                warning('Unable to load plugin %r from %r: '
195
 
                    'It is not a valid python module name.' % (name, d))
 
217
                sanitised_name = re.sub('[-. ]', '_', name)
 
218
                if sanitised_name.startswith('bzr_'):
 
219
                    sanitised_name = sanitised_name[len('bzr_'):]
 
220
                warning("Unable to load %r in %r as a plugin because the "
 
221
                        "file path isn't a valid module name; try renaming "
 
222
                        "it to %r." % (name, d, sanitised_name))
196
223
            else:
197
224
                warning('Unable to load plugin %r from %r' % (name, d))
198
225
            log_exception_quietly()
199
 
 
200
 
 
 
226
            if 'error' in debug.debug_flags:
 
227
                trace.print_exception(sys.exc_info(), sys.stderr)
 
228
 
 
229
 
 
230
@deprecated_function(one_three)
201
231
def load_from_zip(zip_name):
202
232
    """Load all the plugins in a zip."""
203
233
    valid_suffixes = ('.py', '.pyc', '.pyo')    # only python modules/packages
204
234
                                                # is allowed
205
 
 
206
235
    try:
207
236
        index = zip_name.rindex('.zip')
208
237
    except ValueError:
275
304
            warning('Unable to load plugin %r from %r'
276
305
                    % (name, zip_name))
277
306
            log_exception_quietly()
 
307
            if 'error' in debug.debug_flags:
 
308
                trace.print_exception(sys.exc_info(), sys.stderr)
278
309
 
279
310
 
280
311
def plugins():
373
404
        if getattr(self.module, '__path__', None) is not None:
374
405
            return os.path.abspath(self.module.__path__[0])
375
406
        elif getattr(self.module, '__file__', None) is not None:
376
 
            return os.path.abspath(self.module.__file__)
 
407
            path = os.path.abspath(self.module.__file__)
 
408
            if path[-4:] in ('.pyc', '.pyo'):
 
409
                pypath = path[:-4] + '.py'
 
410
                if os.path.isfile(pypath):
 
411
                    path = pypath
 
412
            return path
377
413
        else:
378
414
            return repr(self.module)
379
415
 
391
427
        else:
392
428
            return None
393
429
 
 
430
    def load_plugin_tests(self, loader):
 
431
        """Return the adapted plugin's test suite.
 
432
 
 
433
        :param loader: The custom loader that should be used to load additional
 
434
            tests.
 
435
 
 
436
        """
 
437
        if getattr(self.module, 'load_tests', None) is not None:
 
438
            return loader.loadTestsFromModule(self.module)
 
439
        else:
 
440
            return None
 
441
 
394
442
    def version_info(self):
395
443
        """Return the plugin's version_tuple or None if unknown."""
396
444
        version_info = getattr(self.module, 'version_info', None)
397
445
        if version_info is not None and len(version_info) == 3:
398
446
            version_info = tuple(version_info) + ('final', 0)
399
447
        return version_info
400
 
    
 
448
 
401
449
    def _get__version__(self):
402
450
        version_info = self.version_info()
403
451
        if version_info is None: