summaryrefslogtreecommitdiff
path: root/src/mailman/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/model')
-rw-r--r--src/mailman/model/mailinglist.py107
-rw-r--r--src/mailman/model/tests/test_domain.py2
-rw-r--r--src/mailman/model/tests/test_listmanager.py5
-rw-r--r--src/mailman/model/tests/test_mailinglist.py102
4 files changed, 169 insertions, 47 deletions
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index a0239caa9..e9601e412 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -28,8 +28,8 @@ __all__ = [
import os
from storm.locals import (
- And, Bool, DateTime, Float, Int, Pickle, RawStr, Reference, ReferenceSet,
- Store, TimeDelta, Unicode)
+ And, Bool, DateTime, Float, Int, Pickle, RawStr, Reference, Store,
+ TimeDelta, Unicode)
from urlparse import urljoin
from zope.component import getUtility
from zope.event import notify
@@ -47,7 +47,7 @@ from mailman.interfaces.digests import DigestFrequency
from mailman.interfaces.domain import IDomainManager
from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.mailinglist import (
- IAcceptableAlias, IAcceptableAliasSet, IArchiverList, IListArchiverSet,
+ IAcceptableAlias, IAcceptableAliasSet, IListArchiver, IListArchiverSet,
IMailingList, Personalization, ReplyToMunging)
from mailman.interfaces.member import (
AlreadySubscribedError, MemberRole, MissingPreferredAddressError,
@@ -67,19 +67,6 @@ from mailman.utilities.string import expand
SPACE = ' '
UNDERSCORE = '_'
-@implementer(IArchiverList)
-class ArchiverList(Model):
- __storm_primary__ = "mailing_list_id", "archiver_name"
- mailing_list_id = Int()
- archiver_name = Unicode()
- archiver_enabled = Bool()
-
- def __init__(self, mailing_list_id, archiver_name):
- self.mailing_list_id = mailing_list_id
- self.archiver_name = archiver_name
- self.archiver_enabled = False
-
-
@implementer(IMailingList)
@@ -91,7 +78,6 @@ class MailingList(Model):
# XXX denotes attributes that should be part of the public interface but
# are currently missing.
- archivers = ReferenceSet(id, ArchiverList.mailing_list_id)
# List identity
list_name = Unicode()
mail_host = Unicode()
@@ -553,39 +539,68 @@ class AcceptableAliasSet:
for alias in aliases:
yield alias.alias
-@implementer(IListArchiverSet)
-class ListArchiverSet:
- def __init__(self, mailing_list):
- self._mailing_list = mailing_list
- self.lazyAdd()
- def getAll(self):
- entries = Store.of(self._mailing_list).find(ArchiverList, ArchiverList.mailing_list_id == self._mailing_list.id)
- all_in_config = {archiver.name for archiver in config.archivers}
- ret = {}
- for entry in entries:
- if entry.archiver_name in all_in_config:
- ret[entry.archiver_name] = int(entry.archiver_enabled)
- return ret
+
+@implementer(IListArchiver)
+class ListArchiver(Model):
+ """See `IListArchiver`."""
+
+ id = Int(primary=True)
+
+ mailing_list_id = Int()
+ mailing_list = Reference(mailing_list_id, MailingList.id)
+ name = Unicode()
+ _is_enabled = Bool()
+
+ def __init__(self, mailing_list, archiver_name, system_archiver):
+ self.mailing_list = mailing_list
+ self.name = archiver_name
+ self._is_enabled = system_archiver.is_enabled
- def set(self, archiver, is_enabled):
- bool_enabled = (int(is_enabled) != 0)
- self.get(archiver).set(archiver_enabled=bool_enabled)
+ @property
+ def system_archiver(self):
+ for archiver in config.archivers:
+ if archiver.name == self.name:
+ return archiver
+ return None
+
+ @property
+ def is_enabled(self):
+ return self.system_archiver.is_enabled and self._is_enabled
- def isEnabled(self, archiverName):
- return self.get(archiverName).one().archiver_enabled
+ @is_enabled.setter
+ def is_enabled(self, value):
+ self._is_enabled = value
- def get(self, archiverName):
- return Store.of(self._mailing_list).find(ArchiverList,
- (ArchiverList.mailing_list_id == self._mailing_list.id) & (ArchiverList.archiver_name == archiverName))
- def lazyAdd(self):
- names = []
+@implementer(IListArchiverSet)
+class ListArchiverSet:
+ def __init__(self, mailing_list):
+ self._mailing_list = mailing_list
+ system_archivers = {}
for archiver in config.archivers:
- count = self.get(archiver.name).count()
- names.append((archiver.name, count))
- if not count:
- entry = ArchiverList(self._mailing_list.id, archiver.name)
- Store.of(self._mailing_list).add(entry)
- Store.of(self._mailing_list).commit()
+ system_archivers[archiver.name] = archiver
+ # Add any system enabled archivers which aren't already associated
+ # with the mailing list.
+ store = Store.of(self._mailing_list)
+ for archiver_name in system_archivers:
+ exists = store.find(
+ ListArchiver,
+ And(ListArchiver.mailing_list == mailing_list,
+ ListArchiver.name == archiver_name)).one()
+ if exists is None:
+ store.add(ListArchiver(mailing_list, archiver_name,
+ system_archivers[archiver_name]))
+
+ @property
+ def archivers(self):
+ entries = Store.of(self._mailing_list).find(
+ ListArchiver, ListArchiver.mailing_list == self._mailing_list)
+ for entry in entries:
+ yield entry
+ def get(self, archiver_name):
+ return Store.of(self._mailing_list).find(
+ ListArchiver,
+ And(ListArchiver.mailing_list == self._mailing_list,
+ ListArchiver.name == archiver_name)).one()
diff --git a/src/mailman/model/tests/test_domain.py b/src/mailman/model/tests/test_domain.py
index 3d7f95615..67924d393 100644
--- a/src/mailman/model/tests/test_domain.py
+++ b/src/mailman/model/tests/test_domain.py
@@ -21,6 +21,8 @@ from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
+ 'TestDomainLifecycleEvents',
+ 'TestDomainManager',
]
diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py
index 152d96b9f..b18c8e5d1 100644
--- a/src/mailman/model/tests/test_listmanager.py
+++ b/src/mailman/model/tests/test_listmanager.py
@@ -17,10 +17,13 @@
"""Test the ListManager."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
+ 'TestListCreation',
+ 'TestListLifecycleEvents',
+ 'TestListManager',
]
diff --git a/src/mailman/model/tests/test_mailinglist.py b/src/mailman/model/tests/test_mailinglist.py
new file mode 100644
index 000000000..09c4cb38f
--- /dev/null
+++ b/src/mailman/model/tests/test_mailinglist.py
@@ -0,0 +1,102 @@
+# Copyright (C) 2013 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/>.
+
+"""Test MailingLists and related model objects.."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestListArchiver',
+ 'TestDisabledListArchiver',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.config import config
+from mailman.interfaces.mailinglist import IListArchiverSet
+from mailman.testing.helpers import configuration
+from mailman.testing.layers import ConfigLayer
+
+
+
+class TestListArchiver(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('ant@example.com')
+ self._set = IListArchiverSet(self._mlist)
+
+ def test_list_archivers(self):
+ # Find the set of archivers registered for this mailing list.
+ self.assertEqual(
+ ['mail-archive', 'mhonarc', 'prototype'],
+ sorted(archiver.name for archiver in self._set.archivers))
+
+ def test_get_archiver(self):
+ # Use .get() to see if a mailing list has an archiver.
+ archiver = self._set.get('prototype')
+ self.assertEqual(archiver.name, 'prototype')
+ self.assertTrue(archiver.is_enabled)
+ self.assertEqual(archiver.mailing_list, self._mlist)
+ self.assertEqual(archiver.system_archiver.name, 'prototype')
+
+ def test_get_archiver_no_such(self):
+ # Using .get() on a non-existing name returns None.
+ self.assertIsNone(self._set.get('no-such-archiver'))
+
+ def test_site_disabled(self):
+ # Here the system configuration enables all the archivers in time for
+ # the archive set to be created with all list archivers enabled. But
+ # then the site-wide archiver gets disabled, so the list specific
+ # archiver will also be disabled.
+ archiver_set = IListArchiverSet(self._mlist)
+ archiver = archiver_set.get('prototype')
+ self.assertTrue(archiver.is_enabled)
+ # Disable the site-wide archiver.
+ archiver.system_archiver.is_enabled = False
+ self.assertFalse(archiver.is_enabled)
+
+
+
+class TestDisabledListArchiver(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('ant@example.com')
+
+ @configuration('archiver.prototype', enable='no')
+ def test_enable_list_archiver(self):
+ # When the system configuration file disables an archiver site-wide,
+ # the list-specific mailing list will get initialized as not enabled.
+ # Create the archiver set on the fly so that it doesn't get
+ # initialized with a configuration that enables the prototype archiver.
+ archiver_set = IListArchiverSet(self._mlist)
+ archiver = archiver_set.get('prototype')
+ self.assertFalse(archiver.is_enabled)
+ # Enable both the list archiver and the system archiver.
+ archiver.is_enabled = True
+ config.push('enable prototype', """\
+ [archiver.prototype]
+ enable: yes
+ """)
+ # Get the IListArchiver again.
+ archiver = archiver_set.get('prototype')
+ self.assertTrue(archiver.is_enabled)
+ config.pop('enable prototype')