~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugin.py

  • Committer: Patch Queue Manager
  • Date: 2011-09-22 14:12:18 UTC
  • mfrom: (6155.3.1 jam)
  • Revision ID: pqm@pqm.ubuntu.com-20110922141218-86s4uu6nqvourw4f
(jameinel) Cleanup comments bzrlib/smart/__init__.py (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 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
36
36
from bzrlib import osutils
37
37
 
38
38
from bzrlib.lazy_import import lazy_import
39
 
 
40
39
lazy_import(globals(), """
41
40
import imp
42
41
import re
49
48
    errors,
50
49
    trace,
51
50
    )
 
51
from bzrlib.i18n import gettext
52
52
from bzrlib import plugins as _mod_plugins
53
53
""")
54
54
 
55
 
from bzrlib.symbol_versioning import (
56
 
    deprecated_function,
57
 
    deprecated_in,
58
 
    )
59
 
 
60
55
 
61
56
DEFAULT_PLUGIN_PATH = None
62
57
_loaded = False
63
58
_plugins_disabled = False
64
59
 
65
60
 
 
61
plugin_warnings = {}
 
62
# Map from plugin name, to list of string warnings about eg plugin
 
63
# dependencies.
 
64
 
 
65
 
66
66
def are_plugins_disabled():
67
67
    return _plugins_disabled
68
68
 
77
77
    load_plugins([])
78
78
 
79
79
 
 
80
def describe_plugins(show_paths=False):
 
81
    """Generate text description of plugins.
 
82
 
 
83
    Includes both those that have loaded, and those that failed to 
 
84
    load.
 
85
 
 
86
    :param show_paths: If true,
 
87
    :returns: Iterator of text lines (including newlines.)
 
88
    """
 
89
    from inspect import getdoc
 
90
    loaded_plugins = plugins()
 
91
    all_names = sorted(list(set(
 
92
        loaded_plugins.keys() + plugin_warnings.keys())))
 
93
    for name in all_names:
 
94
        if name in loaded_plugins:
 
95
            plugin = loaded_plugins[name]
 
96
            version = plugin.__version__
 
97
            if version == 'unknown':
 
98
                version = ''
 
99
            yield '%s %s\n' % (name, version)
 
100
            d = getdoc(plugin.module)
 
101
            if d:
 
102
                doc = d.split('\n')[0]
 
103
            else:
 
104
                doc = '(no description)'
 
105
            yield ("  %s\n" % doc)
 
106
            if show_paths:
 
107
                yield ("   %s\n" % plugin.path())
 
108
            del plugin
 
109
        else:
 
110
            yield "%s (failed to load)\n" % name
 
111
        if name in plugin_warnings:
 
112
            for line in plugin_warnings[name]:
 
113
                yield "  ** " + line + '\n'
 
114
        yield '\n'
 
115
 
 
116
 
80
117
def _strip_trailing_sep(path):
81
118
    return path.rstrip("\\/")
82
119
 
101
138
        try:
102
139
            name, path = spec.split('@')
103
140
        except ValueError:
104
 
            raise errors.BzrCommandError(
105
 
                '"%s" is not a valid <plugin_name>@<plugin_path> description '
 
141
            raise errors.BzrCommandError(gettext(
 
142
                '"%s" is not a valid <plugin_name>@<plugin_path> description ')
106
143
                % spec)
107
144
        specs.append((name, path))
108
145
    return specs
236
273
    """Load bzrlib plugins.
237
274
 
238
275
    The environment variable BZR_PLUGIN_PATH is considered a delimited
239
 
    set of paths to look through. Each entry is searched for *.py
 
276
    set of paths to look through. Each entry is searched for `*.py`
240
277
    files (and whatever other extensions are used in the platform,
241
 
    such as *.pyd).
 
278
    such as `*.pyd`).
242
279
 
243
280
    load_from_path() provides the underlying mechanism and is called with
244
281
    the default directory list to provide the normal behaviour.
327
364
    return None, None, (None, None, None)
328
365
 
329
366
 
 
367
def record_plugin_warning(plugin_name, warning_message):
 
368
    trace.mutter(warning_message)
 
369
    plugin_warnings.setdefault(plugin_name, []).append(warning_message)
 
370
 
 
371
 
330
372
def _load_plugin_module(name, dir):
331
373
    """Load plugin name from dir.
332
374
 
340
382
    except KeyboardInterrupt:
341
383
        raise
342
384
    except errors.IncompatibleAPI, e:
343
 
        trace.warning("Unable to load plugin %r. It requested API version "
 
385
        warning_message = (
 
386
            "Unable to load plugin %r. It requested API version "
344
387
            "%s of module %s but the minimum exported version is %s, and "
345
388
            "the maximum is %s" %
346
389
            (name, e.wanted, e.api, e.minimum, e.current))
 
390
        record_plugin_warning(name, warning_message)
347
391
    except Exception, e:
348
392
        trace.warning("%s" % e)
349
393
        if re.search('\.|-| ', name):
354
398
                    "file path isn't a valid module name; try renaming "
355
399
                    "it to %r." % (name, dir, sanitised_name))
356
400
        else:
357
 
            trace.warning('Unable to load plugin %r from %r' % (name, dir))
 
401
            record_plugin_warning(
 
402
                name,
 
403
                'Unable to load plugin %r from %r' % (name, dir))
358
404
        trace.log_exception_quietly()
359
405
        if 'error' in debug.debug_flags:
360
406
            trace.print_exception(sys.exc_info(), sys.stderr)
400
446
    return result
401
447
 
402
448
 
 
449
def format_concise_plugin_list():
 
450
    """Return a string holding a concise list of plugins and their version.
 
451
    """
 
452
    items = []
 
453
    for name, a_plugin in sorted(plugins().items()):
 
454
        items.append("%s[%s]" %
 
455
            (name, a_plugin.__version__))
 
456
    return ', '.join(items)
 
457
 
 
458
 
 
459
 
403
460
class PluginsHelpIndex(object):
404
461
    """A help index that returns help topics for plugins."""
405
462
 
450
507
            result = self.module.__doc__
451
508
        if result[-1] != '\n':
452
509
            result += '\n'
453
 
        # there is code duplicated here and in bzrlib/help_topic.py's
454
 
        # matching Topic code. This should probably be factored in
455
 
        # to a helper function and a common base class.
456
 
        if additional_see_also is not None:
457
 
            see_also = sorted(set(additional_see_also))
458
 
        else:
459
 
            see_also = None
460
 
        if see_also:
461
 
            result += 'See also: '
462
 
            result += ', '.join(see_also)
463
 
            result += '\n'
 
510
        from bzrlib import help_topics
 
511
        result += help_topics._format_see_also(additional_see_also)
464
512
        return result
465
513
 
466
514
    def get_help_topic(self):
467
 
        """Return the modules help topic - its __name__ after bzrlib.plugins.."""
 
515
        """Return the module help topic: its basename."""
468
516
        return self.module.__name__[len('bzrlib.plugins.'):]
469
517
 
470
518