/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 bzrlib/plugin.py

  • Committer: Robert Collins
  • Date: 2009-03-13 02:25:46 UTC
  • mfrom: (4133 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4183.
  • Revision ID: robertc@robertcollins.net-20090313022546-e7de5zsdkbay5okf
MergeĀ .dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2007, 2008 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
26
26
plugins.
27
27
 
28
28
BZR_PLUGIN_PATH is also honoured for any plugins imported via
29
 
'import bzrlib.plugins.PLUGINNAME', as long as set_plugins_path has been 
 
29
'import bzrlib.plugins.PLUGINNAME', as long as set_plugins_path has been
30
30
called.
31
31
"""
32
32
 
33
33
import os
34
34
import sys
35
35
 
 
36
from bzrlib import osutils
 
37
 
36
38
from bzrlib.lazy_import import lazy_import
 
39
 
37
40
lazy_import(globals(), """
38
41
import imp
39
42
import re
41
44
import zipfile
42
45
 
43
46
from bzrlib import (
 
47
    _format_version_tuple,
44
48
    config,
45
49
    debug,
46
50
    errors,
47
 
    osutils,
48
51
    trace,
49
52
    )
50
53
from bzrlib import plugins as _mod_plugins
69
72
 
70
73
    Future calls to load_plugins() will be ignored.
71
74
    """
72
 
    # TODO: jam 20060131 This should probably also disable
73
 
    #       load_from_dirs()
74
 
    global _loaded
75
 
    _loaded = True
 
75
    load_plugins([])
76
76
 
77
77
 
78
78
def _strip_trailing_sep(path):
79
79
    return path.rstrip("\\/")
80
80
 
81
81
 
82
 
def set_plugins_path():
83
 
    """Set the path for plugins to be loaded from."""
 
82
def set_plugins_path(path=None):
 
83
    """Set the path for plugins to be loaded from.
 
84
 
 
85
    :param path: The list of paths to search for plugins.  By default,
 
86
        path will be determined using get_standard_plugins_path.
 
87
        if path is [], no plugins can be loaded.
 
88
    """
 
89
    if path is None:
 
90
        path = get_standard_plugins_path()
 
91
    _mod_plugins.__path__ = path
 
92
    return path
 
93
 
 
94
 
 
95
def get_standard_plugins_path():
 
96
    """Determine a plugin path suitable for general use."""
84
97
    path = os.environ.get('BZR_PLUGIN_PATH',
85
98
                          get_default_plugin_path()).split(os.pathsep)
 
99
    # Get rid of trailing slashes, since Python can't handle them when
 
100
    # it tries to import modules.
 
101
    path = map(_strip_trailing_sep, path)
86
102
    bzr_exe = bool(getattr(sys, 'frozen', None))
87
103
    if bzr_exe:    # expand path for bzr.exe
88
104
        # We need to use relative path to system-wide plugin
97
113
        # so relative path is ../../../plugins
98
114
        path.append(osutils.abspath(osutils.pathjoin(
99
115
            osutils.dirname(__file__), '../../../plugins')))
100
 
    # Get rid of trailing slashes, since Python can't handle them when
101
 
    # it tries to import modules.
102
 
    path = map(_strip_trailing_sep, path)
103
116
    if not bzr_exe:     # don't look inside library.zip
104
117
        # search the plugin path before the bzrlib installed dir
105
118
        path.append(os.path.dirname(_mod_plugins.__file__))
116
129
                    'plugins')
117
130
            if archless_path not in path:
118
131
                path.append(archless_path)
119
 
    _mod_plugins.__path__ = path
120
132
    return path
121
133
 
122
134
 
123
 
def load_plugins():
 
135
def load_plugins(path=None):
124
136
    """Load bzrlib plugins.
125
137
 
126
138
    The environment variable BZR_PLUGIN_PATH is considered a delimited
130
142
 
131
143
    load_from_dirs() provides the underlying mechanism and is called with
132
144
    the default directory list to provide the normal behaviour.
 
145
 
 
146
    :param path: The list of paths to search for plugins.  By default,
 
147
        path will be determined using get_standard_plugins_path.
 
148
        if path is [], no plugins can be loaded.
133
149
    """
134
150
    global _loaded
135
151
    if _loaded:
138
154
    _loaded = True
139
155
 
140
156
    # scan for all plugins in the path.
141
 
    load_from_path(set_plugins_path())
 
157
    load_from_path(set_plugins_path(path))
142
158
 
143
159
 
144
160
def load_from_path(dirs):
174
190
 
175
191
def load_from_dir(d):
176
192
    """Load the plugins in directory d.
177
 
    
 
193
 
178
194
    d must be in the plugins module path already.
179
195
    """
180
196
    # Get the list of valid python suffixes for __init__.py?
203
219
                    break
204
220
            else:
205
221
                continue
206
 
        if getattr(_mod_plugins, f, None):
 
222
        if f == '__init__':
 
223
            continue # We don't load __init__.py again in the plugin dir
 
224
        elif getattr(_mod_plugins, f, None):
207
225
            trace.mutter('Plugin name %s already loaded', f)
208
226
        else:
209
227
            # trace.mutter('add plugin name %s', f)
210
228
            plugin_names.add(f)
211
 
    
 
229
 
212
230
    for name in plugin_names:
213
231
        try:
214
232
            exec "import bzrlib.plugins.%s" % name in {}
269
287
                    if name.startswith(prefix)]
270
288
 
271
289
    trace.mutter('Names in archive: %r', namelist)
272
 
    
 
290
 
273
291
    for name in namelist:
274
292
        if not name or name.endswith('/'):
275
293
            continue
276
 
    
 
294
 
277
295
        # '/' is used to separate pathname components inside zip archives
278
296
        ix = name.rfind('/')
279
297
        if ix == -1:
283
301
        if '/' in head:
284
302
            # we don't need looking in subdirectories
285
303
            continue
286
 
    
 
304
 
287
305
        base, suffix = osutils.splitext(tail)
288
306
        if suffix not in valid_suffixes:
289
307
            continue
290
 
    
 
308
 
291
309
        if base == '__init__':
292
310
            # package
293
311
            plugin_name = head
296
314
            plugin_name = base
297
315
        else:
298
316
            continue
299
 
    
 
317
 
300
318
        if not plugin_name:
301
319
            continue
302
320
        if getattr(_mod_plugins, plugin_name, None):
303
321
            trace.mutter('Plugin name %s already loaded', plugin_name)
304
322
            continue
305
 
    
 
323
 
306
324
        try:
307
325
            exec "import bzrlib.plugins.%s" % plugin_name in {}
308
326
            trace.mutter('Load plugin %s from zip %r', plugin_name, zip_name)
319
337
 
320
338
def plugins():
321
339
    """Return a dictionary of the plugins.
322
 
    
 
340
 
323
341
    Each item in the dictionary is a PlugIn object.
324
342
    """
325
343
    result = {}
379
397
            result = self.module.__doc__
380
398
        if result[-1] != '\n':
381
399
            result += '\n'
382
 
        # there is code duplicated here and in bzrlib/help_topic.py's 
 
400
        # there is code duplicated here and in bzrlib/help_topic.py's
383
401
        # matching Topic code. This should probably be factored in
384
402
        # to a helper function and a common base class.
385
403
        if additional_see_also is not None:
451
469
    def version_info(self):
452
470
        """Return the plugin's version_tuple or None if unknown."""
453
471
        version_info = getattr(self.module, 'version_info', None)
454
 
        if version_info is not None and len(version_info) == 3:
455
 
            version_info = tuple(version_info) + ('final', 0)
 
472
        if version_info is not None:
 
473
            try:
 
474
                if isinstance(version_info, types.StringType):
 
475
                    version_info = version_info.split('.')
 
476
                elif len(version_info) == 3:
 
477
                    version_info = tuple(version_info) + ('final', 0)
 
478
            except TypeError, e:
 
479
                # The given version_info isn't even iteratible
 
480
                trace.log_exception_quietly()
 
481
                version_info = (version_info,)
456
482
        return version_info
457
483
 
458
484
    def _get__version__(self):
459
485
        version_info = self.version_info()
460
 
        if version_info is None:
 
486
        if version_info is None or len(version_info) == 0:
461
487
            return "unknown"
462
 
        if version_info[3] == 'final':
463
 
            version_string = '%d.%d.%d' % version_info[:3]
464
 
        else:
465
 
            version_string = '%d.%d.%d%s%d' % version_info
 
488
        try:
 
489
            version_string = _format_version_tuple(version_info)
 
490
        except (ValueError, TypeError, IndexError), e:
 
491
            trace.log_exception_quietly()
 
492
            # try to return something usefull for bad plugins, in stead of
 
493
            # stack tracing.
 
494
            version_string = '.'.join(map(str, version_info))
466
495
        return version_string
467
496
 
468
497
    __version__ = property(_get__version__)