summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2012-07-20 22:12:04 -0400
committerBarry Warsaw2012-07-20 22:12:04 -0400
commitb3579681d5b25226a9158c9f1c2912a4cb2288cb (patch)
tree27fa85b8f96085e874b84f897df3ef9784918f07
parent27672b5c94c78fecbda8cf91bb62618b7a0dc7cb (diff)
downloadmailman-b3579681d5b25226a9158c9f1c2912a4cb2288cb.tar.gz
mailman-b3579681d5b25226a9158c9f1c2912a4cb2288cb.tar.zst
mailman-b3579681d5b25226a9158c9f1c2912a4cb2288cb.zip
-rw-r--r--src/mailman/database/base.py2
-rw-r--r--src/mailman/database/docs/migration.rst53
-rw-r--r--src/mailman/database/schema/mm_00000000000000_base.py21
-rw-r--r--src/mailman/database/schema/mm_20120407000000.py18
-rw-r--r--src/mailman/database/tests/test_migrations.py29
-rw-r--r--src/mailman/rules/docs/news-moderation.rst2
-rw-r--r--src/mailman/rules/news_moderation.py2
-rw-r--r--src/mailman/testing/database.py47
8 files changed, 119 insertions, 55 deletions
diff --git a/src/mailman/database/base.py b/src/mailman/database/base.py
index 55dee2068..80c62658e 100644
--- a/src/mailman/database/base.py
+++ b/src/mailman/database/base.py
@@ -156,7 +156,7 @@ class StormBaseDatabase:
parent, dot, child = migrations_path.rpartition('.')
else:
parent = migrations_path
- child =''
+ child = ''
# If the database does not yet exist, load the base schema.
filenames = sorted(resource_listdir(parent, child))
# Find out which schema migrations have already been loaded.
diff --git a/src/mailman/database/docs/migration.rst b/src/mailman/database/docs/migration.rst
index 999700ca7..a4d25d648 100644
--- a/src/mailman/database/docs/migration.rst
+++ b/src/mailman/database/docs/migration.rst
@@ -24,17 +24,18 @@ Migrations are applied automatically when Mailman starts up, but can also be
applied at any time by calling in the API directly. Once applied, a
migration's version string is registered so it will not be applied again.
-We see that the base migration is already applied.
+We see that the base migration, as well as subsequent standard migrations, are
+already applied.
>>> from mailman.model.version import Version
>>> results = config.db.store.find(Version, component='schema')
>>> results.count()
- 1
- >>> base = results.one()
- >>> print base.component
- schema
- >>> print base.version
+ 2
+ >>> versions = sorted(result.version for result in results)
+ >>> for version in versions:
+ ... print version
00000000000000
+ 20120407000000
Migrations
@@ -77,7 +78,7 @@ This migration module just adds a marker to the `version` table.
>>> with open(os.path.join(path, '__init__.py'), 'w') as fp:
... pass
- >>> with open(os.path.join(path, 'mm_20120211000000.py'), 'w') as fp:
+ >>> with open(os.path.join(path, 'mm_20129999000000.py'), 'w') as fp:
... print >> fp, """
... from __future__ import unicode_literals
... from mailman.model.version import Version
@@ -94,14 +95,15 @@ This will load the new migration, since it hasn't been loaded before.
>>> for result in sorted(result.version for result in results):
... print result
00000000000000
- 20120211000000
+ 20120407000000
+ 20129999000000
>>> test = config.db.store.find(Version, component='test').one()
>>> print test.version
- 20120211000000
+ 20129999000000
Migrations will only be loaded once.
- >>> with open(os.path.join(path, 'mm_20120211000001.py'), 'w') as fp:
+ >>> with open(os.path.join(path, 'mm_20129999000001.py'), 'w') as fp:
... print >> fp, """
... from __future__ import unicode_literals
... from mailman.model.version import Version
@@ -123,13 +125,14 @@ The first time we load this new migration, we'll get the 801 marker.
>>> for result in sorted(result.version for result in results):
... print result
00000000000000
- 20120211000000
- 20120211000001
+ 20120407000000
+ 20129999000000
+ 20129999000001
>>> test = config.db.store.find(Version, component='test')
>>> for marker in sorted(marker.version for marker in test):
... print marker
00000000000801
- 20120211000000
+ 20129999000000
We do not get an 802 marker because the migration has already been loaded.
@@ -138,13 +141,14 @@ We do not get an 802 marker because the migration has already been loaded.
>>> for result in sorted(result.version for result in results):
... print result
00000000000000
- 20120211000000
- 20120211000001
+ 20120407000000
+ 20129999000000
+ 20129999000001
>>> test = config.db.store.find(Version, component='test')
>>> for marker in sorted(marker.version for marker in test):
... print marker
00000000000801
- 20120211000000
+ 20129999000000
Partial upgrades
@@ -157,13 +161,13 @@ additional migrations, intended to be applied in sequential order.
>>> from shutil import copyfile
>>> from mailman.testing.helpers import chdir
>>> with chdir(path):
- ... copyfile('mm_20120211000000.py', 'mm_20120211000002.py')
- ... copyfile('mm_20120211000000.py', 'mm_20120211000003.py')
- ... copyfile('mm_20120211000000.py', 'mm_20120211000004.py')
+ ... copyfile('mm_20129999000000.py', 'mm_20129999000002.py')
+ ... copyfile('mm_20129999000000.py', 'mm_20129999000003.py')
+ ... copyfile('mm_20129999000000.py', 'mm_20129999000004.py')
Now, only migrate to the ...03 timestamp.
- >>> config.db.load_migrations('20120211000003')
+ >>> config.db.load_migrations('20129999000003')
You'll notice that the ...04 version is not present.
@@ -171,7 +175,8 @@ You'll notice that the ...04 version is not present.
>>> for result in sorted(result.version for result in results):
... print result
00000000000000
- 20120211000000
- 20120211000001
- 20120211000002
- 20120211000003
+ 20120407000000
+ 20129999000000
+ 20129999000001
+ 20129999000002
+ 20129999000003
diff --git a/src/mailman/database/schema/mm_00000000000000_base.py b/src/mailman/database/schema/mm_00000000000000_base.py
index d703088d6..ef448d620 100644
--- a/src/mailman/database/schema/mm_00000000000000_base.py
+++ b/src/mailman/database/schema/mm_00000000000000_base.py
@@ -21,14 +21,14 @@ from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
- 'upgrade',
'post_reset',
'pre_reset',
+ 'upgrade',
]
-_migration_path = None
VERSION = '00000000000000'
+_helper = None
@@ -37,19 +37,12 @@ def upgrade(database, store, version, module_path):
database.load_schema(store, version, filename, module_path)
+
def pre_reset(store):
- global _migration_path
- # Save the entry in the Version table for the test suite reset. This will
- # be restored below.
- from mailman.model.version import Version
- result = store.find(Version, component=VERSION).one()
- # Yes, we abuse this field.
- _migration_path = result.version
+ global _helper
+ from mailman.testing.database import ResetHelper
+ _helper = ResetHelper(VERSION, store)
def post_reset(store):
- from mailman.model.version import Version
- # We need to preserve the Version table entry for this migration, since
- # its existence defines the fact that the tables have been loaded.
- store.add(Version(component='schema', version=VERSION))
- store.add(Version(component=VERSION, version=_migration_path))
+ _helper.restore(store)
diff --git a/src/mailman/database/schema/mm_20120407000000.py b/src/mailman/database/schema/mm_20120407000000.py
index 555d35ea2..ec4fcb2ee 100644
--- a/src/mailman/database/schema/mm_20120407000000.py
+++ b/src/mailman/database/schema/mm_20120407000000.py
@@ -21,6 +21,9 @@ from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
+ 'post_reset',
+ 'pre_reset',
+ 'upgrade',
]
@@ -28,6 +31,10 @@ from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.database import DatabaseError
+VERSION = '20120407000000'
+_helper = None
+
+
def upgrade(database, store, version, module_path):
if database.TAG == 'sqlite':
@@ -68,3 +75,14 @@ def upgrade_sqlite(database, store, version, module_path):
archive_policy, id))
store.execute('drop table mailinglist;')
store.execute('alter table ml_backup rename to mailinglist;')
+
+
+
+def pre_reset(store):
+ global _helper
+ from mailman.testing.database import ResetHelper
+ _helper = ResetHelper(VERSION, store)
+
+
+def post_reset(store):
+ _helper.restore(store)
diff --git a/src/mailman/database/tests/test_migrations.py b/src/mailman/database/tests/test_migrations.py
index 8b4dd1f43..829a447d6 100644
--- a/src/mailman/database/tests/test_migrations.py
+++ b/src/mailman/database/tests/test_migrations.py
@@ -38,7 +38,7 @@ from mailman.config import config
from mailman.interfaces.domain import IDomainManager
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.mailinglist import IAcceptableAliasSet
-from mailman.testing.helpers import configuration
+from mailman.testing.helpers import configuration, temporary_db
from mailman.testing.layers import ConfigLayer
from mailman.utilities.modules import call_name
@@ -137,16 +137,17 @@ class TestMigration20120407(unittest.TestCase):
# Initialize the database and perform the migrations.
database.initialize()
database.load_migrations('20120407000000')
- # Check that the domains survived the migration. This table was
- # not touched so it should be fine.
- domains = list(getUtility(IDomainManager))
- self.assertEqual(len(domains), 1)
- self.assertEqual(domains[0].mail_host, 'example.com')
- # There should be exactly one mailing list defined.
- mlists = list(getUtility(IListManager).mailing_lists)
- self.assertEqual(len(mlists), 1)
- # Get the mailing list object and check its acceptable aliases.
- # This tests that foreign keys continue to work.
- aliases_set = IAcceptableAliasSet(mlists)
- self.assertEqual(set(aliases_set.aliases),
- set(['foo@example.com', 'bar@example.com']))
+ with temporary_db(database):
+ # Check that the domains survived the migration. This table
+ # was not touched so it should be fine.
+ domains = list(getUtility(IDomainManager))
+ self.assertEqual(len(domains), 1)
+ self.assertEqual(domains[0].mail_host, 'example.com')
+ # There should be exactly one mailing list defined.
+ mlists = list(getUtility(IListManager).mailing_lists)
+ self.assertEqual(len(mlists), 1)
+ # Get the mailing list object and check its acceptable
+ # aliases. This tests that foreign keys continue to work.
+ aliases_set = IAcceptableAliasSet(mlists[0])
+ self.assertEqual(set(aliases_set.aliases),
+ set(['foo@example.com', 'bar@example.com']))
diff --git a/src/mailman/rules/docs/news-moderation.rst b/src/mailman/rules/docs/news-moderation.rst
index 651c21bb4..0400c8d9f 100644
--- a/src/mailman/rules/docs/news-moderation.rst
+++ b/src/mailman/rules/docs/news-moderation.rst
@@ -32,6 +32,6 @@ And now all messages will match the rule.
When moderation is turned off, the rule does not match.
- >>> mlist.news_moderation = NewsgroupModeration.none
+ >>> mlist.newsgroup_moderation = NewsgroupModeration.none
>>> rule.check(mlist, msg, {})
False
diff --git a/src/mailman/rules/news_moderation.py b/src/mailman/rules/news_moderation.py
index bd6eb6166..be0d56cb4 100644
--- a/src/mailman/rules/news_moderation.py
+++ b/src/mailman/rules/news_moderation.py
@@ -46,4 +46,4 @@ class ModeratedNewsgroup:
def check(self, mlist, msg, msgdata):
"""See `IRule`."""
- return mlist.news_moderation == NewsgroupModeration.moderated
+ return mlist.newsgroup_moderation == NewsgroupModeration.moderated
diff --git a/src/mailman/testing/database.py b/src/mailman/testing/database.py
new file mode 100644
index 000000000..b442031fa
--- /dev/null
+++ b/src/mailman/testing/database.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2012 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/>.
+
+"""Database test helpers."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'ResetHelper',
+ ]
+
+
+from mailman.model.version import Version
+
+
+
+class ResetHelper:
+ """Help with database resets; used by schema migrations."""
+
+ def __init__(self, version, store):
+ self.version = version
+ # Save the entry in the Version table for the test suite reset. This
+ # will be restored below.
+ result = store.find(Version, component=version).one()
+ self.saved = result.version
+
+ def restore(self, store):
+ # We need to preserve the Version table entry for this migration,
+ # since its existence defines the fact that the tables have been
+ # loaded.
+ store.add(Version(component='schema', version=self.version))
+ store.add(Version(component=self.version, version=self.saved))