------------------------------------------------------------ revno: 6729 committer: Barry Warsaw <[email protected]> branch nick: 3.0 timestamp: Fri 2009-05-15 18:37:29 -0400 message: Add initialization pre- and post- hooks, configurable in the config file. This lets you run a bit of Python at various stages of the initialization process. Move the warnings filters to the top mailman package __init__.py so you always get it. lazr.restful is too chatty. The environment variable $MAILMAN_CONFIG_FILE now overrides -C. Hmm, I think we really want it the original way. added: src/mailman/docs/hooks.txt modified: src/mailman/__init__.py src/mailman/config/config.py src/mailman/config/schema.cfg src/mailman/core/initialize.py src/mailman/options.py src/mailman/rest/webservice.py
=== modified file 'src/mailman/__init__.py' --- src/mailman/__init__.py 2009-03-30 01:20:57 +0000 +++ src/mailman/__init__.py 2009-05-15 22:37:29 +0000 @@ -0,0 +1,31 @@ +# Copyright (C) 2009 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/>. + +"""The `mailman` package.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + ] + + +# lazr.restful uses the sha module, but that's deprecated in Python 2.6 in +# favor of the hashlib module. +import warnings +warnings.filterwarnings( + 'ignore', category=DeprecationWarning, module='lazr.restful._resource') === modified file 'src/mailman/config/config.py' --- src/mailman/config/config.py 2009-05-10 20:13:02 +0000 +++ src/mailman/config/config.py 2009-05-15 22:37:29 +0000 @@ -40,7 +40,6 @@ from mailman.styles.manager import StyleManager from mailman.utilities.filesystem import makedirs - SPACE = ' ' === modified file 'src/mailman/config/schema.cfg' --- src/mailman/config/schema.cfg 2009-05-03 19:35:29 +0000 +++ src/mailman/config/schema.cfg 2009-05-15 22:37:29 +0000 @@ -54,6 +54,14 @@ # the pending database. pending_request_life: 3d +# A callable to run with no arguments early in the initialization process. +# This runs before database initialization. +pre_hook: + +# A callable to run with no arguments late in the initialization process. +# This runs after adapters are initialized. +post_hook: + [passwords] # When Mailman generates them, this is the default length of member passwords. === modified file 'src/mailman/core/initialize.py' --- src/mailman/core/initialize.py 2009-03-06 02:30:14 +0000 +++ src/mailman/core/initialize.py 2009-05-15 22:37:29 +0000 @@ -89,15 +89,21 @@ :param debug: Should the database layer be put in debug mode? :type debug: boolean """ + # Run the pre-hook if there is one. + config = mailman.config.config + if config.mailman.pre_hook: + package, dot, function = config.mailman.pre_hook.rpartition('.') + __import__(package) + getattr(sys.modules[package], function)() # Instantiate the database class, ensure that it's of the right type, and # initialize it. Then stash the object on our configuration object. - database_class = mailman.config.config.database['class'] - module_name, class_name = database_class.rsplit('.', 1) - __import__(module_name) - database = getattr(sys.modules[module_name], class_name)() + database_class = config.database['class'] + package, dot, class_name = database_class.rpartition('.') + __import__(package) + database = getattr(sys.modules[package], class_name)() verifyObject(IDatabase, database) database.initialize(debug) - mailman.config.config.db = database + config.db = database # Initialize the rules and chains. Do the imports here so as to avoid # circular imports. from mailman.app.commands import initialize as initialize_commands @@ -123,6 +129,12 @@ from mailman.database.mailinglist import ( adapt_mailing_list_to_acceptable_alias_set) adapter_hooks.append(adapt_mailing_list_to_acceptable_alias_set) + # Run the post-hook if there is one. + config = mailman.config.config + if config.mailman.post_hook: + package, dot, function = config.mailman.post_hook.rpartition('.') + __import__(package) + getattr(sys.modules[package], function)() === added file 'src/mailman/docs/hooks.txt' --- src/mailman/docs/hooks.txt 1970-01-01 00:00:00 +0000 +++ src/mailman/docs/hooks.txt 2009-05-15 22:37:29 +0000 @@ -0,0 +1,111 @@ +===== +Hooks +===== + +Mailman defines two initialization hooks, one which is run early in the +initialization process and the other run late in the initialization process. +Hooks name an importable callable so it must be accessible on sys.path. + + >>> import os, sys + >>> from mailman.config import config + >>> config_directory = os.path.dirname(config.filename) + >>> sys.path.insert(0, config_directory) + + >>> hook_path = os.path.join(config_directory, 'hooks.py') + >>> with open(hook_path, 'w') as fp: + ... print >> fp, """\ + ... counter = 1 + ... def pre_hook(): + ... global counter + ... print 'pre-hook:', counter + ... counter += 1 + ... + ... def post_hook(): + ... global counter + ... print 'post-hook:', counter + ... counter += 1 + ... """ + >>> fp.close() + + +Pre-hook +======== + +We can set the pre-hook in the configuration file. + + >>> config_path = os.path.join(config_directory, 'hooks.cfg') + >>> with open(config_path, 'w') as fp: + ... print >> fp, """\ + ... [meta] + ... extends: test.cfg + ... + ... [mailman] + ... pre_hook: hooks.pre_hook + ... """ + +The hooks are run in the second and third steps of initialization. However, +we can't run those initialization steps in process, so call `bin/version` to +force the hooks to run. + + >>> import subprocess + >>> def call(): + ... proc = subprocess.Popen( + ... 'bin/version', + ... cwd='../..', # testrunner runs from ./parts/test + ... env=dict(MAILMAN_CONFIG_FILE=config_path, + ... PYTHONPATH=config_directory), + ... stdout=subprocess.PIPE, stderr=subprocess.PIPE) + ... stdout, stderr = proc.communicate() + ... assert proc.returncode == 0, stderr + ... print stdout + + >>> call() + pre-hook: 1 + Using GNU Mailman 3... + <BLANKLINE> + + >>> os.remove(config_path) + + +Post-hook +========= + +We can set the post-hook in the configuration file. + + >>> with open(config_path, 'w') as fp: + ... print >> fp, """\ + ... [meta] + ... extends: test.cfg + ... + ... [mailman] + ... post_hook: hooks.post_hook + ... """ + + >>> call() + post-hook: 1 + Using GNU Mailman 3... + <BLANKLINE> + + >>> os.remove(config_path) + + +Running both hooks +================== + +We can set the pre- and post-hooks in the configuration file. + + >>> with open(config_path, 'w') as fp: + ... print >> fp, """\ + ... [meta] + ... extends: test.cfg + ... + ... [mailman] + ... pre_hook: hooks.pre_hook + ... post_hook: hooks.post_hook + ... """ + + >>> call() + pre-hook: 1 + post-hook: 2 + Using GNU Mailman 3... + <BLANKLINE> === modified file 'src/mailman/options.py' --- src/mailman/options.py 2009-02-05 04:35:49 +0000 +++ src/mailman/options.py 2009-05-15 22:37:29 +0000 @@ -137,10 +137,8 @@ from the configuration files. :type propagate_logs: bool or None. """ - # Fall back to using the environment variable if -C is not given. - config_file = (os.getenv('MAILMAN_CONFIG_FILE') - if self.options.config is None - else self.options.config) + # The environment variable overrides the -C option. + config_file = os.getenv('MAILMAN_CONFIG_FILE', self.options.config) initialize(config_file, propagate_logs=propagate_logs) self.sanity_check() === modified file 'src/mailman/rest/webservice.py' --- src/mailman/rest/webservice.py 2009-05-07 02:07:35 +0000 +++ src/mailman/rest/webservice.py 2009-05-15 22:37:29 +0000 @@ -28,13 +28,6 @@ import logging -import warnings - -# lazr.restful uses the sha module, but that's deprecated in Python 2.6 in -# favor of the hashlib module. -warnings.filterwarnings( - 'ignore', category=DeprecationWarning, module='lazr.restful._resource') - # Don't use wsgiref.simple_server.make_server() because we need to override # BaseHTTPRequestHandler.log_message() so that logging output will go to the -- Primary development focus https://code.launchpad.net/~mailman-coders/mailman/3.0 Your team Mailman Checkins is subscribed to branch lp:mailman. To unsubscribe from this branch go to https://code.launchpad.net/~mailman-coders/mailman/3.0/+edit-subscription. _______________________________________________ Mailman-checkins mailing list [email protected] Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org
