diff options
| author | Barry Warsaw | 2007-07-24 18:45:25 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2007-07-24 18:45:25 -0400 |
| commit | 7a7826e112a1d3f1999cb7a11e6df98cfcb712c9 (patch) | |
| tree | a4c0679185aeb4f4e482e88198b6bee8737837f2 | |
| parent | 8158f01c930d856b0ff892aab53cfbbcc25c85ec (diff) | |
| download | mailman-7a7826e112a1d3f1999cb7a11e6df98cfcb712c9.tar.gz mailman-7a7826e112a1d3f1999cb7a11e6df98cfcb712c9.tar.zst mailman-7a7826e112a1d3f1999cb7a11e6df98cfcb712c9.zip | |
| -rw-r--r-- | Mailman/Defaults.py | 12 | ||||
| -rw-r--r-- | Mailman/database/__init__.py | 47 | ||||
| -rw-r--r-- | Mailman/initialize.py | 49 | ||||
| -rw-r--r-- | Mailman/interfaces/database.py | 48 | ||||
| -rw-r--r-- | setup.py | 6 |
5 files changed, 122 insertions, 40 deletions
diff --git a/Mailman/Defaults.py b/Mailman/Defaults.py index 3c06b709a..7667bc753 100644 --- a/Mailman/Defaults.py +++ b/Mailman/Defaults.py @@ -1,5 +1,3 @@ -# -*- python -*- - # Copyright (C) 1998-2007 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or @@ -19,11 +17,6 @@ """Distributed default settings for significant Mailman config variables.""" -# NEVER make site configuration changes to this file. ALWAYS make them in -# mm_cfg.py instead, in the designated area. See the comments in that file -# for details. - - import os from munepy import Enum @@ -110,11 +103,6 @@ DEFAULT_VAR_DIRECTORY = '/var/mailman' # Database options ##### -# Initialization function for creating the IListManager, IUserManager, and -# IMessageManager objects, as a Python dotted name. This function must take -# zero arguments. -MANAGERS_INIT_FUNCTION = 'Mailman.database.initialize' - # Use this to set the SQLAlchemy database engine URL. You generally have one # primary database connection for all of Mailman. List data and most rosters # will store their data in this database, although external rosters may access diff --git a/Mailman/database/__init__.py b/Mailman/database/__init__.py index 6c6312d0a..d50c33973 100644 --- a/Mailman/database/__init__.py +++ b/Mailman/database/__init__.py @@ -20,30 +20,45 @@ from __future__ import with_statement import os from elixir import objectstore +from zope.interface import implements +from Mailman.interfaces import IDatabase from Mailman.database.listmanager import ListManager from Mailman.database.usermanager import UserManager +__metaclass__ = type __all__ = [ - 'initialize', - 'flush', + 'StockDatabase', + 'flush', # for test convenience ] +flush = None + -def initialize(): - from Mailman.LockFile import LockFile - from Mailman.configuration import config - from Mailman.database import model - # Serialize this so we don't get multiple processes trying to create the - # database at the same time. - lockfile = os.path.join(config.LOCK_DIR, '<dbcreatelock>') - with LockFile(lockfile): - model.initialize() - config.list_manager = ListManager() - config.user_manager = UserManager() - flush() +class StockDatabase: + implements(IDatabase) + + def __init__(self): + # Expose the flush() method for test case convenience using the stock + # database. + global flush + flush = self.flush + self.list_manager = None + self.user_manager = None + def initialize(self): + from Mailman.LockFile import LockFile + from Mailman.configuration import config + from Mailman.database import model + # Serialize this so we don't get multiple processes trying to create the + # database at the same time. + lockfile = os.path.join(config.LOCK_DIR, '<dbcreatelock>') + with LockFile(lockfile): + model.initialize() + self.list_manager = ListManager() + self.user_manager = UserManager() + self.flush() -def flush(): - objectstore.flush() + def flush(self): + objectstore.flush() diff --git a/Mailman/initialize.py b/Mailman/initialize.py index 9dee94cbe..03c861066 100644 --- a/Mailman/initialize.py +++ b/Mailman/initialize.py @@ -26,12 +26,16 @@ by the command line arguments. import os import sys +import pkg_resources + +from zope.interface.verify import verifyObject import Mailman.configuration -import Mailman.database import Mailman.ext import Mailman.loginit +from Mailman.interfaces import IDatabase, IListManager, IUserManager + DOT = '.' @@ -55,17 +59,44 @@ def initialize_1(config, propagate_logs): Mailman.loginit.initialize(propagate_logs) # Set up site extensions directory Mailman.ext.__path__.append(Mailman.configuration.config.EXT_DIR) - # Initialize the IListManager, IMemberManager, and IMessageManager - modparts = Mailman.configuration.config.MANAGERS_INIT_FUNCTION.split(DOT) - funcname = modparts.pop() - modname = DOT.join(modparts) - __import__(modname) - initfunc = getattr(sys.modules[modname], funcname) - initfunc() def initialize_2(): - Mailman.database.initialize() + # Find all declared entry points in the mailman.database group. There + # must be exactly one or two such entry points defined. If there are two, + # then we remove the one called 'stock' since that's the one that we + # distribute and it's obviously being overridden. If we're still left + # with more than one after we filter out the stock one, it is an error. + entrypoints = list(pkg_resources.iter_entry_points('mailman.database')) + if len(entrypoints) == 0: + raise RuntimeError('No database entry points found') + elif len(entrypoints) == 1: + # Okay, this is the one to use. + entrypoint = entrypoints[0] + elif len(database) == 2: + # Find the one /not/ named 'stock'. + entrypoints = [ep for ep in entrypoints if ep.name <> 'stock'] + if len(entrypoints) == 0: + raise RuntimeError('No database entry points found') + elif len(entrypoints) == 2: + raise RuntimeError('Too many database entry points defined') + else: + assert len(entrypoints) == 1, 'Insanity' + entrypoint = entrypoint[0] + else: + raise RuntimeError('Too many database entry points defined') + # Instantiate the database entry point, ensure that it's of the right + # type, and initialize it. Then stash the object on our configuration + # object. + ep_object = entrypoint.load() + db = ep_object() + verifyObject(IDatabase, db) + db.initialize() + Mailman.configuration.config.db = db + verifyObject(IListManager, db.list_manager) + Mailman.configuration.config.list_manager = db.list_manager + verifyObject(IUserManager, db.user_manager) + Mailman.configuration.config.user_manager = db.user_manager def initialize(config=None, propagate_logs=False): diff --git a/Mailman/interfaces/database.py b/Mailman/interfaces/database.py new file mode 100644 index 000000000..8c57ae6b3 --- /dev/null +++ b/Mailman/interfaces/database.py @@ -0,0 +1,48 @@ +# Copyright (C) 2007 by the Free Software Foundation, Inc. +# +# This program 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 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +"""Interfaces for database interaction. + +By providing an object with this interface and declaring it in a package +setup.py file as an entry point in the 'mailman.database' group with the name +'initializer', you can distribute entirely different database layers for +Mailman's back end. +""" + +from zope.interface import Interface, Attribute + + + +class IDatabase(Interface): + """Database layer interface.""" + + def initialize(): + """Initialize the database layer, using whatever means necessary.""" + + def flush(): + """Flush current database changes.""" + + # XXX Eventually we probably need to support a transaction manager + # interface, e.g. begin(), commit(), abort(). We will probably also need + # to support a shutdown() method for cleanly disconnecting from the + # database.sy + + list_manager = Attribute( + """The IListManager instance provided by the database layer.""") + + user_manager = Attribute( + """The IUserManager instance provided by the database layer.""") @@ -82,9 +82,9 @@ Any other spelling is incorrect.""", include_package_data = True, entry_points = { 'console_scripts': list(scripts), - 'setuptools.file_finders': [ - 'bzr = setuptoolsbzr:find_files_for_bzr', - ], + 'setuptools.file_finders': 'bzr = setuptoolsbzr:find_files_for_bzr', + # Entry point for plugging in different database backends. + 'mailman.database': 'stock = Mailman.database:StockDatabase', }, # Third-party requirements. install_requires = [ |
