~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugin.py

  • Committer: Marius Kruger
  • Date: 2010-07-09 22:45:25 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100709224525-a0bijmcw3dw02r8g
* make the backup file name generator in bzrdir available to others
* Whenever bzr is asked to delete stuff, back it up if the content is not in version control.
* Update whitebox tests (Did them first btw. Vila's voice keeps ringing in my head)
* deprecate the now unused BzrRemoveChangedFilesError

Show diffs side-by-side

added added

removed removed

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