diff options
| -rw-r--r-- | src/mailman/config/configure.zcml | 14 | ||||
| -rw-r--r-- | src/mailman/database/factory.py | 58 | ||||
| -rw-r--r-- | src/mailman/database/postgresql.py | 40 | ||||
| -rw-r--r-- | src/mailman/database/sqlite.py | 28 | ||||
| -rw-r--r-- | src/mailman/interfaces/database.py | 19 |
5 files changed, 94 insertions, 65 deletions
diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml index 481ef6d0b..ed85ae1a6 100644 --- a/src/mailman/config/configure.zcml +++ b/src/mailman/config/configure.zcml @@ -22,6 +22,20 @@ factory="mailman.model.requests.ListRequests" /> + <adapter + for="mailman.interfaces.database.IDatabase" + provides="mailman.interfaces.database.ITemporaryDatabase" + factory="mailman.database.sqlite.make_temporary" + name="sqlite" + /> + + <adapter + for="mailman.interfaces.database.IDatabase" + provides="mailman.interfaces.database.ITemporaryDatabase" + factory="mailman.database.postgresql.make_temporary" + name="postgres" + /> + <utility provides="mailman.interfaces.bans.IBanManager" factory="mailman.model.bans.BanManager" diff --git a/src/mailman/database/factory.py b/src/mailman/database/factory.py index 0ea2f4776..127c4aaeb 100644 --- a/src/mailman/database/factory.py +++ b/src/mailman/database/factory.py @@ -27,19 +27,15 @@ __all__ = [ ] -import os import types -import shutil -import tempfile -from functools import partial -from urlparse import urlsplit, urlunsplit +from zope.component import getAdapter from zope.interface import implementer from zope.interface.verify import verifyObject from mailman.config import config -from mailman.interfaces.database import IDatabase, IDatabaseFactory -from mailman.testing.helpers import configuration +from mailman.interfaces.database import ( + IDatabase, IDatabaseFactory, ITemporaryDatabase) from mailman.utilities.modules import call_name @@ -90,16 +86,6 @@ class DatabaseTestingFactory: -def _sqlite_cleanup(self, tempdir): - shutil.rmtree(tempdir) - - -def _postgresql_cleanup(self, database, tempdb_name): - database.store.rollback() - database.store.close() - config.db.store.execute('DROP DATABASE {0}'.format(tempdb_name)) - - @implementer(IDatabaseFactory) class DatabaseTemporaryFactory: """Create a temporary database for some of the migration tests.""" @@ -110,38 +96,6 @@ class DatabaseTemporaryFactory: database_class_name = config.database['class'] database = call_name(database_class_name) verifyObject(IDatabase, database) - if database.TAG == 'sqlite': - tempdir = tempfile.mkdtemp() - url = 'sqlite:///' + os.path.join(tempdir, 'mailman.db') - with configuration('database', url=url): - database.initialize() - database._cleanup = types.MethodType( - partial(_sqlite_cleanup, tempdir=tempdir), database) - # bool column values in SQLite must be integers. - database.FALSE = 0 - database.TRUE = 1 - elif database.TAG == 'postgres': - parts = urlsplit(config.database.url) - assert parts.scheme == 'postgres' - new_parts = list(parts) - new_parts[2] = '/mmtest' - url = urlunsplit(new_parts) - # Use the existing database connection to create a new testing - # database. - config.db.store.execute('ABORT;') - config.db.store.execute('CREATE DATABASE mmtest;') - with configuration('database', url=url): - database.initialize() - database._cleanup = types.MethodType( - partial(_postgresql_cleanup, - database=database, - tempdb_name='mmtest'), - database) - # bool column values in PostgreSQL. - database.FALSE = 'False' - database.TRUE = 'True' - else: - raise RuntimeError( - 'Unsupported test database: {0}'.format(database.TAG)) - # Don't load the migrations. - return database + adapted_database = getAdapter( + database, ITemporaryDatabase, database.TAG) + return adapted_database diff --git a/src/mailman/database/postgresql.py b/src/mailman/database/postgresql.py index 1fb831b3b..49188148f 100644 --- a/src/mailman/database/postgresql.py +++ b/src/mailman/database/postgresql.py @@ -22,12 +22,18 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'PostgreSQLDatabase', + 'make_temporary', ] +import types + +from functools import partial from operator import attrgetter +from urlparse import urlsplit, urlunsplit from mailman.database.base import StormBaseDatabase +from mailman.testing.helpers import configuration @@ -63,3 +69,37 @@ class PostgreSQLDatabase(StormBaseDatabase): max("id") IS NOT null) FROM "{0}"; """.format(model_class.__storm_table__)) + + + +# Test suite adapter for ITemporaryDatabase. + +def _cleanup(self, store, tempdb_name): + from mailman.config import config + store.rollback() + store.close() + # From the original database connection, drop the now unused database. + config.db.store.execute('DROP DATABASE {0}'.format(tempdb_name)) + + +def make_temporary(database): + """Adapts by monkey patching an existing PostgreSQL IDatabase.""" + from mailman.config import config + parts = urlsplit(config.database.url) + assert parts.scheme == 'postgres' + new_parts = list(parts) + new_parts[2] = '/mmtest' + url = urlunsplit(new_parts) + # Use the existing database connection to create a new testing + # database. + config.db.store.execute('ABORT;') + config.db.store.execute('CREATE DATABASE mmtest;') + with configuration('database', url=url): + database.initialize() + database._cleanup = types.MethodType( + partial(_cleanup, store=database.store, tempdb_name='mmtest'), + database) + # bool column values in PostgreSQL. + database.FALSE = 'False' + database.TRUE = 'True' + return database diff --git a/src/mailman/database/sqlite.py b/src/mailman/database/sqlite.py index 305fa006e..a9683457a 100644 --- a/src/mailman/database/sqlite.py +++ b/src/mailman/database/sqlite.py @@ -22,14 +22,20 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ 'SQLiteDatabase', + 'make_temporary', ] import os +import types +import shutil +import tempfile +from functools import partial from urlparse import urlparse from mailman.database.base import StormBaseDatabase +from mailman.testing.helpers import configuration @@ -54,3 +60,25 @@ class SQLiteDatabase(StormBaseDatabase): # Ignore errors if fd > 0: os.close(fd) + + + +# Test suite adapter for ITemporaryDatabase. + +def _cleanup(self, tempdir): + shutil.rmtree(tempdir) + + +def make_temporary(database): + """Adapts by monkey patching an existing SQLite IDatabase.""" + tempdir = tempfile.mkdtemp() + url = 'sqlite:///' + os.path.join(tempdir, 'mailman.db') + with configuration('database', url=url): + database.initialize() + database._cleanup = types.MethodType( + partial(_cleanup, tempdir=tempdir), + database) + # bool column values in SQLite must be integers. + database.FALSE = 0 + database.TRUE = 1 + return database diff --git a/src/mailman/interfaces/database.py b/src/mailman/interfaces/database.py index a74ddd71f..1f39daee7 100644 --- a/src/mailman/interfaces/database.py +++ b/src/mailman/interfaces/database.py @@ -24,6 +24,7 @@ __all__ = [ 'DatabaseError', 'IDatabase', 'IDatabaseFactory', + 'ITemporaryDatabase', ] @@ -50,19 +51,6 @@ class IDatabase(Interface): configuration file setting. """ - def _make_temporary(): - """Make a temporary database. - - This is a @staticmethod used in the test framework. - - :return: An object with one attribute and one method. The attribute - `database` is the temporary `IDatabase`. The method is a callable - named `cleanup()`, taking no arguments which should be called when - the temporary database is no longer necessary. The database will - already be initialized, but no migrations will have been loaded - into it. - """ - def begin(): """Begin the current transaction.""" @@ -77,6 +65,11 @@ class IDatabase(Interface): +class ITemporaryDatabase(Interface): + """Marker interface for test suite adaptation.""" + + + class IDatabaseFactory(Interface): "Interface for creating new databases.""" |
