feat: can order hooks

pull/3351/merge
Gagaro 2017-02-05 10:01:35 +01:00 zatwierdzone przez Matt Westcott
rodzic 72036501e7
commit ac7ad067d2
6 zmienionych plików z 69 dodań i 8 usunięć

Wyświetl plik

@ -5,6 +5,8 @@ Changelog
~~~~~~~~~~~~~~~~~
* Use minified versions of jQuery and jQuery UI in the admin. Total savings without compression 371 KB (Tom Dyson)
* Hooks can now specify the order in which they are run (Gagaro)
1.9 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~

Wyświetl plik

@ -23,6 +23,21 @@ Alternatively, ``hooks.register`` can be called as an ordinary function, passing
hooks.register('name_of_hook', my_hook_function)
If you need your hooks to run in a particular order, you can pass the ``order`` parameter:
.. code-block:: python
@hooks.register('name_of_hook', order=1) # This will run after every hook in the wagtail core
def my_hook_function(arg1, arg2...)
# your code here
@hooks.register('name_of_hook', order=-1) # This will run before every hook in the wagtail core
def my_other_hook_function(arg1, arg2...)
# your code here
@hooks.register('name_of_hook', order=2) # This will run after `my_hook_function`
def yet_another_hook_function(arg1, arg2...)
# your code here
The available hooks are listed below.

Wyświetl plik

@ -14,7 +14,8 @@ What's new
Other features
~~~~~~~~~~~~~~
- Use minified versions of jQuery and jQuery UI in the admin. Total savings without compression 371 KB (Tom Dyson)
* Use minified versions of jQuery and jQuery UI in the admin. Total savings without compression 371 KB (Tom Dyson)
* Hooks can now specify the order in which they are run (Gagaro)
Bug fixes
~~~~~~~~~

Wyświetl plik

@ -104,14 +104,14 @@ class WagtailTestUtils(object):
return _AssertLogsContext(self, logger, level)
@contextmanager
def register_hook(self, hook_name, fn):
def register_hook(self, hook_name, fn, order=0):
from wagtail.wagtailcore import hooks
hooks.register(hook_name, fn)
hooks.register(hook_name, fn, order)
try:
yield
finally:
hooks.get_hooks(hook_name).remove(fn)
hooks._hooks[hook_name].remove((fn, order))
class WagtailPageTests(WagtailTestUtils, TestCase):

Wyświetl plik

@ -1,11 +1,13 @@
from __future__ import absolute_import, unicode_literals
from operator import itemgetter
from wagtail.utils.apps import get_app_submodules
_hooks = {}
def register(hook_name, fn=None):
def register(hook_name, fn=None, order=0):
"""
Register hook for ``hook_name``. Can be used as a decorator::
@ -23,13 +25,13 @@ def register(hook_name, fn=None):
# Pretend to be a decorator if fn is not supplied
if fn is None:
def decorator(fn):
register(hook_name, fn)
register(hook_name, fn, order=order)
return fn
return decorator
if hook_name not in _hooks:
_hooks[hook_name] = []
_hooks[hook_name].append(fn)
_hooks[hook_name].append((fn, order))
_searched_for_hooks = False
@ -43,5 +45,8 @@ def search_for_hooks():
def get_hooks(hook_name):
""" Return the hooks function sorted by their order. """
search_for_hooks()
return _hooks.get(hook_name, [])
hooks = _hooks.get(hook_name, [])
hooks = sorted(hooks, key=itemgetter(1))
return [hook[0] for hook in hooks]

Wyświetl plik

@ -0,0 +1,38 @@
from __future__ import absolute_import, unicode_literals
from django.test import TestCase
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore import hooks
def test_hook():
pass
class TestLoginView(TestCase, WagtailTestUtils):
fixtures = ['test.json']
@classmethod
def setUpClass(cls):
hooks.register('test_hook_name', test_hook)
@classmethod
def tearDownClass(cls):
del hooks._hooks['test_hook_name']
def test_before_hook(self):
def before_hook():
pass
with self.register_hook('test_hook_name', before_hook, order=-1):
hook_fns = hooks.get_hooks('test_hook_name')
self.assertEqual(hook_fns, [before_hook, test_hook])
def test_after_hook(self):
def after_hook():
pass
with self.register_hook('test_hook_name', after_hook, order=1):
hook_fns = hooks.get_hooks('test_hook_name')
self.assertEqual(hook_fns, [test_hook, after_hook])