import sys
from celery import Celery
-from mediagoblin.tools.pluginapi import PluginManager
+from mediagoblin.tools.pluginapi import callable_runall
MANDATORY_CELERY_IMPORTS = ['mediagoblin.processing.task']
celery_app = Celery()
celery_app.config_from_object(celery_settings)
- for callable_hook in PluginManager().get_hook_callables('celery_setup'):
- callable_hook(celery_app)
+ callable_runall('celery_setup', celery_app)
def setup_celery_from_config(app_config, global_config,
from mediagoblin import app, mg_globals
from mediagoblin.init.celery import setup_celery_from_config
-from mediagoblin.tools.pluginapi import PluginManager
+from mediagoblin.tools.pluginapi import callable_runall
OUR_MODULENAME = __name__
logging.config.fileConfig(logging_conf_file)
- for callable_hook in \
- PluginManager().get_hook_callables('celery_logging_setup'):
- callable_hook()
+ callable_runall('celery_logging_setup')
setup_logging.connect(setup_logging_from_paste_ini)
pman.register_hooks(plugin.hooks)
# Execute anything registered to the setup hook.
- setup_list = pman.get_hook_callables('setup')
- for fun in setup_list:
- fun()
+ pluginapi.callable_runall('setup')
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
+
from configobj import ConfigObj
+import pytest
+
from mediagoblin import mg_globals
from mediagoblin.init.plugins import setup_plugins
from mediagoblin.tools import pluginapi
# Make sure we didn't load the plugin
assert len(pman.plugins) == 0
+
+
+@with_cleanup()
+def test_callable_runone():
+ """
+ Test the callable_runone method
+ """
+ cfg = build_config([
+ ('mediagoblin', {}, []),
+ ('plugins', {}, [
+ ('mediagoblin.tests.testplugins.callables1', {}, []),
+ ('mediagoblin.tests.testplugins.callables2', {}, []),
+ ('mediagoblin.tests.testplugins.callables3', {}, []),
+ ])
+ ])
+
+ mg_globals.app_config = cfg['mediagoblin']
+ mg_globals.global_config = cfg
+
+ setup_plugins()
+
+ # Just one hook provided
+ call_log = []
+ assert pluginapi.callable_runone(
+ "just_one", call_log) == "Called just once"
+ assert call_log == ["expect this one call"]
+
+ # Nothing provided and unhandled not okay
+ call_log = []
+ with pytest.raises(pluginapi.UnhandledCallable):
+ pluginapi.callable_runone(
+ "nothing_handling", call_log)
+ assert call_log == []
+
+ # Nothing provided and unhandled okay
+ call_log = []
+ assert pluginapi.callable_runone(
+ "nothing_handling", call_log, unhandled_okay=True) is None
+ assert call_log == []
+
+ # Multiple provided, go with the first!
+ call_log = []
+ assert pluginapi.callable_runone(
+ "multi_handle", call_log) == "the first returns"
+ assert call_log == ["Hi, I'm the first"]
+
+ # Multiple provided, one has CantHandleIt
+ call_log = []
+ assert pluginapi.callable_runone(
+ "multi_handle_with_canthandle",
+ call_log) == "the second returns"
+ assert call_log == ["Hi, I'm the second"]
+
+
+@with_cleanup()
+def test_callable_runall():
+ """
+ Test the callable_runall method
+ """
+ cfg = build_config([
+ ('mediagoblin', {}, []),
+ ('plugins', {}, [
+ ('mediagoblin.tests.testplugins.callables1', {}, []),
+ ('mediagoblin.tests.testplugins.callables2', {}, []),
+ ('mediagoblin.tests.testplugins.callables3', {}, []),
+ ])
+ ])
+
+ mg_globals.app_config = cfg['mediagoblin']
+ mg_globals.global_config = cfg
+
+ setup_plugins()
+
+ # Just one hook, check results
+ call_log = []
+ assert pluginapi.callable_runall(
+ "just_one", call_log) == ["Called just once", None, None]
+ assert call_log == ["expect this one call"]
+
+ # None provided, check results
+ call_log = []
+ assert pluginapi.callable_runall(
+ "nothing_handling", call_log) == []
+ assert call_log == []
+
+ # Multiple provided, check results
+ call_log = []
+ assert pluginapi.callable_runall(
+ "multi_handle", call_log) == [
+ "the first returns",
+ "the second returns",
+ "the third returns",
+ ]
+ assert call_log == [
+ "Hi, I'm the first",
+ "Hi, I'm the second",
+ "Hi, I'm the third"]
+
+ # Multiple provided, one has CantHandleIt, check results
+ call_log = []
+ assert pluginapi.callable_runall(
+ "multi_handle_with_canthandle", call_log) == [
+ "the second returns",
+ "the third returns",
+ ]
+ assert call_log == [
+ "Hi, I'm the second",
+ "Hi, I'm the third"]
--- /dev/null
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
--- /dev/null
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.pluginapi import CantHandleIt
+
+def setup_plugin():
+ pass
+
+
+def just_one(call_log):
+ call_log.append("expect this one call")
+ return "Called just once"
+
+
+def multi_handle(call_log):
+ call_log.append("Hi, I'm the first")
+ return "the first returns"
+
+def multi_handle_with_canthandle(call_log):
+ raise CantHandleIt("I just can't accept this stupid method")
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'just_one': just_one,
+ 'multi_handle': multi_handle,
+ 'multi_handle_with_canthandle': multi_handle_with_canthandle,
+ }
--- /dev/null
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+def setup_plugin():
+ pass
+
+
+def just_one(call_log):
+ assert "SHOULD NOT HAPPEN"
+
+def multi_handle(call_log):
+ call_log.append("Hi, I'm the second")
+ return "the second returns"
+
+def multi_handle_with_canthandle(call_log):
+ call_log.append("Hi, I'm the second")
+ return "the second returns"
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'just_one': just_one,
+ 'multi_handle': multi_handle,
+ 'multi_handle_with_canthandle': multi_handle_with_canthandle,
+ }
--- /dev/null
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+def setup_plugin():
+ pass
+
+
+def just_one(call_log):
+ assert "SHOULD NOT HAPPEN"
+
+def multi_handle(call_log):
+ call_log.append("Hi, I'm the third")
+ return "the third returns"
+
+def multi_handle_with_canthandle(call_log):
+ call_log.append("Hi, I'm the third")
+ return "the third returns"
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'just_one': just_one,
+ 'multi_handle': multi_handle,
+ 'multi_handle_with_canthandle': multi_handle_with_canthandle,
+ }
A list of strings representing template paths.
"""
return PluginManager().get_template_hooks(hook_name)
+
+
+###########################
+# Callable convenience code
+###########################
+
+class CantHandleIt(Exception):
+ """
+ A callable may call this method if they look at the relevant
+ arguments passed and decide it's not possible for them to handle
+ things.
+ """
+ pass
+
+class UnhandledCallable(Exception):
+ """
+ Raise this method if no callables were available to handle the
+ specified hook. Only used by callable_runone.
+ """
+ pass
+
+
+def callable_runone(hookname, *args, **kwargs):
+ """
+ Run the callable hook HOOKNAME... run until the first response,
+ then return.
+
+ This function will run stop at the first hook that handles the
+ result. Hooks raising CantHandleIt will be skipped.
+
+ Unless unhandled_okay is True, this will error out if no hooks
+ have been registered to handle this function.
+ """
+ callables = PluginManager().get_hook_callables(hookname)
+
+ unhandled_okay = kwargs.pop("unhandled_okay", False)
+
+ for callable in callables:
+ try:
+ return callable(*args, **kwargs)
+ except CantHandleIt:
+ continue
+
+ if unhandled_okay is False:
+ raise UnhandledCallable(
+ "No hooks registered capable of handling '%s'" % hookname)
+
+
+def callable_runall(hookname, *args, **kwargs):
+ """
+ Run all callables for HOOKNAME.
+
+ This method will run *all* hooks that handle this method (skipping
+ those that raise CantHandleIt), and will return a list of all
+ results.
+ """
+ callables = PluginManager().get_hook_callables(hookname)
+
+ results = []
+
+ for callable in callables:
+ try:
+ results.append(callable(*args, **kwargs))
+ except CantHandleIt:
+ continue
+
+ return results