/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/hooks.py

Return mapping in revision_id_bzr_to_foreign() as required by the interface.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
18
 
"""Support for plugin hooking logic."""
19
 
from bzrlib.lazy_import import lazy_import
20
 
from bzrlib.symbol_versioning import deprecated_method, one_five
21
 
lazy_import(globals(), """
22
 
import textwrap
23
 
 
24
 
from bzrlib import (
25
 
        _format_version_tuple,
26
 
        errors,
27
 
        )
28
 
""")
29
 
 
30
 
 
31
 
class Hooks(dict):
32
 
    """A dictionary mapping hook name to a list of callables.
33
 
 
34
 
    e.g. ['FOO'] Is the list of items to be called when the
35
 
    FOO hook is triggered.
36
 
    """
37
 
 
38
 
    def __init__(self):
39
 
        dict.__init__(self)
40
 
        self._callable_names = {}
41
 
 
42
 
    def create_hook(self, hook):
43
 
        """Create a hook which can have callbacks registered for it.
44
 
 
45
 
        :param hook: The hook to create. An object meeting the protocol of
46
 
            bzrlib.hooks.HookPoint. It's name is used as the key for future
47
 
            lookups.
48
 
        """
49
 
        if hook.name in self:
50
 
            raise errors.DuplicateKey(hook.name)
51
 
        self[hook.name] = hook
52
 
 
53
 
    def docs(self):
54
 
        """Generate the documentation for this Hooks instance.
55
 
 
56
 
        This introspects all the individual hooks and returns their docs as well.
57
 
        """
58
 
        hook_names = sorted(self.keys())
59
 
        hook_docs = []
60
 
        for hook_name in hook_names:
61
 
            hook = self[hook_name]
62
 
            try:
63
 
                hook_docs.append(hook.docs())
64
 
            except AttributeError:
65
 
                # legacy hook
66
 
                strings = []
67
 
                strings.append(hook_name)
68
 
                strings.append("-" * len(hook_name))
69
 
                strings.append("")
70
 
                strings.append("An old-style hook. For documentation see the __init__ "
71
 
                    "method of '%s'\n" % (self.__class__.__name__,))
72
 
                hook_docs.extend(strings)
73
 
        return "\n".join(hook_docs)
74
 
 
75
 
    def get_hook_name(self, a_callable):
76
 
        """Get the name for a_callable for UI display.
77
 
 
78
 
        If no name has been registered, the string 'No hook name' is returned.
79
 
        We use a fixed string rather than repr or the callables module because
80
 
        the code names are rarely meaningful for end users and this is not
81
 
        intended for debugging.
82
 
        """
83
 
        return self._callable_names.get(a_callable, "No hook name")
84
 
 
85
 
    @deprecated_method(one_five)
86
 
    def install_hook(self, hook_name, a_callable):
87
 
        """Install a_callable in to the hook hook_name.
88
 
 
89
 
        :param hook_name: A hook name. See the __init__ method of BranchHooks
90
 
            for the complete list of hooks.
91
 
        :param a_callable: The callable to be invoked when the hook triggers.
92
 
            The exact signature will depend on the hook - see the __init__
93
 
            method of BranchHooks for details on each hook.
94
 
        """
95
 
        self.install_named_hook(hook_name, a_callable, None)
96
 
 
97
 
    def install_named_hook(self, hook_name, a_callable, name):
98
 
        """Install a_callable in to the hook hook_name, and label it name.
99
 
 
100
 
        :param hook_name: A hook name. See the __init__ method of BranchHooks
101
 
            for the complete list of hooks.
102
 
        :param a_callable: The callable to be invoked when the hook triggers.
103
 
            The exact signature will depend on the hook - see the __init__
104
 
            method of BranchHooks for details on each hook.
105
 
        :param name: A name to associate a_callable with, to show users what is
106
 
            running.
107
 
        """
108
 
        try:
109
 
            hook = self[hook_name]
110
 
        except KeyError:
111
 
            raise errors.UnknownHook(self.__class__.__name__, hook_name)
112
 
        try:
113
 
            # list hooks, old-style, not yet deprecated but less useful.
114
 
            hook.append(a_callable)
115
 
        except AttributeError:
116
 
            hook.hook(a_callable, name)
117
 
        if name is not None:
118
 
            self.name_hook(a_callable, name)
119
 
 
120
 
    def name_hook(self, a_callable, name):
121
 
        """Associate name with a_callable to show users what is running."""
122
 
        self._callable_names[a_callable] = name
123
 
 
124
 
 
125
 
class HookPoint(object):
126
 
    """A single hook that clients can register to be called back when it fires.
127
 
 
128
 
    :ivar name: The name of the hook.
129
 
    :ivar introduced: A version tuple specifying what version the hook was
130
 
        introduced in. None indicates an unknown version.
131
 
    :ivar deprecated: A version tuple specifying what version the hook was
132
 
        deprecated or superceded in. None indicates that the hook is not
133
 
        superceded or deprecated. If the hook is superceded then the doc
134
 
        should describe the recommended replacement hook to register for.
135
 
    :ivar doc: The docs for using the hook.
136
 
    """
137
 
 
138
 
    def __init__(self, name, doc, introduced, deprecated):
139
 
        """Create a HookPoint.
140
 
 
141
 
        :param name: The name of the hook, for clients to use when registering.
142
 
        :param doc: The docs for the hook.
143
 
        :param introduced: When the hook was introduced (e.g. (0, 15)).
144
 
        :param deprecated: When the hook was deprecated, None for
145
 
            not-deprecated.
146
 
        """
147
 
        self.name = name
148
 
        self.__doc__ = doc
149
 
        self.introduced = introduced
150
 
        self.deprecated = deprecated
151
 
        self._callbacks = []
152
 
        self._callback_names = {}
153
 
 
154
 
    def docs(self):
155
 
        """Generate the documentation for this HookPoint.
156
 
 
157
 
        :return: A string terminated in \n.
158
 
        """
159
 
        strings = []
160
 
        strings.append(self.name)
161
 
        strings.append('-'*len(self.name))
162
 
        strings.append('')
163
 
        if self.introduced:
164
 
            introduced_string = _format_version_tuple(self.introduced)
165
 
        else:
166
 
            introduced_string = 'unknown'
167
 
        strings.append('Introduced in: %s' % introduced_string)
168
 
        if self.deprecated:
169
 
            deprecated_string = _format_version_tuple(self.deprecated)
170
 
        else:
171
 
            deprecated_string = 'Not deprecated'
172
 
        strings.append('Deprecated in: %s' % deprecated_string)
173
 
        strings.append('')
174
 
        strings.extend(textwrap.wrap(self.__doc__))
175
 
        strings.append('')
176
 
        return '\n'.join(strings)
177
 
 
178
 
    def hook(self, callback, callback_label):
179
 
        """Register a callback to be called when this HookPoint fires.
180
 
 
181
 
        :param callback: The callable to use when this HookPoint fires.
182
 
        :param callback_label: A label to show in the UI while this callback is
183
 
            processing.
184
 
        """
185
 
        self._callbacks.append(callback)
186
 
        self._callback_names[callback] = callback_label
187
 
 
188
 
    def __iter__(self):
189
 
        return iter(self._callbacks)
190
 
 
191
 
    def __repr__(self):
192
 
        strings = []
193
 
        strings.append("<%s(" % type(self).__name__)
194
 
        strings.append(self.name)
195
 
        strings.append("), callbacks=[")
196
 
        for callback in self._callbacks:
197
 
            strings.append(repr(callback))
198
 
            strings.append("(")
199
 
            strings.append(self._callback_names[callback])
200
 
            strings.append("),")
201
 
        if len(self._callbacks) == 1:
202
 
            strings[-1] = ")"
203
 
        strings.append("]>")
204
 
        return ''.join(strings)