From 370e678ae41da49693ad5cfe10c23aba371e87c1 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Nov 05 2018 15:40:20 +0000 Subject: Make it possible to create hooks that don't have DB entries. Fixes #3972 --- diff --git a/pagure/hooks/__init__.py b/pagure/hooks/__init__.py index 67212ae..cad4c94 100644 --- a/pagure/hooks/__init__.py +++ b/pagure/hooks/__init__.py @@ -145,6 +145,7 @@ class BaseHook(object): name = None form = None description = None + backref = None db_object = None # hook_type is not used in hooks that use a Runner class, as those can # implement run actions on whatever is useful to them. @@ -259,6 +260,26 @@ class BaseHook(object): if not cls.runner: raise ValueError("BaseHook.remove called for runner-less hook") + @classmethod + def is_enabled_for(cls, project): + """ Determine if this hook should be run for given project. + + On some Pagure instances, some hooks should be run on all projects + that fulfill certain criteria. It is therefore not necessary to keep + database objects for them. + + If a hook's backref is set to None, this method is run to determine + whether the hook should be run or not. These hooks also won't show + up on settings page, since they can't be turned off. + + :arg project: The project to inspect + :type project: pagure.lib.model.Project + :return: True if this hook should be run on the given project, + False otherwise + + """ + return False + def run_project_hooks( session, diff --git a/pagure/lib/plugins.py b/pagure/lib/plugins.py index 09fb49c..6bd8944 100644 --- a/pagure/lib/plugins.py +++ b/pagure/lib/plugins.py @@ -15,8 +15,16 @@ from straight.plugin import load from pagure.lib.model_base import BASE -def get_plugin_names(blacklist=None): - """ Return the list of plugins names. """ +def get_plugin_names(blacklist=None, without_backref=False): + """ Return the list of plugins names. + + :arg blacklist: name or list of names to not return + :type blacklist: string or list of strings + :arg without_backref: whether or not to include hooks that + have backref "None" + :type without_backref: bool + :return: list of plugin names (strings) + """ from pagure.hooks import BaseHook plugins = load("pagure.hooks", subclasses=BaseHook) @@ -26,7 +34,8 @@ def get_plugin_names(blacklist=None): blacklist = [blacklist] output = [ - plugin.name for plugin in plugins if plugin.name not in blacklist + plugin.name for plugin in plugins + if plugin.name not in blacklist and (plugin.backref or without_backref) ] # The default hook is not one we show if "default" in output: @@ -69,9 +78,13 @@ def get_enabled_plugins(project, with_default=False): for plugin in load("pagure.hooks", subclasses=BaseHook): if plugin.name == "default": continue - plugin.db_object() - if hasattr(project, plugin.backref): - dbobj = getattr(project, plugin.backref) - if dbobj and dbobj.active: - enabled.append((plugin, dbobj)) + if plugin.backref is None: + if plugin.is_enabled_for(project): + enabled.append((plugin, None)) + else: + plugin.db_object() + if hasattr(project, plugin.backref): + dbobj = getattr(project, plugin.backref) + if dbobj and dbobj.active: + enabled.append((plugin, dbobj)) return enabled diff --git a/tests/test_pagure_lib_plugins.py b/tests/test_pagure_lib_plugins.py new file mode 100644 index 0000000..b6a174b --- /dev/null +++ b/tests/test_pagure_lib_plugins.py @@ -0,0 +1,76 @@ +# coding=utf-8 +""" + (c) 2015-2018 - Copyright Red Hat Inc + + Authors: + Slavek Kabrda + +""" + +from __future__ import unicode_literals + +__requires__ = ['SQLAlchemy >= 0.8'] +import pkg_resources + +import os +import sys + +from mock import patch + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import pagure.hooks +import pagure.lib.plugins +import tests + + +class EnabledForAll(pagure.hooks.BaseHook): + name = "EnabledForAll" + + @classmethod + def is_enabled_for(cls, project): + return True + +class DisabledForAll(pagure.hooks.BaseHook): + name = "DisabledForAll" + # disabled for all is the default + +class PagureLibtests_plugins(tests.Modeltests): + """ + Test the pagure.lib.plugins module + """ + + maxDiff = None + + @patch("pagure.lib.plugins.load") + def test_plugin_is_enabled_for(self, load): + """ Test the is_enabled_for method of plugins is properly + handled by pagure.lib.plugins.get_enabled_plugins. + """ + tests.create_projects(self.session) + project = pagure.lib.query._get_project(self.session, "test") + + load.return_value = [EnabledForAll] + self.assertEqual( + pagure.lib.plugins.get_enabled_plugins(project), + [(EnabledForAll, None)] + ) + + load.return_value = [DisabledForAll] + self.assertEqual( + pagure.lib.plugins.get_enabled_plugins(project), + [] + ) + + @patch("pagure.lib.plugins.load") + def test_get_plugin_names(self, load): + """ Test the get_plugin_names method with plugins that don't + have backref. + """ + load.return_value = [EnabledForAll] + self.assertEqual(pagure.lib.plugins.get_plugin_names(), []) + self.assertEqual( + pagure.lib.plugins.get_plugin_names(without_backref=True), + ['EnabledForAll'] + )