/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2007-2012, 2016 Canonical Ltd
2553.1.1 by Robert Collins
Give Hooks names.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2553.1.1 by Robert Collins
Give Hooks names.
16
17
"""Tests for the core Hooks logic."""
18
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
19
from .. import (
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
20
    branch,
21
    errors,
5691.2.3 by Jelmer Vernooij
Fix tests.
22
    hooks as _mod_hooks,
5622.2.5 by Jelmer Vernooij
Add more tests for lazy hooks.
23
    pyutils,
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
24
    tests,
25
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
26
from ..hooks import (
4098.2.2 by Robert Collins
Review feedback.
27
    HookPoint,
2553.1.1 by Robert Collins
Give Hooks names.
28
    Hooks,
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
29
    UnknownHook,
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
30
    install_lazy_named_hook,
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
31
    known_hooks,
32
    known_hooks_key_to_object,
2553.1.1 by Robert Collins
Give Hooks names.
33
    )
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
34
35
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
36
class TestErrors(tests.TestCase):
37
38
    def test_unknown_hook(self):
39
        error = UnknownHook("branch", "foo")
40
        self.assertEqualDiff("The branch hook 'foo' is unknown in this version"
7143.15.2 by Jelmer Vernooij
Run autopep8.
41
                             " of breezy.",
42
                             str(error))
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
43
        error = UnknownHook("tree", "bar")
44
        self.assertEqualDiff("The tree hook 'bar' is unknown in this version"
7143.15.2 by Jelmer Vernooij
Run autopep8.
45
                             " of breezy.",
46
                             str(error))
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
47
48
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
49
class TestHooks(tests.TestCase):
2553.1.1 by Robert Collins
Give Hooks names.
50
4098.2.1 by Robert Collins
Allow self documenting hooks.
51
    def test_docs(self):
52
        """docs() should return something reasonable about the Hooks."""
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
53
        class MyHooks(Hooks):
54
            pass
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
55
        hooks = MyHooks("breezy.tests.test_hooks", "some_hooks")
4098.2.1 by Robert Collins
Allow self documenting hooks.
56
        hooks['legacy'] = []
5622.3.13 by Jelmer Vernooij
Catch deprecation warnings.
57
        hooks.add_hook('post_tip_change',
7143.15.2 by Jelmer Vernooij
Run autopep8.
58
                       "Invoked after the tip of a branch changes. Called with "
59
                       "a ChangeBranchTipParams object.", (1, 4))
5622.3.13 by Jelmer Vernooij
Catch deprecation warnings.
60
        hooks.add_hook('pre_tip_change',
7143.15.2 by Jelmer Vernooij
Run autopep8.
61
                       "Invoked before the tip of a branch changes. Called with "
62
                       "a ChangeBranchTipParams object. Hooks should raise "
63
                       "TipChangeRejected to signal that a tip change is not permitted.",
64
                       (1, 6), None)
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
65
        self.assertEqualDiff(
66
            "MyHooks\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
67
            "-------\n"
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
68
            "\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
69
            "legacy\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
70
            "~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
71
            "\n"
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
72
            "An old-style hook. For documentation see the __init__ method of 'MyHooks'\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
73
            "\n"
74
            "post_tip_change\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
75
            "~~~~~~~~~~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
76
            "\n"
77
            "Introduced in: 1.4\n"
78
            "\n"
79
            "Invoked after the tip of a branch changes. Called with a\n"
80
            "ChangeBranchTipParams object.\n"
81
            "\n"
82
            "pre_tip_change\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
83
            "~~~~~~~~~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
84
            "\n"
85
            "Introduced in: 1.6\n"
86
            "\n"
87
            "Invoked before the tip of a branch changes. Called with a\n"
88
            "ChangeBranchTipParams object. Hooks should raise TipChangeRejected to\n"
89
            "signal that a tip change is not permitted.\n", hooks.docs())
90
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
91
    def test_install_named_hook_raises_unknown_hook(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
92
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
93
        self.assertRaises(UnknownHook, hooks.install_named_hook, 'silly',
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
94
                          None, "")
95
96
    def test_install_named_hook_appends_known_hook(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
97
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
98
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
99
        hooks.install_named_hook('set_rh', None, "demo")
100
        self.assertEqual(hooks['set_rh'], [None])
101
102
    def test_install_named_hook_and_retrieve_name(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
103
        hooks = Hooks("breezy.tests.test_hooks", "somehooks")
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
104
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
105
        hooks.install_named_hook('set_rh', None, "demo")
3256.2.1 by Daniel Watkins
Added tests from Hooks.install_hook with an optional name parameter.
106
        self.assertEqual("demo", hooks.get_hook_name(None))
107
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
108
    def test_uninstall_named_hook(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
109
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
5622.4.3 by Jelmer Vernooij
Remove all callables with specified label, not just the first.
110
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
111
        hooks.install_named_hook('set_rh', None, "demo")
112
        self.assertEqual(1, len(hooks["set_rh"]))
113
        hooks.uninstall_named_hook("set_rh", "demo")
114
        self.assertEqual(0, len(hooks["set_rh"]))
115
5622.4.3 by Jelmer Vernooij
Remove all callables with specified label, not just the first.
116
    def test_uninstall_multiple_named_hooks(self):
117
        # Multiple callbacks with the same label all get removed
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
118
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
5622.4.3 by Jelmer Vernooij
Remove all callables with specified label, not just the first.
119
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
120
        hooks.install_named_hook('set_rh', 1, "demo")
121
        hooks.install_named_hook('set_rh', 2, "demo")
122
        hooks.install_named_hook('set_rh', 3, "othername")
123
        self.assertEqual(3, len(hooks["set_rh"]))
124
        hooks.uninstall_named_hook("set_rh", "demo")
125
        self.assertEqual(1, len(hooks["set_rh"]))
126
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
127
    def test_uninstall_named_hook_unknown_callable(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
128
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
129
        hooks.add_hook('set_rh', "Set revision hsitory", (2, 0))
130
        self.assertRaises(KeyError, hooks.uninstall_named_hook, "set_rh",
7143.15.2 by Jelmer Vernooij
Run autopep8.
131
                          "demo")
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
132
133
    def test_uninstall_named_hook_raises_unknown_hook(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
134
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
6734.1.15 by Jelmer Vernooij
Move errors for breezy.directory_service.
135
        self.assertRaises(UnknownHook, hooks.uninstall_named_hook, 'silly', "")
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
136
137
    def test_uninstall_named_hook_old_style(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
138
        hooks = Hooks("breezy.tests.test_hooks", "some_hooks")
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
139
        hooks["set_rh"] = []
140
        hooks.install_named_hook('set_rh', None, "demo")
141
        self.assertRaises(errors.UnsupportedOperation,
7143.15.2 by Jelmer Vernooij
Run autopep8.
142
                          hooks.uninstall_named_hook, "set_rh", "demo")
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
143
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
144
    hooks = Hooks("breezy.tests.test_hooks", "TestHooks.hooks")
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
145
146
    def test_install_lazy_named_hook(self):
147
        # When the hook points are not yet registered the hook is
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
148
        # added to the _lazy_hooks dictionary in breezy.hooks.
5622.2.6 by Jelmer Vernooij
Put module/member information on Hooks, not individual hook points.
149
        self.hooks.add_hook('set_rh', "doc", (0, 15))
7143.15.2 by Jelmer Vernooij
Run autopep8.
150
151
        def set_rh(): return None
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
152
        install_lazy_named_hook('breezy.tests.test_hooks',
7143.15.2 by Jelmer Vernooij
Run autopep8.
153
                                'TestHooks.hooks', 'set_rh', set_rh, "demo")
5691.2.3 by Jelmer Vernooij
Fix tests.
154
        set_rh_lazy_hooks = _mod_hooks._lazy_hooks[
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
155
            ('breezy.tests.test_hooks', 'TestHooks.hooks', 'set_rh')]
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
156
        self.assertEqual(1, len(set_rh_lazy_hooks))
157
        self.assertEqual(set_rh, set_rh_lazy_hooks[0][0].get_obj())
158
        self.assertEqual("demo", set_rh_lazy_hooks[0][1])
5622.2.5 by Jelmer Vernooij
Add more tests for lazy hooks.
159
        self.assertEqual(list(TestHooks.hooks['set_rh']), [set_rh])
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
160
7143.15.2 by Jelmer Vernooij
Run autopep8.
161
    def set_rh(): return None
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
162
163
    def test_install_named_hook_lazy(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
164
        hooks = Hooks("breezy.tests.hooks", "some_hooks")
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
165
        hooks['set_rh'] = HookPoint("set_rh", "doc", (0, 15), None)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
166
        hooks.install_named_hook_lazy('set_rh', 'breezy.tests.test_hooks',
7143.15.2 by Jelmer Vernooij
Run autopep8.
167
                                      'TestHooks.set_rh', "demo")
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
168
        self.assertEqual(list(hooks['set_rh']), [TestHooks.set_rh])
169
170
    def test_install_named_hook_lazy_old(self):
171
        # An exception is raised if a lazy hook is raised for
172
        # an old style hook point.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
173
        hooks = Hooks("breezy.tests.hooks", "some_hooks")
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
174
        hooks['set_rh'] = []
175
        self.assertRaises(errors.UnsupportedOperation,
7143.15.2 by Jelmer Vernooij
Run autopep8.
176
                          hooks.install_named_hook_lazy,
177
                          'set_rh', 'breezy.tests.test_hooks', 'TestHooks.set_rh',
178
                          "demo")
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
179
5622.2.5 by Jelmer Vernooij
Add more tests for lazy hooks.
180
    def test_valid_lazy_hooks(self):
181
        # Make sure that all the registered lazy hooks are referring to existing
182
        # hook points which allow lazy registration.
6759.2.1 by Martin
One last dict.iteritems() in hooks tests
183
        for key, callbacks in _mod_hooks._lazy_hooks.items():
5622.2.8 by Jelmer Vernooij
more tests.
184
            (module_name, member_name, hook_name) = key
5622.2.5 by Jelmer Vernooij
Add more tests for lazy hooks.
185
            obj = pyutils.get_named_object(module_name, member_name)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
186
            self.assertEqual(obj._module, module_name)
187
            self.assertEqual(obj._member_name, member_name)
5622.2.6 by Jelmer Vernooij
Put module/member information on Hooks, not individual hook points.
188
            self.assertTrue(hook_name in obj)
5622.2.8 by Jelmer Vernooij
more tests.
189
            self.assertIs(callbacks, obj[hook_name]._callbacks)
5622.2.5 by Jelmer Vernooij
Add more tests for lazy hooks.
190
4098.2.1 by Robert Collins
Allow self documenting hooks.
191
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
192
class TestHook(tests.TestCase):
4098.2.1 by Robert Collins
Allow self documenting hooks.
193
194
    def test___init__(self):
195
        doc = ("Invoked after changing the tip of a branch object. Called with"
7143.15.2 by Jelmer Vernooij
Run autopep8.
196
               "a breezy.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
197
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
198
        self.assertEqual(doc, hook.__doc__)
199
        self.assertEqual("post_tip_change", hook.name)
200
        self.assertEqual((0, 15), hook.introduced)
201
        self.assertEqual(None, hook.deprecated)
202
        self.assertEqual([], list(hook))
203
204
    def test_docs(self):
205
        doc = ("Invoked after changing the tip of a branch object. Called with"
7143.15.2 by Jelmer Vernooij
Run autopep8.
206
               " a breezy.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
207
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
208
        self.assertEqual("post_tip_change\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
209
                         "~~~~~~~~~~~~~~~\n"
210
                         "\n"
211
                         "Introduced in: 0.15\n"
212
                         "\n"
213
                         "Invoked after changing the tip of a branch object. Called with a\n"
214
                         "breezy.branch.PostChangeBranchTipParams object\n", hook.docs())
4098.2.1 by Robert Collins
Allow self documenting hooks.
215
216
    def test_hook(self):
4098.2.2 by Robert Collins
Review feedback.
217
        hook = HookPoint("foo", "no docs", None, None)
7143.15.2 by Jelmer Vernooij
Run autopep8.
218
4098.2.1 by Robert Collins
Allow self documenting hooks.
219
        def callback():
220
            pass
221
        hook.hook(callback, "my callback")
222
        self.assertEqual([callback], list(hook))
223
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
224
    def lazy_callback():
225
        pass
226
227
    def test_lazy_hook(self):
228
        hook = HookPoint("foo", "no docs", None, None)
229
        hook.hook_lazy(
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
230
            "breezy.tests.test_hooks", "TestHook.lazy_callback",
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
231
            "my callback")
232
        self.assertEqual([TestHook.lazy_callback], list(hook))
233
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
234
    def test_uninstall(self):
235
        hook = HookPoint("foo", "no docs", None, None)
236
        hook.hook_lazy(
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
237
            "breezy.tests.test_hooks", "TestHook.lazy_callback",
5622.4.2 by Jelmer Vernooij
Allow uninstalling hooks.
238
            "my callback")
239
        self.assertEqual([TestHook.lazy_callback], list(hook))
240
        hook.uninstall("my callback")
241
        self.assertEqual([], list(hook))
242
243
    def test_uninstall_unknown(self):
244
        hook = HookPoint("foo", "no docs", None, None)
245
        self.assertRaises(KeyError, hook.uninstall, "my callback")
246
4098.2.1 by Robert Collins
Allow self documenting hooks.
247
    def test___repr(self):
248
        # The repr should list all the callbacks, with names.
4098.2.2 by Robert Collins
Review feedback.
249
        hook = HookPoint("foo", "no docs", None, None)
7143.15.2 by Jelmer Vernooij
Run autopep8.
250
4098.2.1 by Robert Collins
Allow self documenting hooks.
251
        def callback():
252
            pass
253
        hook.hook(callback, "my callback")
254
        callback_repr = repr(callback)
255
        self.assertEqual(
4098.2.2 by Robert Collins
Review feedback.
256
            '<HookPoint(foo), callbacks=[%s(my callback)]>' %
4098.2.1 by Robert Collins
Allow self documenting hooks.
257
            callback_repr, repr(hook))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
258
259
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
260
class TestHookRegistry(tests.TestCase):
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
261
262
    def test_items_are_reasonable_keys(self):
263
        # All the items in the known_hooks registry need to map from
264
        # (module_name, member_name) tuples to the callable used to get an
4230.1.2 by James Westby
Update the comments based on those in the test.
265
        # empty Hooks for that attribute. This is used to support the test
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
266
        # suite which needs to generate empty hooks (and HookPoints) to ensure
267
        # isolation and prevent tests failing spuriously.
268
        for key, factory in known_hooks.items():
269
            self.assertTrue(callable(factory),
7143.15.2 by Jelmer Vernooij
Run autopep8.
270
                            "The factory(%r) for %r is not callable" % (factory, key))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
271
            obj = known_hooks_key_to_object(key)
272
            self.assertIsInstance(obj, Hooks)
5622.3.11 by Jelmer Vernooij
Revert some unnecessary changes.
273
            new_hooks = factory()
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
274
            self.assertIsInstance(obj, Hooks)
275
            self.assertEqual(type(obj), type(new_hooks))
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
276
            self.assertEqual("No hook name", new_hooks.get_hook_name(None))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
277
278
    def test_known_hooks_key_to_object(self):
279
        self.assertIs(branch.Branch.hooks,
7143.15.2 by Jelmer Vernooij
Run autopep8.
280
                      known_hooks_key_to_object(('breezy.branch', 'Branch.hooks')))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
281
282
    def test_known_hooks_key_to_parent_and_attribute(self):
283
        self.assertEqual((branch.Branch, 'hooks'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
284
                         known_hooks.key_to_parent_and_attribute(
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
285
            ('breezy.branch', 'Branch.hooks')))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
286
        self.assertEqual((branch, 'Branch'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
287
                         known_hooks.key_to_parent_and_attribute(
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
288
            ('breezy.branch', 'Branch')))