summaryrefslogtreecommitdiff
path: root/src/mailman/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/core')
-rw-r--r--src/mailman/core/chains.py5
-rw-r--r--src/mailman/core/initialize.py50
-rw-r--r--src/mailman/core/pipelines.py6
-rw-r--r--src/mailman/core/plugins.py41
-rw-r--r--src/mailman/core/rules.py4
-rw-r--r--src/mailman/core/workflows.py4
6 files changed, 94 insertions, 16 deletions
diff --git a/src/mailman/core/chains.py b/src/mailman/core/chains.py
index c251d38bc..48ed82d63 100644
--- a/src/mailman/core/chains.py
+++ b/src/mailman/core/chains.py
@@ -19,7 +19,7 @@
from mailman.config import config
from mailman.interfaces.chain import IChain, LinkAction
-from mailman.utilities.modules import add_components
+from mailman.utilities.plugins import add_pluggable_components
from public import public
@@ -89,5 +89,4 @@ def process(mlist, msg, msgdata, start_chain='default-posting-chain'):
@public
def initialize():
"""Set up chains, both built-in and from the database."""
- add_components('mailman.chains', IChain, config.chains)
- # XXX Read chains from the database and initialize them.
+ add_pluggable_components('chains', IChain, config.chains)
diff --git a/src/mailman/core/initialize.py b/src/mailman/core/initialize.py
index dfa365448..ae9ff623e 100644
--- a/src/mailman/core/initialize.py
+++ b/src/mailman/core/initialize.py
@@ -26,9 +26,12 @@ by the command line arguments.
import os
import sys
+import warnings
+import traceback
import mailman.config.config
import mailman.core.logging
+from mailman.core.i18n import _
from mailman.interfaces.database import IDatabaseFactory
from mailman.utilities.modules import call_name
from pkg_resources import resource_string as resource_bytes
@@ -133,7 +136,7 @@ def initialize_2(debug=False, propagate_logs=None, testing=False):
* Database
* Logging
- * Pre-hook
+ * Plugin's pre_hook
* Rules
* Chains
* Pipelines
@@ -146,10 +149,34 @@ def initialize_2(debug=False, propagate_logs=None, testing=False):
"""
# Create the queue and log directories if they don't already exist.
mailman.core.logging.initialize(propagate_logs)
- # Run the pre-hook if there is one.
+ # Initialize plugins
+ from mailman.core.plugins import initialize as initialize_plugins
+ initialize_plugins()
+ # Check for deprecated features in config.
config = mailman.config.config
- if config.mailman.pre_hook:
+ if config.mailman.pre_hook: # pragma: nocover
+ warnings.warn(
+ _('The pre_hook configuration value has been replaced by the '
+ 'plugins infrastructure.'), UserWarning)
call_name(config.mailman.pre_hook)
+ # Run the plugin pre_hooks, if one fails, disable the offending plugin.
+ for name in list(config.plugins.keys()):
+ plugin = config.plugins[name]
+ try:
+ plugin.pre_hook()
+ except: # pragma: nocover
+ traceback.print_exc()
+ warnings.warn(_('Plugin $name failed to run its pre_hook,'
+ 'it will be disabled and its components'
+ 'wont be loaded.'), RuntimeWarning)
+ # It failed, push disabling overlay to config. This will stop
+ # components from being loaded.
+ config.push(name + '_error', """\
+[plugin.{}]
+enable: no
+ """.format(name))
+ # And forget about it. This will stop running its post_hook.
+ del config.plugins[name]
# Instantiate the database class, ensure that it's of the right type, and
# initialize it. Then stash the object on our configuration object.
utility_name = ('testing' if testing else 'production')
@@ -173,12 +200,23 @@ def initialize_2(debug=False, propagate_logs=None, testing=False):
def initialize_3():
"""Third initialization step.
- * Post-hook
+ * Plugin's post_hook
"""
- # Run the post-hook if there is one.
+ # Run the plugin post_hooks
config = mailman.config.config
- if config.mailman.post_hook:
+ if config.mailman.post_hook: # pragma: nocover
+ warnings.warn(
+ _('The post_hook configuration value has been replaced by the '
+ 'plugins infrastructure.'), UserWarning)
call_name(config.mailman.post_hook)
+ for plugin in config.plugins.values():
+ try:
+ plugin.post_hook()
+ except: # pragma: nocover
+ # A post_hook may fail, here we just hope for the best that the
+ # plugin can work even if it post_hook failed as it's components
+ # are already loaded.
+ pass
@public
diff --git a/src/mailman/core/pipelines.py b/src/mailman/core/pipelines.py
index 4265d24d1..6e2ad4a27 100644
--- a/src/mailman/core/pipelines.py
+++ b/src/mailman/core/pipelines.py
@@ -24,7 +24,7 @@ from mailman.config import config
from mailman.interfaces.handler import IHandler
from mailman.interfaces.pipeline import (
DiscardMessage, IPipeline, RejectMessage)
-from mailman.utilities.modules import add_components
+from mailman.utilities.plugins import add_pluggable_components
from public import public
@@ -63,6 +63,6 @@ def process(mlist, msg, msgdata, pipeline_name='built-in'):
def initialize():
"""Initialize the pipelines."""
# Find all handlers in the registered plugins.
- add_components('mailman.handlers', IHandler, config.handlers)
+ add_pluggable_components('handlers', IHandler, config.handlers)
# Set up some pipelines.
- add_components('mailman.pipelines', IPipeline, config.pipelines)
+ add_pluggable_components('pipelines', IPipeline, config.pipelines)
diff --git a/src/mailman/core/plugins.py b/src/mailman/core/plugins.py
new file mode 100644
index 000000000..e891f380d
--- /dev/null
+++ b/src/mailman/core/plugins.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2008-2017 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman 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 General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Various plugin helpers."""
+
+from lazr.config import as_boolean
+from mailman.config import config
+from mailman.interfaces.plugin import IPlugin
+from mailman.utilities.modules import find_name
+from public import public
+from zope.interface.verify import verifyObject
+
+
+@public
+def initialize():
+ """Initialize all enabled plugins."""
+ for name, plugin_config in config.plugin_configs:
+ plugin_class_path = plugin_config['class']
+ if as_boolean(plugin_config.enable) and plugin_class_path:
+ plugin_class = find_name(plugin_class_path)
+ plugin = plugin_class()
+ verifyObject(IPlugin, plugin)
+ plugin.name = name
+ assert plugin.name not in config.plugins, (
+ 'Duplicate plugin "{}" found in {}'.format(
+ plugin.name, plugin_class))
+ config.plugins[plugin.name] = plugin
diff --git a/src/mailman/core/rules.py b/src/mailman/core/rules.py
index 8e0d9197c..74934eb99 100644
--- a/src/mailman/core/rules.py
+++ b/src/mailman/core/rules.py
@@ -19,7 +19,7 @@
from mailman.config import config
from mailman.interfaces.rules import IRule
-from mailman.utilities.modules import add_components
+from mailman.utilities.plugins import add_pluggable_components
from public import public
@@ -27,4 +27,4 @@ from public import public
def initialize():
"""Find and register all rules in all plugins."""
# Find rules in plugins.
- add_components('mailman.rules', IRule, config.rules)
+ add_pluggable_components('rules', IRule, config.rules)
diff --git a/src/mailman/core/workflows.py b/src/mailman/core/workflows.py
index b16da7df9..4581956d2 100644
--- a/src/mailman/core/workflows.py
+++ b/src/mailman/core/workflows.py
@@ -19,14 +19,14 @@
from mailman.config import config
from mailman.interfaces.workflows import IWorkflow
-from mailman.utilities.modules import find_components
+from mailman.utilities.plugins import find_pluggable_components
from public import public
@public
def initialize():
"""Find and register all workflows in all plugins."""
- for workflow in find_components('mailman.workflows', IWorkflow):
+ for workflow in find_pluggable_components('workflows', IWorkflow):
assert workflow.name not in config.workflows, (
'Duplicate key "{}" found in {}: "{}"'.format(
workflow.name, config.workflows,