From da566eb047608ed2e65c71dd25979f01c825c843 Mon Sep 17 00:00:00 2001
From: Barry Warsaw
Date: Fri, 21 Aug 2009 16:11:50 -0400
Subject: * Updated NEWS.txt for 3.0a3. * Use the IListManager() adapter
instead of hanging the list manager off of config.db. This makes the code
somewhat cleaner.
---
src/attic/add_members.py | 186 ++++++++++++++++++++++++++++++++++++
src/mailman/Archiver/HyperArch.py | 3 +-
src/mailman/app/lifecycle.py | 5 +-
src/mailman/app/registrar.py | 3 +-
src/mailman/bin/add_members.py | 186 ------------------------------------
src/mailman/bin/inject.py | 3 +-
src/mailman/commands/cli_lists.py | 6 +-
src/mailman/commands/cli_members.py | 3 +-
src/mailman/config/configure.zcml | 6 ++
src/mailman/database/__init__.py | 2 -
src/mailman/database/listmanager.py | 20 ++--
11 files changed, 220 insertions(+), 203 deletions(-)
create mode 100644 src/attic/add_members.py
delete mode 100644 src/mailman/bin/add_members.py
(limited to 'src')
diff --git a/src/attic/add_members.py b/src/attic/add_members.py
new file mode 100644
index 000000000..540c0facb
--- /dev/null
+++ b/src/attic/add_members.py
@@ -0,0 +1,186 @@
+# Copyright (C) 1998-2009 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 .
+
+import os
+import sys
+import codecs
+
+from cStringIO import StringIO
+from email.utils import parseaddr
+
+from mailman import Utils
+from mailman import i18n
+from mailman.app.membership import add_member
+from mailman.config import config
+from mailman.core import errors
+from mailman.email.message import UserNotification
+from mailman.interfaces.member import AlreadySubscribedError, DeliveryMode
+from mailman.options import SingleMailingListOptions
+
+_ = i18n._
+
+
+
+class ScriptOptions(SingleMailingListOptions):
+ usage=_("""\
+%prog [options]
+
+Add members to a list. 'listname' is the name of the Mailman list you are
+adding members to; the list must already exist.
+
+You must supply at least one of -r and -d options. At most one of the
+files can be '-'.
+""")
+
+ def add_options(self):
+ super(ScriptOptions, self).add_options()
+ self.parser.add_option(
+ '-r', '--regular-members-file',
+ type='string', dest='regular', help=_("""\
+A file containing addresses of the members to be added, one address per line.
+This list of people become non-digest members. If file is '-', read addresses
+from stdin."""))
+ self.parser.add_option(
+ '-d', '--digest-members-file',
+ type='string', dest='digest', help=_("""\
+Similar to -r, but these people become digest members."""))
+ self.parser.add_option(
+ '-w', '--welcome-msg',
+ type='yesno', metavar='', help=_("""\
+Set whether or not to send the list members a welcome message, overriding
+whatever the list's 'send_welcome_msg' setting is."""))
+ self.parser.add_option(
+ '-a', '--admin-notify',
+ type='yesno', metavar='', help=_("""\
+Set whether or not to send the list administrators a notification on the
+success/failure of these subscriptions, overriding whatever the list's
+'admin_notify_mchanges' setting is."""))
+
+ def sanity_check(self):
+ if not self.options.listname:
+ self.parser.error(_('Missing listname'))
+ if len(self.arguments) > 0:
+ self.parser.print_error(_('Unexpected arguments'))
+ if self.options.regular is None and self.options.digest is None:
+ parser.error(_('At least one of -r or -d is required'))
+ if self.options.regular == '-' and self.options.digest == '-':
+ parser.error(_("-r and -d cannot both be '-'"))
+
+
+
+def readfile(filename):
+ if filename == '-':
+ fp = sys.stdin
+ else:
+ # XXX Need to specify other encodings.
+ fp = codecs.open(filename, encoding='utf-8')
+ # Strip all the lines of whitespace and discard blank lines
+ try:
+ return set(line.strip() for line in fp if line)
+ finally:
+ if fp is not sys.stdin:
+ fp.close()
+
+
+
+class Tee:
+ def __init__(self, outfp):
+ self._outfp = outfp
+
+ def write(self, msg):
+ sys.stdout.write(msg)
+ self._outfp.write(msg)
+
+
+
+def addall(mlist, subscribers, delivery_mode, ack, admin_notify, outfp):
+ tee = Tee(outfp)
+ for subscriber in subscribers:
+ try:
+ fullname, address = parseaddr(subscriber)
+ # Watch out for the empty 8-bit string.
+ if not fullname:
+ fullname = u''
+ password = Utils.MakeRandomPassword()
+ add_member(mlist, address, fullname, password, delivery_mode,
+ unicode(config.mailman.default_language))
+ # XXX Support ack and admin_notify
+ except AlreadySubscribedError:
+ print >> tee, _('Already a member: $subscriber')
+ except errors.InvalidEmailAddress:
+ if not address:
+ print >> tee, _('Bad/Invalid email address: blank line')
+ else:
+ print >> tee, _('Bad/Invalid email address: $subscriber')
+ else:
+ print >> tee, _('Subscribing: $subscriber')
+
+
+
+def main():
+ options = ScriptOptions()
+ options.initialize()
+
+ fqdn_listname = options.options.listname
+ mlist = config.db.list_manager.get(fqdn_listname)
+ if mlist is None:
+ parser.error(_('No such list: $fqdn_listname'))
+
+ # Set up defaults.
+ send_welcome_msg = (options.options.welcome_msg
+ if options.options.welcome_msg is not None
+ else mlist.send_welcome_msg)
+ admin_notify = (options.options.admin_notify
+ if options.options.admin_notify is not None
+ else mlist.admin_notify)
+
+ with i18n.using_language(mlist.preferred_language):
+ if options.options.digest:
+ dmembers = readfile(options.options.digest)
+ else:
+ dmembers = set()
+ if options.options.regular:
+ nmembers = readfile(options.options.regular)
+ else:
+ nmembers = set()
+
+ if not dmembers and not nmembers:
+ print _('Nothing to do.')
+ sys.exit(0)
+
+ outfp = StringIO()
+ if nmembers:
+ addall(mlist, nmembers, DeliveryMode.regular,
+ send_welcome_msg, admin_notify, outfp)
+
+ if dmembers:
+ addall(mlist, dmembers, DeliveryMode.mime_digests,
+ send_welcome_msg, admin_notify, outfp)
+
+ config.db.commit()
+
+ if admin_notify:
+ subject = _('$mlist.real_name subscription notification')
+ msg = UserNotification(
+ mlist.owner, mlist.no_reply_address, subject,
+ outfp.getvalue(), mlist.preferred_language)
+ msg.send(mlist)
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/mailman/Archiver/HyperArch.py b/src/mailman/Archiver/HyperArch.py
index d78831e8e..b3601f5fa 100644
--- a/src/mailman/Archiver/HyperArch.py
+++ b/src/mailman/Archiver/HyperArch.py
@@ -49,6 +49,7 @@ from mailman import i18n
from mailman.Archiver import HyperDatabase
from mailman.Archiver import pipermail
from mailman.config import config
+from mailman.interfaces.listmanager import IListManager
log = logging.getLogger('mailman.error')
@@ -319,7 +320,7 @@ class Article(pipermail.Article):
listname = d.get('__listname')
if listname:
del d['__listname']
- d['_mlist'] = config.db.list_manager.get(listname)
+ d['_mlist'] = IListManager(config).get(listname)
if not d.has_key('_lang'):
if hasattr(self, '_mlist'):
self._lang = self._mlist.preferred_language
diff --git a/src/mailman/app/lifecycle.py b/src/mailman/app/lifecycle.py
index d7a8ec1a7..b7f30afd8 100644
--- a/src/mailman/app/lifecycle.py
+++ b/src/mailman/app/lifecycle.py
@@ -34,6 +34,7 @@ from mailman.config import config
from mailman.email.validate import validate
from mailman.interfaces.domain import (
BadDomainSpecificationError, IDomainManager)
+from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.member import MemberRole
from mailman.utilities.modules import call_name
@@ -51,7 +52,7 @@ def create_list(fqdn_listname, owners=None):
listname, domain = fqdn_listname.split('@', 1)
if domain not in IDomainManager(config):
raise BadDomainSpecificationError(domain)
- mlist = config.db.list_manager.create(fqdn_listname)
+ mlist = IListManager(config).create(fqdn_listname)
for style in config.style_manager.lookup(mlist):
style.apply(mlist)
# Coordinate with the MTA, as defined in the configuration file.
@@ -80,7 +81,7 @@ def remove_list(fqdn_listname, mailing_list=None, archives=True):
for member in mailing_list.subscribers.members:
member.unsubscribe()
# Delete the mailing list from the database.
- config.db.list_manager.delete(mailing_list)
+ IListManager(config).delete(mailing_list)
# Do the MTA-specific list deletion tasks
call_name(config.mta.incoming).create(mailing_list)
# Remove the list directory.
diff --git a/src/mailman/app/registrar.py b/src/mailman/app/registrar.py
index 4ec7991d6..3161ed149 100644
--- a/src/mailman/app/registrar.py
+++ b/src/mailman/app/registrar.py
@@ -35,6 +35,7 @@ from mailman.email.message import UserNotification
from mailman.email.validate import validate
from mailman.i18n import _
from mailman.interfaces.domain import IDomain
+from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.member import MemberRole
from mailman.interfaces.pending import IPendable
from mailman.interfaces.registrar import IRegistrar
@@ -136,7 +137,7 @@ class Registrar:
# to the list right now.
list_name = pendable.get('list_name')
if list_name is not None:
- mlist = config.db.list_manager.get(list_name)
+ mlist = IListManager(config).get(list_name)
if mlist:
addr.subscribe(mlist, MemberRole.member)
return True
diff --git a/src/mailman/bin/add_members.py b/src/mailman/bin/add_members.py
deleted file mode 100644
index 540c0facb..000000000
--- a/src/mailman/bin/add_members.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright (C) 1998-2009 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 .
-
-import os
-import sys
-import codecs
-
-from cStringIO import StringIO
-from email.utils import parseaddr
-
-from mailman import Utils
-from mailman import i18n
-from mailman.app.membership import add_member
-from mailman.config import config
-from mailman.core import errors
-from mailman.email.message import UserNotification
-from mailman.interfaces.member import AlreadySubscribedError, DeliveryMode
-from mailman.options import SingleMailingListOptions
-
-_ = i18n._
-
-
-
-class ScriptOptions(SingleMailingListOptions):
- usage=_("""\
-%prog [options]
-
-Add members to a list. 'listname' is the name of the Mailman list you are
-adding members to; the list must already exist.
-
-You must supply at least one of -r and -d options. At most one of the
-files can be '-'.
-""")
-
- def add_options(self):
- super(ScriptOptions, self).add_options()
- self.parser.add_option(
- '-r', '--regular-members-file',
- type='string', dest='regular', help=_("""\
-A file containing addresses of the members to be added, one address per line.
-This list of people become non-digest members. If file is '-', read addresses
-from stdin."""))
- self.parser.add_option(
- '-d', '--digest-members-file',
- type='string', dest='digest', help=_("""\
-Similar to -r, but these people become digest members."""))
- self.parser.add_option(
- '-w', '--welcome-msg',
- type='yesno', metavar='', help=_("""\
-Set whether or not to send the list members a welcome message, overriding
-whatever the list's 'send_welcome_msg' setting is."""))
- self.parser.add_option(
- '-a', '--admin-notify',
- type='yesno', metavar='', help=_("""\
-Set whether or not to send the list administrators a notification on the
-success/failure of these subscriptions, overriding whatever the list's
-'admin_notify_mchanges' setting is."""))
-
- def sanity_check(self):
- if not self.options.listname:
- self.parser.error(_('Missing listname'))
- if len(self.arguments) > 0:
- self.parser.print_error(_('Unexpected arguments'))
- if self.options.regular is None and self.options.digest is None:
- parser.error(_('At least one of -r or -d is required'))
- if self.options.regular == '-' and self.options.digest == '-':
- parser.error(_("-r and -d cannot both be '-'"))
-
-
-
-def readfile(filename):
- if filename == '-':
- fp = sys.stdin
- else:
- # XXX Need to specify other encodings.
- fp = codecs.open(filename, encoding='utf-8')
- # Strip all the lines of whitespace and discard blank lines
- try:
- return set(line.strip() for line in fp if line)
- finally:
- if fp is not sys.stdin:
- fp.close()
-
-
-
-class Tee:
- def __init__(self, outfp):
- self._outfp = outfp
-
- def write(self, msg):
- sys.stdout.write(msg)
- self._outfp.write(msg)
-
-
-
-def addall(mlist, subscribers, delivery_mode, ack, admin_notify, outfp):
- tee = Tee(outfp)
- for subscriber in subscribers:
- try:
- fullname, address = parseaddr(subscriber)
- # Watch out for the empty 8-bit string.
- if not fullname:
- fullname = u''
- password = Utils.MakeRandomPassword()
- add_member(mlist, address, fullname, password, delivery_mode,
- unicode(config.mailman.default_language))
- # XXX Support ack and admin_notify
- except AlreadySubscribedError:
- print >> tee, _('Already a member: $subscriber')
- except errors.InvalidEmailAddress:
- if not address:
- print >> tee, _('Bad/Invalid email address: blank line')
- else:
- print >> tee, _('Bad/Invalid email address: $subscriber')
- else:
- print >> tee, _('Subscribing: $subscriber')
-
-
-
-def main():
- options = ScriptOptions()
- options.initialize()
-
- fqdn_listname = options.options.listname
- mlist = config.db.list_manager.get(fqdn_listname)
- if mlist is None:
- parser.error(_('No such list: $fqdn_listname'))
-
- # Set up defaults.
- send_welcome_msg = (options.options.welcome_msg
- if options.options.welcome_msg is not None
- else mlist.send_welcome_msg)
- admin_notify = (options.options.admin_notify
- if options.options.admin_notify is not None
- else mlist.admin_notify)
-
- with i18n.using_language(mlist.preferred_language):
- if options.options.digest:
- dmembers = readfile(options.options.digest)
- else:
- dmembers = set()
- if options.options.regular:
- nmembers = readfile(options.options.regular)
- else:
- nmembers = set()
-
- if not dmembers and not nmembers:
- print _('Nothing to do.')
- sys.exit(0)
-
- outfp = StringIO()
- if nmembers:
- addall(mlist, nmembers, DeliveryMode.regular,
- send_welcome_msg, admin_notify, outfp)
-
- if dmembers:
- addall(mlist, dmembers, DeliveryMode.mime_digests,
- send_welcome_msg, admin_notify, outfp)
-
- config.db.commit()
-
- if admin_notify:
- subject = _('$mlist.real_name subscription notification')
- msg = UserNotification(
- mlist.owner, mlist.no_reply_address, subject,
- outfp.getvalue(), mlist.preferred_language)
- msg.send(mlist)
-
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/mailman/bin/inject.py b/src/mailman/bin/inject.py
index 73f1b9015..591d6697b 100644
--- a/src/mailman/bin/inject.py
+++ b/src/mailman/bin/inject.py
@@ -24,6 +24,7 @@ from mailman import Utils
from mailman.configuration import config
from mailman.i18n import _
from mailman.inject import inject_text
+from mailman.interfaces.listmanager import IListManager
from mailman.message import Message
from mailman.options import SingleMailingListOptions
@@ -71,7 +72,7 @@ def main():
options.parser.error(_('Bad queue directory: $qdir'))
fqdn_listname = options.options.listname
- mlist = config.db.list_manager.get(fqdn_listname)
+ mlist = IListManager(config).get(fqdn_listname)
if mlist is None:
options.parser.error(_('No such list: $fqdn_listname'))
diff --git a/src/mailman/commands/cli_lists.py b/src/mailman/commands/cli_lists.py
index b95d1a779..95c7b650c 100644
--- a/src/mailman/commands/cli_lists.py
+++ b/src/mailman/commands/cli_lists.py
@@ -39,7 +39,7 @@ from mailman.i18n import _, using_language
from mailman.interfaces.command import ICLISubCommand
from mailman.interfaces.domain import (
BadDomainSpecificationError, IDomainManager)
-from mailman.interfaces.listmanager import ListAlreadyExistsError
+from mailman.interfaces.listmanager import IListManager, ListAlreadyExistsError
@@ -76,7 +76,7 @@ class Lists:
def process(self, args):
"""See `ICLISubCommand`."""
mailing_lists = []
- list_manager = config.db.list_manager
+ list_manager = IListManager(config)
# Gather the matching mailing lists.
for fqdn_name in sorted(list_manager.names):
mlist = list_manager.get(fqdn_name)
@@ -251,7 +251,7 @@ remove any residual archives."""))
assert len(args.listname) == 1, (
'Unexpected positional arguments: %s' % args.listname)
fqdn_listname = args.listname[0]
- mlist = config.db.list_manager.get(fqdn_listname)
+ mlist = IListManager(config).get(fqdn_listname)
if mlist is None:
if args.archives:
log(_('No such list: $fqdn_listname; '
diff --git a/src/mailman/commands/cli_members.py b/src/mailman/commands/cli_members.py
index 7e22166ed..5a2a419f7 100644
--- a/src/mailman/commands/cli_members.py
+++ b/src/mailman/commands/cli_members.py
@@ -35,6 +35,7 @@ from mailman.app.membership import add_member
from mailman.config import config
from mailman.i18n import _
from mailman.interfaces.command import ICLISubCommand
+from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.member import DeliveryMode
@@ -67,7 +68,7 @@ class Members:
assert len(args.listname) == 1, (
'Unexpected positional arguments: %s' % args.listname)
fqdn_listname = args.listname[0]
- mlist = config.db.list_manager.get(fqdn_listname)
+ mlist = IListManager(config).get(fqdn_listname)
if mlist is None:
self.parser.error(_('No such list: $fqdn_listname'))
if args.filename == '-':
diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml
index cc1a9face..7e139980c 100644
--- a/src/mailman/config/configure.zcml
+++ b/src/mailman/config/configure.zcml
@@ -6,6 +6,12 @@
+
+