diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/interfaces/mailinglist.py | 11 | ||||
| -rw-r--r-- | src/mailman/model/mailinglist.py | 59 | ||||
| -rw-r--r-- | src/mailman/rest/configuration.py | 29 | ||||
| -rw-r--r-- | src/mailman/runners/archive.py | 31 |
4 files changed, 111 insertions, 19 deletions
diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py index 7beaf9c46..8519238db 100644 --- a/src/mailman/interfaces/mailinglist.py +++ b/src/mailman/interfaces/mailinglist.py @@ -24,6 +24,7 @@ __all__ = [ 'IAcceptableAlias', 'IAcceptableAliasSet', 'IMailingList', + 'IArchiverList', 'Personalization', 'ReplyToMunging', ] @@ -54,6 +55,16 @@ class ReplyToMunging(Enum): # An explicit Reply-To header is added explicit_header = 2 +class IArchiverList(Interface): + mailing_list_id = Attribute("""List id""") + archiver_name = Attribute("""Archiver name""") + archiver_enabled = Attribute("""If is enabled.""") + +class IListArchiverSet(Interface): + def getAll(): + """Return dict containing all archivers and their settings.""" + def set(archiver, is_enabled): + """Set archiver for this list.""" class IMailingList(Interface): diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py index dd7a528c3..a0239caa9 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, Store, - TimeDelta, Unicode) + And, Bool, DateTime, Float, Int, Pickle, RawStr, Reference, ReferenceSet, + Store, TimeDelta, Unicode) from urlparse import urljoin from zope.component import getUtility from zope.event import notify @@ -47,8 +47,8 @@ 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, IMailingList, Personalization, - ReplyToMunging) + IAcceptableAlias, IAcceptableAliasSet, IArchiverList, IListArchiverSet, + IMailingList, Personalization, ReplyToMunging) from mailman.interfaces.member import ( AlreadySubscribedError, MemberRole, MissingPreferredAddressError, SubscriptionEvent) @@ -67,6 +67,19 @@ 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) @@ -78,6 +91,7 @@ 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() @@ -538,3 +552,40 @@ class AcceptableAliasSet: AcceptableAlias.mailing_list == self._mailing_list) 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 + + def set(self, archiver, is_enabled): + bool_enabled = (int(is_enabled) != 0) + self.get(archiver).set(archiver_enabled=bool_enabled) + + def isEnabled(self, archiverName): + return self.get(archiverName).one().archiver_enabled + + 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 = [] + 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() + diff --git a/src/mailman/rest/configuration.py b/src/mailman/rest/configuration.py index c726d8a81..eec248ad0 100644 --- a/src/mailman/rest/configuration.py +++ b/src/mailman/rest/configuration.py @@ -34,9 +34,10 @@ from mailman.core.errors import ( from mailman.interfaces.action import Action from mailman.interfaces.archiver import ArchivePolicy from mailman.interfaces.autorespond import ResponseAction -from mailman.interfaces.mailinglist import IAcceptableAliasSet, ReplyToMunging +from mailman.interfaces.mailinglist import IAcceptableAliasSet, IListArchiverSet, ReplyToMunging from mailman.rest.helpers import GetterSetter, PATCH, etag, no_content from mailman.rest.validator import PatchValidator, Validator, enum_validator +from mailman.model.mailinglist import ListArchiverSet @@ -64,6 +65,22 @@ class AcceptableAliases(GetterSetter): for alias in value: alias_set.add(unicode(alias)) +class ListArchivers(GetterSetter): + + def get(self, mlist, attribute): + """Return the mailing list's acceptable aliases.""" + assert attribute == 'archivers', ( + 'Unexpected attribute: {0}'.format(attribute)) + archivers = ListArchiverSet(mlist) + return archivers.getAll() + + def put(self, mlist, attribute, value): + assert attribute == 'archivers', ( + 'Unexpected attribute: {0}'.format(attribute)) + archivers = ListArchiverSet(mlist) + for key, value in value.iteritems(): + archivers.set(key, value) + # Additional validators for converting from web request strings to internal @@ -80,6 +97,15 @@ def list_of_unicode(values): """Turn a list of things into a list of unicodes.""" return [unicode(value) for value in values] +def list_of_pairs_to_dict(pairs): + dict = {} + # If pairs has only one element then it is not a list but a string. + if not isinstance(pairs, list): + pairs = [pairs] + for key_value in pairs: + parts = key_value.split('|') + dict[parts[0]] = parts[1] + return dict # This is the list of IMailingList attributes that are exposed through the @@ -98,6 +124,7 @@ def list_of_unicode(values): ATTRIBUTES = dict( acceptable_aliases=AcceptableAliases(list_of_unicode), + archivers=ListArchivers(list_of_pairs_to_dict), admin_immed_notify=GetterSetter(as_boolean), admin_notify_mchanges=GetterSetter(as_boolean), administrivia=GetterSetter(as_boolean), diff --git a/src/mailman/runners/archive.py b/src/mailman/runners/archive.py index f18bd7c61..9eb1dd0a2 100644 --- a/src/mailman/runners/archive.py +++ b/src/mailman/runners/archive.py @@ -36,6 +36,7 @@ from mailman.config import config from mailman.core.runner import Runner from mailman.interfaces.archiver import ClobberDate from mailman.utilities.datetime import RFC822_DATE_FMT, now +from mailman.model.mailinglist import ListArchiverSet log = logging.getLogger('mailman.error') @@ -91,17 +92,19 @@ class ArchiveRunner(Runner): def _dispose(self, mlist, msg, msgdata): received_time = msgdata.get('received_time', now(strip_tzinfo=False)) for archiver in config.archivers: - msg_copy = copy.deepcopy(msg) - if _should_clobber(msg, msgdata, archiver.name): - original_date = msg_copy['date'] - del msg_copy['date'] - del msg_copy['x-original-date'] - msg_copy['Date'] = received_time.strftime(RFC822_DATE_FMT) - if original_date: - msg_copy['X-Original-Date'] = original_date - # A problem in one archiver should not prevent other archivers - # from running. - try: - archiver.archive_message(mlist, msg_copy) - except Exception: - log.exception('Broken archiver: %s' % archiver.name) + archSet = ListArchiverSet(mlist) + if archSet.isEnabled(archiver.name): + msg_copy = copy.deepcopy(msg) + if _should_clobber(msg, msgdata, archiver.name): + original_date = msg_copy['date'] + del msg_copy['date'] + del msg_copy['x-original-date'] + msg_copy['Date'] = received_time.strftime(RFC822_DATE_FMT) + if original_date: + msg_copy['X-Original-Date'] = original_date + # A problem in one archiver should not prevent other archivers + # from running. + try: + archiver.archive_message(mlist, msg_copy) + except Exception: + log.exception('Broken archiver: %s' % archiver.name) |
