From 3ffddba89c0a0c66280a90b6643d9a66632a5b74 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 22 Apr 2012 16:40:34 -0400 Subject: - Convert the CLI modules to use print_function. - Use the @transactional decorator. - Use the transaction context manager. --- src/mailman/commands/cli_members.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/mailman/commands/cli_members.py') diff --git a/src/mailman/commands/cli_members.py b/src/mailman/commands/cli_members.py index 2bf6be848..17312e8ec 100644 --- a/src/mailman/commands/cli_members.py +++ b/src/mailman/commands/cli_members.py @@ -37,6 +37,7 @@ from zope.interface import implements from mailman.app.membership import add_member from mailman.config import config from mailman.core.i18n import _ +from mailman.database.transaction import transactional from mailman.interfaces.command import ICLISubCommand from mailman.interfaces.listmanager import IListManager from mailman.interfaces.member import ( @@ -177,6 +178,7 @@ class Members: if fp is not sys.stdout: fp.close() + @transactional def add_members(self, mlist, args): """Add the members in a file to a mailing list. @@ -207,9 +209,8 @@ class Members: except AlreadySubscribedError: # It's okay if the address is already subscribed, just # print a warning and continue. - print('Already subscribed (skipping):', + print('Already subscribed (skipping):', email, display_name) finally: if fp is not sys.stdin: fp.close() - config.db.commit() -- cgit v1.2.3-70-g09d2 From 658fad42b04420962e6ac478247411ee77483d93 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Wed, 25 Apr 2012 22:08:22 -0400 Subject: General code cleanup. - Add explicit dependency on zope.event in setup.py. - Use Python 3 compatible syntax for specifying that a class implements an interface, i.e. the @implementer class decorator. - print_function futures. - Whitespace normalization. --- setup.py | 1 + src/mailman/app/bounces.py | 6 ++-- src/mailman/app/docs/lifecycle.rst | 6 ++-- src/mailman/app/registrar.py | 7 ++--- src/mailman/app/subscriptions.py | 5 ++- src/mailman/app/templates.py | 5 ++- src/mailman/archiving/mailarchive.py | 7 ++--- src/mailman/archiving/mhonarc.py | 7 ++--- src/mailman/archiving/prototype.py | 7 ++--- src/mailman/chains/base.py | 14 ++++----- src/mailman/chains/builtin.py | 7 ++--- src/mailman/chains/headers.py | 6 ++-- src/mailman/chains/hold.py | 6 ++-- src/mailman/chains/moderation.py | 8 ++--- src/mailman/commands/cli_aliases.py | 14 ++++----- src/mailman/commands/cli_control.py | 29 ++++++++---------- src/mailman/commands/cli_help.py | 7 ++--- src/mailman/commands/cli_import.py | 5 ++- src/mailman/commands/cli_info.py | 28 ++++++++--------- src/mailman/commands/cli_inject.py | 13 ++++---- src/mailman/commands/cli_lists.py | 11 +++---- src/mailman/commands/cli_members.py | 5 ++- src/mailman/commands/cli_qfile.py | 15 +++++---- src/mailman/commands/cli_status.py | 11 +++---- src/mailman/commands/cli_unshunt.py | 11 +++---- src/mailman/commands/cli_version.py | 9 +++--- src/mailman/commands/cli_withlist.py | 49 +++++++++++++++--------------- src/mailman/commands/docs/end.rst | 8 ++--- src/mailman/commands/eml_confirm.py | 13 ++++---- src/mailman/commands/eml_echo.py | 4 +-- src/mailman/commands/eml_end.py | 6 ++-- src/mailman/commands/eml_help.py | 9 +++--- src/mailman/commands/eml_membership.py | 12 +++----- src/mailman/config/config.py | 5 ++- src/mailman/core/constants.py | 7 ++--- src/mailman/core/pipelines.py | 5 ++- src/mailman/core/runner.py | 7 ++--- src/mailman/core/switchboard.py | 7 +++-- src/mailman/core/system.py | 7 +++-- src/mailman/core/tests/test_pipelines.py | 10 +++--- src/mailman/database/base.py | 9 +++--- src/mailman/email/validate.py | 5 ++- src/mailman/handlers/acknowledge.py | 6 ++-- src/mailman/handlers/after_delivery.py | 7 ++--- src/mailman/handlers/avoid_duplicates.py | 7 ++--- src/mailman/handlers/cleanse.py | 7 ++--- src/mailman/handlers/cleanse_dkim.py | 7 ++--- src/mailman/handlers/cook_headers.py | 7 ++--- src/mailman/handlers/decorate.py | 7 ++--- src/mailman/handlers/file_recipients.py | 7 ++--- src/mailman/handlers/member_recipients.py | 5 ++- src/mailman/handlers/mime_delete.py | 7 ++--- src/mailman/handlers/owner_recipients.py | 5 ++- src/mailman/handlers/replybot.py | 7 ++--- src/mailman/handlers/rfc_2369.py | 7 ++--- src/mailman/handlers/tagger.py | 7 ++--- src/mailman/handlers/to_archive.py | 7 ++--- src/mailman/handlers/to_digest.py | 7 ++--- src/mailman/handlers/to_outgoing.py | 7 ++--- src/mailman/handlers/to_usenet.py | 5 ++- src/mailman/languages/language.py | 8 ++--- src/mailman/languages/manager.py | 7 ++--- src/mailman/model/address.py | 7 +++-- src/mailman/model/autorespond.py | 8 +++-- src/mailman/model/bans.py | 8 +++-- src/mailman/model/bounce.py | 8 +++-- src/mailman/model/digests.py | 7 +++-- src/mailman/model/docs/pending.rst | 9 ++++-- src/mailman/model/docs/registration.rst | 9 ++++-- src/mailman/model/domain.py | 8 ++--- src/mailman/model/language.py | 7 +++-- src/mailman/model/listmanager.py | 5 ++- src/mailman/model/mailinglist.py | 14 ++++++--- src/mailman/model/member.py | 5 +-- src/mailman/model/message.py | 5 ++- src/mailman/model/messagestore.py | 5 +-- src/mailman/model/mime.py | 8 ++--- src/mailman/model/pending.py | 15 +++++---- src/mailman/model/preferences.py | 7 +++-- src/mailman/model/requests.py | 7 +++-- src/mailman/model/roster.py | 8 ++--- src/mailman/model/user.py | 5 ++- src/mailman/model/usermanager.py | 5 +-- src/mailman/mta/aliases.py | 7 ++--- src/mailman/mta/base.py | 7 ++--- src/mailman/mta/null.py | 8 ++--- src/mailman/mta/postfix.py | 22 +++++++------- src/mailman/rules/administrivia.py | 6 ++-- src/mailman/rules/any.py | 6 ++-- src/mailman/rules/approved.py | 6 ++-- src/mailman/rules/emergency.py | 6 ++-- src/mailman/rules/implicit_dest.py | 6 ++-- src/mailman/rules/loop.py | 6 ++-- src/mailman/rules/max_recipients.py | 6 ++-- src/mailman/rules/max_size.py | 6 ++-- src/mailman/rules/moderation.py | 8 ++--- src/mailman/rules/news_moderation.py | 6 ++-- src/mailman/rules/no_subject.py | 6 ++-- src/mailman/rules/suspicious.py | 6 ++-- src/mailman/rules/truth.py | 6 ++-- src/mailman/runners/command.py | 7 ++--- src/mailman/runners/tests/test_archiver.py | 6 ++-- src/mailman/runners/tests/test_bounce.py | 11 +++++-- src/mailman/runners/tests/test_pipeline.py | 9 ++++-- src/mailman/styles/default.py | 7 ++--- src/mailman/styles/docs/styles.rst | 6 ++-- src/mailman/styles/manager.py | 7 ++--- src/mailman/styles/tests/test_styles.py | 4 +-- src/mailman/testing/mta.py | 7 ++--- 109 files changed, 431 insertions(+), 464 deletions(-) (limited to 'src/mailman/commands/cli_members.py') diff --git a/setup.py b/setup.py index 89f67a899..a37068ee6 100644 --- a/setup.py +++ b/setup.py @@ -108,6 +108,7 @@ case second `m'. Any other spelling is incorrect.""", 'zc.buildout', 'zope.component', 'zope.configuration', + 'zope.event', 'zope.interface', 'zope.testing<4', ], diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py index 4107a8c6e..0a291d671 100644 --- a/src/mailman/app/bounces.py +++ b/src/mailman/app/bounces.py @@ -17,7 +17,7 @@ """Application level bounce handling.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -38,7 +38,7 @@ from email.mime.text import MIMEText from email.utils import parseaddr from string import Template from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -176,9 +176,9 @@ class ProbeVERP(_BaseVERPParser): +@implementer(IPendable) class _ProbePendable(dict): """The pendable dictionary for probe messages.""" - implements(IPendable) def send_probe(member, msg): diff --git a/src/mailman/app/docs/lifecycle.rst b/src/mailman/app/docs/lifecycle.rst index 08a25ccff..9a3337123 100644 --- a/src/mailman/app/docs/lifecycle.rst +++ b/src/mailman/app/docs/lifecycle.rst @@ -44,10 +44,10 @@ Creating a list applies its styles Start by registering a test style. :: - >>> from zope.interface import implements + >>> from zope.interface import implementer >>> from mailman.interfaces.styles import IStyle - >>> class TestStyle(object): - ... implements(IStyle) + >>> @implementer(IStyle) + ... class TestStyle(object): ... name = 'test' ... priority = 10 ... def apply(self, mailing_list): diff --git a/src/mailman/app/registrar.py b/src/mailman/app/registrar.py index 030a504f7..63e3c5144 100644 --- a/src/mailman/app/registrar.py +++ b/src/mailman/app/registrar.py @@ -28,7 +28,7 @@ __all__ = [ import logging from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.notifications import send_welcome_message from mailman.core.i18n import _ @@ -47,17 +47,16 @@ log = logging.getLogger('mailman.error') +@implementer(IPendable) class PendableRegistration(dict): - implements(IPendable) PEND_KEY = 'registration' +@implementer(IRegistrar) class Registrar: """Handle registrations and confirmations for subscriptions.""" - implements(IRegistrar) - def register(self, mlist, email, display_name=None, delivery_mode=None): """See `IUserRegistrar`.""" if delivery_mode is None: diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py index 5852a7483..ebbe14492 100644 --- a/src/mailman/app/subscriptions.py +++ b/src/mailman/app/subscriptions.py @@ -31,7 +31,7 @@ from operator import attrgetter from storm.expr import And, Or from uuid import UUID from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.membership import add_member, delete_member from mailman.config import config @@ -62,11 +62,10 @@ def _membership_sort_key(member): +@implementer(ISubscriptionService) class SubscriptionService: """Subscription services for the REST API.""" - implements(ISubscriptionService) - __name__ = 'members' def get_members(self): diff --git a/src/mailman/app/templates.py b/src/mailman/app/templates.py index a91231cfc..f29781e58 100644 --- a/src/mailman/app/templates.py +++ b/src/mailman/app/templates.py @@ -31,7 +31,7 @@ from contextlib import closing from urllib import addinfourl from urlparse import urlparse from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.utilities.i18n import TemplateNotFoundError, find from mailman.interfaces.languages import ILanguageManager @@ -92,11 +92,10 @@ class MailmanHandler(urllib2.BaseHandler): +@implementer(ITemplateLoader) class TemplateLoader: """Loader of templates, with caching and support for mailman:// URIs.""" - implements(ITemplateLoader) - def __init__(self): opener = urllib2.build_opener(MailmanHandler()) urllib2.install_opener(opener) diff --git a/src/mailman/archiving/mailarchive.py b/src/mailman/archiving/mailarchive.py index c72cde11c..69ca77e52 100644 --- a/src/mailman/archiving/mailarchive.py +++ b/src/mailman/archiving/mailarchive.py @@ -17,7 +17,7 @@ """The Mail-Archive.com archiver.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,21 +27,20 @@ __all__ = [ from urllib import quote from urlparse import urljoin -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.archiver import IArchiver +@implementer(IArchiver) class MailArchive: """Public archiver at the Mail-Archive.com. Messages get archived at http://go.mail-archive.com. """ - implements(IArchiver) - name = 'mail-archive' @staticmethod diff --git a/src/mailman/archiving/mhonarc.py b/src/mailman/archiving/mhonarc.py index 0beeed73e..7f0af6cd6 100644 --- a/src/mailman/archiving/mhonarc.py +++ b/src/mailman/archiving/mhonarc.py @@ -17,7 +17,7 @@ """MHonArc archiver.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -29,7 +29,7 @@ import logging import subprocess from urlparse import urljoin -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.archiver import IArchiver @@ -40,11 +40,10 @@ log = logging.getLogger('mailman.archiver') +@implementer(IArchiver) class MHonArc: """Local MHonArc archiver.""" - implements(IArchiver) - name = 'mhonarc' @staticmethod diff --git a/src/mailman/archiving/prototype.py b/src/mailman/archiving/prototype.py index 453c6c770..3ce51ddb5 100644 --- a/src/mailman/archiving/prototype.py +++ b/src/mailman/archiving/prototype.py @@ -17,7 +17,7 @@ """Prototypical permalinking archiver.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -34,7 +34,7 @@ from mailbox import Maildir from urlparse import urljoin from flufl.lock import Lock, TimeOutError -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.archiver import IArchiver @@ -43,6 +43,7 @@ log = logging.getLogger('mailman.error') +@implementer(IArchiver) class Prototype: """A prototype of a third party archiver. @@ -50,8 +51,6 @@ class Prototype: servers and archivers: . """ - implements(IArchiver) - name = 'prototype' @staticmethod diff --git a/src/mailman/chains/base.py b/src/mailman/chains/base.py index 8a2e87ee2..b75d66989 100644 --- a/src/mailman/chains/base.py +++ b/src/mailman/chains/base.py @@ -17,7 +17,7 @@ """Base class for terminal chains.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.chain import ( @@ -36,9 +36,9 @@ from mailman.interfaces.chain import ( +@implementer(IChainLink) class Link: """A chain link.""" - implements(IChainLink) def __init__(self, rule, action=None, chain=None, function=None): self.rule = rule @@ -61,13 +61,12 @@ class Link: +@implementer(IChain, IChainIterator) class TerminalChainBase: """A base chain that always matches and executes a method. The method is called '_process()' and must be provided by the subclass. """ - implements(IChain, IChainIterator) - def _process(self, mlist, msg, msgdata): """Process the message for the given mailing list. @@ -93,9 +92,9 @@ class TerminalChainBase: +@implementer(IMutableChain) class Chain: """Generic chain base class.""" - implements(IMutableChain) def __init__(self, name, description): assert name not in config.chains, ( @@ -125,11 +124,10 @@ class Chain: +@implementer(IChainIterator) class ChainIterator: """Generic chain iterator.""" - implements(IChainIterator) - def __init__(self, chain): self._chain = chain diff --git a/src/mailman/chains/builtin.py b/src/mailman/chains/builtin.py index 5d51e075d..7ed60dcec 100644 --- a/src/mailman/chains/builtin.py +++ b/src/mailman/chains/builtin.py @@ -17,7 +17,7 @@ """The default built-in starting chain.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import logging -from zope.interface import implements +from zope.interface import implementer from mailman.chains.base import Link from mailman.config import config @@ -39,11 +39,10 @@ log = logging.getLogger('mailman.vette') +@implementer(IChain) class BuiltInChain: """Default built-in chain.""" - implements(IChain) - name = 'default-posting-chain' description = _('The built-in moderation chain.') diff --git a/src/mailman/chains/headers.py b/src/mailman/chains/headers.py index d9f8356f8..2dafa07f0 100644 --- a/src/mailman/chains/headers.py +++ b/src/mailman/chains/headers.py @@ -17,7 +17,7 @@ """The header-matching chain.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import re import logging -from zope.interface import implements +from zope.interface import implementer from mailman.chains.base import Chain, Link from mailman.config import config @@ -60,9 +60,9 @@ def make_link(header, pattern): +@implementer(IRule) class HeaderMatchRule: """Header matching rule used by header-match chain.""" - implements(IRule) # Sequential rule counter. _count = 1 diff --git a/src/mailman/chains/hold.py b/src/mailman/chains/hold.py index f095bc182..a8b7ec57b 100644 --- a/src/mailman/chains/hold.py +++ b/src/mailman/chains/hold.py @@ -17,7 +17,7 @@ """The terminal 'hold' chain.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -33,7 +33,7 @@ from email.mime.text import MIMEText from email.utils import formatdate, make_msgid from zope.component import getUtility from zope.event import notify -from zope.interface import implements +from zope.interface import implementer from mailman.app.moderator import hold_message from mailman.app.replybot import can_acknowledge @@ -54,8 +54,8 @@ SEMISPACE = '; ' +@implementer(IPendable) class HeldMessagePendable(dict): - implements(IPendable) PEND_KEY = 'held message' diff --git a/src/mailman/chains/moderation.py b/src/mailman/chains/moderation.py index 9f9633346..6c2ed1180 100644 --- a/src/mailman/chains/moderation.py +++ b/src/mailman/chains/moderation.py @@ -34,7 +34,7 @@ made as to the disposition of the message. `defer` is the default for members, while `hold` is the default for nonmembers. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -42,7 +42,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.chains.base import Link from mailman.config import config @@ -52,15 +52,13 @@ from mailman.interfaces.chain import IChain, LinkAction +@implementer(IChain) class ModerationChain: """Dynamically produce a link jumping to the appropriate terminal chain. The terminal chain will be one of the Accept, Hold, Discard, or Reject chains, based on the member's or nonmember's moderation action setting. """ - - implements(IChain) - name = 'moderation' description = _('Moderation chain') diff --git a/src/mailman/commands/cli_aliases.py b/src/mailman/commands/cli_aliases.py index 7c1577c9c..d692ba356 100644 --- a/src/mailman/commands/cli_aliases.py +++ b/src/mailman/commands/cli_aliases.py @@ -17,7 +17,7 @@ """Generate Mailman alias files for your MTA.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -29,7 +29,7 @@ import sys from operator import attrgetter from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -41,11 +41,10 @@ from mailman.utilities.modules import call_name +@implementer(ICLISubCommand) class Aliases: """Regenerate the aliases appropriate for your MTA.""" - implements(ICLISubCommand) - name = 'aliases' def add(self, parser, command_parser): @@ -91,11 +90,10 @@ class Aliases: +@implementer(IMailTransportAgentLifecycle) class Dummy: """Dummy aliases implementation for simpler output format.""" - implements(IMailTransportAgentLifecycle) - def create(self, mlist): """See `IMailTransportAgentLifecycle`.""" raise NotImplementedError @@ -132,5 +130,5 @@ class Dummy: for mlist in sorted(by_domain[domain], key=sort_key): utility = getUtility(IMailTransportAgentAliases) for alias in utility.aliases(mlist): - print >> fp, alias - print >> fp + print(alias, file=fp) + print(file=fp) diff --git a/src/mailman/commands/cli_control.py b/src/mailman/commands/cli_control.py index 2013d6745..8349feb60 100644 --- a/src/mailman/commands/cli_control.py +++ b/src/mailman/commands/cli_control.py @@ -17,7 +17,7 @@ """Module stuff.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -34,7 +34,7 @@ import errno import signal import logging -from zope.interface import implements +from zope.interface import implementer from mailman.bin.master import WatcherState, master_state from mailman.config import config @@ -46,11 +46,10 @@ qlog = logging.getLogger('mailman.runner') +@implementer(ICLISubCommand) class Start: """Start the Mailman daemons.""" - implements(ICLISubCommand) - name = 'start' def add(self, parser, command_parser): @@ -107,7 +106,7 @@ class Start: 'cleanly. Try using --force.')) def log(message): if not args.quiet: - print message + print(message) # Daemon process startup according to Stevens, Advanced Programming in # the UNIX Environment, Chapter 13. pid = os.fork() @@ -147,27 +146,26 @@ def kill_watcher(sig): pid = int(fp.read().strip()) except (IOError, ValueError) as error: # For i18n convenience - print >> sys.stderr, _('PID unreadable in: $config.PID_FILE') - print >> sys.stderr, error - print >> sys.stderr, _('Is the master even running?') + print(_('PID unreadable in: $config.PID_FILE'), file=sys.stderr) + print(error, file=sys.stderr) + print(_('Is the master even running?'), file=sys.stderr) return try: os.kill(pid, sig) except OSError as error: if error.errno != errno.ESRCH: raise - print >> sys.stderr, _('No child with pid: $pid') - print >> sys.stderr, error - print >> sys.stderr, _('Stale pid file removed.') + print(_('No child with pid: $pid'), file=sys.stderr) + print(error, file=sys.stderr) + print(_('Stale pid file removed.'), file=sys.stderr) os.unlink(config.PID_FILE) +@implementer(ICLISubCommand) class SignalCommand: """Common base class for simple, signal sending commands.""" - implements(ICLISubCommand) - name = None message = None signal = None @@ -184,7 +182,7 @@ class SignalCommand: def process(self, args): """See `ICLISubCommand`.""" if not args.quiet: - print _(self.message) + print(_(self.message)) kill_watcher(self.signal) @@ -204,11 +202,10 @@ class Reopen(SignalCommand): signal = signal.SIGHUP +@implementer(ICLISubCommand) class Restart(SignalCommand): """Stop the Mailman daemons.""" - implements(ICLISubCommand) - name = 'restart' message = _('Restarting the Mailman runners') signal = signal.SIGUSR1 diff --git a/src/mailman/commands/cli_help.py b/src/mailman/commands/cli_help.py index 538d9c520..a85dcd442 100644 --- a/src/mailman/commands/cli_help.py +++ b/src/mailman/commands/cli_help.py @@ -17,7 +17,7 @@ """The 'help' subcommand.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,18 +25,17 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.command import ICLISubCommand +@implementer(ICLISubCommand) class Help: # Lowercase, to match argparse's default --help text. """show this help message and exit""" - implements(ICLISubCommand) - name = 'help' def add(self, parser, command_parser): diff --git a/src/mailman/commands/cli_import.py b/src/mailman/commands/cli_import.py index 716a8ede1..f6c016585 100644 --- a/src/mailman/commands/cli_import.py +++ b/src/mailman/commands/cli_import.py @@ -29,7 +29,7 @@ import sys import cPickle from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.database.transaction import transactional @@ -39,11 +39,10 @@ from mailman.utilities.importer import import_config_pck +@implementer(ICLISubCommand) class Import21: """Import Mailman 2.1 list data.""" - implements(ICLISubCommand) - name = 'import21' def add(self, parser, command_parser): diff --git a/src/mailman/commands/cli_info.py b/src/mailman/commands/cli_info.py index 24ccec4fb..0e9c72f60 100644 --- a/src/mailman/commands/cli_info.py +++ b/src/mailman/commands/cli_info.py @@ -17,7 +17,7 @@ """Information about this Mailman instance.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import sys -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -37,11 +37,10 @@ from mailman.version import MAILMAN_VERSION_FULL +@implementer(ICLISubCommand) class Info: """Information about this Mailman instance.""" - implements(ICLISubCommand) - name = 'info' def add(self, parser, command_parser): @@ -65,15 +64,16 @@ class Info: # We don't need to close output because that will happen # automatically when the script exits. output = open(args.output, 'w') - print >> output, MAILMAN_VERSION_FULL - print >> output, 'Python', sys.version - print >> output, 'config file:', config.filename - print >> output, 'db url:', config.db.url - print >> output, 'REST root url:', path_to('/') - print >> output, 'REST credentials: {0}:{1}'.format( - config.webservice.admin_user, config.webservice.admin_pass) + print(MAILMAN_VERSION_FULL, file=output) + print('Python', sys.version, file=output) + print('config file:', config.filename, file=output) + print('db url:', config.db.url, file=output) + print('REST root url:', path_to('/'), file=output) + print('REST credentials: {0}:{1}'.format( + config.webservice.admin_user, config.webservice.admin_pass), + file=output) if args.verbose: - print >> output, 'File system paths:' + print('File system paths:', file=output) longest = 0 paths = {} for attribute in dir(config): @@ -81,5 +81,5 @@ class Info: paths[attribute] = getattr(config, attribute) longest = max(longest, len(attribute)) for attribute in sorted(paths): - print ' {0:{2}} = {1}'.format(attribute, paths[attribute], - longest) + print(' {0:{2}} = {1}'.format( + attribute, paths[attribute], longest)) diff --git a/src/mailman/commands/cli_inject.py b/src/mailman/commands/cli_inject.py index 321a92c78..1434fd2a6 100644 --- a/src/mailman/commands/cli_inject.py +++ b/src/mailman/commands/cli_inject.py @@ -17,7 +17,7 @@ """bin/mailman inject""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import sys from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.inject import inject_text from mailman.config import config @@ -38,11 +38,10 @@ from mailman.interfaces.listmanager import IListManager +@implementer(ICLISubCommand) class Inject: """Inject a message from a file into a mailing list's queue.""" - implements(ICLISubCommand) - name = 'inject' def add(self, parser, command_parser): @@ -82,9 +81,9 @@ class Inject: # Process --show first; if given, print output and exit, ignoring all # other command line switches. if args.show: - print 'Available queues:' + print('Available queues:') for switchboard in sorted(config.switchboards): - print ' ', switchboard + print(' ', switchboard) return # Could be None or sequence of length 0. if args.listname is None: @@ -106,7 +105,7 @@ class Inject: try: message_text = sys.stdin.read() except KeyboardInterrupt: - print 'Interrupted' + print('Interrupted') sys.exit(1) else: with open(args.filename) as fp: diff --git a/src/mailman/commands/cli_lists.py b/src/mailman/commands/cli_lists.py index 17d4bc375..cf72c51a8 100644 --- a/src/mailman/commands/cli_lists.py +++ b/src/mailman/commands/cli_lists.py @@ -28,7 +28,7 @@ __all__ = [ from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.lifecycle import create_list, remove_list from mailman.core.constants import system_preferences @@ -49,11 +49,10 @@ COMMASPACE = ', ' +@implementer(ICLISubCommand) class Lists: """List all mailing lists""" - implements(ICLISubCommand) - name = 'lists' def add(self, parser, command_parser): @@ -125,11 +124,10 @@ class Lists: +@implementer(ICLISubCommand) class Create: """Create a mailing list""" - implements(ICLISubCommand) - name = 'create' def add(self, parser, command_parser): @@ -242,11 +240,10 @@ class Create: +@implementer(ICLISubCommand) class Remove: """Remove a mailing list""" - implements(ICLISubCommand) - name = 'remove' def add(self, parser, command_parser): diff --git a/src/mailman/commands/cli_members.py b/src/mailman/commands/cli_members.py index 17312e8ec..aef3991d8 100644 --- a/src/mailman/commands/cli_members.py +++ b/src/mailman/commands/cli_members.py @@ -32,7 +32,7 @@ from email.utils import formataddr, parseaddr from flufl.password import generate from operator import attrgetter from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.membership import add_member from mailman.config import config @@ -45,11 +45,10 @@ from mailman.interfaces.member import ( +@implementer(ICLISubCommand) class Members: """Manage list memberships. With no arguments, list all members.""" - implements(ICLISubCommand) - name = 'members' def add(self, parser, command_parser): diff --git a/src/mailman/commands/cli_qfile.py b/src/mailman/commands/cli_qfile.py index 78156f08c..b9e0eff02 100644 --- a/src/mailman/commands/cli_qfile.py +++ b/src/mailman/commands/cli_qfile.py @@ -17,7 +17,7 @@ """Getting information out of a qfile.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import cPickle from pprint import PrettyPrinter -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.command import ICLISubCommand @@ -39,11 +39,10 @@ m = [] +@implementer(ICLISubCommand) class QFile: """Get information out of a queue file.""" - implements(ICLISubCommand) - name = 'qfile' def add(self, parser, command_parser): @@ -79,15 +78,15 @@ class QFile: except EOFError: break if args.doprint: - print _('[----- start pickle -----]') + print(_('[----- start pickle -----]')) for i, obj in enumerate(m): count = i + 1 - print _('<----- start object $count ----->') + print(_('<----- start object $count ----->')) if isinstance(obj, basestring): - print obj + print(obj) else: printer.pprint(obj) - print _('[----- end pickle -----]') + print(_('[----- end pickle -----]')) count = len(m) banner = _("The variable 'm' contains $count objects") if args.interactive: diff --git a/src/mailman/commands/cli_status.py b/src/mailman/commands/cli_status.py index 14b0d976b..9cbaa4f22 100644 --- a/src/mailman/commands/cli_status.py +++ b/src/mailman/commands/cli_status.py @@ -15,9 +15,9 @@ # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . -"""Module stuff.""" +"""bin/mailman status.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import socket -from zope.interface import implements +from zope.interface import implementer from mailman.bin.master import WatcherState, master_state from mailman.core.i18n import _ @@ -35,11 +35,10 @@ from mailman.interfaces.command import ICLISubCommand +@implementer(ICLISubCommand) class Status: """Status of the Mailman system.""" - implements(ICLISubCommand) - name = 'status' def add(self, parser, command_parser): @@ -64,5 +63,5 @@ class Status: 'Invalid enum value: %s' % status) message = _('GNU Mailman is in an unexpected state ' '($hostname != $fqdn_name)') - print message + print(message) return int(status) diff --git a/src/mailman/commands/cli_unshunt.py b/src/mailman/commands/cli_unshunt.py index 4ce711b83..bc50d95ef 100644 --- a/src/mailman/commands/cli_unshunt.py +++ b/src/mailman/commands/cli_unshunt.py @@ -17,7 +17,7 @@ """The 'unshunt' command.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import sys -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -35,11 +35,10 @@ from mailman.interfaces.command import ICLISubCommand +@implementer(ICLISubCommand) class Unshunt: """Unshunt messages.""" - implements(ICLISubCommand) - name = 'unshunt' def add(self, parser, command_parser): @@ -64,8 +63,8 @@ class Unshunt: if not args.discard: config.switchboards[which_queue].enqueue(msg, msgdata) except Exception as error: - print >> sys.stderr, _( - 'Cannot unshunt message $filebase, skipping:\n$error') + print(_('Cannot unshunt message $filebase, skipping:\n$error'), + file=sys.stderr) else: # Unlink the .bak file left by dequeue() shunt_queue.finish(filebase) diff --git a/src/mailman/commands/cli_version.py b/src/mailman/commands/cli_version.py index 4090b1173..b5e9b65ff 100644 --- a/src/mailman/commands/cli_version.py +++ b/src/mailman/commands/cli_version.py @@ -17,7 +17,7 @@ """The Mailman version.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,18 +25,17 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.command import ICLISubCommand from mailman.version import MAILMAN_VERSION_FULL +@implementer(ICLISubCommand) class Version: """Mailman's version.""" - implements(ICLISubCommand) - name = 'version' def add(self, parser, command_parser): @@ -46,4 +45,4 @@ class Version: def process(self, args): """See `ICLISubCommand`.""" - print MAILMAN_VERSION_FULL + print(MAILMAN_VERSION_FULL) diff --git a/src/mailman/commands/cli_withlist.py b/src/mailman/commands/cli_withlist.py index e514c798f..4ccdd8798 100644 --- a/src/mailman/commands/cli_withlist.py +++ b/src/mailman/commands/cli_withlist.py @@ -17,7 +17,7 @@ """bin/mailman withlist""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -31,7 +31,7 @@ import sys from lazr.config import as_boolean from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -47,14 +47,13 @@ r = None +@implementer(ICLISubCommand) class Withlist: """Operate on a mailing list. For detailed help, see --details """ - implements(ICLISubCommand) - name = 'withlist' def add(self, parser, command_parser): @@ -163,7 +162,7 @@ class Withlist: ipshell = InteractiveShellEmbed(banner1=banner, user_ns=overrides) ipshell() except ImportError: - print _('ipython is not available, set use_ipython to no') + print(_('ipython is not available, set use_ipython to no')) def _start_python(self, overrides, banner): # Set the tab completion. @@ -178,25 +177,25 @@ class Withlist: def _details(self): """Print detailed usage.""" # Split this up into paragraphs for easier translation. - print _("""\ + print(_("""\ This script provides you with a general framework for interacting with a -mailing list.""") - print - print _("""\ +mailing list.""")) + print() + print(_("""\ There are two ways to use this script: interactively or programmatically. Using it interactively allows you to play with, examine and modify a mailing list from Python's interactive interpreter. When running interactively, the variable 'm' will be available in the global namespace. It will reference the -mailing list object.""") - print - print _("""\ +mailing list object.""")) + print() + print(_("""\ Programmatically, you can write a function to operate on a mailing list, and this script will take care of the housekeeping (see below for examples). In that case, the general usage syntax is: - % bin/mailman withlist [options] listname [args ...]""") - print - print _("""\ + % bin/mailman withlist [options] listname [args ...]""")) + print() + print(_("""\ Here's an example of how to use the --run option. Say you have a file in the Mailman installation directory called 'listaddr.py', with the following two functions: @@ -205,26 +204,26 @@ functions: print mlist.posting_address def requestaddr(mlist): - print mlist.request_address""") - print - print _("""\ + print mlist.request_address""")) + print() + print(_("""\ You can print the list's posting address by running the following from the command line: % bin/mailman withlist -r listaddr mylist@example.com Importing listaddr ... Running listaddr.listaddr() ... - mylist@example.com""") - print - print _("""\ + mylist@example.com""")) + print() + print(_("""\ And you can print the list's request address by running: % bin/mailman withlist -r listaddr.requestaddr mylist Importing listaddr ... Running listaddr.requestaddr() ... - mylist-request@example.com""") - print - print _("""\ + mylist-request@example.com""")) + print() + print(_("""\ As another example, say you wanted to change the display name for a particular mailing list. You could put the following function in a file called 'change.pw': @@ -236,7 +235,7 @@ mailing list. You could put the following function in a file called and run this from the command line: - % bin/mailman withlist -r change mylist@example.com 'My List'""") + % bin/mailman withlist -r change mylist@example.com 'My List'""")) diff --git a/src/mailman/commands/docs/end.rst b/src/mailman/commands/docs/end.rst index accf91b90..8cd4b2409 100644 --- a/src/mailman/commands/docs/end.rst +++ b/src/mailman/commands/docs/end.rst @@ -13,8 +13,8 @@ processing email messages. The 'end' command takes no arguments. - >>> command.argument_description - '' + >>> print 'DESCRIPTION:', command.argument_description + DESCRIPTION: The command itself is fairly simple; it just stops command processing, and the message isn't even looked at. @@ -31,7 +31,7 @@ The 'stop' command is a synonym for 'end'. stop >>> print command.description An alias for 'end'. - >>> command.argument_description - '' + >>> print 'DESCRIPTION:', command.argument_description + DESCRIPTION: >>> print command.process(mlist, Message(), {}, (), None) ContinueProcessing.no diff --git a/src/mailman/commands/eml_confirm.py b/src/mailman/commands/eml_confirm.py index 55619a503..c82dc64c3 100644 --- a/src/mailman/commands/eml_confirm.py +++ b/src/mailman/commands/eml_confirm.py @@ -17,7 +17,7 @@ """Module stuff.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.command import ContinueProcessing, IEmailCommand @@ -34,11 +34,10 @@ from mailman.interfaces.registrar import IRegistrar +@implementer(IEmailCommand) class Confirm: """The email 'confirm' command.""" - implements(IEmailCommand) - name = 'confirm' argument_description = 'token' description = _('Confirm a subscription request.') @@ -48,7 +47,7 @@ class Confirm: """See `IEmailCommand`.""" # The token must be in the arguments. if len(arguments) == 0: - print >> results, _('No confirmation token found') + print(_('No confirmation token found'), file=results) return ContinueProcessing.no # Make sure we don't try to confirm the same token more than once. token = arguments[0] @@ -60,7 +59,7 @@ class Confirm: results.confirms = tokens succeeded = getUtility(IRegistrar).confirm(token) if succeeded: - print >> results, _('Confirmed') + print(_('Confirmed'), file=results) return ContinueProcessing.yes - print >> results, _('Confirmation token did not match') + print(_('Confirmation token did not match'), file=results) return ContinueProcessing.no diff --git a/src/mailman/commands/eml_echo.py b/src/mailman/commands/eml_echo.py index 06d5ee5e7..885edcbae 100644 --- a/src/mailman/commands/eml_echo.py +++ b/src/mailman/commands/eml_echo.py @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.command import ContinueProcessing, IEmailCommand @@ -35,9 +35,9 @@ SPACE = ' ' +@implementer(IEmailCommand) class Echo: """The email 'echo' command.""" - implements(IEmailCommand) name = 'echo' argument_description = '[args]' diff --git a/src/mailman/commands/eml_end.py b/src/mailman/commands/eml_end.py index 3cd70813c..32a024205 100644 --- a/src/mailman/commands/eml_end.py +++ b/src/mailman/commands/eml_end.py @@ -17,6 +17,8 @@ """The email commands 'end' and 'stop'.""" +from __future__ import absolute_import, print_function, unicode_literals + __metaclass__ = type __all__ = [ 'End', @@ -24,16 +26,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.command import ContinueProcessing, IEmailCommand +@implementer(IEmailCommand) class End: """The email 'end' command.""" - implements(IEmailCommand) name = 'end' argument_description = '' diff --git a/src/mailman/commands/eml_help.py b/src/mailman/commands/eml_help.py index 6fddb4ef3..a27717179 100644 --- a/src/mailman/commands/eml_help.py +++ b/src/mailman/commands/eml_help.py @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -37,11 +37,10 @@ SPACE = ' ' +@implementer(IEmailCommand) class Help: """The email 'help' command.""" - implements(IEmailCommand) - name = 'help' argument_description = '[command]' description = _('Get help about available email commands.') @@ -58,14 +57,14 @@ class Help: command = config.commands[command_name] short_description = getattr( command, 'short_description', _('n/a')) - print(format.format(command.name, short_description), + print(format.format(command.name, short_description), file=results) return ContinueProcessing.yes elif len(arguments) == 1: command_name = arguments[0] command = config.commands.get(command_name) if command is None: - print(_('$self.name: no such command: $command_name'), + print(_('$self.name: no such command: $command_name'), file=results) return ContinueProcessing.no print('{0} {1}'.format(command.name, command.argument_description), diff --git a/src/mailman/commands/eml_membership.py b/src/mailman/commands/eml_membership.py index d6f7a47d9..860e42f47 100644 --- a/src/mailman/commands/eml_membership.py +++ b/src/mailman/commands/eml_membership.py @@ -30,7 +30,7 @@ __all__ = [ from email.utils import formataddr, parseaddr from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.command import ContinueProcessing, IEmailCommand @@ -41,11 +41,10 @@ from mailman.interfaces.usermanager import IUserManager +@implementer(IEmailCommand) class Join: """The email 'join' command.""" - implements(IEmailCommand) - name = 'join' # XXX 2012-02-29 BAW: DeliveryMode.summary is not yet supported. argument_description = '[digest=]' @@ -89,7 +88,7 @@ used. if len(members) > 0: print(_('$person is already a member'), file=results) else: - getUtility(IRegistrar).register(mlist, address, + getUtility(IRegistrar).register(mlist, address, display_name, delivery_mode) print(_('Confirmation email sent to $person'), file=results) return ContinueProcessing.yes @@ -131,14 +130,13 @@ class Subscribe(Join): +@implementer(IEmailCommand) class Leave: """The email 'leave' command.""" - implements(IEmailCommand) - name = 'leave' argument_description = '' - description = _("""Leave this mailing list. + description = _("""Leave this mailing list. You may be asked to confirm your request.""") short_description = _('Leave this mailing list.') diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index 48c849148..fc82a2be7 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -32,7 +32,7 @@ from lazr.config import ConfigSchema, as_boolean from pkg_resources import resource_stream from string import Template from zope.component import getUtility -from zope.interface import Interface, implements +from zope.interface import Interface, implementer import mailman.templates @@ -52,11 +52,10 @@ class IConfiguration(Interface): +@implementer(IConfiguration) class Configuration: """The core global configuration object.""" - implements(IConfiguration) - def __init__(self): self.switchboards = {} self.QFILE_SCHEMA_VERSION = version.QFILE_SCHEMA_VERSION diff --git a/src/mailman/core/constants.py b/src/mailman/core/constants.py index 02d46a088..4562f4c74 100644 --- a/src/mailman/core/constants.py +++ b/src/mailman/core/constants.py @@ -17,7 +17,7 @@ """Various constants and enumerations.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.languages import ILanguageManager @@ -35,11 +35,10 @@ from mailman.interfaces.preferences import IPreferences +@implementer(IPreferences) class SystemDefaultPreferences: """The default system preferences.""" - implements(IPreferences) - acknowledge_posts = False hide_address = True receive_list_copy = True diff --git a/src/mailman/core/pipelines.py b/src/mailman/core/pipelines.py index 25bb68030..972417c2c 100644 --- a/src/mailman/core/pipelines.py +++ b/src/mailman/core/pipelines.py @@ -32,7 +32,7 @@ __all__ = [ import logging -from zope.interface import implements +from zope.interface import implementer from zope.interface.verify import verifyObject from mailman.app.bounces import bounce_message @@ -75,11 +75,10 @@ def process(mlist, msg, msgdata, pipeline_name='built-in'): +@implementer(IPipeline) class BasePipeline: """Base pipeline implementation.""" - implements(IPipeline) - _default_handlers = () def __init__(self): diff --git a/src/mailman/core/runner.py b/src/mailman/core/runner.py index e86741c41..39382cea0 100644 --- a/src/mailman/core/runner.py +++ b/src/mailman/core/runner.py @@ -17,7 +17,7 @@ """The process runner base class.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -32,7 +32,7 @@ import traceback from cStringIO import StringIO from lazr.config import as_boolean, as_timedelta from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -48,9 +48,8 @@ elog = logging.getLogger('mailman.error') +@implementer(IRunner) class Runner: - implements(IRunner) - intercept_signals = True def __init__(self, name, slice=None): diff --git a/src/mailman/core/switchboard.py b/src/mailman/core/switchboard.py index 7cab4f4ad..c65b92fac 100644 --- a/src/mailman/core/switchboard.py +++ b/src/mailman/core/switchboard.py @@ -24,7 +24,7 @@ written. First, the message is written to the pickle, then the metadata dictionary is written. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -40,7 +40,7 @@ import cPickle import hashlib import logging -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.email.message import Message @@ -63,8 +63,9 @@ elog = logging.getLogger('mailman.error') +@implementer(ISwitchboard) class Switchboard: - implements(ISwitchboard) + """See `ISwitchboard`.""" @staticmethod def initialize(): diff --git a/src/mailman/core/system.py b/src/mailman/core/system.py index ce66761a7..b29567827 100644 --- a/src/mailman/core/system.py +++ b/src/mailman/core/system.py @@ -17,7 +17,7 @@ """System information.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,15 +27,16 @@ __all__ = [ import sys -from zope.interface import implements +from zope.interface import implementer from mailman import version from mailman.interfaces.system import ISystem +@implementer(ISystem) class System: - implements(ISystem) + """See `ISystem`.""" @property def mailman_version(self): diff --git a/src/mailman/core/tests/test_pipelines.py b/src/mailman/core/tests/test_pipelines.py index 8f851de95..8e76cf033 100644 --- a/src/mailman/core/tests/test_pipelines.py +++ b/src/mailman/core/tests/test_pipelines.py @@ -29,7 +29,7 @@ __all__ = [ import unittest from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.lifecycle import create_list from mailman.config import config @@ -48,24 +48,24 @@ from mailman.testing.layers import ConfigLayer +@implementer(IHandler) class DiscardingHandler: - implements(IHandler) name = 'discarding' def process(self, mlist, msg, msgdata): raise DiscardMessage('by test handler') +@implementer(IHandler) class RejectHandler: - implements(IHandler) name = 'rejecting' def process(self, mlist, msg, msgdata): raise RejectMessage('by test handler') +@implementer(IPipeline) class DiscardingPipeline: - implements(IPipeline) name = 'test-discarding' description = 'Discarding test pipeline' @@ -73,8 +73,8 @@ class DiscardingPipeline: yield DiscardingHandler() +@implementer(IPipeline) class RejectingPipeline: - implements(IPipeline) name = 'test-rejecting' description = 'Rejectinging test pipeline' diff --git a/src/mailman/database/base.py b/src/mailman/database/base.py index a69e99395..1595007f1 100644 --- a/src/mailman/database/base.py +++ b/src/mailman/database/base.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -32,7 +32,7 @@ from lazr.config import as_boolean from pkg_resources import resource_listdir, resource_string from storm.cache import GenerationalCache from storm.locals import create_database, Store -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.database import IDatabase @@ -45,6 +45,7 @@ NL = '\n' +@implementer(IDatabase) class StormBaseDatabase: """The database base class for use with the Storm ORM. @@ -55,8 +56,6 @@ class StormBaseDatabase: # classes. TAG = '' - implements(IDatabase) - def __init__(self): self.url = None self.store = None @@ -187,7 +186,7 @@ class StormBaseDatabase: :param store: The Storm store to load the schema into. :type store: storm.locals.Store` - :param version: The schema version identifier of the form + :param version: The schema version identifier of the form YYYYMMDDHHMMSS. :type version: string :param filename: The file name containing the schema to load. Pass diff --git a/src/mailman/email/validate.py b/src/mailman/email/validate.py index 1861a8121..021e4c073 100644 --- a/src/mailman/email/validate.py +++ b/src/mailman/email/validate.py @@ -27,7 +27,7 @@ __all__ = [ import re -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.address import ( IEmailValidator, InvalidEmailAddressError) @@ -39,11 +39,10 @@ _badchars = re.compile(r'[][()<>|;^,\000-\037\177-\377]') +@implementer(IEmailValidator) class Validator: """An email address validator.""" - implements(IEmailValidator) - def is_valid(self, email): """See `IEmailValidator`.""" if not email or ' ' in email: diff --git a/src/mailman/handlers/acknowledge.py b/src/mailman/handlers/acknowledge.py index 0e0916337..0366f8ce6 100644 --- a/src/mailman/handlers/acknowledge.py +++ b/src/mailman/handlers/acknowledge.py @@ -20,7 +20,7 @@ This only happens if the sender has set their AcknowledgePosts attribute. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -29,7 +29,7 @@ __all__ = [ from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.email.message import UserNotification @@ -40,9 +40,9 @@ from mailman.utilities.string import oneline +@implementer(IHandler) class Acknowledge: """Send an acknowledgment.""" - implements(IHandler) name = 'acknowledge' description = _("""Send an acknowledgment of a posting.""") diff --git a/src/mailman/handlers/after_delivery.py b/src/mailman/handlers/after_delivery.py index a964804b5..0a3ba2c75 100644 --- a/src/mailman/handlers/after_delivery.py +++ b/src/mailman/handlers/after_delivery.py @@ -17,7 +17,7 @@ """Perform some bookkeeping after a successful post.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler @@ -33,11 +33,10 @@ from mailman.utilities.datetime import now +@implementer(IHandler) class AfterDelivery: """Perform some bookkeeping after a successful post.""" - implements(IHandler) - name = 'after-delivery' description = _('Perform some bookkeeping after a successful post.') diff --git a/src/mailman/handlers/avoid_duplicates.py b/src/mailman/handlers/avoid_duplicates.py index ffbc80c85..de1939822 100644 --- a/src/mailman/handlers/avoid_duplicates.py +++ b/src/mailman/handlers/avoid_duplicates.py @@ -23,7 +23,7 @@ has already received a copy, we either drop the message, add a duplicate warning header, or pass it through, depending on the user's preferences. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -32,7 +32,7 @@ __all__ = [ from email.utils import getaddresses, formataddr -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler @@ -42,11 +42,10 @@ COMMASPACE = ', ' +@implementer(IHandler) class AvoidDuplicates: """If the user wishes it, do not send duplicates of the same message.""" - implements(IHandler) - name = 'avoid-duplicates' description = _('Suppress some duplicates of the same message.') diff --git a/src/mailman/handlers/cleanse.py b/src/mailman/handlers/cleanse.py index 605b843d0..32d3455ca 100644 --- a/src/mailman/handlers/cleanse.py +++ b/src/mailman/handlers/cleanse.py @@ -17,7 +17,7 @@ """Cleanse certain headers from all messages.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import logging from email.utils import formataddr -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.handlers.cook_headers import uheader @@ -39,11 +39,10 @@ log = logging.getLogger('mailman.post') +@implementer(IHandler) class Cleanse: """Cleanse certain headers from all messages.""" - implements(IHandler) - name = 'cleanse' description = _('Cleanse certain headers from all messages.') diff --git a/src/mailman/handlers/cleanse_dkim.py b/src/mailman/handlers/cleanse_dkim.py index d2cd32636..bc23980b7 100644 --- a/src/mailman/handlers/cleanse_dkim.py +++ b/src/mailman/handlers/cleanse_dkim.py @@ -25,7 +25,7 @@ and it will also give the MTA the opportunity to regenerate valid keys originating at the Mailman server for the outgoing message. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -34,7 +34,7 @@ __all__ = [ from lazr.config import as_boolean -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -42,11 +42,10 @@ from mailman.interfaces.handler import IHandler +@implementer(IHandler) class CleanseDKIM: """Remove DomainKeys headers.""" - implements(IHandler) - name = 'cleanse-dkim' description = _('Remove DomainKeys headers.') diff --git a/src/mailman/handlers/cook_headers.py b/src/mailman/handlers/cook_headers.py index 5d1e416a6..535155ab7 100644 --- a/src/mailman/handlers/cook_headers.py +++ b/src/mailman/handlers/cook_headers.py @@ -17,7 +17,7 @@ """Cook a message's headers.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -30,7 +30,7 @@ import re from email.errors import HeaderParseError from email.header import Header, decode_header, make_header from email.utils import parseaddr, formataddr, getaddresses -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler @@ -279,11 +279,10 @@ def ch_oneline(headerstr): +@implementer(IHandler) class CookHeaders: """Modify message headers.""" - implements(IHandler) - name = 'cook-headers' description = _('Modify message headers.') diff --git a/src/mailman/handlers/decorate.py b/src/mailman/handlers/decorate.py index d6d156048..c5fad2891 100644 --- a/src/mailman/handlers/decorate.py +++ b/src/mailman/handlers/decorate.py @@ -31,7 +31,7 @@ import logging from email.mime.text import MIMEText from urllib2 import URLError from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.email.message import Message @@ -57,7 +57,7 @@ def process(mlist, msg, msgdata): d['user_address'] = recipient d['user_delivered_to'] = member.address.original_email d['user_language'] = member.preferred_language.description - d['user_name'] = (member.user.display_name + d['user_name'] = (member.user.display_name if member.user.display_name else member.address.original_email) d['user_optionsurl'] = member.options_url @@ -232,11 +232,10 @@ def decorate(mlist, uri, extradict=None): +@implementer(IHandler) class Decorate: """Decorate a message with headers and footers.""" - implements(IHandler) - name = 'decorate' description = _('Decorate a message with headers and footers.') diff --git a/src/mailman/handlers/file_recipients.py b/src/mailman/handlers/file_recipients.py index d087ff2bb..750357a90 100644 --- a/src/mailman/handlers/file_recipients.py +++ b/src/mailman/handlers/file_recipients.py @@ -17,7 +17,7 @@ """Get the normal delivery recipients from a Sendmail style :include: file.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,18 +28,17 @@ __all__ = [ import os import errno -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler +@implementer(IHandler) class FileRecipients: """Get the normal delivery recipients from an include file.""" - implements(IHandler) - name = 'file-recipients' description = _('Get the normal delivery recipients from an include file.') diff --git a/src/mailman/handlers/member_recipients.py b/src/mailman/handlers/member_recipients.py index 956ea6adc..ec8ed77b1 100644 --- a/src/mailman/handlers/member_recipients.py +++ b/src/mailman/handlers/member_recipients.py @@ -31,7 +31,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core import errors @@ -42,11 +42,10 @@ from mailman.utilities.string import wrap +@implementer(IHandler) class MemberRecipients: """Calculate the regular (i.e. non-digest) recipients of the message.""" - implements(IHandler) - name = 'member-recipients' description = _('Calculate the regular recipients of the message.') diff --git a/src/mailman/handlers/mime_delete.py b/src/mailman/handlers/mime_delete.py index c9c1eb408..52fcc99fa 100644 --- a/src/mailman/handlers/mime_delete.py +++ b/src/mailman/handlers/mime_delete.py @@ -24,7 +24,7 @@ wrapping only single sections after other processing are replaced by their contents. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -42,7 +42,7 @@ from email.mime.message import MIMEMessage from email.mime.text import MIMEText from lazr.config import as_boolean from os.path import splitext -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core import errors @@ -285,11 +285,10 @@ def get_file_ext(m): +@implementer(IHandler) class MIMEDelete: """Filter the MIME content of messages.""" - implements(IHandler) - name = 'mime-delete' description = _('Filter the MIME content of messages.') diff --git a/src/mailman/handlers/owner_recipients.py b/src/mailman/handlers/owner_recipients.py index e431d00cf..66c380635 100644 --- a/src/mailman/handlers/owner_recipients.py +++ b/src/mailman/handlers/owner_recipients.py @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -34,11 +34,10 @@ from mailman.interfaces.member import DeliveryStatus +@implementer(IHandler) class OwnerRecipients: """Calculate the owner (and moderator) recipients for -owner postings.""" - implements(IHandler) - name = 'owner-recipients' description = _('Calculate the owner and moderator recipients.') diff --git a/src/mailman/handlers/replybot.py b/src/mailman/handlers/replybot.py index 83aa40214..a25f4f30b 100644 --- a/src/mailman/handlers/replybot.py +++ b/src/mailman/handlers/replybot.py @@ -17,7 +17,7 @@ """Handler for automatic responses.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import logging from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.email.message import UserNotification @@ -44,11 +44,10 @@ log = logging.getLogger('mailman.error') +@implementer(IHandler) class Replybot: """Send automatic responses.""" - implements(IHandler) - name = 'replybot' description = _('Send automatic responses.') diff --git a/src/mailman/handlers/rfc_2369.py b/src/mailman/handlers/rfc_2369.py index ece4e83cb..a6e53413a 100644 --- a/src/mailman/handlers/rfc_2369.py +++ b/src/mailman/handlers/rfc_2369.py @@ -17,7 +17,7 @@ """RFC 2369 List-* and related headers.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from email.utils import formataddr -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -100,11 +100,10 @@ def process(mlist, msg, msgdata): +@implementer(IHandler) class RFC2369: """Add the RFC 2369 List-* headers.""" - implements(IHandler) - name = 'rfc-2369' description = _('Add the RFC 2369 List-* headers.') diff --git a/src/mailman/handlers/tagger.py b/src/mailman/handlers/tagger.py index 49e004a12..9d78372e6 100644 --- a/src/mailman/handlers/tagger.py +++ b/src/mailman/handlers/tagger.py @@ -17,7 +17,7 @@ """Extract topics from the original mail message.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -29,7 +29,7 @@ import re import email.iterators import email.parser -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.handler import IHandler @@ -178,11 +178,10 @@ class _ForgivingParser(email.parser.HeaderParser): +@implementer(IHandler) class Tagger: """Tag messages with topic matches.""" - implements(IHandler) - name = 'tagger' description = _('Tag messages with topic matches.') diff --git a/src/mailman/handlers/to_archive.py b/src/mailman/handlers/to_archive.py index fd5259a14..0dc5bad1a 100644 --- a/src/mailman/handlers/to_archive.py +++ b/src/mailman/handlers/to_archive.py @@ -17,7 +17,7 @@ """Add the message to the archives.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -33,11 +33,10 @@ from mailman.interfaces.handler import IHandler +@implementer(IHandler) class ToArchive: """Add the message to the archives.""" - implements(IHandler) - name = 'to-archive' description = _('Add the message to the archives.') diff --git a/src/mailman/handlers/to_digest.py b/src/mailman/handlers/to_digest.py index 71511f136..8067e2c0c 100644 --- a/src/mailman/handlers/to_digest.py +++ b/src/mailman/handlers/to_digest.py @@ -17,7 +17,7 @@ """Add the message to the list's current digest.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import os -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -39,11 +39,10 @@ from mailman.utilities.mailbox import Mailbox +@implementer(IHandler) class ToDigest: """Add the message to the digest, possibly sending it.""" - implements(IHandler) - name = 'to-digest' description = _('Add the message to the digest, possibly sending it.') diff --git a/src/mailman/handlers/to_outgoing.py b/src/mailman/handlers/to_outgoing.py index 971f87757..a212485c7 100644 --- a/src/mailman/handlers/to_outgoing.py +++ b/src/mailman/handlers/to_outgoing.py @@ -22,7 +22,7 @@ posted to the list membership. Anything else that needs to go out to some recipient should just be placed in the out queue directly. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -30,7 +30,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -38,11 +38,10 @@ from mailman.interfaces.handler import IHandler +@implementer(IHandler) class ToOutgoing: """Send the message to the outgoing queue.""" - implements(IHandler) - name = 'to-outgoing' description = _('Send the message to the outgoing queue.') diff --git a/src/mailman/handlers/to_usenet.py b/src/mailman/handlers/to_usenet.py index 021f8f9e5..79f4c9b1b 100644 --- a/src/mailman/handlers/to_usenet.py +++ b/src/mailman/handlers/to_usenet.py @@ -27,7 +27,7 @@ __all__ = [ import logging -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -39,11 +39,10 @@ log = logging.getLogger('mailman.error') +@implementer(IHandler) class ToUsenet: """Move the message to the outgoing news queue.""" - implements(IHandler) - name = 'to-usenet' description = _('Move the message to the outgoing news queue.') diff --git a/src/mailman/languages/language.py b/src/mailman/languages/language.py index 04f9c6639..effcf9c1b 100644 --- a/src/mailman/languages/language.py +++ b/src/mailman/languages/language.py @@ -18,7 +18,7 @@ """The representation of a language.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,16 +26,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer + from mailman.interfaces.languages import ILanguage +@implementer(ILanguage) class Language: """The representation of a language.""" - implements(ILanguage) - def __init__(self, code, charset, description): self.code = code self.charset = charset diff --git a/src/mailman/languages/manager.py b/src/mailman/languages/manager.py index ca7001102..7844bd87c 100644 --- a/src/mailman/languages/manager.py +++ b/src/mailman/languages/manager.py @@ -17,25 +17,24 @@ """Language manager.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'LanguageManager', ] -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.languages import ILanguageManager from mailman.languages.language import Language +@implementer(ILanguageManager) class LanguageManager: """Language manager.""" - implements(ILanguageManager) - def __init__(self): # Mapping from 2-letter code to Language instance. self._languages = {} diff --git a/src/mailman/model/address.py b/src/mailman/model/address.py index a12a993a8..d8ab65a80 100644 --- a/src/mailman/model/address.py +++ b/src/mailman/model/address.py @@ -17,7 +17,7 @@ """Model for addresses.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ from email.utils import formataddr from storm.locals import DateTime, Int, Reference, Unicode from zope.event import notify -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.interfaces.address import AddressVerificationEvent, IAddress @@ -36,8 +36,9 @@ from mailman.utilities.datetime import now +@implementer(IAddress) class Address(Model): - implements(IAddress) + """See `IAddress`.""" id = Int(primary=True) email = Unicode() diff --git a/src/mailman/model/autorespond.py b/src/mailman/model/autorespond.py index 9e0fbd042..567dcd19e 100644 --- a/src/mailman/model/autorespond.py +++ b/src/mailman/model/autorespond.py @@ -27,7 +27,7 @@ __all__ = [ from storm.locals import And, Date, Desc, Int, Reference -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -38,8 +38,9 @@ from mailman.utilities.datetime import today +@implementer(IAutoResponseRecord) class AutoResponseRecord(Model): - implements(IAutoResponseRecord) + """See `IAutoResponseRecord`.""" id = Int(primary=True) @@ -60,8 +61,9 @@ class AutoResponseRecord(Model): +@implementer(IAutoResponseSet) class AutoResponseSet: - implements(IAutoResponseSet) + """See `IAutoResponseSet`.""" def __init__(self, mailing_list): self._mailing_list = mailing_list diff --git a/src/mailman/model/bans.py b/src/mailman/model/bans.py index 89addd8c7..b6de9336f 100644 --- a/src/mailman/model/bans.py +++ b/src/mailman/model/bans.py @@ -28,7 +28,7 @@ __all__ = [ import re from storm.locals import Int, Unicode -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -36,8 +36,9 @@ from mailman.interfaces.bans import IBan, IBanManager +@implementer(IBan) class Ban(Model): - implements(IBan) + """See `IBan`.""" id = Int(primary=True) email = Unicode() @@ -50,8 +51,9 @@ class Ban(Model): +@implementer(IBanManager) class BanManager: - implements(IBanManager) + """See `IBanManager`.""" @dbconnection def ban(self, store, email, mailing_list=None): diff --git a/src/mailman/model/bounce.py b/src/mailman/model/bounce.py index b957a2243..628e076bf 100644 --- a/src/mailman/model/bounce.py +++ b/src/mailman/model/bounce.py @@ -27,7 +27,7 @@ __all__ = [ from storm.locals import Bool, Int, DateTime, Unicode -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -38,8 +38,9 @@ from mailman.utilities.datetime import now +@implementer(IBounceEvent) class BounceEvent(Model): - implements(IBounceEvent) + """See `IBounceEvent`.""" id = Int(primary=True) list_name = Unicode() @@ -59,8 +60,9 @@ class BounceEvent(Model): +@implementer(IBounceProcessor) class BounceProcessor: - implements(IBounceProcessor) + """See `IBounceProcessor`.""" @dbconnection def register(self, store, mlist, email, msg, where=None): diff --git a/src/mailman/model/digests.py b/src/mailman/model/digests.py index d7805ebf6..1d422ce8b 100644 --- a/src/mailman/model/digests.py +++ b/src/mailman/model/digests.py @@ -17,7 +17,7 @@ """One last digest.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from storm.locals import Int, Reference -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.types import Enum @@ -35,8 +35,9 @@ from mailman.interfaces.member import DeliveryMode +@implementer(IOneLastDigest) class OneLastDigest(Model): - implements(IOneLastDigest) + """See `IOneLastDigest`.""" id = Int(primary=True) diff --git a/src/mailman/model/docs/pending.rst b/src/mailman/model/docs/pending.rst index 1bf1ee0e9..3d33dd5da 100644 --- a/src/mailman/model/docs/pending.rst +++ b/src/mailman/model/docs/pending.rst @@ -15,11 +15,14 @@ In order to pend an event, you first need a pending database. The pending database can add any ``IPendable`` to the database, returning a token that can be used in urls and such. +:: - >>> from zope.interface import implements + >>> from zope.interface import implementer >>> from mailman.interfaces.pending import IPendable - >>> class SimplePendable(dict): - ... implements(IPendable) + >>> @implementer(IPendable) + ... class SimplePendable(dict): + ... pass + >>> subscription = SimplePendable( ... type='subscription', ... address='aperson@example.com', diff --git a/src/mailman/model/docs/registration.rst b/src/mailman/model/docs/registration.rst index eecb3a8cd..58e9d7a86 100644 --- a/src/mailman/model/docs/registration.rst +++ b/src/mailman/model/docs/registration.rst @@ -318,12 +318,15 @@ confirm method will just return False. Likewise, if you try to confirm, through the `IUserRegistrar` interface, a token that doesn't match a registration event, you will get ``None``. However, the pending event matched with that token will still be removed. +:: >>> from mailman.interfaces.pending import IPendable - >>> from zope.interface import implements + >>> from zope.interface import implementer + + >>> @implementer(IPendable) + ... class SimplePendable(dict): + ... pass - >>> class SimplePendable(dict): - ... implements(IPendable) >>> pendable = SimplePendable(type='foo', bar='baz') >>> token = pendingdb.add(pendable) >>> registrar.confirm(token) diff --git a/src/mailman/model/domain.py b/src/mailman/model/domain.py index e93335328..de6a9005a 100644 --- a/src/mailman/model/domain.py +++ b/src/mailman/model/domain.py @@ -29,7 +29,7 @@ __all__ = [ from urlparse import urljoin, urlparse from storm.locals import Int, Unicode from zope.event import notify -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -40,11 +40,10 @@ from mailman.model.mailinglist import MailingList +@implementer(IDomain) class Domain(Model): """Domains.""" - implements(IDomain) - id = Int(primary=True) mail_host = Unicode() @@ -115,11 +114,10 @@ class Domain(Model): +@implementer(IDomainManager) class DomainManager: """Domain manager.""" - implements(IDomainManager) - @dbconnection def add(self, store, mail_host, diff --git a/src/mailman/model/language.py b/src/mailman/model/language.py index da86b326c..b593721df 100644 --- a/src/mailman/model/language.py +++ b/src/mailman/model/language.py @@ -17,7 +17,7 @@ """Model for languages.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,15 +26,16 @@ __all__ = [ from storm.locals import Int, Unicode -from zope.interface import implements +from zope.interface import implementer from mailman.database import Model from mailman.interfaces import ILanguage +@implementer(ILanguage) class Language(Model): - implements(ILanguage) + """See `ILanguage`.""" id = Int(primary=True) code = Unicode() diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py index 8d845b36f..b4bc4b323 100644 --- a/src/mailman/model/listmanager.py +++ b/src/mailman/model/listmanager.py @@ -26,7 +26,7 @@ __all__ = [ from zope.event import notify -from zope.interface import implements +from zope.interface import implementer from mailman.database.transaction import dbconnection from mailman.interfaces.address import InvalidEmailAddressError @@ -38,11 +38,10 @@ from mailman.utilities.datetime import now +@implementer(IListManager) class ListManager: """An implementation of the `IListManager` interface.""" - implements(IListManager) - @dbconnection def create(self, store, fqdn_listname): """See `IListManager`.""" diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py index d51c89514..bff4fbf88 100644 --- a/src/mailman/model/mailinglist.py +++ b/src/mailman/model/mailinglist.py @@ -17,7 +17,7 @@ """Model for mailing lists.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -33,7 +33,7 @@ from storm.locals import ( TimeDelta, Unicode) from urlparse import urljoin from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.database.model import Model @@ -67,8 +67,9 @@ UNDERSCORE = '_' +@implementer(IMailingList) class MailingList(Model): - implements(IMailingList) + """See `IMailingList`.""" id = Int(primary=True) @@ -492,8 +493,9 @@ class MailingList(Model): +@implementer(IAcceptableAlias) class AcceptableAlias(Model): - implements(IAcceptableAlias) + """See `IAcceptableAlias`.""" id = Int(primary=True) @@ -507,8 +509,10 @@ class AcceptableAlias(Model): self.alias = alias + +@implementer(IAcceptableAliasSet) class AcceptableAliasSet: - implements(IAcceptableAliasSet) + """See `IAcceptableAliasSet`.""" def __init__(self, mailing_list): self._mailing_list = mailing_list diff --git a/src/mailman/model/member.py b/src/mailman/model/member.py index 5a71eb8be..b791ea0f2 100644 --- a/src/mailman/model/member.py +++ b/src/mailman/model/member.py @@ -27,7 +27,7 @@ __all__ = [ from storm.locals import Int, Reference, Unicode from storm.properties import UUID from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.constants import system_preferences from mailman.database.model import Model @@ -46,8 +46,9 @@ uid_factory = UniqueIDFactory(context='members') +@implementer(IMember) class Member(Model): - implements(IMember) + """See `IMember`.""" id = Int(primary=True) _member_id = UUID() diff --git a/src/mailman/model/message.py b/src/mailman/model/message.py index 67c4caf79..190b4055c 100644 --- a/src/mailman/model/message.py +++ b/src/mailman/model/message.py @@ -25,7 +25,7 @@ __all__ = [ ] from storm.locals import AutoReload, Int, RawStr, Unicode -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -33,11 +33,10 @@ from mailman.interfaces.messages import IMessage +@implementer(IMessage) class Message(Model): """A message in the message store.""" - implements(IMessage) - id = Int(primary=True, default=AutoReload) message_id = Unicode() message_id_hash = RawStr() diff --git a/src/mailman/model/messagestore.py b/src/mailman/model/messagestore.py index df2205ff8..156375e6f 100644 --- a/src/mailman/model/messagestore.py +++ b/src/mailman/model/messagestore.py @@ -30,7 +30,7 @@ import base64 import hashlib import cPickle as pickle -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.database.transaction import dbconnection @@ -46,8 +46,9 @@ EMPTYSTRING = '' +@implementer(IMessageStore) class MessageStore: - implements(IMessageStore) + """See `IMessageStore`.""" @dbconnection def add(self, store, message): diff --git a/src/mailman/model/mime.py b/src/mailman/model/mime.py index c611aab89..462bb9016 100644 --- a/src/mailman/model/mime.py +++ b/src/mailman/model/mime.py @@ -15,9 +15,9 @@ # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . -"""Module stuff.""" +"""The content filter.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from storm.locals import Int, Reference, Unicode -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.types import Enum @@ -34,9 +34,9 @@ from mailman.interfaces.mime import IContentFilter, FilterType +@implementer(IContentFilter) class ContentFilter(Model): """A single filter criteria.""" - implements(IContentFilter) id = Int(primary=True) diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py index 39845e0bf..727e4f754 100644 --- a/src/mailman/model/pending.py +++ b/src/mailman/model/pending.py @@ -32,7 +32,7 @@ import hashlib from lazr.config import as_timedelta from storm.locals import DateTime, Int, RawStr, ReferenceSet, Unicode -from zope.interface import implements +from zope.interface import implementer from zope.interface.verify import verifyObject from mailman.config import config @@ -45,11 +45,10 @@ from mailman.utilities.modules import call_name +@implementer(IPendedKeyValue) class PendedKeyValue(Model): """A pended key/value pair, tied to a token.""" - implements(IPendedKeyValue) - def __init__(self, key, value): self.key = key self.value = value @@ -60,11 +59,11 @@ class PendedKeyValue(Model): pended_id = Int() + +@implementer(IPended) class Pended(Model): """A pended event, tied to a token.""" - implements(IPended) - def __init__(self, token, expiration_date): super(Pended, self).__init__() self.token = token @@ -77,16 +76,16 @@ class Pended(Model): +@implementer(IPendable) class UnpendedPendable(dict): - implements(IPendable) + pass +@implementer(IPendings) class Pendings: """Implementation of the IPending interface.""" - implements(IPendings) - @dbconnection def add(self, store, pendable, lifetime=None): verifyObject(IPendable, pendable) diff --git a/src/mailman/model/preferences.py b/src/mailman/model/preferences.py index 234c7399e..fdc30a94d 100644 --- a/src/mailman/model/preferences.py +++ b/src/mailman/model/preferences.py @@ -17,7 +17,7 @@ """Model for preferences.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ from storm.locals import Bool, Int, Unicode from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.types import Enum @@ -37,8 +37,9 @@ from mailman.interfaces.preferences import IPreferences +@implementer(IPreferences) class Preferences(Model): - implements(IPreferences) + """See `IPreferences`.""" id = Int(primary=True) acknowledge_posts = Bool() diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py index 030c630b9..a92332e4a 100644 --- a/src/mailman/model/requests.py +++ b/src/mailman/model/requests.py @@ -27,7 +27,7 @@ __all__ = [ from datetime import timedelta from storm.locals import AutoReload, Int, RawStr, Reference, Unicode from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -37,13 +37,14 @@ from mailman.interfaces.requests import IListRequests, RequestType +@implementer(IPendable) class DataPendable(dict): - implements(IPendable) + pass +@implementer(IListRequests) class ListRequests: - implements(IListRequests) def __init__(self, mailing_list): self.mailing_list = mailing_list diff --git a/src/mailman/model/roster.py b/src/mailman/model/roster.py index 84ed12930..56dad4bc8 100644 --- a/src/mailman/model/roster.py +++ b/src/mailman/model/roster.py @@ -38,7 +38,7 @@ __all__ = [ from storm.expr import And, Or -from zope.interface import implements +from zope.interface import implementer from mailman.database.transaction import dbconnection from mailman.interfaces.member import DeliveryMode, MemberRole @@ -48,6 +48,7 @@ from mailman.model.member import Member +@implementer(IRoster) class AbstractRoster: """An abstract IRoster class. @@ -57,8 +58,6 @@ class AbstractRoster: This requires that subclasses implement the 'members' property. """ - implements(IRoster) - role = None def __init__(self, mlist): @@ -255,11 +254,10 @@ class Subscribers(AbstractRoster): +@implementer(IRoster) class Memberships: """A roster of a single user's memberships.""" - implements(IRoster) - name = 'memberships' def __init__(self, user): diff --git a/src/mailman/model/user.py b/src/mailman/model/user.py index 15ed9170f..a723df44e 100644 --- a/src/mailman/model/user.py +++ b/src/mailman/model/user.py @@ -28,7 +28,7 @@ from storm.locals import ( DateTime, Int, RawStr, Reference, ReferenceSet, Unicode) from storm.properties import UUID from zope.event import notify -from zope.interface import implements +from zope.interface import implementer from mailman.database.model import Model from mailman.database.transaction import dbconnection @@ -47,11 +47,10 @@ uid_factory = UniqueIDFactory(context='users') +@implementer(IUser) class User(Model): """Mailman users.""" - implements(IUser) - id = Int(primary=True) display_name = Unicode() _password = RawStr(name='password') diff --git a/src/mailman/model/usermanager.py b/src/mailman/model/usermanager.py index 2c4158b90..4c7daaa59 100644 --- a/src/mailman/model/usermanager.py +++ b/src/mailman/model/usermanager.py @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.database.transaction import dbconnection from mailman.interfaces.address import ExistingAddressError @@ -37,8 +37,9 @@ from mailman.model.user import User +@implementer(IUserManager) class UserManager: - implements(IUserManager) + """See `IUserManager`.""" def create_user(self, email=None, display_name=None): """See `IUserManager`.""" diff --git a/src/mailman/mta/aliases.py b/src/mailman/mta/aliases.py index 573160d3c..e87f5880f 100644 --- a/src/mailman/mta/aliases.py +++ b/src/mailman/mta/aliases.py @@ -17,7 +17,7 @@ """Utility for generating all the aliases of a mailing list.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.mta import IMailTransportAgentAliases @@ -43,11 +43,10 @@ SUBDESTINATIONS = ( +@implementer(IMailTransportAgentAliases) class MailTransportAgentAliases: """Utility for generating all the aliases of a mailing list.""" - implements(IMailTransportAgentAliases) - def aliases(self, mlist): """See `IMailTransportAgentAliases`.""" # Always return diff --git a/src/mailman/mta/base.py b/src/mailman/mta/base.py index 8068eaec1..e11c37ff6 100644 --- a/src/mailman/mta/base.py +++ b/src/mailman/mta/base.py @@ -17,7 +17,7 @@ """Base delivery class.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -31,7 +31,7 @@ import socket import logging import smtplib -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.mta import IMailTransportAgentDelivery @@ -42,11 +42,10 @@ log = logging.getLogger('mailman.smtp') +@implementer(IMailTransportAgentDelivery) class BaseDelivery: """Base delivery class.""" - implements(IMailTransportAgentDelivery) - def __init__(self): """Create a basic deliverer.""" username = (config.mta.smtp_user if config.mta.smtp_user else None) diff --git a/src/mailman/mta/null.py b/src/mailman/mta/null.py index 6b2f76a1c..c94fa1015 100644 --- a/src/mailman/mta/null.py +++ b/src/mailman/mta/null.py @@ -20,7 +20,7 @@ Exim one example of an MTA that Just Works. """ -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,16 +28,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer + from mailman.interfaces.mta import IMailTransportAgentLifecycle +@implementer(IMailTransportAgentLifecycle) class NullMTA: """Null MTA that just satisfies the interface.""" - implements(IMailTransportAgentLifecycle) - def create(self, mlist): """See `IMailTransportAgentLifecycle`.""" pass diff --git a/src/mailman/mta/postfix.py b/src/mailman/mta/postfix.py index 32bdb8268..c04e38f02 100644 --- a/src/mailman/mta/postfix.py +++ b/src/mailman/mta/postfix.py @@ -17,7 +17,7 @@ """Creation/deletion hooks for the Postfix MTA.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -31,7 +31,7 @@ import logging from flufl.lock import Lock from operator import attrgetter from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.interfaces.listmanager import IListManager @@ -55,11 +55,10 @@ class _FakeList: +@implementer(IMailTransportAgentLifecycle) class LMTP: """Connect Mailman to Postfix via LMTP.""" - implements(IMailTransportAgentLifecycle) - def create(self, mlist): """See `IMailTransportAgentLifecycle`.""" # We can ignore the mlist argument because for LMTP delivery, we just @@ -117,23 +116,24 @@ class LMTP: for list_name, mail_host in list_manager.name_components: mlist = _FakeList(list_name, mail_host) by_domain.setdefault(mlist.mail_host, []).append(mlist) - print >> fp, """\ + print("""\ # AUTOMATICALLY GENERATED BY MAILMAN ON {0} # # This file is generated by Mailman, and is kept in sync with the binary hash # file. YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you know what you're # doing, and can keep the two files properly in sync. If you screw it up, # you're on your own. -""".format(now().replace(microsecond=0)) +""".format(now().replace(microsecond=0)), file=fp) sort_key = attrgetter('list_name') for domain in sorted(by_domain): - print >> fp, """\ -# Aliases which are visible only in the @{0} domain.""".format(domain) + print("""\ +# Aliases which are visible only in the @{0} domain.""".format(domain), + file=fp) for mlist in sorted(by_domain[domain], key=sort_key): utility = getUtility(IMailTransportAgentAliases) aliases = list(utility.aliases(mlist)) width = max(len(alias) for alias in aliases) + 3 - print >> fp, ALIASTMPL.format(aliases.pop(0), config, width) + print(ALIASTMPL.format(aliases.pop(0), config, width), file=fp) for alias in aliases: - print >> fp, ALIASTMPL.format(alias, config, width) - print >> fp + print(ALIASTMPL.format(alias, config, width), file=fp) + print(file=fp) diff --git a/src/mailman/rules/administrivia.py b/src/mailman/rules/administrivia.py index 41c6edf30..4c49e4ff2 100644 --- a/src/mailman/rules/administrivia.py +++ b/src/mailman/rules/administrivia.py @@ -17,7 +17,7 @@ """The administrivia rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from email.iterators import typed_subpart_iterator -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -53,9 +53,9 @@ EMAIL_COMMANDS = { +@implementer(IRule) class Administrivia: """The administrivia rule.""" - implements(IRule) name = 'administrivia' description = _('Catch mis-addressed email commands.') diff --git a/src/mailman/rules/any.py b/src/mailman/rules/any.py index b0d147bec..33c20394d 100644 --- a/src/mailman/rules/any.py +++ b/src/mailman/rules/any.py @@ -17,7 +17,7 @@ """Check if any previous rules have matched.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class Any: """Look for any previous rule match.""" - implements(IRule) name = 'any' description = _('Look for any previous rule hit.') diff --git a/src/mailman/rules/approved.py b/src/mailman/rules/approved.py index 3e2b7bc83..1f4fc1369 100644 --- a/src/mailman/rules/approved.py +++ b/src/mailman/rules/approved.py @@ -29,7 +29,7 @@ import re from email.iterators import typed_subpart_iterator from flufl.password import verify -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule @@ -45,9 +45,9 @@ HEADERS = [ +@implementer(IRule) class Approved: """Look for moderator pre-approval.""" - implements(IRule) name = 'approved' description = _('The message has a matching Approve or Approved header.') @@ -119,7 +119,7 @@ class Approved: else: for header in HEADERS: del msg[header] - return (password is not missing and + return (password is not missing and verify(mlist.moderator_password, password)) diff --git a/src/mailman/rules/emergency.py b/src/mailman/rules/emergency.py index 7b2100875..7c11b0aa3 100644 --- a/src/mailman/rules/emergency.py +++ b/src/mailman/rules/emergency.py @@ -17,7 +17,7 @@ """The emergency hold rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class Emergency: """The emergency hold rule.""" - implements(IRule) name = 'emergency' diff --git a/src/mailman/rules/implicit_dest.py b/src/mailman/rules/implicit_dest.py index 321a1775d..41d0403bc 100644 --- a/src/mailman/rules/implicit_dest.py +++ b/src/mailman/rules/implicit_dest.py @@ -17,7 +17,7 @@ """The implicit destination rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ import re from email.utils import getaddresses -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.mailinglist import IAcceptableAliasSet @@ -35,9 +35,9 @@ from mailman.interfaces.rules import IRule +@implementer(IRule) class ImplicitDestination: """The implicit destination rule.""" - implements(IRule) name = 'implicit-dest' description = _('Catch messages with implicit destination.') diff --git a/src/mailman/rules/loop.py b/src/mailman/rules/loop.py index 9e4aa0061..9282b1705 100644 --- a/src/mailman/rules/loop.py +++ b/src/mailman/rules/loop.py @@ -17,7 +17,7 @@ """Look for a posting loop.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class Loop: """Look for a posting loop.""" - implements(IRule) name = 'loop' description = _('Look for a posting loop.') diff --git a/src/mailman/rules/max_recipients.py b/src/mailman/rules/max_recipients.py index 79396c72f..fd09114e2 100644 --- a/src/mailman/rules/max_recipients.py +++ b/src/mailman/rules/max_recipients.py @@ -17,7 +17,7 @@ """The maximum number of recipients rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,16 +26,16 @@ __all__ = [ from email.utils import getaddresses -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class MaximumRecipients: """The maximum number of recipients rule.""" - implements(IRule) name = 'max-recipients' description = _('Catch messages with too many explicit recipients.') diff --git a/src/mailman/rules/max_size.py b/src/mailman/rules/max_size.py index 420d63571..a67d87771 100644 --- a/src/mailman/rules/max_size.py +++ b/src/mailman/rules/max_size.py @@ -17,7 +17,7 @@ """The maximum message size rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class MaximumSize: """The implicit destination rule.""" - implements(IRule) name = 'max-size' description = _('Catch messages that are bigger than a specified maximum.') diff --git a/src/mailman/rules/moderation.py b/src/mailman/rules/moderation.py index cb27d89d8..b2c777dc7 100644 --- a/src/mailman/rules/moderation.py +++ b/src/mailman/rules/moderation.py @@ -17,7 +17,7 @@ """Membership related rules.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -27,7 +27,7 @@ __all__ = [ from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.action import Action @@ -37,9 +37,9 @@ from mailman.interfaces.usermanager import IUserManager +@implementer(IRule) class MemberModeration: """The member moderation rule.""" - implements(IRule) name = 'member-moderation' description = _('Match messages sent by moderated members.') @@ -65,9 +65,9 @@ class MemberModeration: +@implementer(IRule) class NonmemberModeration: """The nonmember moderation rule.""" - implements(IRule) name = 'nonmember-moderation' description = _('Match messages sent by nonmembers.') diff --git a/src/mailman/rules/news_moderation.py b/src/mailman/rules/news_moderation.py index 4ca9a0d8a..1e820a61f 100644 --- a/src/mailman/rules/news_moderation.py +++ b/src/mailman/rules/news_moderation.py @@ -17,7 +17,7 @@ """The news moderation rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,7 +25,7 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.nntp import NewsModeration @@ -33,9 +33,9 @@ from mailman.interfaces.rules import IRule +@implementer(IRule) class ModeratedNewsgroup: """The news moderation rule.""" - implements(IRule) name = 'news-moderation' description = _( diff --git a/src/mailman/rules/no_subject.py b/src/mailman/rules/no_subject.py index 1a2bab1d5..1fd0dfb8b 100644 --- a/src/mailman/rules/no_subject.py +++ b/src/mailman/rules/no_subject.py @@ -17,7 +17,7 @@ """The no-Subject header rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class NoSubject: """The no-Subject rule.""" - implements(IRule) name = 'no-subject' description = _('Catch messages with no, or empty, Subject headers.') diff --git a/src/mailman/rules/suspicious.py b/src/mailman/rules/suspicious.py index ad1ab42cd..75fe0afab 100644 --- a/src/mailman/rules/suspicious.py +++ b/src/mailman/rules/suspicious.py @@ -17,7 +17,7 @@ """The historical 'suspicious header' rule.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ import re import logging -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule @@ -37,9 +37,9 @@ log = logging.getLogger('mailman.error') +@implementer(IRule) class SuspiciousHeader: """The historical 'suspicious header' rule.""" - implements(IRule) name = 'suspicious-header' description = _('Catch messages with suspicious headers.') diff --git a/src/mailman/rules/truth.py b/src/mailman/rules/truth.py index 20c152e4d..752618ced 100644 --- a/src/mailman/rules/truth.py +++ b/src/mailman/rules/truth.py @@ -17,7 +17,7 @@ """A rule which always matches.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -25,16 +25,16 @@ __all__ = [ ] -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +@implementer(IRule) class Truth: """Look for any previous rule match.""" - implements(IRule) name = 'truth' description = _('A rule which always matches.') diff --git a/src/mailman/runners/command.py b/src/mailman/runners/command.py index ac611ed3a..6501474a3 100644 --- a/src/mailman/runners/command.py +++ b/src/mailman/runners/command.py @@ -38,7 +38,7 @@ from email.errors import HeaderParseError from email.header import decode_header, make_header from email.iterators import typed_subpart_iterator from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.config import config from mailman.core.i18n import _ @@ -117,7 +117,7 @@ class CommandFinder: continue # Ensure that all the parts are unicodes. Since we only accept # ASCII commands and arguments, ignore anything else. - parts = [(part + parts = [(part if isinstance(part, unicode) else part.decode('ascii', 'ignore')) for part in parts] @@ -125,11 +125,10 @@ class CommandFinder: +@implementer(IEmailResults) class Results: """The email command results.""" - implements(IEmailResults) - def __init__(self, charset='us-ascii'): self._output = StringIO() self.charset = charset diff --git a/src/mailman/runners/tests/test_archiver.py b/src/mailman/runners/tests/test_archiver.py index 6f5804cae..30cb9e461 100644 --- a/src/mailman/runners/tests/test_archiver.py +++ b/src/mailman/runners/tests/test_archiver.py @@ -29,7 +29,7 @@ import os import unittest from email import message_from_file -from zope.interface import implements +from zope.interface import implementer from mailman.app.lifecycle import create_list from mailman.config import config @@ -44,8 +44,8 @@ from mailman.utilities.datetime import RFC822_DATE_FMT, factory, now +@implementer(IArchiver) class DummyArchiver: - implements(IArchiver) name = 'dummy' @staticmethod @@ -193,7 +193,7 @@ First post! self.assertEqual(archived['x-original-date'], 'Mon, 01 Aug 2005 07:49:23 +0000') - @configuration('archiver.dummy', + @configuration('archiver.dummy', enable='yes', clobber_date='maybe', clobber_skew='1d') def test_clobber_date_maybe_when_insane(self): # The date is clobbered if it's farther off from now than its skew diff --git a/src/mailman/runners/tests/test_bounce.py b/src/mailman/runners/tests/test_bounce.py index 76eb65c1f..5c21000bf 100644 --- a/src/mailman/runners/tests/test_bounce.py +++ b/src/mailman/runners/tests/test_bounce.py @@ -17,17 +17,20 @@ """Test the bounce runner.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ + 'TestBounceRunner', + 'TestBounceRunnerBug876774', + 'TestStyle', ] import unittest from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from mailman.app.bounces import send_probe from mailman.app.lifecycle import create_list @@ -235,8 +238,9 @@ Message-Id: # attributes. In particular, this will not set the bogus `bounce_processing` # attribute which the default style set (before LP: #876774 was fixed). +@implementer(IStyle) class TestStyle: - implements(IStyle) + """See `IStyle`.""" name = 'test' priority = 10 @@ -249,6 +253,7 @@ class TestStyle: styles.append(self) + class TestBounceRunnerBug876774(unittest.TestCase): """Test LP: #876774. diff --git a/src/mailman/runners/tests/test_pipeline.py b/src/mailman/runners/tests/test_pipeline.py index 8776bf844..3f8f62ab0 100644 --- a/src/mailman/runners/tests/test_pipeline.py +++ b/src/mailman/runners/tests/test_pipeline.py @@ -27,7 +27,7 @@ __all__ = [ import unittest -from zope.interface import implements +from zope.interface import implementer from mailman.app.lifecycle import create_list from mailman.config import config @@ -41,8 +41,10 @@ from mailman.testing.layers import ConfigLayer +@implementer(IHandler) class MyTestHandler: - implements(IHandler) + """See `IHandler`.""" + name = 'test handler' description = 'A test handler' @@ -54,8 +56,9 @@ class MyTestHandler: self._test.mark(self._marker) + +@implementer(IPipeline) class MyTestPipeline: - implements(IPipeline) name = 'test' description = 'a test pipeline' diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py index b6900dca6..ef94dd4e6 100644 --- a/src/mailman/styles/default.py +++ b/src/mailman/styles/default.py @@ -17,7 +17,7 @@ """Application of list styles to new and existing lists.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -28,7 +28,7 @@ __all__ = [ # XXX Styles need to be reconciled with lazr.config. from datetime import timedelta -from zope.interface import implements +from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.action import Action, FilterAction @@ -41,11 +41,10 @@ from mailman.interfaces.styles import IStyle +@implementer(IStyle) class DefaultStyle: """The default (i.e. legacy) style.""" - implements(IStyle) - name = 'default' priority = 0 # the lowest priority style diff --git a/src/mailman/styles/docs/styles.rst b/src/mailman/styles/docs/styles.rst index 90a02227b..8f589f10b 100644 --- a/src/mailman/styles/docs/styles.rst +++ b/src/mailman/styles/docs/styles.rst @@ -62,10 +62,10 @@ Registering styles New styles must implement the ``IStyle`` interface. - >>> from zope.interface import implements + >>> from zope.interface import implementer >>> from mailman.interfaces.styles import IStyle - >>> class TestStyle: - ... implements(IStyle) + >>> @implementer(IStyle) + ... class TestStyle: ... name = 'test' ... priority = 10 ... def apply(self, mailing_list): diff --git a/src/mailman/styles/manager.py b/src/mailman/styles/manager.py index f1d3f1dfb..8ec832f18 100644 --- a/src/mailman/styles/manager.py +++ b/src/mailman/styles/manager.py @@ -17,7 +17,7 @@ """Style manager.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -26,7 +26,7 @@ __all__ = [ from operator import attrgetter -from zope.interface import implements +from zope.interface import implementer from zope.interface.verify import verifyObject from mailman.interfaces.styles import ( @@ -35,11 +35,10 @@ from mailman.utilities.modules import call_name +@implementer(IStyleManager) class StyleManager: """The built-in style manager.""" - implements(IStyleManager) - def __init__(self): """Install all styles from the configuration files.""" self._styles = {} diff --git a/src/mailman/styles/tests/test_styles.py b/src/mailman/styles/tests/test_styles.py index ce8b5064d..990ce541f 100644 --- a/src/mailman/styles/tests/test_styles.py +++ b/src/mailman/styles/tests/test_styles.py @@ -28,7 +28,7 @@ __all__ = [ import unittest from zope.component import getUtility -from zope.interface import implements +from zope.interface import implementer from zope.interface.exceptions import DoesNotImplement from mailman.interfaces.styles import ( @@ -37,8 +37,8 @@ from mailman.testing.layers import ConfigLayer +@implementer(IStyle) class DummyStyle: - implements(IStyle) name = 'dummy' priority = 1 diff --git a/src/mailman/testing/mta.py b/src/mailman/testing/mta.py index 4699cb882..bba450352 100644 --- a/src/mailman/testing/mta.py +++ b/src/mailman/testing/mta.py @@ -17,7 +17,7 @@ """Fake MTA for testing purposes.""" -from __future__ import absolute_import, unicode_literals +from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ @@ -31,7 +31,7 @@ from Queue import Empty, Queue from lazr.smtptest.controller import QueueController from lazr.smtptest.server import Channel, QueueServer -from zope.interface import implements +from zope.interface import implementer from mailman.interfaces.mta import IMailTransportAgentLifecycle @@ -40,11 +40,10 @@ log = logging.getLogger('lazr.smtptest') +@implementer(IMailTransportAgentLifecycle) class FakeMTA: """Fake MTA for testing purposes.""" - implements(IMailTransportAgentLifecycle) - def create(self, mlist): pass -- cgit v1.2.3-70-g09d2 From 955d267e5f4479cea6adb93871af1eb80aa492b6 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Wed, 27 Jun 2012 23:03:04 -0400 Subject: Replace flufl.password with passlib, albeit with a wrapper. --- setup.py | 2 +- src/mailman/app/membership.py | 9 ++--- src/mailman/app/subscriptions.py | 2 +- src/mailman/app/tests/test_membership.py | 7 ++-- src/mailman/commands/cli_members.py | 2 +- src/mailman/config/schema.cfg | 5 +-- src/mailman/model/docs/requests.rst | 2 +- src/mailman/rest/docs/users.rst | 14 ++++---- src/mailman/rest/users.py | 6 ++-- src/mailman/rules/approved.py | 2 +- src/mailman/rules/docs/approved.rst | 5 ++- src/mailman/rules/tests/test_approved.py | 13 +++----- src/mailman/testing/layers.py | 2 +- src/mailman/utilities/passwords.py | 57 ++++++++++++++++++++++++++++++++ 14 files changed, 89 insertions(+), 39 deletions(-) create mode 100644 src/mailman/utilities/passwords.py (limited to 'src/mailman/commands/cli_members.py') diff --git a/setup.py b/setup.py index a37068ee6..236faa3f5 100644 --- a/setup.py +++ b/setup.py @@ -98,11 +98,11 @@ case second `m'. Any other spelling is incorrect.""", 'flufl.enum', 'flufl.i18n', 'flufl.lock', - 'flufl.password', 'httplib2', 'lazr.config', 'lazr.smtptest', 'mock', + 'passlib', 'restish', 'storm', 'zc.buildout', diff --git a/src/mailman/app/membership.py b/src/mailman/app/membership.py index e31a1695c..e11cef44a 100644 --- a/src/mailman/app/membership.py +++ b/src/mailman/app/membership.py @@ -27,11 +27,9 @@ __all__ = [ from email.utils import formataddr -from flufl.password import lookup, make_secret from zope.component import getUtility from mailman.app.notifications import send_goodbye_message -from mailman.config import config from mailman.core.i18n import _ from mailman.email.message import OwnerNotification from mailman.interfaces.address import IEmailValidator @@ -40,6 +38,7 @@ from mailman.interfaces.member import ( MemberRole, MembershipIsBannedError, NotAMemberError) from mailman.interfaces.usermanager import IUserManager from mailman.utilities.i18n import make +from mailman.utilities.passwords import encrypt @@ -96,10 +95,8 @@ def add_member(mlist, email, display_name, password, delivery_mode, language, user.display_name = ( display_name if display_name else address.display_name) user.link(address) - # Encrypt the password using the currently selected scheme. The - # scheme is recorded in the hashed password string. - scheme = lookup(config.passwords.password_scheme.upper()) - user.password = make_secret(password, scheme) + # Encrypt the password using the currently selected hash scheme. + user.password = encrypt(password) user.preferences.preferred_language = language member = mlist.subscribe(address, role) member.preferences.delivery_mode = delivery_mode diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py index ebbe14492..7949f83ee 100644 --- a/src/mailman/app/subscriptions.py +++ b/src/mailman/app/subscriptions.py @@ -26,8 +26,8 @@ __all__ = [ ] -from flufl.password import generate from operator import attrgetter +from passlib.utils import generate_password as generate from storm.expr import And, Or from uuid import UUID from zope.component import getUtility diff --git a/src/mailman/app/tests/test_membership.py b/src/mailman/app/tests/test_membership.py index 74e15d0e2..c3c310b6c 100644 --- a/src/mailman/app/tests/test_membership.py +++ b/src/mailman/app/tests/test_membership.py @@ -134,7 +134,7 @@ class AddMemberTest(unittest.TestCase): self.assertEqual(member.address.email, 'aperson@example.com') self.assertEqual(member.mailing_list, 'test@example.com') self.assertEqual(member.role, MemberRole.moderator) - + def test_add_member_twice(self): # Adding a member with the same role twice causes an # AlreadySubscribedError to be raised. @@ -182,7 +182,7 @@ class AddMemberPasswordTest(unittest.TestCase): # inappropriate for unit tests. config.push('password scheme', """ [passwords] - password_scheme: sha + password_scheme: passlib.hash.sha1_crypt """) def tearDown(self): @@ -195,4 +195,5 @@ class AddMemberPasswordTest(unittest.TestCase): 'Anne Person', 'abc', DeliveryMode.regular, system_preferences.preferred_language) self.assertEqual( - member.user.password, '{SHA}qZk-NkcGgWq6PiVxeFDCbJzQ2J0=') + member.user.password, + '{sha1_crypt}$sha1$40000$$nY5NBnPWWAD5KI4X8Jjzp7.1YhV6') diff --git a/src/mailman/commands/cli_members.py b/src/mailman/commands/cli_members.py index aef3991d8..7c5d3b8f3 100644 --- a/src/mailman/commands/cli_members.py +++ b/src/mailman/commands/cli_members.py @@ -29,8 +29,8 @@ import sys import codecs from email.utils import formataddr, parseaddr -from flufl.password import generate from operator import attrgetter +from passlib.utils import generate_password as generate from zope.component import getUtility from zope.interface import implementer diff --git a/src/mailman/config/schema.cfg b/src/mailman/config/schema.cfg index 00b8d9325..8d17d806c 100644 --- a/src/mailman/config/schema.cfg +++ b/src/mailman/config/schema.cfg @@ -156,8 +156,9 @@ wait: 10s [passwords] # The default scheme to use to encrypt new passwords. Existing passwords # include the scheme that was used to encrypt them, so it's okay to change -# this after users have been added. -password_scheme: ssha +# this after users have been added. This is the path to a passlib hash +# algorithm. See http://packages.python.org/passlib/lib/passlib.hash.html +password_scheme: passlib.hash.pbkdf2_sha512 # When Mailman generates them, this is the default length of passwords. password_length: 8 diff --git a/src/mailman/model/docs/requests.rst b/src/mailman/model/docs/requests.rst index a20823a91..a51cbc099 100644 --- a/src/mailman/model/docs/requests.rst +++ b/src/mailman/model/docs/requests.rst @@ -696,7 +696,7 @@ Frank Person is now a member of the mailing list. >>> print member.user.display_name Frank Person >>> print member.user.password - {CLEARTEXT}abcxyz + {plaintext}abcxyz Holding unsubscription requests diff --git a/src/mailman/rest/docs/users.rst b/src/mailman/rest/docs/users.rst index a20306e17..cdede10ee 100644 --- a/src/mailman/rest/docs/users.rst +++ b/src/mailman/rest/docs/users.rst @@ -94,7 +94,7 @@ It is also available via the location given in the response. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -105,7 +105,7 @@ them with user ids. Thus, a user can be retrieved via its email address. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -129,7 +129,7 @@ therefore cannot be retrieved. It can be reset though. created_on: 2005-08-01T07:49:23 display_name: Cris Person http_etag: "..." - password: {CLEARTEXT}... + password: {plaintext}... self_link: http://localhost:9001/3.0/users/4 user_id: 4 @@ -227,7 +227,7 @@ In fact, any of these addresses can be used to look up Bart's user record. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -235,7 +235,7 @@ In fact, any of these addresses can be used to look up Bart's user record. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -243,7 +243,7 @@ In fact, any of these addresses can be used to look up Bart's user record. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -251,6 +251,6 @@ In fact, any of these addresses can be used to look up Bart's user record. created_on: 2005-08-01T07:49:23 display_name: Bart Person http_etag: "..." - password: {CLEARTEXT}bbb + password: {plaintext}bbb self_link: http://localhost:9001/3.0/users/3 user_id: 3 diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py index 4e1362120..6bab7c789 100644 --- a/src/mailman/rest/users.py +++ b/src/mailman/rest/users.py @@ -26,7 +26,7 @@ __all__ = [ ] -from flufl.password import lookup, make_secret, generate +from passlib.utils import generate_password as generate from restish import http, resource from uuid import UUID from zope.component import getUtility @@ -38,6 +38,7 @@ from mailman.rest.addresses import UserAddresses from mailman.rest.helpers import CollectionMixin, etag, no_content, path_to from mailman.rest.preferences import Preferences from mailman.rest.validator import Validator +from mailman.utilities.passwords import encrypt @@ -102,8 +103,7 @@ class AllUsers(_UserBase): if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) - scheme = lookup(config.passwords.password_scheme.upper()) - user.password = make_secret(password, scheme) + user.password = encrypt(password) location = path_to('users/{0}'.format(user.user_id.int)) return http.created(location, [], None) diff --git a/src/mailman/rules/approved.py b/src/mailman/rules/approved.py index 1f4fc1369..dadc25322 100644 --- a/src/mailman/rules/approved.py +++ b/src/mailman/rules/approved.py @@ -28,11 +28,11 @@ __all__ = [ import re from email.iterators import typed_subpart_iterator -from flufl.password import verify from zope.interface import implementer from mailman.core.i18n import _ from mailman.interfaces.rules import IRule +from mailman.utilities.passwords import verify EMPTYSTRING = '' diff --git a/src/mailman/rules/docs/approved.rst b/src/mailman/rules/docs/approved.rst index 9c61a7419..7f0714e17 100644 --- a/src/mailman/rules/docs/approved.rst +++ b/src/mailman/rules/docs/approved.rst @@ -20,9 +20,8 @@ which is shared among all the administrators. This password will not be stored in clear text, so it must be hashed using the configured hash protocol. - >>> from flufl.password import lookup, make_secret - >>> scheme = lookup(config.passwords.password_scheme.upper()) - >>> mlist.moderator_password = make_secret('super secret', scheme) + >>> from mailman.utilities.passwords import encrypt + >>> mlist.moderator_password = encrypt('super secret') The ``approved`` rule determines whether the message contains the proper approval or not. diff --git a/src/mailman/rules/tests/test_approved.py b/src/mailman/rules/tests/test_approved.py index d078556ba..de409f654 100644 --- a/src/mailman/rules/tests/test_approved.py +++ b/src/mailman/rules/tests/test_approved.py @@ -30,14 +30,12 @@ __all__ = [ import unittest -from flufl.password import lookup, make_secret - from mailman.app.lifecycle import create_list -from mailman.config import config from mailman.rules import approved from mailman.testing.helpers import ( specialized_message_from_string as mfs) from mailman.testing.layers import ConfigLayer +from mailman.utilities.passwords import encrypt @@ -48,8 +46,7 @@ class TestApproved(unittest.TestCase): def setUp(self): self._mlist = create_list('test@example.com') - scheme = lookup(config.passwords.password_scheme.upper()) - self._mlist.moderator_password = make_secret('super secret', scheme) + self._mlist.moderator_password = encrypt('super secret') self._rule = approved.Approved() self._msg = mfs("""\ From: anne@example.com @@ -150,8 +147,7 @@ class TestApprovedPseudoHeader(unittest.TestCase): def setUp(self): self._mlist = create_list('test@example.com') - scheme = lookup(config.passwords.password_scheme.upper()) - self._mlist.moderator_password = make_secret('super secret', scheme) + self._mlist.moderator_password = encrypt('super secret') self._rule = approved.Approved() self._msg = mfs("""\ From: anne@example.com @@ -283,8 +279,7 @@ class TestApprovedPseudoHeaderMIME(unittest.TestCase): def setUp(self): self._mlist = create_list('test@example.com') - scheme = lookup(config.passwords.password_scheme.upper()) - self._mlist.moderator_password = make_secret('super secret', scheme) + self._mlist.moderator_password = encrypt('super secret') self._rule = approved.Approved() self._msg_text_template = """\ From: anne@example.com diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py index 0faa1c8e4..7a019f53a 100644 --- a/src/mailman/testing/layers.py +++ b/src/mailman/testing/layers.py @@ -118,7 +118,7 @@ class ConfigLayer(MockAndMonkeyLayer): [mailman] layout: testing [passwords] - password_scheme: cleartext + password_scheme: passlib.hash.plaintext [paths.testing] var_dir: %s [devmode] diff --git a/src/mailman/utilities/passwords.py b/src/mailman/utilities/passwords.py new file mode 100644 index 000000000..b9981f057 --- /dev/null +++ b/src/mailman/utilities/passwords.py @@ -0,0 +1,57 @@ +# 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 . + +"""A wrapper around passlib.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'encrypt', + 'verify', + ] + + +import re + +from passlib.registry import get_crypt_handler + +from mailman.config import config +from mailman.testing import layers +from mailman.utilities.modules import find_name + +SCHEME_RE = r'{(?P[^}]+?)}(?P.*)'.encode() + + + +def encrypt(secret): + hasher = find_name(config.passwords.password_scheme) + # For reproducibility, don't use any salt in the test suite. + kws = {} + if layers.is_testing and 'salt' in hasher.setting_kwds: + kws['salt'] = b'' + hashed = hasher.encrypt(secret, **kws) + return b'{{{0}}}{1}'.format(hasher.name, hashed) + + +def verify(hashed, password): + mo = re.match(SCHEME_RE, hashed, re.IGNORECASE) + if not mo: + return False + scheme, secret = mo.groups(('scheme', 'rest')) + hasher = get_crypt_handler(scheme) + return hasher.verify(password, secret) -- cgit v1.2.3-70-g09d2