~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/hooks.py

merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
115
115
    FOO hook is triggered.
116
116
    """
117
117
 
118
 
    def __init__(self):
 
118
    def __init__(self, module=None, member_name=None):
 
119
        """Create a new hooks dictionary.
 
120
 
 
121
        :param module: The module from which this hooks dictionary should be loaded
 
122
            (used for lazy hooks)
 
123
        :param member_name: Name under which this hooks dictionary should be loaded.
 
124
            (used for lazy hooks)
 
125
        """
119
126
        dict.__init__(self)
120
127
        self._callable_names = {}
 
128
        self._module = module
 
129
        self._member_name = member_name
 
130
 
 
131
    def add_hook(self, name, doc, introduced, deprecated=None):
 
132
        """Add a hook point to this dictionary.
 
133
 
 
134
        :param name: The name of the hook, for clients to use when registering.
 
135
        :param doc: The docs for the hook.
 
136
        :param introduced: When the hook was introduced (e.g. (0, 15)).
 
137
        :param deprecated: When the hook was deprecated, None for
 
138
            not-deprecated.
 
139
        """
 
140
        if name in self:
 
141
            raise errors.DuplicateKey(name)
 
142
        if self._module:
 
143
            callbacks = _lazy_hooks.setdefault(
 
144
                (self._module, self._member_name, name), [])
 
145
        else:
 
146
            callbacks = None
 
147
        hookpoint = HookPoint(name=name, doc=doc, introduced=introduced,
 
148
                              deprecated=deprecated,
 
149
                              callbacks=callbacks)
 
150
        self[name] = hookpoint
121
151
 
122
152
    def create_hook(self, hook):
123
153
        """Create a hook which can have callbacks registered for it.
166
196
        """
167
197
        return self._callable_names.get(a_callable, "No hook name")
168
198
 
 
199
    def install_named_hook_lazy(self, hook_name, callable_module,
 
200
        callable_member, name):
 
201
        """Install a_callable in to the hook hook_name lazily, and label it.
 
202
 
 
203
        :param hook_name: A hook name. See the __init__ method for the complete
 
204
            list of hooks.
 
205
        :param callable_module: Name of the module in which the callable is
 
206
            present.
 
207
        :param callable_member: Member name of the callable.
 
208
        :param name: A name to associate the callable with, to show users what
 
209
            is running.
 
210
        """
 
211
        try:
 
212
            hook = self[hook_name]
 
213
        except KeyError:
 
214
            raise errors.UnknownHook(self.__class__.__name__, hook_name)
 
215
        try:
 
216
            hook_lazy = getattr(hook, "hook_lazy")
 
217
        except AttributeError:
 
218
            raise errors.UnsupportedOperation(self.install_named_hook_lazy,
 
219
                self)
 
220
        else:
 
221
            hook_lazy(callable_module, callable_member, name)
 
222
 
169
223
    def install_named_hook(self, hook_name, a_callable, name):
170
224
        """Install a_callable in to the hook hook_name, and label it name.
171
225
 
172
 
        :param hook_name: A hook name. See the __init__ method of BranchHooks
173
 
            for the complete list of hooks.
 
226
        :param hook_name: A hook name. See the __init__ method for the complete
 
227
            list of hooks.
174
228
        :param a_callable: The callable to be invoked when the hook triggers.
175
229
            The exact signature will depend on the hook - see the __init__
176
 
            method of BranchHooks for details on each hook.
 
230
            method for details on each hook.
177
231
        :param name: A name to associate a_callable with, to show users what is
178
232
            running.
179
233
        """
207
261
        should describe the recommended replacement hook to register for.
208
262
    """
209
263
 
210
 
    def __init__(self, name, doc, introduced, deprecated):
 
264
    def __init__(self, name, doc, introduced, deprecated=None, callbacks=None):
211
265
        """Create a HookPoint.
212
266
 
213
267
        :param name: The name of the hook, for clients to use when registering.
220
274
        self.__doc__ = doc
221
275
        self.introduced = introduced
222
276
        self.deprecated = deprecated
223
 
        self._callbacks = []
224
 
        self._callback_names = {}
 
277
        if callbacks is None:
 
278
            self._callbacks = []
 
279
        else:
 
280
            self._callbacks = callbacks
225
281
 
226
282
    def docs(self):
227
283
        """Generate the documentation for this HookPoint.
247
303
        return '\n'.join(strings)
248
304
 
249
305
    def __eq__(self, other):
250
 
        return (type(other) == type(self) and 
251
 
            other.__dict__ == self.__dict__)
 
306
        return (type(other) == type(self) and other.__dict__ == self.__dict__)
 
307
 
 
308
    def hook_lazy(self, callback_module, callback_member, callback_label):
 
309
        """Lazily register a callback to be called when this HookPoint fires.
 
310
 
 
311
        :param callback_module: Module of the callable to use when this
 
312
            HookPoint fires.
 
313
        :param callback_member: Member name of the callback.
 
314
        :param callback_label: A label to show in the UI while this callback is
 
315
            processing.
 
316
        """
 
317
        obj_getter = registry._LazyObjectGetter(callback_module,
 
318
            callback_member)
 
319
        self._callbacks.append((obj_getter, callback_label))
252
320
 
253
321
    def hook(self, callback, callback_label):
254
322
        """Register a callback to be called when this HookPoint fires.
257
325
        :param callback_label: A label to show in the UI while this callback is
258
326
            processing.
259
327
        """
260
 
        self._callbacks.append(callback)
261
 
        if callback_label is not None:
262
 
            self._callback_names[callback] = callback_label
 
328
        obj_getter = registry._ObjectGetter(callback)
 
329
        self._callbacks.append((obj_getter, callback_label))
263
330
 
264
331
    def __iter__(self):
265
 
        return iter(self._callbacks)
 
332
        return (callback.get_obj() for callback, name in self._callbacks)
266
333
 
267
334
    def __len__(self):
268
335
        return len(self._callbacks)
272
339
        strings.append("<%s(" % type(self).__name__)
273
340
        strings.append(self.name)
274
341
        strings.append("), callbacks=[")
275
 
        for callback in self._callbacks:
276
 
            strings.append(repr(callback))
 
342
        callbacks = self._callbacks
 
343
        for (callback, callback_name) in callbacks:
 
344
            strings.append(repr(callback.get_obj()))
277
345
            strings.append("(")
278
 
            strings.append(self._callback_names[callback])
 
346
            strings.append(callback_name)
279
347
            strings.append("),")
280
 
        if len(self._callbacks) == 1:
 
348
        if len(callbacks) == 1:
281
349
            strings[-1] = ")"
282
350
        strings.append("]>")
283
351
        return ''.join(strings)
322
390
        hooks = known_hooks_key_to_object(hook_key)
323
391
        segments.append(hooks.docs())
324
392
    return '\n'.join(segments)
 
393
 
 
394
 
 
395
_lazy_hooks = {}
 
396
 
 
397
 
 
398
def install_lazy_named_hook(hookpoints_module, hookpoints_name, hook_name,
 
399
    a_callable, name):
 
400
    """Install a callable in to a hook lazily, and label it name.
 
401
 
 
402
    :param hookpoints_module: Module name of the hook points.
 
403
    :param hookpoints_name: Name of the hook points.
 
404
    :param hook_name: A hook name.
 
405
    :param callable: a callable to call for the hook.
 
406
    :param name: A name to associate a_callable with, to show users what is
 
407
        running.
 
408
    """
 
409
    key = (hookpoints_module, hookpoints_name, hook_name)
 
410
    obj_getter = registry._ObjectGetter(a_callable)
 
411
    _lazy_hooks.setdefault(key, []).append((obj_getter, name))