summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Sapiro2016-12-04 15:40:12 -0800
committerMark Sapiro2016-12-04 15:40:12 -0800
commitb7eef6badf3fc6e6bd0534ca58647f0e8219e977 (patch)
tree7e2999232b8e3c6b54fffc5a31a90414c167ffe1 /src
parent0846595ab8f75afda49fcdf35abe87b609af55d5 (diff)
parentb50fc4b57c9a8886407fd9ae0b88bdaa2075d3a2 (diff)
downloadmailman-b7eef6badf3fc6e6bd0534ca58647f0e8219e977.tar.gz
mailman-b7eef6badf3fc6e6bd0534ca58647f0e8219e977.tar.zst
mailman-b7eef6badf3fc6e6bd0534ca58647f0e8219e977.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman/__init__.py14
-rw-r--r--src/mailman/app/bounces.py2
-rw-r--r--src/mailman/app/commands.py2
-rw-r--r--src/mailman/app/digests.py2
-rw-r--r--src/mailman/app/domain.py2
-rw-r--r--src/mailman/app/events.py2
-rw-r--r--src/mailman/app/inject.py2
-rw-r--r--src/mailman/app/lifecycle.py2
-rw-r--r--src/mailman/app/membership.py2
-rw-r--r--src/mailman/app/moderator.py2
-rw-r--r--src/mailman/app/notifications.py2
-rw-r--r--src/mailman/app/replybot.py2
-rw-r--r--src/mailman/app/subscriptions.py2
-rw-r--r--src/mailman/app/workflow.py2
-rw-r--r--src/mailman/archiving/mailarchive.py2
-rw-r--r--src/mailman/archiving/mhonarc.py2
-rw-r--r--src/mailman/archiving/prototype.py2
-rw-r--r--src/mailman/bin/mailman.py2
-rw-r--r--src/mailman/bin/master.py2
-rw-r--r--src/mailman/bin/runner.py2
-rw-r--r--src/mailman/chains/accept.py2
-rw-r--r--src/mailman/chains/base.py2
-rw-r--r--src/mailman/chains/builtin.py2
-rw-r--r--src/mailman/chains/discard.py2
-rw-r--r--src/mailman/chains/headers.py2
-rw-r--r--src/mailman/chains/hold.py2
-rw-r--r--src/mailman/chains/moderation.py2
-rw-r--r--src/mailman/chains/owner.py2
-rw-r--r--src/mailman/chains/reject.py2
-rw-r--r--src/mailman/commands/cli_aliases.py2
-rw-r--r--src/mailman/commands/cli_conf.py2
-rw-r--r--src/mailman/commands/cli_control.py2
-rw-r--r--src/mailman/commands/cli_digests.py2
-rw-r--r--src/mailman/commands/cli_help.py2
-rw-r--r--src/mailman/commands/cli_import.py2
-rw-r--r--src/mailman/commands/cli_info.py2
-rw-r--r--src/mailman/commands/cli_inject.py2
-rw-r--r--src/mailman/commands/cli_lists.py2
-rw-r--r--src/mailman/commands/cli_members.py2
-rw-r--r--src/mailman/commands/cli_qfile.py2
-rw-r--r--src/mailman/commands/cli_status.py2
-rw-r--r--src/mailman/commands/cli_unshunt.py2
-rw-r--r--src/mailman/commands/cli_version.py2
-rw-r--r--src/mailman/commands/cli_withlist.py2
-rw-r--r--src/mailman/commands/eml_confirm.py2
-rw-r--r--src/mailman/commands/eml_echo.py2
-rw-r--r--src/mailman/commands/eml_end.py2
-rw-r--r--src/mailman/commands/eml_help.py2
-rw-r--r--src/mailman/commands/eml_membership.py2
-rw-r--r--src/mailman/commands/tests/test_control.py58
-rw-r--r--src/mailman/config/__init__.py2
-rw-r--r--src/mailman/config/config.py3
-rw-r--r--src/mailman/config/passlib.cfg1
-rw-r--r--src/mailman/config/tests/test_archivers.py6
-rw-r--r--src/mailman/core/api.py2
-rw-r--r--src/mailman/core/chains.py2
-rw-r--r--src/mailman/core/constants.py2
-rw-r--r--src/mailman/core/i18n.py2
-rw-r--r--src/mailman/core/initialize.py2
-rw-r--r--src/mailman/core/logging.py2
-rw-r--r--src/mailman/core/pipelines.py2
-rw-r--r--src/mailman/core/rules.py2
-rw-r--r--src/mailman/core/runner.py2
-rw-r--r--src/mailman/core/switchboard.py2
-rw-r--r--src/mailman/core/system.py3
-rw-r--r--src/mailman/database/alembic/__init__.py2
-rw-r--r--src/mailman/database/alembic/env.py2
-rw-r--r--src/mailman/database/base.py2
-rw-r--r--src/mailman/database/factory.py2
-rw-r--r--src/mailman/database/helpers.py2
-rw-r--r--src/mailman/database/model.py2
-rw-r--r--src/mailman/database/mysql.py2
-rw-r--r--src/mailman/database/postgresql.py2
-rw-r--r--src/mailman/database/sqlite.py2
-rw-r--r--src/mailman/database/transaction.py2
-rw-r--r--src/mailman/database/types.py2
-rw-r--r--src/mailman/docs/NEWS.rst3
-rw-r--r--src/mailman/docs/__init__.py2
-rw-r--r--src/mailman/email/message.py9
-rw-r--r--src/mailman/email/tests/test_message.py9
-rw-r--r--src/mailman/email/validate.py2
-rw-r--r--src/mailman/handlers/acknowledge.py2
-rw-r--r--src/mailman/handlers/after_delivery.py2
-rw-r--r--src/mailman/handlers/avoid_duplicates.py2
-rw-r--r--src/mailman/handlers/cleanse.py2
-rw-r--r--src/mailman/handlers/cleanse_dkim.py2
-rw-r--r--src/mailman/handlers/cook_headers.py2
-rw-r--r--src/mailman/handlers/decorate.py2
-rw-r--r--src/mailman/handlers/file_recipients.py2
-rw-r--r--src/mailman/handlers/member_recipients.py2
-rw-r--r--src/mailman/handlers/mime_delete.py2
-rw-r--r--src/mailman/handlers/owner_recipients.py2
-rw-r--r--src/mailman/handlers/replybot.py2
-rw-r--r--src/mailman/handlers/rfc_2369.py2
-rw-r--r--src/mailman/handlers/subject_prefix.py4
-rw-r--r--src/mailman/handlers/tagger.py2
-rw-r--r--src/mailman/handlers/to_archive.py2
-rw-r--r--src/mailman/handlers/to_digest.py2
-rw-r--r--src/mailman/handlers/to_outgoing.py2
-rw-r--r--src/mailman/handlers/to_usenet.py2
-rw-r--r--src/mailman/interfaces/action.py2
-rw-r--r--src/mailman/interfaces/address.py2
-rw-r--r--src/mailman/interfaces/api.py2
-rw-r--r--src/mailman/interfaces/archiver.py2
-rw-r--r--src/mailman/interfaces/autorespond.py2
-rw-r--r--src/mailman/interfaces/bans.py2
-rw-r--r--src/mailman/interfaces/bounce.py2
-rw-r--r--src/mailman/interfaces/cache.py2
-rw-r--r--src/mailman/interfaces/chain.py2
-rw-r--r--src/mailman/interfaces/command.py2
-rw-r--r--src/mailman/interfaces/configuration.py2
-rw-r--r--src/mailman/interfaces/database.py2
-rw-r--r--src/mailman/interfaces/digests.py2
-rw-r--r--src/mailman/interfaces/domain.py2
-rw-r--r--src/mailman/interfaces/errors.py2
-rw-r--r--src/mailman/interfaces/handler.py2
-rw-r--r--src/mailman/interfaces/languages.py2
-rw-r--r--src/mailman/interfaces/listmanager.py2
-rw-r--r--src/mailman/interfaces/mailinglist.py2
-rw-r--r--src/mailman/interfaces/member.py2
-rw-r--r--src/mailman/interfaces/messages.py2
-rw-r--r--src/mailman/interfaces/mime.py2
-rw-r--r--src/mailman/interfaces/mlistrequest.py2
-rw-r--r--src/mailman/interfaces/mta.py2
-rw-r--r--src/mailman/interfaces/nntp.py2
-rw-r--r--src/mailman/interfaces/pending.py2
-rw-r--r--src/mailman/interfaces/pipeline.py2
-rw-r--r--src/mailman/interfaces/preferences.py2
-rw-r--r--src/mailman/interfaces/requests.py2
-rw-r--r--src/mailman/interfaces/roster.py2
-rw-r--r--src/mailman/interfaces/rules.py2
-rw-r--r--src/mailman/interfaces/runner.py2
-rw-r--r--src/mailman/interfaces/styles.py2
-rw-r--r--src/mailman/interfaces/subscriptions.py2
-rw-r--r--src/mailman/interfaces/switchboard.py2
-rw-r--r--src/mailman/interfaces/system.py2
-rw-r--r--src/mailman/interfaces/template.py2
-rw-r--r--src/mailman/interfaces/user.py2
-rw-r--r--src/mailman/interfaces/usermanager.py2
-rw-r--r--src/mailman/interfaces/workflow.py2
-rw-r--r--src/mailman/languages/language.py2
-rw-r--r--src/mailman/languages/manager.py2
-rw-r--r--src/mailman/model/address.py2
-rw-r--r--src/mailman/model/autorespond.py2
-rw-r--r--src/mailman/model/bans.py2
-rw-r--r--src/mailman/model/bounce.py2
-rw-r--r--src/mailman/model/cache.py2
-rw-r--r--src/mailman/model/digests.py2
-rw-r--r--src/mailman/model/domain.py2
-rw-r--r--src/mailman/model/language.py2
-rw-r--r--src/mailman/model/listmanager.py2
-rw-r--r--src/mailman/model/mailinglist.py2
-rw-r--r--src/mailman/model/member.py2
-rw-r--r--src/mailman/model/message.py2
-rw-r--r--src/mailman/model/messagestore.py2
-rw-r--r--src/mailman/model/mime.py2
-rw-r--r--src/mailman/model/pending.py2
-rw-r--r--src/mailman/model/preferences.py2
-rw-r--r--src/mailman/model/requests.py2
-rw-r--r--src/mailman/model/roster.py2
-rw-r--r--src/mailman/model/subscriptions.py2
-rw-r--r--src/mailman/model/template.py2
-rw-r--r--src/mailman/model/tests/test_mailinglist.py14
-rw-r--r--src/mailman/model/uid.py2
-rw-r--r--src/mailman/model/user.py2
-rw-r--r--src/mailman/model/usermanager.py2
-rw-r--r--src/mailman/model/workflow.py2
-rw-r--r--src/mailman/mta/aliases.py2
-rw-r--r--src/mailman/mta/base.py2
-rw-r--r--src/mailman/mta/bulk.py2
-rw-r--r--src/mailman/mta/connection.py2
-rw-r--r--src/mailman/mta/decorating.py2
-rw-r--r--src/mailman/mta/deliver.py2
-rw-r--r--src/mailman/mta/exim4.py2
-rw-r--r--src/mailman/mta/null.py2
-rw-r--r--src/mailman/mta/personalized.py2
-rw-r--r--src/mailman/mta/postfix.py2
-rw-r--r--src/mailman/mta/verp.py2
-rw-r--r--src/mailman/rest/addresses.py2
-rw-r--r--src/mailman/rest/bans.py2
-rw-r--r--src/mailman/rest/docs/__init__.py2
-rw-r--r--src/mailman/rest/docs/lists.rst4
-rw-r--r--src/mailman/rest/domains.py2
-rw-r--r--src/mailman/rest/header_matches.py2
-rw-r--r--src/mailman/rest/helpers.py8
-rw-r--r--src/mailman/rest/listconf.py2
-rw-r--r--src/mailman/rest/lists.py8
-rw-r--r--src/mailman/rest/members.py2
-rw-r--r--src/mailman/rest/post_moderation.py2
-rw-r--r--src/mailman/rest/preferences.py2
-rw-r--r--src/mailman/rest/queues.py2
-rw-r--r--src/mailman/rest/root.py2
-rw-r--r--src/mailman/rest/sub_moderation.py2
-rw-r--r--src/mailman/rest/templates.py2
-rw-r--r--src/mailman/rest/tests/test_helpers.py25
-rw-r--r--src/mailman/rest/tests/test_lists.py8
-rw-r--r--src/mailman/rest/uris.py2
-rw-r--r--src/mailman/rest/users.py2
-rw-r--r--src/mailman/rest/validator.py2
-rw-r--r--src/mailman/rest/wsgiapp.py2
-rw-r--r--src/mailman/rules/administrivia.py2
-rw-r--r--src/mailman/rules/any.py2
-rw-r--r--src/mailman/rules/approved.py2
-rw-r--r--src/mailman/rules/banned_address.py2
-rw-r--r--src/mailman/rules/emergency.py2
-rw-r--r--src/mailman/rules/implicit_dest.py2
-rw-r--r--src/mailman/rules/loop.py2
-rw-r--r--src/mailman/rules/max_recipients.py2
-rw-r--r--src/mailman/rules/max_size.py2
-rw-r--r--src/mailman/rules/moderation.py2
-rw-r--r--src/mailman/rules/news_moderation.py2
-rw-r--r--src/mailman/rules/no_subject.py6
-rw-r--r--src/mailman/rules/suspicious.py6
-rw-r--r--src/mailman/rules/tests/test_no_subject.py48
-rw-r--r--src/mailman/rules/tests/test_suspicious.py44
-rw-r--r--src/mailman/rules/truth.py2
-rw-r--r--src/mailman/runners/archive.py2
-rw-r--r--src/mailman/runners/bounce.py2
-rw-r--r--src/mailman/runners/command.py2
-rw-r--r--src/mailman/runners/digest.py2
-rw-r--r--src/mailman/runners/incoming.py2
-rw-r--r--src/mailman/runners/lmtp.py11
-rw-r--r--src/mailman/runners/nntp.py2
-rw-r--r--src/mailman/runners/outgoing.py2
-rw-r--r--src/mailman/runners/pipeline.py2
-rw-r--r--src/mailman/runners/rest.py2
-rw-r--r--src/mailman/runners/retry.py2
-rw-r--r--src/mailman/runners/virgin.py2
-rw-r--r--src/mailman/styles/base.py2
-rw-r--r--src/mailman/styles/default.py2
-rw-r--r--src/mailman/styles/manager.py2
-rw-r--r--src/mailman/testing/documentation.py2
-rw-r--r--src/mailman/testing/flake8.py141
-rw-r--r--src/mailman/testing/helpers.py10
-rw-r--r--src/mailman/testing/i18n.py2
-rw-r--r--src/mailman/testing/layers.py2
-rw-r--r--src/mailman/testing/mta.py2
-rw-r--r--src/mailman/testing/nose.py118
-rw-r--r--src/mailman/testing/testing.cfg2
-rw-r--r--src/mailman/utilities/datetime.py2
-rw-r--r--src/mailman/utilities/email.py2
-rw-r--r--src/mailman/utilities/filesystem.py2
-rw-r--r--src/mailman/utilities/i18n.py2
-rw-r--r--src/mailman/utilities/importer.py4
-rw-r--r--src/mailman/utilities/interact.py11
-rw-r--r--src/mailman/utilities/mailbox.py3
-rw-r--r--src/mailman/utilities/modules.py2
-rw-r--r--src/mailman/utilities/options.py2
-rw-r--r--src/mailman/utilities/passwords.py2
-rw-r--r--src/mailman/utilities/protocols.py2
-rw-r--r--src/mailman/utilities/queries.py2
-rw-r--r--src/mailman/utilities/string.py2
-rw-r--r--src/mailman/utilities/tests/test_import.py9
-rw-r--r--src/mailman/utilities/tests/test_modules.py4
-rw-r--r--src/mailman/utilities/uid.py2
255 files changed, 487 insertions, 557 deletions
diff --git a/src/mailman/__init__.py b/src/mailman/__init__.py
index c54830915..15ce69608 100644
--- a/src/mailman/__init__.py
+++ b/src/mailman/__init__.py
@@ -29,20 +29,6 @@ except ImportError: # pragma: no cover
__path__ = pkgutil.extend_path(__path__, __name__)
-# I hate myself: http://bugs.python.org/issue26632
-def public(thing=None, **kws):
- mdict = (sys._getframe(1).f_globals
- if thing is None
- else sys.modules[thing.__module__].__dict__)
- dunder_all = mdict.setdefault('__all__', [])
- if thing is not None:
- dunder_all.append(thing.__name__)
- for key, value in kws.items():
- dunder_all.append(key)
- mdict[key] = value
- return thing
-
-
# We have to initialize the i18n subsystem before anything else happens,
# however, we'll initialize it differently for tests. We have to do it this
# early so that module contents is set up before anything that needs it is
diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py
index 98076dc9b..7fcbe4c2a 100644
--- a/src/mailman/app/bounces.py
+++ b/src/mailman/app/bounces.py
@@ -24,7 +24,6 @@ import logging
from email.mime.message import MIMEMessage
from email.mime.text import MIMEText
from email.utils import parseaddr
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification, UserNotification
@@ -35,6 +34,7 @@ from mailman.interfaces.subscriptions import ISubscriptionService
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.email import split_email
from mailman.utilities.string import expand, oneline, wrap
+from public import public
from string import Template
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/app/commands.py b/src/mailman/app/commands.py
index 4c484bc0b..093156d78 100644
--- a/src/mailman/app/commands.py
+++ b/src/mailman/app/commands.py
@@ -17,10 +17,10 @@
"""Initialize the email commands."""
-from mailman import public
from mailman.config import config
from mailman.interfaces.command import IEmailCommand
from mailman.utilities.modules import find_components
+from public import public
from zope.interface.verify import verifyObject
diff --git a/src/mailman/app/digests.py b/src/mailman/app/digests.py
index 0d47df328..409c22125 100644
--- a/src/mailman/app/digests.py
+++ b/src/mailman/app/digests.py
@@ -19,11 +19,11 @@
import os
-from mailman import public
from mailman.config import config
from mailman.email.message import Message
from mailman.interfaces.digests import DigestFrequency
from mailman.utilities.datetime import now as right_now
+from public import public
@public
diff --git a/src/mailman/app/domain.py b/src/mailman/app/domain.py
index 66abf9c3e..33546d34a 100644
--- a/src/mailman/app/domain.py
+++ b/src/mailman/app/domain.py
@@ -17,9 +17,9 @@
"""Application level domain support."""
-from mailman import public
from mailman.interfaces.domain import DomainDeletingEvent
from mailman.interfaces.listmanager import IListManager
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/app/events.py b/src/mailman/app/events.py
index f3323b6ce..c7d4857cb 100644
--- a/src/mailman/app/events.py
+++ b/src/mailman/app/events.py
@@ -17,12 +17,12 @@
"""Global events."""
-from mailman import public
from mailman.app import domain, membership, moderator, subscriptions
from mailman.core import i18n, switchboard
from mailman.languages import manager as language_manager
from mailman.styles import manager as style_manager
from mailman.utilities import passwords
+from public import public
from zope import event
diff --git a/src/mailman/app/inject.py b/src/mailman/app/inject.py
index decc0fd0e..ca03942ea 100644
--- a/src/mailman/app/inject.py
+++ b/src/mailman/app/inject.py
@@ -19,10 +19,10 @@
from email import message_from_string
from email.utils import formatdate, make_msgid
-from mailman import public
from mailman.config import config
from mailman.email.message import Message
from mailman.utilities.email import add_message_hash
+from public import public
@public
diff --git a/src/mailman/app/lifecycle.py b/src/mailman/app/lifecycle.py
index 50145ce8f..ccd3e4b35 100644
--- a/src/mailman/app/lifecycle.py
+++ b/src/mailman/app/lifecycle.py
@@ -21,7 +21,6 @@ import shutil
import logging
from contextlib import suppress
-from mailman import public
from mailman.config import config
from mailman.interfaces.address import IEmailValidator
from mailman.interfaces.domain import (
@@ -31,6 +30,7 @@ from mailman.interfaces.member import MemberRole
from mailman.interfaces.styles import IStyleManager
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.modules import call_name
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/app/membership.py b/src/mailman/app/membership.py
index 534eed15d..5eb15cf30 100644
--- a/src/mailman/app/membership.py
+++ b/src/mailman/app/membership.py
@@ -18,7 +18,6 @@
"""Application support for membership management."""
from email.utils import formataddr
-from mailman import public
from mailman.app.notifications import (
send_admin_subscription_notice, send_goodbye_message,
send_welcome_message)
@@ -33,6 +32,7 @@ from mailman.interfaces.template import ITemplateLoader
from mailman.interfaces.user import IUser
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.string import expand
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index 109138686..deb54e9b5 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -21,7 +21,6 @@ import time
import logging
from email.utils import formatdate, getaddresses, make_msgid
-from mailman import public
from mailman.app.membership import delete_member
from mailman.config import config
from mailman.core.i18n import _
@@ -34,6 +33,7 @@ from mailman.interfaces.requests import IListRequests, RequestType
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.datetime import now
from mailman.utilities.string import expand, wrap
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/app/notifications.py b/src/mailman/app/notifications.py
index 31a15d820..4d5c1be12 100644
--- a/src/mailman/app/notifications.py
+++ b/src/mailman/app/notifications.py
@@ -21,13 +21,13 @@ import logging
from email.utils import formataddr
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification, UserNotification
from mailman.interfaces.member import DeliveryMode
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.string import expand, wrap
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/app/replybot.py b/src/mailman/app/replybot.py
index fc911c5a1..f707fec89 100644
--- a/src/mailman/app/replybot.py
+++ b/src/mailman/app/replybot.py
@@ -17,7 +17,7 @@
"""Application level auto-reply code."""
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index 52c90ded1..7d02a4e6c 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -23,7 +23,6 @@ import logging
from datetime import timedelta
from email.utils import formataddr
from enum import Enum
-from mailman import public
from mailman.app.membership import delete_member
from mailman.app.workflow import Workflow
from mailman.core.i18n import _
@@ -45,6 +44,7 @@ from mailman.interfaces.usermanager import IUserManager
from mailman.interfaces.workflow import IWorkflowStateManager
from mailman.utilities.datetime import now
from mailman.utilities.string import expand, wrap
+from public import public
from zope.component import getUtility
from zope.event import notify
from zope.interface import implementer
diff --git a/src/mailman/app/workflow.py b/src/mailman/app/workflow.py
index cd9124993..e11ae03cf 100644
--- a/src/mailman/app/workflow.py
+++ b/src/mailman/app/workflow.py
@@ -22,8 +22,8 @@ import json
import logging
from collections import deque
-from mailman import public
from mailman.interfaces.workflow import IWorkflowStateManager
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/archiving/mailarchive.py b/src/mailman/archiving/mailarchive.py
index 782cec29a..bd1a34580 100644
--- a/src/mailman/archiving/mailarchive.py
+++ b/src/mailman/archiving/mailarchive.py
@@ -17,10 +17,10 @@
"""The Mail-Archive.com archiver."""
-from mailman import public
from mailman.config import config
from mailman.config.config import external_configuration
from mailman.interfaces.archiver import ArchivePolicy, IArchiver
+from public import public
from urllib.parse import quote, urljoin
from zope.interface import implementer
diff --git a/src/mailman/archiving/mhonarc.py b/src/mailman/archiving/mhonarc.py
index 857a61e06..80cba043b 100644
--- a/src/mailman/archiving/mhonarc.py
+++ b/src/mailman/archiving/mhonarc.py
@@ -19,11 +19,11 @@
import logging
-from mailman import public
from mailman.config import config
from mailman.config.config import external_configuration
from mailman.interfaces.archiver import IArchiver
from mailman.utilities.string import expand
+from public import public
from subprocess import PIPE, Popen
from urllib.parse import urljoin
from zope.interface import implementer
diff --git a/src/mailman/archiving/prototype.py b/src/mailman/archiving/prototype.py
index 9790129da..b37bfa61e 100644
--- a/src/mailman/archiving/prototype.py
+++ b/src/mailman/archiving/prototype.py
@@ -24,9 +24,9 @@ from contextlib import suppress
from datetime import timedelta
from flufl.lock import Lock, TimeOutError
from mailbox import Maildir
-from mailman import public
from mailman.config import config
from mailman.interfaces.archiver import IArchiver
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/bin/mailman.py b/src/mailman/bin/mailman.py
index b4d144b7c..3f8f66d6e 100644
--- a/src/mailman/bin/mailman.py
+++ b/src/mailman/bin/mailman.py
@@ -21,13 +21,13 @@ import os
import argparse
from functools import cmp_to_key
-from mailman import public
from mailman.core.i18n import _
from mailman.core.initialize import initialize
from mailman.database.transaction import transaction
from mailman.interfaces.command import ICLISubCommand
from mailman.utilities.modules import find_components
from mailman.version import MAILMAN_VERSION_FULL
+from public import public
from zope.interface.verify import verifyObject
diff --git a/src/mailman/bin/master.py b/src/mailman/bin/master.py
index 8e0b1265f..3acff1fc8 100644
--- a/src/mailman/bin/master.py
+++ b/src/mailman/bin/master.py
@@ -28,11 +28,11 @@ from datetime import timedelta
from enum import Enum
from flufl.lock import Lock, NotLockedError, TimeOutError
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.logging import reopen
from mailman.utilities.options import Options
+from public import public
DOT = '.'
diff --git a/src/mailman/bin/runner.py b/src/mailman/bin/runner.py
index 591f5ee31..39e1e9105 100644
--- a/src/mailman/bin/runner.py
+++ b/src/mailman/bin/runner.py
@@ -24,12 +24,12 @@ import logging
import argparse
import traceback
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.initialize import initialize
from mailman.utilities.modules import find_name
from mailman.version import MAILMAN_VERSION_FULL
+from public import public
log = None
diff --git a/src/mailman/chains/accept.py b/src/mailman/chains/accept.py
index 8b0a0507e..c245927bf 100644
--- a/src/mailman/chains/accept.py
+++ b/src/mailman/chains/accept.py
@@ -19,11 +19,11 @@
import logging
-from mailman import public
from mailman.chains.base import TerminalChainBase
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.chain import AcceptEvent
+from public import public
from zope.event import notify
diff --git a/src/mailman/chains/base.py b/src/mailman/chains/base.py
index 677ec501c..d54baf8b6 100644
--- a/src/mailman/chains/base.py
+++ b/src/mailman/chains/base.py
@@ -17,11 +17,11 @@
"""Base class for terminal chains."""
-from mailman import public
from mailman.config import config
from mailman.interfaces.chain import (
IChain, IChainIterator, IChainLink, IMutableChain, LinkAction)
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/chains/builtin.py b/src/mailman/chains/builtin.py
index b805fca0f..16de1043a 100644
--- a/src/mailman/chains/builtin.py
+++ b/src/mailman/chains/builtin.py
@@ -19,10 +19,10 @@
import logging
-from mailman import public
from mailman.chains.base import Link
from mailman.core.i18n import _
from mailman.interfaces.chain import IChain, LinkAction
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/chains/discard.py b/src/mailman/chains/discard.py
index f77c7eb0f..e9fc8d05d 100644
--- a/src/mailman/chains/discard.py
+++ b/src/mailman/chains/discard.py
@@ -19,10 +19,10 @@
import logging
-from mailman import public
from mailman.chains.base import TerminalChainBase
from mailman.core.i18n import _
from mailman.interfaces.chain import DiscardEvent
+from public import public
from zope.event import notify
diff --git a/src/mailman/chains/headers.py b/src/mailman/chains/headers.py
index 5698740d3..56ac179e9 100644
--- a/src/mailman/chains/headers.py
+++ b/src/mailman/chains/headers.py
@@ -21,12 +21,12 @@ import re
import logging
from itertools import count
-from mailman import public
from mailman.chains.base import Chain, Link
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.chain import LinkAction
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/chains/hold.py b/src/mailman/chains/hold.py
index a44bd6a0c..86761c3e1 100644
--- a/src/mailman/chains/hold.py
+++ b/src/mailman/chains/hold.py
@@ -22,7 +22,6 @@ import logging
from email.mime.message import MIMEMessage
from email.mime.text import MIMEText
from email.utils import formatdate, make_msgid
-from mailman import public
from mailman.app.moderator import hold_message
from mailman.app.replybot import can_acknowledge
from mailman.chains.base import TerminalChainBase
@@ -36,6 +35,7 @@ from mailman.interfaces.pending import IPendable, IPendings
from mailman.interfaces.template import ITemplateLoader
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.string import expand, oneline, wrap
+from public import public
from zope.component import getUtility
from zope.event import notify
from zope.interface import implementer
diff --git a/src/mailman/chains/moderation.py b/src/mailman/chains/moderation.py
index 9bb4bf0d5..e8f507603 100644
--- a/src/mailman/chains/moderation.py
+++ b/src/mailman/chains/moderation.py
@@ -34,11 +34,11 @@ made as to the disposition of the message. `defer` is the default for
members, while `hold` is the default for nonmembers.
"""
-from mailman import public
from mailman.chains.base import Link
from mailman.core.i18n import _
from mailman.interfaces.action import Action
from mailman.interfaces.chain import IChain, LinkAction
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/chains/owner.py b/src/mailman/chains/owner.py
index f7454435f..4fb8e1723 100644
--- a/src/mailman/chains/owner.py
+++ b/src/mailman/chains/owner.py
@@ -19,11 +19,11 @@
import logging
-from mailman import public
from mailman.chains.base import TerminalChainBase
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.chain import AcceptOwnerEvent
+from public import public
from zope.event import notify
diff --git a/src/mailman/chains/reject.py b/src/mailman/chains/reject.py
index 27fce8d4e..96be8f2de 100644
--- a/src/mailman/chains/reject.py
+++ b/src/mailman/chains/reject.py
@@ -19,12 +19,12 @@
import logging
-from mailman import public
from mailman.app.bounces import bounce_message
from mailman.chains.base import TerminalChainBase
from mailman.core.i18n import _
from mailman.interfaces.chain import RejectEvent
from mailman.interfaces.pipeline import RejectMessage
+from public import public
from zope.event import notify
diff --git a/src/mailman/commands/cli_aliases.py b/src/mailman/commands/cli_aliases.py
index 76713555a..f48814854 100644
--- a/src/mailman/commands/cli_aliases.py
+++ b/src/mailman/commands/cli_aliases.py
@@ -17,11 +17,11 @@
"""Generate Mailman alias files for your MTA."""
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.utilities.modules import call_name
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_conf.py b/src/mailman/commands/cli_conf.py
index 67db4ac53..0a00f5006 100644
--- a/src/mailman/commands/cli_conf.py
+++ b/src/mailman/commands/cli_conf.py
@@ -21,10 +21,10 @@ import sys
from contextlib import closing
from lazr.config._config import Section
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_control.py b/src/mailman/commands/cli_control.py
index 5ba0b5427..846f4a5c6 100644
--- a/src/mailman/commands/cli_control.py
+++ b/src/mailman/commands/cli_control.py
@@ -23,11 +23,11 @@ import errno
import signal
import logging
-from mailman import public
from mailman.bin.master import WatcherState, master_state
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_digests.py b/src/mailman/commands/cli_digests.py
index 3a4d6614f..151a9332c 100644
--- a/src/mailman/commands/cli_digests.py
+++ b/src/mailman/commands/cli_digests.py
@@ -19,12 +19,12 @@
import sys
-from mailman import public
from mailman.app.digests import (
bump_digest_number_and_volume, maybe_send_digest_now)
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.interfaces.listmanager import IListManager
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_help.py b/src/mailman/commands/cli_help.py
index 9222cd00f..5d6372e51 100644
--- a/src/mailman/commands/cli_help.py
+++ b/src/mailman/commands/cli_help.py
@@ -17,8 +17,8 @@
"""The 'help' subcommand."""
-from mailman import public
from mailman.interfaces.command import ICLISubCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_import.py b/src/mailman/commands/cli_import.py
index 126c026d0..d9384b5bc 100644
--- a/src/mailman/commands/cli_import.py
+++ b/src/mailman/commands/cli_import.py
@@ -21,12 +21,12 @@ import sys
import pickle
from contextlib import ExitStack, contextmanager
-from mailman import public
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.utilities.importer import Import21Error, import_config_pck
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_info.py b/src/mailman/commands/cli_info.py
index fd6c83f88..46643ae1d 100644
--- a/src/mailman/commands/cli_info.py
+++ b/src/mailman/commands/cli_info.py
@@ -20,12 +20,12 @@
import sys
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.api import API30, API31
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.version import MAILMAN_VERSION_FULL
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_inject.py b/src/mailman/commands/cli_inject.py
index acbc37d67..0255b71d2 100644
--- a/src/mailman/commands/cli_inject.py
+++ b/src/mailman/commands/cli_inject.py
@@ -19,12 +19,12 @@
import sys
-from mailman import public
from mailman.app.inject import inject_text
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.interfaces.listmanager import IListManager
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_lists.py b/src/mailman/commands/cli_lists.py
index f5e6d724a..3a598ab05 100644
--- a/src/mailman/commands/cli_lists.py
+++ b/src/mailman/commands/cli_lists.py
@@ -17,7 +17,6 @@
"""The 'lists' subcommand."""
-from mailman import public
from mailman.app.lifecycle import create_list, remove_list
from mailman.core.constants import system_preferences
from mailman.core.i18n import _
@@ -32,6 +31,7 @@ from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.listmanager import IListManager, ListAlreadyExistsError
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.string import expand, wrap
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_members.py b/src/mailman/commands/cli_members.py
index 476d1f77d..1eb6550d6 100644
--- a/src/mailman/commands/cli_members.py
+++ b/src/mailman/commands/cli_members.py
@@ -21,7 +21,6 @@ import sys
from contextlib import ExitStack
from email.utils import formataddr, parseaddr
-from mailman import public
from mailman.app.membership import add_member
from mailman.core.i18n import _
from mailman.database.transaction import transactional
@@ -31,6 +30,7 @@ from mailman.interfaces.member import (
AlreadySubscribedError, DeliveryMode, DeliveryStatus, MemberRole)
from mailman.interfaces.subscriptions import RequestRecord
from operator import attrgetter
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_qfile.py b/src/mailman/commands/cli_qfile.py
index f6502f14a..c8d3ec84b 100644
--- a/src/mailman/commands/cli_qfile.py
+++ b/src/mailman/commands/cli_qfile.py
@@ -19,11 +19,11 @@
import pickle
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.utilities.interact import interact
from pprint import PrettyPrinter
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_status.py b/src/mailman/commands/cli_status.py
index 6b4abe45e..b60ba8841 100644
--- a/src/mailman/commands/cli_status.py
+++ b/src/mailman/commands/cli_status.py
@@ -19,10 +19,10 @@
import socket
-from mailman import public
from mailman.bin.master import WatcherState, master_state
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_unshunt.py b/src/mailman/commands/cli_unshunt.py
index 6bb1a9800..49b9c6e26 100644
--- a/src/mailman/commands/cli_unshunt.py
+++ b/src/mailman/commands/cli_unshunt.py
@@ -19,10 +19,10 @@
import sys
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_version.py b/src/mailman/commands/cli_version.py
index 4660087de..bc26d0115 100644
--- a/src/mailman/commands/cli_version.py
+++ b/src/mailman/commands/cli_version.py
@@ -17,9 +17,9 @@
"""The Mailman version."""
-from mailman import public
from mailman.interfaces.command import ICLISubCommand
from mailman.version import MAILMAN_VERSION_FULL
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/cli_withlist.py b/src/mailman/commands/cli_withlist.py
index 23250c1a5..42eb57cfc 100644
--- a/src/mailman/commands/cli_withlist.py
+++ b/src/mailman/commands/cli_withlist.py
@@ -23,13 +23,13 @@ import sys
from contextlib import ExitStack, suppress
from functools import partial
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.interfaces.listmanager import IListManager
from mailman.utilities.interact import DEFAULT_BANNER, interact
from mailman.utilities.modules import call_name
+from public import public
from string import Template
from traceback import print_exc
from zope.component import getUtility
diff --git a/src/mailman/commands/eml_confirm.py b/src/mailman/commands/eml_confirm.py
index 6787b0987..425bb00e8 100644
--- a/src/mailman/commands/eml_confirm.py
+++ b/src/mailman/commands/eml_confirm.py
@@ -17,10 +17,10 @@
"""The 'confirm' email command."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
from mailman.interfaces.subscriptions import ISubscriptionManager, TokenOwner
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/eml_echo.py b/src/mailman/commands/eml_echo.py
index 67f917d3e..db340fda9 100644
--- a/src/mailman/commands/eml_echo.py
+++ b/src/mailman/commands/eml_echo.py
@@ -17,9 +17,9 @@
"""The email command 'echo'."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/eml_end.py b/src/mailman/commands/eml_end.py
index 82b66a1a6..c280cc52f 100644
--- a/src/mailman/commands/eml_end.py
+++ b/src/mailman/commands/eml_end.py
@@ -17,9 +17,9 @@
"""The email commands 'end' and 'stop'."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/eml_help.py b/src/mailman/commands/eml_help.py
index 4ca2d72a4..b4a39009a 100644
--- a/src/mailman/commands/eml_help.py
+++ b/src/mailman/commands/eml_help.py
@@ -17,11 +17,11 @@
"""The email command 'help'."""
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
from mailman.utilities.string import wrap
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/commands/eml_membership.py b/src/mailman/commands/eml_membership.py
index e658e7b58..22f26e24d 100644
--- a/src/mailman/commands/eml_membership.py
+++ b/src/mailman/commands/eml_membership.py
@@ -18,13 +18,13 @@
"""The email commands 'join' and 'subscribe'."""
from email.utils import formataddr, parseaddr
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.subscriptions import (
ISubscriptionManager, ISubscriptionService)
from mailman.interfaces.usermanager import IUserManager
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/commands/tests/test_control.py b/src/mailman/commands/tests/test_control.py
index 7377c4666..4425b3411 100644
--- a/src/mailman/commands/tests/test_control.py
+++ b/src/mailman/commands/tests/test_control.py
@@ -64,6 +64,59 @@ def find_master():
return None
+def kill_with_extreme_prejudice(pid=None):
+ # 2016-12-03 barry: We have intermittent hangs during both local and CI
+ # test suite runs where killing a runner or master process doesn't
+ # terminate the process. In those cases, wait()ing on the child can
+ # suspend the test process indefinitely. Locally, you have to C-c the
+ # test process, but that still doesn't kill it; the process continues to
+ # run in the background. If you then search for the process's pid and
+ # SIGTERM it, it will usually exit, which is why I don't understand why
+ # the above SIGTERM doesn't kill it sometimes. However, when run under
+ # CI, the test suite will just hang until the CI runner times it out. It
+ # would be better to figure out the underlying cause, because we have
+ # definitely seen other situations where a runner process won't exit, but
+ # for testing purposes we're just trying to clean up some resources so
+ # after a brief attempt at SIGTERMing it, let's SIGKILL it and warn.
+ if pid is not None:
+ os.kill(pid, signal.SIGTERM)
+ until = timedelta(seconds=10) + datetime.now()
+ while datetime.now() < until:
+ try:
+ if pid is None:
+ os.wait3(os.WNOHANG)
+ else:
+ os.waitpid(pid, os.WNOHANG)
+ except ChildProcessError:
+ # This basically means we went one too many times around the
+ # loop. The previous iteration successfully reaped the child.
+ # Because the return status of wait3() and waitpid() are different
+ # in those cases, it's easier just to catch the exception for
+ # either call and exit.
+ return
+ time.sleep(0.1)
+ else:
+ if pid is None:
+ # There's really not much more we can do because we have no pid to
+ # SIGKILL. Just report the problem and continue.
+ print('WARNING: NO CHANGE IN CHILD PROCESS STATES',
+ file=sys.stderr)
+ return
+ print('WARNING: SIGTERM DID NOT EXIT PROCESS; SIGKILLing',
+ file=sys.stderr)
+ if pid is not None:
+ os.kill(pid, signal.SIGKILL)
+ until = timedelta(seconds=10) + datetime.now()
+ while datetime.now() < until:
+ status = os.waitpid(pid, os.WNOHANG)
+ if status == (0, 0):
+ # The child was reaped.
+ return
+ time.sleep(0.1)
+ else:
+ print('WARNING: SIGKILL DID NOT EXIT PROCESS!', file=sys.stderr)
+
+
class FakeArgs:
force = None
run_as_user = None
@@ -171,7 +224,7 @@ class TestBinDir(unittest.TestCase):
args_config = Configuration()
args_config.load(self.args.config)
self.assertFalse(os.path.exists(args_config.PID_FILE))
- os.wait()
+ kill_with_extreme_prejudice()
def test_master_is_elsewhere_and_findable(self):
with ExitStack() as resources:
@@ -188,5 +241,4 @@ class TestBinDir(unittest.TestCase):
# killable. We might have to wait until the process has started.
master_pid = find_master()
self.assertIsNotNone(master_pid, 'master did not start')
- os.kill(master_pid, signal.SIGTERM)
- os.waitpid(master_pid, 0)
+ kill_with_extreme_prejudice(master_pid)
diff --git a/src/mailman/config/__init__.py b/src/mailman/config/__init__.py
index 5c45d6599..66b298217 100644
--- a/src/mailman/config/__init__.py
+++ b/src/mailman/config/__init__.py
@@ -17,8 +17,8 @@
"""Mailman configuration package."""
-from mailman import public
from mailman.config.config import Configuration
+from public import public
public(config=Configuration())
diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py
index 5454c5e5a..a274aa3b9 100644
--- a/src/mailman/config/config.py
+++ b/src/mailman/config/config.py
@@ -24,13 +24,14 @@ import mailman.templates
from configparser import ConfigParser
from flufl.lock import Lock
from lazr.config import ConfigSchema, as_boolean
-from mailman import public, version
+from mailman import version
from mailman.interfaces.configuration import (
ConfigurationUpdatedEvent, IConfiguration, MissingConfigurationFileError)
from mailman.interfaces.languages import ILanguageManager
from mailman.utilities.filesystem import makedirs
from mailman.utilities.modules import call_name, expand_path
from pkg_resources import resource_filename, resource_string as resource_bytes
+from public import public
from string import Template
from zope.component import getUtility
from zope.event import notify
diff --git a/src/mailman/config/passlib.cfg b/src/mailman/config/passlib.cfg
index 805f0fb11..0564f9eb3 100644
--- a/src/mailman/config/passlib.cfg
+++ b/src/mailman/config/passlib.cfg
@@ -3,7 +3,6 @@
# See http://packages.python.org/passlib/index.html for details.
schemes = sha512_crypt, sha256_crypt
default = sha512_crypt
-all__vary_rounds = 0.1
sha256_crypt__min_rounds = 80000
sha512_crypt__min_rounds = 60000
admin__sha256_crypt__min_rounds = 160000
diff --git a/src/mailman/config/tests/test_archivers.py b/src/mailman/config/tests/test_archivers.py
index 322a5040d..b09b89273 100644
--- a/src/mailman/config/tests/test_archivers.py
+++ b/src/mailman/config/tests/test_archivers.py
@@ -28,11 +28,11 @@ class TestArchivers(unittest.TestCase):
layer = ConfigLayer
def test_enabled(self):
- # By default, the testing configuration enables the archivers.
+ # By default, the testing configuration enables some archivers.
archivers = {}
for archiver in config.archivers:
archivers[archiver.name] = archiver
- self.assertTrue(archivers['prototype'].is_enabled)
+ self.assertFalse(archivers['prototype'].is_enabled)
self.assertTrue(archivers['mail-archive'].is_enabled)
self.assertTrue(archivers['mhonarc'].is_enabled)
@@ -42,6 +42,6 @@ class TestArchivers(unittest.TestCase):
archivers = {}
for archiver in config.archivers:
archivers[archiver.name] = archiver
- self.assertTrue(archivers['prototype'].is_enabled)
+ self.assertFalse(archivers['prototype'].is_enabled)
self.assertTrue(archivers['mail-archive'].is_enabled)
self.assertFalse(archivers['mhonarc'].is_enabled)
diff --git a/src/mailman/core/api.py b/src/mailman/core/api.py
index e6e013af0..c9e377bbf 100644
--- a/src/mailman/core/api.py
+++ b/src/mailman/core/api.py
@@ -18,9 +18,9 @@
"""REST web service API contexts."""
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.interfaces.api import IAPI
+from public import public
from uuid import UUID
from zope.interface import implementer
diff --git a/src/mailman/core/chains.py b/src/mailman/core/chains.py
index ec84db2c4..0af61fd2a 100644
--- a/src/mailman/core/chains.py
+++ b/src/mailman/core/chains.py
@@ -17,11 +17,11 @@
"""Application support for chain processing."""
-from mailman import public
from mailman.chains.base import Chain, TerminalChainBase
from mailman.config import config
from mailman.interfaces.chain import IChain, LinkAction
from mailman.utilities.modules import find_components
+from public import public
from zope.interface.verify import verifyObject
diff --git a/src/mailman/core/constants.py b/src/mailman/core/constants.py
index f82783e9f..e5d265256 100644
--- a/src/mailman/core/constants.py
+++ b/src/mailman/core/constants.py
@@ -17,11 +17,11 @@
"""Various constants and enumerations."""
-from mailman import public
from mailman.config import config
from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.member import DeliveryMode, DeliveryStatus
from mailman.interfaces.preferences import IPreferences
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/core/i18n.py b/src/mailman/core/i18n.py
index 5536fcdaf..345020a13 100644
--- a/src/mailman/core/i18n.py
+++ b/src/mailman/core/i18n.py
@@ -20,8 +20,8 @@
import mailman.messages
from flufl.i18n import PackageStrategy, registry
-from mailman import public
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
+from public import public
public(_=None)
diff --git a/src/mailman/core/initialize.py b/src/mailman/core/initialize.py
index 7b39465c5..6bd1d6777 100644
--- a/src/mailman/core/initialize.py
+++ b/src/mailman/core/initialize.py
@@ -29,10 +29,10 @@ import sys
import mailman.config.config
import mailman.core.logging
-from mailman import public
from mailman.interfaces.database import IDatabaseFactory
from mailman.utilities.modules import call_name
from pkg_resources import resource_string as resource_bytes
+from public import public
from zope.component import getUtility
from zope.configuration import xmlconfig
diff --git a/src/mailman/core/logging.py b/src/mailman/core/logging.py
index a7e8b2554..53bb2cf1c 100644
--- a/src/mailman/core/logging.py
+++ b/src/mailman/core/logging.py
@@ -23,8 +23,8 @@ import codecs
import logging
from lazr.config import as_boolean, as_log_level
-from mailman import public
from mailman.config import config
+from public import public
_handlers = {}
diff --git a/src/mailman/core/pipelines.py b/src/mailman/core/pipelines.py
index 5df21ed15..fb663cee9 100644
--- a/src/mailman/core/pipelines.py
+++ b/src/mailman/core/pipelines.py
@@ -19,7 +19,6 @@
import logging
-from mailman import public
from mailman.app.bounces import bounce_message
from mailman.config import config
from mailman.core.i18n import _
@@ -27,6 +26,7 @@ from mailman.interfaces.handler import IHandler
from mailman.interfaces.pipeline import (
DiscardMessage, IPipeline, RejectMessage)
from mailman.utilities.modules import find_components
+from public import public
from zope.interface import implementer
from zope.interface.verify import verifyObject
diff --git a/src/mailman/core/rules.py b/src/mailman/core/rules.py
index f6ca87726..680d4f007 100644
--- a/src/mailman/core/rules.py
+++ b/src/mailman/core/rules.py
@@ -17,10 +17,10 @@
"""Various rule helpers"""
-from mailman import public
from mailman.config import config
from mailman.interfaces.rules import IRule
from mailman.utilities.modules import find_components
+from public import public
from zope.interface.verify import verifyObject
diff --git a/src/mailman/core/runner.py b/src/mailman/core/runner.py
index d0ff6f5ce..ed1c26d38 100644
--- a/src/mailman/core/runner.py
+++ b/src/mailman/core/runner.py
@@ -25,7 +25,6 @@ import traceback
from contextlib import suppress
from io import StringIO
from lazr.config import as_boolean, as_timedelta
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.logging import reopen
@@ -34,6 +33,7 @@ from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.runner import IRunner, RunnerCrashEvent
from mailman.utilities.string import expand
+from public import public
from zope.component import getUtility
from zope.event import notify
from zope.interface import implementer
diff --git a/src/mailman/core/switchboard.py b/src/mailman/core/switchboard.py
index cfbb371ba..f03ee11e5 100644
--- a/src/mailman/core/switchboard.py
+++ b/src/mailman/core/switchboard.py
@@ -31,13 +31,13 @@ import pickle
import hashlib
import logging
-from mailman import public
from mailman.config import config
from mailman.email.message import Message
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
from mailman.interfaces.switchboard import ISwitchboard
from mailman.utilities.filesystem import makedirs
from mailman.utilities.string import expand
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/core/system.py b/src/mailman/core/system.py
index ee88c5adf..41ddced95 100644
--- a/src/mailman/core/system.py
+++ b/src/mailman/core/system.py
@@ -19,8 +19,9 @@
import sys
-from mailman import public, version
+from mailman import version
from mailman.interfaces.system import ISystem
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/database/alembic/__init__.py b/src/mailman/database/alembic/__init__.py
index af2596f04..ff74113d7 100644
--- a/src/mailman/database/alembic/__init__.py
+++ b/src/mailman/database/alembic/__init__.py
@@ -18,8 +18,8 @@
"""Alembic configuration initization."""
from alembic.config import Config
-from mailman import public
from mailman.utilities.modules import expand_path
+from public import public
public(alembic_cfg=Config(expand_path('python:mailman.config.alembic')))
diff --git a/src/mailman/database/alembic/env.py b/src/mailman/database/alembic/env.py
index c7a5e151d..e359b201d 100644
--- a/src/mailman/database/alembic/env.py
+++ b/src/mailman/database/alembic/env.py
@@ -19,11 +19,11 @@
from alembic import context
from contextlib import closing
-from mailman import public
from mailman.config import config
from mailman.core.initialize import initialize_1
from mailman.database.model import Model
from mailman.utilities.string import expand
+from public import public
from sqlalchemy import create_engine
diff --git a/src/mailman/database/base.py b/src/mailman/database/base.py
index f57228029..586e1b20d 100644
--- a/src/mailman/database/base.py
+++ b/src/mailman/database/base.py
@@ -19,10 +19,10 @@
import logging
-from mailman import public
from mailman.config import config
from mailman.interfaces.database import IDatabase
from mailman.utilities.string import expand
+from public import public
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from zope.interface import implementer
diff --git a/src/mailman/database/factory.py b/src/mailman/database/factory.py
index ff7fa59a9..4d003c39c 100644
--- a/src/mailman/database/factory.py
+++ b/src/mailman/database/factory.py
@@ -24,13 +24,13 @@ import alembic.command
from alembic.migration import MigrationContext
from alembic.script import ScriptDirectory
from flufl.lock import Lock
-from mailman import public
from mailman.config import config
from mailman.database.alembic import alembic_cfg
from mailman.database.model import Model
from mailman.interfaces.database import (
DatabaseError, IDatabase, IDatabaseFactory)
from mailman.utilities.modules import call_name
+from public import public
from sqlalchemy import MetaData
from zope.interface import implementer
from zope.interface.verify import verifyObject
diff --git a/src/mailman/database/helpers.py b/src/mailman/database/helpers.py
index b1dc381df..27c870058 100644
--- a/src/mailman/database/helpers.py
+++ b/src/mailman/database/helpers.py
@@ -19,7 +19,7 @@
import sqlalchemy as sa
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/database/model.py b/src/mailman/database/model.py
index c2ee90491..098f62d4b 100644
--- a/src/mailman/database/model.py
+++ b/src/mailman/database/model.py
@@ -18,8 +18,8 @@
"""Base class for all database classes."""
from contextlib import closing
-from mailman import public
from mailman.config import config
+from public import public
from sqlalchemy.ext.declarative import declarative_base
diff --git a/src/mailman/database/mysql.py b/src/mailman/database/mysql.py
index 0c0de54a9..cff16e208 100644
--- a/src/mailman/database/mysql.py
+++ b/src/mailman/database/mysql.py
@@ -17,9 +17,9 @@
"""MySQL database support"""
-from mailman import public
from mailman.database.base import SABaseDatabase
from mailman.database.model import Model
+from public import public
@public
diff --git a/src/mailman/database/postgresql.py b/src/mailman/database/postgresql.py
index b1095e45f..d0c208a50 100644
--- a/src/mailman/database/postgresql.py
+++ b/src/mailman/database/postgresql.py
@@ -17,9 +17,9 @@
"""PostgreSQL database support."""
-from mailman import public
from mailman.database.base import SABaseDatabase
from mailman.database.model import Model
+from public import public
from sqlalchemy import Integer
diff --git a/src/mailman/database/sqlite.py b/src/mailman/database/sqlite.py
index 08700bfb2..3659efaff 100644
--- a/src/mailman/database/sqlite.py
+++ b/src/mailman/database/sqlite.py
@@ -19,8 +19,8 @@
import os
-from mailman import public
from mailman.database.base import SABaseDatabase
+from public import public
from urllib.parse import urlparse
diff --git a/src/mailman/database/transaction.py b/src/mailman/database/transaction.py
index 09dfda8e3..1b5368a39 100644
--- a/src/mailman/database/transaction.py
+++ b/src/mailman/database/transaction.py
@@ -18,8 +18,8 @@
"""Transactional support."""
from contextlib import contextmanager
-from mailman import public
from mailman.config import config
+from public import public
@public
diff --git a/src/mailman/database/types.py b/src/mailman/database/types.py
index bbd040d96..10b826e7c 100644
--- a/src/mailman/database/types.py
+++ b/src/mailman/database/types.py
@@ -19,7 +19,7 @@
import uuid
-from mailman import public
+from public import public
from sqlalchemy import Integer
from sqlalchemy.dialects import postgresql
from sqlalchemy.ext.compiler import compiles
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 27f3ea5eb..1841f8fb7 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -151,6 +151,7 @@ Interfaces
Internal
--------
+ * Add official support for Python 3.6. (Closes #295)
* A handful of unused legacy exceptions have been removed. The redundant
`MailmanException` has been removed; use `MailmanError` everywhere.
* Drop the use of the `lazr.smtptest` library, which is based on the
@@ -245,6 +246,8 @@ REST
Aurélien Bompard. (Closes #284)
* Query parameters now allow you to filter mailing lists by the
``advertised`` boolean parameter. Given by Aurélien Bompard.
+ * Only the system-enabled archivers are returned in the REST API. Given by
+ Aurélien Bompard.
Other
-----
diff --git a/src/mailman/docs/__init__.py b/src/mailman/docs/__init__.py
index 68c7bb4cf..939c1e6e6 100644
--- a/src/mailman/docs/__init__.py
+++ b/src/mailman/docs/__init__.py
@@ -17,8 +17,8 @@
"""General Mailman doc tests."""
-from mailman import public
from mailman.testing.layers import ConfigLayer
+from public import public
public(layer=ConfigLayer)
diff --git a/src/mailman/email/message.py b/src/mailman/email/message.py
index ebfef9d9b..da2ce837f 100644
--- a/src/mailman/email/message.py
+++ b/src/mailman/email/message.py
@@ -29,9 +29,9 @@ import email.utils
from email.header import Header
from email.mime.multipart import MIMEMultipart
-from mailman import public
from mailman.config import config
from mailman.interfaces.member import DeliveryStatus
+from public import public
COMMASPACE = ', '
@@ -93,9 +93,10 @@ class Message(email.message.Message):
if envelope_sender is not None
else '')
else:
- field_values = self.get_all(header, [])
- senders.extend(address.lower() for (display_name, address)
- in email.utils.getaddresses(field_values))
+ for field_value in self.get_all(header, []):
+ # Convert the header to str in case it's a Header instance.
+ name, address = email.utils.parseaddr(str(field_value))
+ senders.append(address.lower())
# Filter out None and the empty string, and convert to unicode.
clean_senders = []
for sender in senders:
diff --git a/src/mailman/email/tests/test_message.py b/src/mailman/email/tests/test_message.py
index 3ec099904..461659865 100644
--- a/src/mailman/email/tests/test_message.py
+++ b/src/mailman/email/tests/test_message.py
@@ -19,6 +19,7 @@
import unittest
+from email.header import Header
from email.parser import FeedParser
from mailman.app.lifecycle import create_list
from mailman.email.message import Message, UserNotification
@@ -52,6 +53,8 @@ class TestMessage(unittest.TestCase):
class TestMessageSubclass(unittest.TestCase):
+ layer = ConfigLayer
+
def test_i18n_filenames(self):
parser = FeedParser(_factory=Message)
parser.feed("""\
@@ -79,3 +82,9 @@ Test content
except TypeError as error:
self.fail(error)
self.assertEqual(filename, u'd\xe9jeuner.txt')
+
+ def test_senders_header_instances(self):
+ msg = Message()
+ msg['From'] = Header('test@example.com')
+ # Make sure the senders property does not fail
+ self.assertEqual(msg.senders, ['test@example.com'])
diff --git a/src/mailman/email/validate.py b/src/mailman/email/validate.py
index 99371d9e5..be8ba775a 100644
--- a/src/mailman/email/validate.py
+++ b/src/mailman/email/validate.py
@@ -19,10 +19,10 @@
import re
-from mailman import public
from mailman.interfaces.address import (
IEmailValidator, InvalidEmailAddressError)
from mailman.utilities.email import split_email
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/acknowledge.py b/src/mailman/handlers/acknowledge.py
index c7035de67..56608a3e9 100644
--- a/src/mailman/handlers/acknowledge.py
+++ b/src/mailman/handlers/acknowledge.py
@@ -20,13 +20,13 @@
This only happens if the sender has set their AcknowledgePosts attribute.
"""
-from mailman import public
from mailman.core.i18n import _
from mailman.email.message import UserNotification
from mailman.interfaces.handler import IHandler
from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.string import expand, oneline
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/handlers/after_delivery.py b/src/mailman/handlers/after_delivery.py
index efe38ec63..928f90f76 100644
--- a/src/mailman/handlers/after_delivery.py
+++ b/src/mailman/handlers/after_delivery.py
@@ -17,10 +17,10 @@
"""Perform some bookkeeping after a successful post."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.utilities.datetime import now
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/avoid_duplicates.py b/src/mailman/handlers/avoid_duplicates.py
index 59cb568de..7fe2136da 100644
--- a/src/mailman/handlers/avoid_duplicates.py
+++ b/src/mailman/handlers/avoid_duplicates.py
@@ -24,9 +24,9 @@ warning header, or pass it through, depending on the user's preferences.
"""
from email.utils import getaddresses, formataddr
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/cleanse.py b/src/mailman/handlers/cleanse.py
index 56add9ef7..8704491f6 100644
--- a/src/mailman/handlers/cleanse.py
+++ b/src/mailman/handlers/cleanse.py
@@ -20,10 +20,10 @@
import logging
from email.utils import formataddr
-from mailman import public
from mailman.core.i18n import _
from mailman.handlers.cook_headers import uheader
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/cleanse_dkim.py b/src/mailman/handlers/cleanse_dkim.py
index 72a9c5e81..cc04858be 100644
--- a/src/mailman/handlers/cleanse_dkim.py
+++ b/src/mailman/handlers/cleanse_dkim.py
@@ -26,10 +26,10 @@ originating at the Mailman server for the outgoing message.
"""
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/cook_headers.py b/src/mailman/handlers/cook_headers.py
index 5f203fcbd..672738bf9 100644
--- a/src/mailman/handlers/cook_headers.py
+++ b/src/mailman/handlers/cook_headers.py
@@ -22,11 +22,11 @@ import logging
from email.header import Header
from email.utils import formataddr, getaddresses, parseaddr
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.interfaces.mailinglist import Personalization, ReplyToMunging
from mailman.version import VERSION
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/decorate.py b/src/mailman/handlers/decorate.py
index 7f5519fd0..6a16dfc76 100644
--- a/src/mailman/handlers/decorate.py
+++ b/src/mailman/handlers/decorate.py
@@ -22,13 +22,13 @@ import logging
from email.mime.text import MIMEText
from email.utils import formataddr
-from mailman import public
from mailman.core.i18n import _
from mailman.email.message import Message
from mailman.interfaces.handler import IHandler
from mailman.interfaces.mailinglist import IListArchiverSet
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.string import expand
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/handlers/file_recipients.py b/src/mailman/handlers/file_recipients.py
index 95160706a..e283d936e 100644
--- a/src/mailman/handlers/file_recipients.py
+++ b/src/mailman/handlers/file_recipients.py
@@ -20,9 +20,9 @@
import os
import errno
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/member_recipients.py b/src/mailman/handlers/member_recipients.py
index ffcecfb18..309603ef0 100644
--- a/src/mailman/handlers/member_recipients.py
+++ b/src/mailman/handlers/member_recipients.py
@@ -23,13 +23,13 @@ on the `recipients' attribute of the message. This attribute is used by the
SendmailDeliver and BulkDeliver modules.
"""
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.interfaces.member import DeliveryStatus
from mailman.interfaces.pipeline import RejectMessage
from mailman.utilities.string import wrap
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/mime_delete.py b/src/mailman/handlers/mime_delete.py
index b88c40b0c..ac56e5dd6 100644
--- a/src/mailman/handlers/mime_delete.py
+++ b/src/mailman/handlers/mime_delete.py
@@ -36,7 +36,6 @@ from email.mime.message import MIMEMessage
from email.mime.text import MIMEText
from itertools import count
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification
@@ -45,6 +44,7 @@ from mailman.interfaces.handler import IHandler
from mailman.interfaces.pipeline import DiscardMessage, RejectMessage
from mailman.utilities.string import oneline
from mailman.version import VERSION
+from public import public
from string import Template
from zope.interface import implementer
diff --git a/src/mailman/handlers/owner_recipients.py b/src/mailman/handlers/owner_recipients.py
index 9ef2568f5..4a4ee9a24 100644
--- a/src/mailman/handlers/owner_recipients.py
+++ b/src/mailman/handlers/owner_recipients.py
@@ -17,11 +17,11 @@
"""Calculate the list owner recipients (includes moderators)."""
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.interfaces.member import DeliveryStatus
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/replybot.py b/src/mailman/handlers/replybot.py
index a86ccbbf3..e8b9e4fc6 100644
--- a/src/mailman/handlers/replybot.py
+++ b/src/mailman/handlers/replybot.py
@@ -19,7 +19,6 @@
import logging
-from mailman import public
from mailman.core.i18n import _
from mailman.email.message import UserNotification
from mailman.interfaces.autorespond import (
@@ -28,6 +27,7 @@ from mailman.interfaces.handler import IHandler
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.datetime import today
from mailman.utilities.string import expand, wrap
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/handlers/rfc_2369.py b/src/mailman/handlers/rfc_2369.py
index e042bc5e3..7f36dd057 100644
--- a/src/mailman/handlers/rfc_2369.py
+++ b/src/mailman/handlers/rfc_2369.py
@@ -20,12 +20,12 @@
import logging
from email.utils import formataddr
-from mailman import public
from mailman.core.i18n import _
from mailman.handlers.cook_headers import uheader
from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.handler import IHandler
from mailman.interfaces.mailinglist import IListArchiverSet
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/subject_prefix.py b/src/mailman/handlers/subject_prefix.py
index ff728d92e..7bb1a3e5d 100644
--- a/src/mailman/handlers/subject_prefix.py
+++ b/src/mailman/handlers/subject_prefix.py
@@ -21,9 +21,9 @@ import re
from contextlib import suppress
from email.header import Header, decode_header, make_header
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
@@ -162,7 +162,7 @@ class SubjectPrefix:
if p.search(prefix, 1):
# The prefix has number, so we should search prefix w/number in
# subject. Also, force new style.
- prefix_pattern = p.sub(r'\s*\d+\s*', prefix_pattern)
+ prefix_pattern = p.sub(r'\\s*\\d+\\s*', prefix_pattern)
# Substitute %d in prefix with post_id
with suppress(TypeError):
prefix = prefix % mlist.post_id
diff --git a/src/mailman/handlers/tagger.py b/src/mailman/handlers/tagger.py
index fb0a24ba5..f7c637085 100644
--- a/src/mailman/handlers/tagger.py
+++ b/src/mailman/handlers/tagger.py
@@ -21,9 +21,9 @@ import re
import email.iterators
import email.parser
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/to_archive.py b/src/mailman/handlers/to_archive.py
index d5b980ab4..d2805ea3e 100644
--- a/src/mailman/handlers/to_archive.py
+++ b/src/mailman/handlers/to_archive.py
@@ -17,11 +17,11 @@
"""Add the message to the archives."""
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/to_digest.py b/src/mailman/handlers/to_digest.py
index 671a2197c..2de911f46 100644
--- a/src/mailman/handlers/to_digest.py
+++ b/src/mailman/handlers/to_digest.py
@@ -19,11 +19,11 @@
import os
-from mailman import public
from mailman.app.digests import maybe_send_digest_now
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.utilities.mailbox import Mailbox
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/to_outgoing.py b/src/mailman/handlers/to_outgoing.py
index b9fae912c..4726973f2 100644
--- a/src/mailman/handlers/to_outgoing.py
+++ b/src/mailman/handlers/to_outgoing.py
@@ -22,10 +22,10 @@ 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 mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/handlers/to_usenet.py b/src/mailman/handlers/to_usenet.py
index 4bfa00c5f..f5e01ef6e 100644
--- a/src/mailman/handlers/to_usenet.py
+++ b/src/mailman/handlers/to_usenet.py
@@ -19,10 +19,10 @@
import logging
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/interfaces/action.py b/src/mailman/interfaces/action.py
index dcff41cbd..08dc9c5ca 100644
--- a/src/mailman/interfaces/action.py
+++ b/src/mailman/interfaces/action.py
@@ -18,7 +18,7 @@
"""Message actions."""
from enum import Enum
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/interfaces/address.py b/src/mailman/interfaces/address.py
index 8a1ac81d5..d460e96ca 100644
--- a/src/mailman/interfaces/address.py
+++ b/src/mailman/interfaces/address.py
@@ -17,8 +17,8 @@
"""Interface for email address related information."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/api.py b/src/mailman/interfaces/api.py
index 3ba158b35..e2c6645db 100644
--- a/src/mailman/interfaces/api.py
+++ b/src/mailman/interfaces/api.py
@@ -17,7 +17,7 @@
"""REST web service API context."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/archiver.py b/src/mailman/interfaces/archiver.py
index cd10b22e3..eb9227dd8 100644
--- a/src/mailman/interfaces/archiver.py
+++ b/src/mailman/interfaces/archiver.py
@@ -18,7 +18,7 @@
"""Interface for archiving schemes."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/autorespond.py b/src/mailman/interfaces/autorespond.py
index 645a6c76b..b9f3f0e3a 100644
--- a/src/mailman/interfaces/autorespond.py
+++ b/src/mailman/interfaces/autorespond.py
@@ -19,7 +19,7 @@
from datetime import timedelta
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/bans.py b/src/mailman/interfaces/bans.py
index 055ad69a3..59928ff8e 100644
--- a/src/mailman/interfaces/bans.py
+++ b/src/mailman/interfaces/bans.py
@@ -17,7 +17,7 @@
"""Manager of email address bans."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/bounce.py b/src/mailman/interfaces/bounce.py
index 0e39ca3b9..368657c47 100644
--- a/src/mailman/interfaces/bounce.py
+++ b/src/mailman/interfaces/bounce.py
@@ -18,7 +18,7 @@
"""Interface to bounce detection components."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/cache.py b/src/mailman/interfaces/cache.py
index 74fb2084a..39d3e7c73 100644
--- a/src/mailman/interfaces/cache.py
+++ b/src/mailman/interfaces/cache.py
@@ -17,7 +17,7 @@
"""File caches."""
-from mailman import public
+from public import public
from zope.interface import Interface
diff --git a/src/mailman/interfaces/chain.py b/src/mailman/interfaces/chain.py
index 0af9bf8e5..146abafd7 100644
--- a/src/mailman/interfaces/chain.py
+++ b/src/mailman/interfaces/chain.py
@@ -18,7 +18,7 @@
"""Interfaces describing the basics of chains and links."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/command.py b/src/mailman/interfaces/command.py
index 95719b504..be3fd5bb2 100644
--- a/src/mailman/interfaces/command.py
+++ b/src/mailman/interfaces/command.py
@@ -18,7 +18,7 @@
"""Interfaces defining email commands."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/configuration.py b/src/mailman/interfaces/configuration.py
index 2e38e614c..b4f9d696c 100644
--- a/src/mailman/interfaces/configuration.py
+++ b/src/mailman/interfaces/configuration.py
@@ -17,8 +17,8 @@
"""Configuration system interface."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Interface
diff --git a/src/mailman/interfaces/database.py b/src/mailman/interfaces/database.py
index 1f658c556..052c7d4bb 100644
--- a/src/mailman/interfaces/database.py
+++ b/src/mailman/interfaces/database.py
@@ -17,8 +17,8 @@
"""Interfaces for database interaction."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/digests.py b/src/mailman/interfaces/digests.py
index cff838284..fd38b374a 100644
--- a/src/mailman/interfaces/digests.py
+++ b/src/mailman/interfaces/digests.py
@@ -18,7 +18,7 @@
"""One last digest."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/domain.py b/src/mailman/interfaces/domain.py
index b1940f400..6318e9551 100644
--- a/src/mailman/interfaces/domain.py
+++ b/src/mailman/interfaces/domain.py
@@ -17,8 +17,8 @@
"""Interface representing domains."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/errors.py b/src/mailman/interfaces/errors.py
index dbf74c035..b21d07418 100644
--- a/src/mailman/interfaces/errors.py
+++ b/src/mailman/interfaces/errors.py
@@ -22,7 +22,7 @@ components. More specific exceptions will be located in the relevant
interfaces.
"""
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/interfaces/handler.py b/src/mailman/interfaces/handler.py
index f6b2aea66..29061c369 100644
--- a/src/mailman/interfaces/handler.py
+++ b/src/mailman/interfaces/handler.py
@@ -17,7 +17,7 @@
"""Interface describing a pipeline handler."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/languages.py b/src/mailman/interfaces/languages.py
index b45083575..18f928be9 100644
--- a/src/mailman/interfaces/languages.py
+++ b/src/mailman/interfaces/languages.py
@@ -17,7 +17,7 @@
"""Interfaces for managing languages."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/listmanager.py b/src/mailman/interfaces/listmanager.py
index 2c7208496..dde23ab1f 100644
--- a/src/mailman/interfaces/listmanager.py
+++ b/src/mailman/interfaces/listmanager.py
@@ -17,8 +17,8 @@
"""Interface for list storage, deleting, and finding."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py
index 877016f41..359cd5069 100644
--- a/src/mailman/interfaces/mailinglist.py
+++ b/src/mailman/interfaces/mailinglist.py
@@ -18,8 +18,8 @@
"""Interface for a mailing list."""
from enum import Enum
-from mailman import public
from mailman.interfaces.member import MemberRole
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/member.py b/src/mailman/interfaces/member.py
index 094652521..a2a9c7cbd 100644
--- a/src/mailman/interfaces/member.py
+++ b/src/mailman/interfaces/member.py
@@ -18,8 +18,8 @@
"""Interface describing the basics of a member."""
from enum import Enum
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/messages.py b/src/mailman/interfaces/messages.py
index 2ea2aa312..29f92fdc7 100644
--- a/src/mailman/interfaces/messages.py
+++ b/src/mailman/interfaces/messages.py
@@ -17,7 +17,7 @@
"""The message storage service."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/mime.py b/src/mailman/interfaces/mime.py
index c1a6e050f..94a98b58e 100644
--- a/src/mailman/interfaces/mime.py
+++ b/src/mailman/interfaces/mime.py
@@ -18,7 +18,7 @@
"""MIME content filtering."""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/mlistrequest.py b/src/mailman/interfaces/mlistrequest.py
index 45712ed86..ca83f77c1 100644
--- a/src/mailman/interfaces/mlistrequest.py
+++ b/src/mailman/interfaces/mlistrequest.py
@@ -17,7 +17,7 @@
"""Interface for a web request accessing a mailing list."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/mta.py b/src/mailman/interfaces/mta.py
index 47436ead5..2917c0f79 100644
--- a/src/mailman/interfaces/mta.py
+++ b/src/mailman/interfaces/mta.py
@@ -17,8 +17,8 @@
"""Interface for mail transport agent integration."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Interface
diff --git a/src/mailman/interfaces/nntp.py b/src/mailman/interfaces/nntp.py
index 72a74fe90..2bb9c45b1 100644
--- a/src/mailman/interfaces/nntp.py
+++ b/src/mailman/interfaces/nntp.py
@@ -18,7 +18,7 @@
"""NNTP and newsgroup interfaces."""
from enum import Enum
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/interfaces/pending.py b/src/mailman/interfaces/pending.py
index cf92fed9e..c630e2133 100644
--- a/src/mailman/interfaces/pending.py
+++ b/src/mailman/interfaces/pending.py
@@ -22,7 +22,7 @@ maps these events to a unique hash that can be used as a token for end user
confirmation.
"""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/pipeline.py b/src/mailman/interfaces/pipeline.py
index cdef6a768..a41e9b6f7 100644
--- a/src/mailman/interfaces/pipeline.py
+++ b/src/mailman/interfaces/pipeline.py
@@ -17,7 +17,7 @@
"""Interface for describing pipelines."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/preferences.py b/src/mailman/interfaces/preferences.py
index 024fdea3c..0d830bdd7 100644
--- a/src/mailman/interfaces/preferences.py
+++ b/src/mailman/interfaces/preferences.py
@@ -17,7 +17,7 @@
"""Interface for preferences."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/requests.py b/src/mailman/interfaces/requests.py
index 3098772a9..8b316e79f 100644
--- a/src/mailman/interfaces/requests.py
+++ b/src/mailman/interfaces/requests.py
@@ -22,7 +22,7 @@ moderators, such as subscription requests and held messages.
"""
from enum import Enum
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/roster.py b/src/mailman/interfaces/roster.py
index 2993e4fc4..bf8489e33 100644
--- a/src/mailman/interfaces/roster.py
+++ b/src/mailman/interfaces/roster.py
@@ -17,7 +17,7 @@
"""Interface for a roster of members."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/rules.py b/src/mailman/interfaces/rules.py
index 9f5f1365e..cca8cf565 100644
--- a/src/mailman/interfaces/rules.py
+++ b/src/mailman/interfaces/rules.py
@@ -17,7 +17,7 @@
"""Interface describing the basics of rules."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/runner.py b/src/mailman/interfaces/runner.py
index e39efb097..06caf0e95 100644
--- a/src/mailman/interfaces/runner.py
+++ b/src/mailman/interfaces/runner.py
@@ -17,7 +17,7 @@
"""Interface for runners."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/styles.py b/src/mailman/interfaces/styles.py
index a183933f7..e4b5288c1 100644
--- a/src/mailman/interfaces/styles.py
+++ b/src/mailman/interfaces/styles.py
@@ -17,8 +17,8 @@
"""Interfaces for list styles."""
-from mailman import public
from mailman.interfaces.errors import MailmanError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/subscriptions.py b/src/mailman/interfaces/subscriptions.py
index 284261de5..dc3563def 100644
--- a/src/mailman/interfaces/subscriptions.py
+++ b/src/mailman/interfaces/subscriptions.py
@@ -19,9 +19,9 @@
from collections import namedtuple
from enum import Enum
-from mailman import public
from mailman.interfaces.errors import MailmanError
from mailman.interfaces.member import DeliveryMode, MembershipError
+from public import public
from zope.interface import Interface
diff --git a/src/mailman/interfaces/switchboard.py b/src/mailman/interfaces/switchboard.py
index 4428f4b12..d9e2f9aab 100644
--- a/src/mailman/interfaces/switchboard.py
+++ b/src/mailman/interfaces/switchboard.py
@@ -17,7 +17,7 @@
"""Interface for switchboards."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/system.py b/src/mailman/interfaces/system.py
index 1b0a9a2de..440611537 100644
--- a/src/mailman/interfaces/system.py
+++ b/src/mailman/interfaces/system.py
@@ -17,7 +17,7 @@
"""System information."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/template.py b/src/mailman/interfaces/template.py
index 24f956b78..6b6bcd7a3 100644
--- a/src/mailman/interfaces/template.py
+++ b/src/mailman/interfaces/template.py
@@ -17,7 +17,7 @@
"""Template downloader with cache."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/user.py b/src/mailman/interfaces/user.py
index a6c470b6e..e103f38fd 100644
--- a/src/mailman/interfaces/user.py
+++ b/src/mailman/interfaces/user.py
@@ -17,8 +17,8 @@
"""Interface describing the basics of a user."""
-from mailman import public
from mailman.interfaces.address import AddressError
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/usermanager.py b/src/mailman/interfaces/usermanager.py
index 87d4bf6e2..4cd8af7aa 100644
--- a/src/mailman/interfaces/usermanager.py
+++ b/src/mailman/interfaces/usermanager.py
@@ -17,7 +17,7 @@
"""Interface describing the user management service."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/interfaces/workflow.py b/src/mailman/interfaces/workflow.py
index 9846f4683..b0b5a23da 100644
--- a/src/mailman/interfaces/workflow.py
+++ b/src/mailman/interfaces/workflow.py
@@ -17,7 +17,7 @@
"""Interfaces describing the state of a workflow."""
-from mailman import public
+from public import public
from zope.interface import Attribute, Interface
diff --git a/src/mailman/languages/language.py b/src/mailman/languages/language.py
index 014852c5c..afe217048 100644
--- a/src/mailman/languages/language.py
+++ b/src/mailman/languages/language.py
@@ -18,8 +18,8 @@
"""The representation of a language."""
-from mailman import public
from mailman.interfaces.languages import ILanguage
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/languages/manager.py b/src/mailman/languages/manager.py
index 9832eb3eb..5e56ec0e0 100644
--- a/src/mailman/languages/manager.py
+++ b/src/mailman/languages/manager.py
@@ -17,10 +17,10 @@
"""Language manager."""
-from mailman import public
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
from mailman.interfaces.languages import ILanguageManager
from mailman.languages.language import Language
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/model/address.py b/src/mailman/model/address.py
index a31e9a429..63896c728 100644
--- a/src/mailman/model/address.py
+++ b/src/mailman/model/address.py
@@ -18,12 +18,12 @@
"""Model for addresses."""
from email.utils import formataddr
-from mailman import public
from mailman.database.model import Model
from mailman.database.types import SAUnicode
from mailman.interfaces.address import (
AddressVerificationEvent, IAddress, IEmailValidator)
from mailman.utilities.datetime import now
+from public import public
from sqlalchemy import Column, DateTime, ForeignKey, Integer
from sqlalchemy.orm import backref, relationship
from zope.component import getUtility
diff --git a/src/mailman/model/autorespond.py b/src/mailman/model/autorespond.py
index 20c19889f..e9509c4f8 100644
--- a/src/mailman/model/autorespond.py
+++ b/src/mailman/model/autorespond.py
@@ -17,13 +17,13 @@
"""Autoresponder records."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import Enum
from mailman.interfaces.autorespond import (
IAutoResponseRecord, IAutoResponseSet, Response)
from mailman.utilities.datetime import today
+from public import public
from sqlalchemy import Column, Date, ForeignKey, Integer, desc
from sqlalchemy.orm import relationship
from zope.interface import implementer
diff --git a/src/mailman/model/bans.py b/src/mailman/model/bans.py
index c8d43c5ae..1c4cbde8c 100644
--- a/src/mailman/model/bans.py
+++ b/src/mailman/model/bans.py
@@ -19,12 +19,12 @@
import re
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode
from mailman.interfaces.bans import IBan, IBanManager
from mailman.utilities.queries import QuerySequence
+from public import public
from sqlalchemy import Column, Integer
from zope.interface import implementer
diff --git a/src/mailman/model/bounce.py b/src/mailman/model/bounce.py
index 856d91f20..6db55a3c7 100644
--- a/src/mailman/model/bounce.py
+++ b/src/mailman/model/bounce.py
@@ -17,13 +17,13 @@
"""Bounce support."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import Enum, SAUnicode
from mailman.interfaces.bounce import (
BounceContext, IBounceEvent, IBounceProcessor)
from mailman.utilities.datetime import now
+from public import public
from sqlalchemy import Boolean, Column, DateTime, Integer
from zope.interface import implementer
diff --git a/src/mailman/model/cache.py b/src/mailman/model/cache.py
index 6be5fbc9d..d1ef9f05c 100644
--- a/src/mailman/model/cache.py
+++ b/src/mailman/model/cache.py
@@ -22,13 +22,13 @@ import hashlib
from contextlib import ExitStack
from lazr.config import as_timedelta
-from mailman import public
from mailman.config import config
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode
from mailman.interfaces.cache import ICacheManager
from mailman.utilities.datetime import now
+from public import public
from sqlalchemy import Boolean, Column, DateTime, Integer
from zope.interface import implementer
diff --git a/src/mailman/model/digests.py b/src/mailman/model/digests.py
index ac49249cc..a0daaebbc 100644
--- a/src/mailman/model/digests.py
+++ b/src/mailman/model/digests.py
@@ -17,11 +17,11 @@
"""One last digest."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.types import Enum
from mailman.interfaces.digests import IOneLastDigest
from mailman.interfaces.member import DeliveryMode
+from public import public
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship
from zope.interface import implementer
diff --git a/src/mailman/model/domain.py b/src/mailman/model/domain.py
index 5bb569585..2622ba80b 100644
--- a/src/mailman/model/domain.py
+++ b/src/mailman/model/domain.py
@@ -17,7 +17,6 @@
"""Domains."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode
@@ -27,6 +26,7 @@ from mailman.interfaces.domain import (
from mailman.interfaces.user import IUser
from mailman.interfaces.usermanager import IUserManager
from mailman.model.mailinglist import MailingList
+from public import public
from sqlalchemy import Column, Integer
from sqlalchemy.orm import relationship
from zope.component import getUtility
diff --git a/src/mailman/model/language.py b/src/mailman/model/language.py
index 596e580e1..c762b9715 100644
--- a/src/mailman/model/language.py
+++ b/src/mailman/model/language.py
@@ -17,10 +17,10 @@
"""Model for languages."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.types import SAUnicode
from mailman.interfaces.languages import ILanguage
+from public import public
from sqlalchemy import Column, Integer
from zope.interface import implementer
diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py
index e2519af5b..bd07e6c27 100644
--- a/src/mailman/model/listmanager.py
+++ b/src/mailman/model/listmanager.py
@@ -17,7 +17,6 @@
"""A mailing list manager."""
-from mailman import public
from mailman.database.transaction import dbconnection
from mailman.interfaces.address import InvalidEmailAddressError
from mailman.interfaces.listmanager import (
@@ -30,6 +29,7 @@ from mailman.model.mailinglist import (
from mailman.model.mime import ContentFilter
from mailman.utilities.datetime import now
from mailman.utilities.queries import QuerySequence
+from public import public
from zope.event import notify
from zope.interface import implementer
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index eec58ad04..bd6538aaf 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -19,7 +19,6 @@
import os
-from mailman import public
from mailman.config import config
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
@@ -49,6 +48,7 @@ from mailman.model.mime import ContentFilter
from mailman.model.preferences import Preferences
from mailman.utilities.filesystem import makedirs
from mailman.utilities.string import expand
+from public import public
from sqlalchemy import (
Boolean, Column, DateTime, Float, ForeignKey, Integer, Interval,
LargeBinary, PickleType)
diff --git a/src/mailman/model/member.py b/src/mailman/model/member.py
index aacaa73b6..93d0c7feb 100644
--- a/src/mailman/model/member.py
+++ b/src/mailman/model/member.py
@@ -17,7 +17,6 @@
"""Model for members."""
-from mailman import public
from mailman.core.constants import system_preferences
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
@@ -30,6 +29,7 @@ from mailman.interfaces.member import (
from mailman.interfaces.user import IUser, UnverifiedAddressError
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.uid import UIDFactory
+from public import public
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship
from zope.component import getUtility
diff --git a/src/mailman/model/message.py b/src/mailman/model/message.py
index 576baab5c..233e8b5b5 100644
--- a/src/mailman/model/message.py
+++ b/src/mailman/model/message.py
@@ -17,11 +17,11 @@
"""Model for messages."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode
from mailman.interfaces.messages import IMessage
+from public import public
from sqlalchemy import Column, Integer
from zope.interface import implementer
diff --git a/src/mailman/model/messagestore.py b/src/mailman/model/messagestore.py
index 8949c56c6..dc037c44f 100644
--- a/src/mailman/model/messagestore.py
+++ b/src/mailman/model/messagestore.py
@@ -21,13 +21,13 @@ import os
import errno
import pickle
-from mailman import public
from mailman.config import config
from mailman.database.transaction import dbconnection
from mailman.interfaces.messages import IMessageStore
from mailman.model.message import Message
from mailman.utilities.email import add_message_hash
from mailman.utilities.filesystem import makedirs, safe_remove
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/model/mime.py b/src/mailman/model/mime.py
index da5f11f05..a21cfb35d 100644
--- a/src/mailman/model/mime.py
+++ b/src/mailman/model/mime.py
@@ -17,10 +17,10 @@
"""The content filter."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.types import Enum, SAUnicode
from mailman.interfaces.mime import FilterType, IContentFilter
+from public import public
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship
from zope.interface import implementer
diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py
index 7e7f0b2eb..5889f9cc1 100644
--- a/src/mailman/model/pending.py
+++ b/src/mailman/model/pending.py
@@ -20,7 +20,6 @@
import json
from lazr.config import as_timedelta
-from mailman import public
from mailman.config import config
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
@@ -29,6 +28,7 @@ from mailman.interfaces.pending import (
IPendable, IPended, IPendedKeyValue, IPendings)
from mailman.utilities.datetime import now
from mailman.utilities.uid import TokenFactory
+from public import public
from sqlalchemy import Column, DateTime, ForeignKey, Integer, and_
from sqlalchemy.orm import aliased, relationship
from zope.interface import implementer
diff --git a/src/mailman/model/preferences.py b/src/mailman/model/preferences.py
index 366ed97c2..4e57ce659 100644
--- a/src/mailman/model/preferences.py
+++ b/src/mailman/model/preferences.py
@@ -17,13 +17,13 @@
"""Model for preferences."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import Enum, SAUnicode
from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.member import DeliveryMode, DeliveryStatus
from mailman.interfaces.preferences import IPreferences
+from public import public
from sqlalchemy import Boolean, Column, Integer
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py
index 0f0f96dfe..04717f49a 100644
--- a/src/mailman/model/requests.py
+++ b/src/mailman/model/requests.py
@@ -18,7 +18,6 @@
"""Implementations of the pending requests interfaces."""
from datetime import timedelta
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import Enum, SAUnicode
@@ -26,6 +25,7 @@ from mailman.interfaces.pending import IPendable, IPendings
from mailman.interfaces.requests import IListRequests, RequestType
from mailman.utilities.queries import QuerySequence
from pickle import dumps, loads
+from public import public
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship
from zope.component import getUtility
diff --git a/src/mailman/model/roster.py b/src/mailman/model/roster.py
index 5dc0423b2..d3dc1b661 100644
--- a/src/mailman/model/roster.py
+++ b/src/mailman/model/roster.py
@@ -22,12 +22,12 @@ the ones that fit a particular role. These are used as the member, owner,
moderator, and administrator roster filters.
"""
-from mailman import public
from mailman.database.transaction import dbconnection
from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.roster import IRoster
from mailman.model.address import Address
from mailman.model.member import Member
+from public import public
from sqlalchemy import or_
from zope.interface import implementer
diff --git a/src/mailman/model/subscriptions.py b/src/mailman/model/subscriptions.py
index d3fdc3a8a..485524a68 100644
--- a/src/mailman/model/subscriptions.py
+++ b/src/mailman/model/subscriptions.py
@@ -17,7 +17,6 @@
"""Subscription services."""
-from mailman import public
from mailman.app.membership import delete_member
from mailman.database.transaction import dbconnection
from mailman.interfaces.listmanager import IListManager, NoSuchListError
@@ -30,6 +29,7 @@ from mailman.model.member import Member
from mailman.model.user import User
from mailman.utilities.queries import QuerySequence
from operator import attrgetter
+from public import public
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/model/template.py b/src/mailman/model/template.py
index b09c644bb..eb776293f 100644
--- a/src/mailman/model/template.py
+++ b/src/mailman/model/template.py
@@ -19,7 +19,6 @@
import logging
-from mailman import public
from mailman.config import config
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
@@ -32,6 +31,7 @@ from mailman.interfaces.template import (
from mailman.utilities import protocols
from mailman.utilities.i18n import find
from mailman.utilities.string import expand
+from public import public
from requests import HTTPError
from sqlalchemy import Column, Integer
from urllib.error import URLError
diff --git a/src/mailman/model/tests/test_mailinglist.py b/src/mailman/model/tests/test_mailinglist.py
index 0a5c8a5e9..658ffc7d1 100644
--- a/src/mailman/model/tests/test_mailinglist.py
+++ b/src/mailman/model/tests/test_mailinglist.py
@@ -121,11 +121,11 @@ class TestListArchiver(unittest.TestCase):
def test_get_archiver(self):
# Use .get() to see if a mailing list has an archiver.
- archiver = self._set.get('prototype')
- self.assertEqual(archiver.name, 'prototype')
+ archiver = self._set.get('mhonarc')
+ self.assertEqual(archiver.name, 'mhonarc')
self.assertTrue(archiver.is_enabled)
self.assertEqual(archiver.mailing_list, self._mlist)
- self.assertEqual(archiver.system_archiver.name, 'prototype')
+ self.assertEqual(archiver.system_archiver.name, 'mhonarc')
def test_get_archiver_no_such(self):
# Using .get() on a non-existing name returns None.
@@ -137,15 +137,15 @@ class TestListArchiver(unittest.TestCase):
# then the site-wide archiver gets disabled, so the list specific
# archiver will also be disabled.
archiver_set = IListArchiverSet(self._mlist)
- archiver = archiver_set.get('prototype')
+ archiver = archiver_set.get('mhonarc')
self.assertTrue(archiver.is_enabled)
# Disable the site-wide archiver.
- config.push('enable prototype', """\
- [archiver.prototype]
+ config.push('enable mhonarc', """\
+ [archiver.mhonarc]
enable: no
""")
self.assertFalse(archiver.is_enabled)
- config.pop('enable prototype')
+ config.pop('enable mhonarc')
class TestDisabledListArchiver(unittest.TestCase):
diff --git a/src/mailman/model/uid.py b/src/mailman/model/uid.py
index 2cf61668f..9daefa318 100644
--- a/src/mailman/model/uid.py
+++ b/src/mailman/model/uid.py
@@ -17,10 +17,10 @@
"""Unique IDs."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import UUID
+from public import public
from sqlalchemy import Column, Integer
diff --git a/src/mailman/model/user.py b/src/mailman/model/user.py
index edda2a9e8..dc9c097d5 100644
--- a/src/mailman/model/user.py
+++ b/src/mailman/model/user.py
@@ -17,7 +17,6 @@
"""Model for users."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode, UUID
@@ -31,6 +30,7 @@ from mailman.model.preferences import Preferences
from mailman.model.roster import Memberships
from mailman.utilities.datetime import factory as date_factory
from mailman.utilities.uid import UIDFactory
+from public import public
from sqlalchemy import (
Boolean, Column, DateTime, ForeignKey, Integer)
from sqlalchemy.orm import backref, relationship
diff --git a/src/mailman/model/usermanager.py b/src/mailman/model/usermanager.py
index fba8e2ec0..2a62e0cf1 100644
--- a/src/mailman/model/usermanager.py
+++ b/src/mailman/model/usermanager.py
@@ -17,7 +17,6 @@
"""A user manager."""
-from mailman import public
from mailman.database.transaction import dbconnection
from mailman.interfaces.address import ExistingAddressError
from mailman.interfaces.usermanager import IUserManager
@@ -27,6 +26,7 @@ from mailman.model.digests import OneLastDigest
from mailman.model.member import Member
from mailman.model.preferences import Preferences
from mailman.model.user import User
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/model/workflow.py b/src/mailman/model/workflow.py
index 53763a0e8..8b782b5e0 100644
--- a/src/mailman/model/workflow.py
+++ b/src/mailman/model/workflow.py
@@ -17,11 +17,11 @@
"""Model for workflow states."""
-from mailman import public
from mailman.database.model import Model
from mailman.database.transaction import dbconnection
from mailman.database.types import SAUnicode
from mailman.interfaces.workflow import IWorkflowState, IWorkflowStateManager
+from public import public
from sqlalchemy import Column
from zope.interface import implementer
diff --git a/src/mailman/mta/aliases.py b/src/mailman/mta/aliases.py
index dc434c613..889375c04 100644
--- a/src/mailman/mta/aliases.py
+++ b/src/mailman/mta/aliases.py
@@ -17,8 +17,8 @@
"""Utility for generating all the aliases of a mailing list."""
-from mailman import public
from mailman.interfaces.mta import IMailTransportAgentAliases
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/mta/base.py b/src/mailman/mta/base.py
index 679faefd5..4f5bb1d58 100644
--- a/src/mailman/mta/base.py
+++ b/src/mailman/mta/base.py
@@ -22,10 +22,10 @@ import socket
import logging
import smtplib
-from mailman import public
from mailman.config import config
from mailman.interfaces.mta import IMailTransportAgentDelivery
from mailman.mta.connection import Connection
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/mta/bulk.py b/src/mailman/mta/bulk.py
index 1741e0d4c..91b04957a 100644
--- a/src/mailman/mta/bulk.py
+++ b/src/mailman/mta/bulk.py
@@ -17,8 +17,8 @@
"""Bulk message delivery."""
-from mailman import public
from mailman.mta.base import BaseDelivery
+from public import public
# A mapping of top-level domains to bucket numbers. The zeroth bucket is
diff --git a/src/mailman/mta/connection.py b/src/mailman/mta/connection.py
index 44cc31d86..318bc5e8e 100644
--- a/src/mailman/mta/connection.py
+++ b/src/mailman/mta/connection.py
@@ -22,8 +22,8 @@ import smtplib
from contextlib import suppress
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
+from public import public
log = logging.getLogger('mailman.smtp')
diff --git a/src/mailman/mta/decorating.py b/src/mailman/mta/decorating.py
index e9d6f5785..32db852da 100644
--- a/src/mailman/mta/decorating.py
+++ b/src/mailman/mta/decorating.py
@@ -17,9 +17,9 @@
"""Individualized delivery with header/footer decorations."""
-from mailman import public
from mailman.config import config
from mailman.mta.verp import VERPDelivery
+from public import public
@public
diff --git a/src/mailman/mta/deliver.py b/src/mailman/mta/deliver.py
index a5a4e2433..7624979bf 100644
--- a/src/mailman/mta/deliver.py
+++ b/src/mailman/mta/deliver.py
@@ -20,7 +20,6 @@
import time
import logging
-from mailman import public
from mailman.config import config
from mailman.interfaces.mailinglist import Personalization
from mailman.interfaces.mta import SomeRecipientsFailed
@@ -30,6 +29,7 @@ from mailman.mta.decorating import DecoratingMixin
from mailman.mta.personalized import PersonalizedMixin
from mailman.mta.verp import VERPMixin
from mailman.utilities.string import expand
+from public import public
COMMA = ','
diff --git a/src/mailman/mta/exim4.py b/src/mailman/mta/exim4.py
index 7151768a8..ec2e77708 100644
--- a/src/mailman/mta/exim4.py
+++ b/src/mailman/mta/exim4.py
@@ -17,8 +17,8 @@
"""Creation/deletion hooks for the Exim4 MTA."""
-from mailman import public
from mailman.interfaces.mta import IMailTransportAgentLifecycle
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/mta/null.py b/src/mailman/mta/null.py
index 165c5f0ee..e5368e689 100644
--- a/src/mailman/mta/null.py
+++ b/src/mailman/mta/null.py
@@ -20,8 +20,8 @@
Exim one example of an MTA that Just Works.
"""
-from mailman import public
from mailman.interfaces.mta import IMailTransportAgentLifecycle
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/mta/personalized.py b/src/mailman/mta/personalized.py
index 7cfbfff43..01ba686f3 100644
--- a/src/mailman/mta/personalized.py
+++ b/src/mailman/mta/personalized.py
@@ -19,10 +19,10 @@
from email.header import Header
from email.utils import formataddr
-from mailman import public
from mailman.interfaces.mailinglist import Personalization
from mailman.interfaces.usermanager import IUserManager
from mailman.mta.verp import VERPDelivery
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/mta/postfix.py b/src/mailman/mta/postfix.py
index ff4b92117..07bf17a22 100644
--- a/src/mailman/mta/postfix.py
+++ b/src/mailman/mta/postfix.py
@@ -21,7 +21,6 @@ import os
import logging
from flufl.lock import Lock
-from mailman import public
from mailman.config import config
from mailman.config.config import external_configuration
from mailman.interfaces.listmanager import IListManager
@@ -29,6 +28,7 @@ from mailman.interfaces.mta import (
IMailTransportAgentAliases, IMailTransportAgentLifecycle)
from mailman.utilities.datetime import now
from operator import attrgetter
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/mta/verp.py b/src/mailman/mta/verp.py
index 8ede6cb67..6ce80c795 100644
--- a/src/mailman/mta/verp.py
+++ b/src/mailman/mta/verp.py
@@ -19,11 +19,11 @@
import logging
-from mailman import public
from mailman.config import config
from mailman.mta.base import IndividualDelivery
from mailman.utilities.email import split_email
from mailman.utilities.string import expand
+from public import public
DOT = '.'
diff --git a/src/mailman/rest/addresses.py b/src/mailman/rest/addresses.py
index f0cb8edef..8e8b543b9 100644
--- a/src/mailman/rest/addresses.py
+++ b/src/mailman/rest/addresses.py
@@ -17,7 +17,6 @@
"""REST for addresses."""
-from mailman import public
from mailman.interfaces.address import (
ExistingAddressError, InvalidEmailAddressError)
from mailman.interfaces.usermanager import IUserManager
@@ -29,6 +28,7 @@ from mailman.rest.preferences import Preferences
from mailman.rest.validator import Validator
from mailman.utilities.datetime import now
from operator import attrgetter
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/bans.py b/src/mailman/rest/bans.py
index ce575885b..981c1b549 100644
--- a/src/mailman/rest/bans.py
+++ b/src/mailman/rest/bans.py
@@ -17,12 +17,12 @@
"""REST for banned emails."""
-from mailman import public
from mailman.interfaces.bans import IBanManager
from mailman.rest.helpers import (
CollectionMixin, bad_request, child, created, etag, no_content, not_found,
okay)
from mailman.rest.validator import Validator
+from public import public
class _BannedBase:
diff --git a/src/mailman/rest/docs/__init__.py b/src/mailman/rest/docs/__init__.py
index 5a039ac3d..dc27a6525 100644
--- a/src/mailman/rest/docs/__init__.py
+++ b/src/mailman/rest/docs/__init__.py
@@ -20,9 +20,9 @@
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
-from mailman import public
from mailman.testing.helpers import wait_for_webservice
from mailman.testing.layers import RESTLayer
+from public import public
# New in Python 3.5.
diff --git a/src/mailman/rest/docs/lists.rst b/src/mailman/rest/docs/lists.rst
index 247b2f4e7..6a034df94 100644
--- a/src/mailman/rest/docs/lists.rst
+++ b/src/mailman/rest/docs/lists.rst
@@ -275,7 +275,6 @@ archivers are available, and whether they are enabled for this mailing list.
http_etag: "..."
mail-archive: True
mhonarc: True
- prototype: True
You can set all the archiver states by putting new state flags on the
resource.
@@ -285,7 +284,6 @@ resource.
... 'http://localhost:9001/3.0/lists/dog@example.com/archivers', {
... 'mail-archive': False,
... 'mhonarc': True,
- ... 'prototype': False,
... }, method='PUT')
content-length: 0
date: ...
@@ -296,7 +294,6 @@ resource.
http_etag: "..."
mail-archive: False
mhonarc: True
- prototype: False
You can change the state of a subset of the list archivers.
::
@@ -314,7 +311,6 @@ You can change the state of a subset of the list archivers.
http_etag: "..."
mail-archive: False
mhonarc: False
- prototype: False
List digests
diff --git a/src/mailman/rest/domains.py b/src/mailman/rest/domains.py
index c6b8daa7c..ce96204b4 100644
--- a/src/mailman/rest/domains.py
+++ b/src/mailman/rest/domains.py
@@ -17,7 +17,6 @@
"""REST for domains."""
-from mailman import public
from mailman.interfaces.domain import (
BadDomainSpecificationError, IDomainManager)
from mailman.rest.helpers import (
@@ -27,6 +26,7 @@ from mailman.rest.lists import ListsForDomain
from mailman.rest.uris import ADomainURI, AllDomainURIs
from mailman.rest.users import ListOfDomainOwners, OwnersForDomain
from mailman.rest.validator import Validator, list_of_strings_validator
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/header_matches.py b/src/mailman/rest/header_matches.py
index 25c519ef3..13dad97ad 100644
--- a/src/mailman/rest/header_matches.py
+++ b/src/mailman/rest/header_matches.py
@@ -17,13 +17,13 @@
"""REST API for a mailing list's header matches."""
-from mailman import public
from mailman.interfaces.action import Action
from mailman.interfaces.mailinglist import IHeaderMatchList
from mailman.rest.helpers import (
CollectionMixin, bad_request, child, created, etag, no_content, not_found,
okay)
from mailman.rest.validator import Validator, enum_validator
+from public import public
def lowercase(value):
diff --git a/src/mailman/rest/helpers.py b/src/mailman/rest/helpers.py
index 9ab1f434e..6b45eb78a 100644
--- a/src/mailman/rest/helpers.py
+++ b/src/mailman/rest/helpers.py
@@ -23,11 +23,13 @@ import hashlib
from contextlib import suppress
from datetime import datetime, timedelta
+from email.header import Header
+from email.message import Message
from enum import Enum
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from pprint import pformat
+from public import public
class ExtendedEncoder(json.JSONEncoder):
@@ -49,6 +51,10 @@ class ExtendedEncoder(json.JSONEncoder):
return obj.name
elif isinstance(obj, bytes):
return bytes_to_str(obj)
+ elif isinstance(obj, Message):
+ return obj.as_string()
+ elif isinstance(obj, Header):
+ return str(obj)
return super().default(obj)
diff --git a/src/mailman/rest/listconf.py b/src/mailman/rest/listconf.py
index 861e54dd1..94598b0ab 100644
--- a/src/mailman/rest/listconf.py
+++ b/src/mailman/rest/listconf.py
@@ -18,7 +18,6 @@
"""Mailing list configuration via REST API."""
from lazr.config import as_boolean, as_timedelta
-from mailman import public
from mailman.config import config
from mailman.interfaces.action import Action
from mailman.interfaces.archiver import ArchivePolicy
@@ -32,6 +31,7 @@ from mailman.rest.helpers import (
from mailman.rest.validator import (
PatchValidator, ReadOnlyPATCHRequestError, UnknownPATCHRequestError,
Validator, enum_validator, list_of_strings_validator)
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py
index 8952f1156..cdebdebd9 100644
--- a/src/mailman/rest/lists.py
+++ b/src/mailman/rest/lists.py
@@ -18,7 +18,6 @@
"""REST for mailing lists."""
from lazr.config import as_boolean
-from mailman import public
from mailman.app.digests import (
bump_digest_number_and_volume, maybe_send_digest_now)
from mailman.app.lifecycle import create_list, remove_list
@@ -41,6 +40,7 @@ from mailman.rest.post_moderation import HeldMessages
from mailman.rest.sub_moderation import SubscriptionRequests
from mailman.rest.uris import AListURI, AllListURIs
from mailman.rest.validator import Validator, list_of_strings_validator
+from public import public
from zope.component import getUtility
@@ -337,13 +337,15 @@ class ListArchivers:
"""Get all the archiver statuses."""
archiver_set = IListArchiverSet(self._mlist)
resource = {archiver.name: archiver.is_enabled
- for archiver in archiver_set.archivers}
+ for archiver in archiver_set.archivers
+ if archiver.system_archiver.is_enabled}
okay(response, etag(resource))
def patch_put(self, request, response, is_optional):
archiver_set = IListArchiverSet(self._mlist)
kws = {archiver.name: ArchiverGetterSetter(self._mlist)
- for archiver in archiver_set.archivers}
+ for archiver in archiver_set.archivers
+ if archiver.system_archiver.is_enabled}
if is_optional:
# For a PATCH, all attributes are optional.
kws['_optional'] = kws.keys()
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index b35440af4..ea7eaa394 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -17,7 +17,6 @@
"""REST for members."""
-from mailman import public
from mailman.app.membership import add_member, delete_member
from mailman.interfaces.action import Action
from mailman.interfaces.address import IAddress
@@ -36,6 +35,7 @@ from mailman.rest.helpers import (
from mailman.rest.preferences import Preferences, ReadOnlyPreferences
from mailman.rest.validator import (
Validator, enum_validator, subscriber_validator)
+from public import public
from uuid import UUID
from zope.component import getUtility
diff --git a/src/mailman/rest/post_moderation.py b/src/mailman/rest/post_moderation.py
index 33a32de20..9a56ada00 100644
--- a/src/mailman/rest/post_moderation.py
+++ b/src/mailman/rest/post_moderation.py
@@ -17,7 +17,6 @@
"""REST API for held message moderation."""
-from mailman import public
from mailman.app.moderator import handle_message
from mailman.interfaces.action import Action
from mailman.interfaces.messages import IMessageStore
@@ -25,6 +24,7 @@ from mailman.interfaces.requests import IListRequests, RequestType
from mailman.rest.helpers import (
CollectionMixin, bad_request, child, etag, no_content, not_found, okay)
from mailman.rest.validator import Validator, enum_validator
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/preferences.py b/src/mailman/rest/preferences.py
index cf26380fe..549751d1e 100644
--- a/src/mailman/rest/preferences.py
+++ b/src/mailman/rest/preferences.py
@@ -18,12 +18,12 @@
"""Preferences."""
from lazr.config import as_boolean
-from mailman import public
from mailman.interfaces.member import DeliveryMode, DeliveryStatus
from mailman.rest.helpers import (
GetterSetter, bad_request, etag, no_content, not_found, okay)
from mailman.rest.validator import (
Validator, enum_validator, language_validator)
+from public import public
PREFERENCES = (
diff --git a/src/mailman/rest/queues.py b/src/mailman/rest/queues.py
index 9fa5b9dc6..27e9c698e 100644
--- a/src/mailman/rest/queues.py
+++ b/src/mailman/rest/queues.py
@@ -17,13 +17,13 @@
"""<api>/queues."""
-from mailman import public
from mailman.app.inject import inject_text
from mailman.config import config
from mailman.interfaces.listmanager import IListManager
from mailman.rest.helpers import (
CollectionMixin, bad_request, created, etag, no_content, not_found, okay)
from mailman.rest.validator import Validator
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py
index 7f6be0353..c4c0b865f 100644
--- a/src/mailman/rest/root.py
+++ b/src/mailman/rest/root.py
@@ -17,7 +17,6 @@
"""The root of the REST API."""
-from mailman import public
from mailman.config import config
from mailman.core.api import API30, API31
from mailman.core.constants import system_preferences
@@ -36,6 +35,7 @@ from mailman.rest.queues import AQueue, AQueueFile, AllQueues
from mailman.rest.templates import TemplateFinder
from mailman.rest.uris import ASiteURI, AllSiteURIs
from mailman.rest.users import AUser, AllUsers, ServerOwners
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/sub_moderation.py b/src/mailman/rest/sub_moderation.py
index 55b6a7609..39976826c 100644
--- a/src/mailman/rest/sub_moderation.py
+++ b/src/mailman/rest/sub_moderation.py
@@ -17,7 +17,6 @@
"""REST API for held subscription requests."""
-from mailman import public
from mailman.app.moderator import send_rejection
from mailman.core.i18n import _
from mailman.interfaces.action import Action
@@ -28,6 +27,7 @@ from mailman.rest.helpers import (
CollectionMixin, bad_request, child, conflict, etag, no_content,
not_found, okay)
from mailman.rest.validator import Validator, enum_validator
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/templates.py b/src/mailman/rest/templates.py
index fe5e34a8e..7f4e5a3af 100644
--- a/src/mailman/rest/templates.py
+++ b/src/mailman/rest/templates.py
@@ -17,9 +17,9 @@
"""Template finder."""
-from mailman import public
from mailman.rest.helpers import not_found
from mailman.utilities.i18n import TemplateNotFoundError, find
+from public import public
# Use mimetypes.guess_all_extensions()?
diff --git a/src/mailman/rest/tests/test_helpers.py b/src/mailman/rest/tests/test_helpers.py
index 982b97ef3..07ae784c8 100644
--- a/src/mailman/rest/tests/test_helpers.py
+++ b/src/mailman/rest/tests/test_helpers.py
@@ -17,11 +17,14 @@
"""Additional tests for helpers."""
+import json
import unittest
from datetime import timedelta
+from email.header import Header
+from email.message import Message
from mailman.rest import helpers
-from mailman.testing.layers import ConfigLayer
+from mailman.testing.layers import ConfigLayer, RESTLayer
class FakeResponse:
@@ -74,3 +77,23 @@ class TestHelpers(unittest.TestCase):
def test_json_encoding_default(self):
resource = dict(interval=Unserializable())
self.assertRaises(TypeError, helpers.etag, resource)
+
+
+class TestJSONEncoder(unittest.TestCase):
+ """Test the JSON ExtendedEncoder."""
+ layer = RESTLayer
+
+ def test_encode_message(self):
+ msg = Message()
+ msg['From'] = 'test@example.com'
+ msg.set_payload('Test content.')
+ result = json.dumps(msg, cls=helpers.ExtendedEncoder)
+ self.assertEqual(
+ result, json.dumps('From: test@example.com\n\nTest content.'))
+
+ def test_encode_header(self):
+ value = 'Contains non-ascii \u00e9 \u00e7 \u00e0'
+ result = json.dumps(
+ Header(value, charset='utf-8'),
+ cls=helpers.ExtendedEncoder)
+ self.assertEqual(result, json.dumps(value))
diff --git a/src/mailman/rest/tests/test_lists.py b/src/mailman/rest/tests/test_lists.py
index da6e95f3b..49764f86f 100644
--- a/src/mailman/rest/tests/test_lists.py
+++ b/src/mailman/rest/tests/test_lists.py
@@ -339,7 +339,6 @@ class TestListArchivers(unittest.TestCase):
self.assertEqual(resource, {
'mail-archive': True,
'mhonarc': True,
- 'prototype': True,
})
def test_archiver_statuses_on_missing_lists(self):
@@ -375,7 +374,7 @@ class TestListArchivers(unittest.TestCase):
def test_put_incomplete_statuses(self):
# PUT requires the full resource representation. This one forgets to
- # specify the prototype and mhonarc archiver.
+ # specify the mhonarc archiver.
with self.assertRaises(HTTPError) as cm:
call_api(
'http://localhost:9001/3.0/lists/ant.example.com/archivers', {
@@ -384,7 +383,7 @@ class TestListArchivers(unittest.TestCase):
method='PUT')
self.assertEqual(cm.exception.code, 400)
self.assertEqual(cm.exception.reason,
- b'Missing parameters: mhonarc, prototype')
+ b'Missing parameters: mhonarc')
def test_patch_bogus_status(self):
# Archiver statuses must be interpretable as booleans.
@@ -392,8 +391,7 @@ class TestListArchivers(unittest.TestCase):
call_api(
'http://localhost:9001/3.0/lists/ant.example.com/archivers', {
'mail-archive': 'sure',
- 'mhonarc': False,
- 'prototype': 'no'
+ 'mhonarc': 'no'
},
method='PATCH')
self.assertEqual(cm.exception.code, 400)
diff --git a/src/mailman/rest/uris.py b/src/mailman/rest/uris.py
index 2fc062262..d94b3b237 100644
--- a/src/mailman/rest/uris.py
+++ b/src/mailman/rest/uris.py
@@ -17,12 +17,12 @@
"""URI templates."""
-from mailman import public
from mailman.interfaces.template import ALL_TEMPLATES, ITemplateManager
from mailman.rest.helpers import (
CollectionMixin, bad_request, etag, no_content, not_found, okay)
from mailman.rest.validator import Validator
from operator import attrgetter
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py
index f9ce9b132..c50bfe3d0 100644
--- a/src/mailman/rest/users.py
+++ b/src/mailman/rest/users.py
@@ -19,7 +19,6 @@
from functools import lru_cache
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.interfaces.address import ExistingAddressError
from mailman.interfaces.usermanager import IUserManager
@@ -32,6 +31,7 @@ from mailman.rest.validator import (
PatchValidator, ReadOnlyPATCHRequestError, UnknownPATCHRequestError,
Validator, list_of_strings_validator)
from passlib.utils import generate_password as generate
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/validator.py b/src/mailman/rest/validator.py
index 19e8d684a..439c25b8e 100644
--- a/src/mailman/rest/validator.py
+++ b/src/mailman/rest/validator.py
@@ -17,10 +17,10 @@
"""REST web form validation."""
-from mailman import public
from mailman.interfaces.address import IEmailValidator
from mailman.interfaces.errors import MailmanError
from mailman.interfaces.languages import ILanguageManager
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py
index 3ba122c00..b2dbc7409 100644
--- a/src/mailman/rest/wsgiapp.py
+++ b/src/mailman/rest/wsgiapp.py
@@ -23,10 +23,10 @@ import logging
from base64 import b64decode
from falcon import API, HTTPUnauthorized
from falcon.routing import create_http_method_map
-from mailman import public
from mailman.config import config
from mailman.database.transaction import transactional
from mailman.rest.root import Root
+from public import public
from wsgiref.simple_server import (
WSGIRequestHandler, WSGIServer, make_server as wsgi_server)
diff --git a/src/mailman/rules/administrivia.py b/src/mailman/rules/administrivia.py
index e5defee6e..6dc6c38b4 100644
--- a/src/mailman/rules/administrivia.py
+++ b/src/mailman/rules/administrivia.py
@@ -18,10 +18,10 @@
"""The administrivia rule."""
from email.iterators import typed_subpart_iterator
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
# The list of email commands we search for in the Subject header and payload.
diff --git a/src/mailman/rules/any.py b/src/mailman/rules/any.py
index 466735ebe..6d3bbe21f 100644
--- a/src/mailman/rules/any.py
+++ b/src/mailman/rules/any.py
@@ -17,9 +17,9 @@
"""Check if any previous rules have matched."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/approved.py b/src/mailman/rules/approved.py
index a4ea1145e..66f21c8eb 100644
--- a/src/mailman/rules/approved.py
+++ b/src/mailman/rules/approved.py
@@ -20,10 +20,10 @@
import re
from email.iterators import typed_subpart_iterator
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/banned_address.py b/src/mailman/rules/banned_address.py
index 8ed33a5e6..850f101db 100644
--- a/src/mailman/rules/banned_address.py
+++ b/src/mailman/rules/banned_address.py
@@ -17,10 +17,10 @@
"""Banned addresses rule."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.bans import IBanManager
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/emergency.py b/src/mailman/rules/emergency.py
index 442ccf136..59c0c6a84 100644
--- a/src/mailman/rules/emergency.py
+++ b/src/mailman/rules/emergency.py
@@ -17,9 +17,9 @@
"""The emergency hold rule."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/implicit_dest.py b/src/mailman/rules/implicit_dest.py
index c0e116d1c..88429a6ac 100644
--- a/src/mailman/rules/implicit_dest.py
+++ b/src/mailman/rules/implicit_dest.py
@@ -21,10 +21,10 @@ import re
from contextlib import suppress
from email.utils import getaddresses
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.mailinglist import IAcceptableAliasSet
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/loop.py b/src/mailman/rules/loop.py
index 0f8047e76..d9b7c299d 100644
--- a/src/mailman/rules/loop.py
+++ b/src/mailman/rules/loop.py
@@ -17,9 +17,9 @@
"""Look for a posting loop."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/max_recipients.py b/src/mailman/rules/max_recipients.py
index 61df613cb..1d38e28c1 100644
--- a/src/mailman/rules/max_recipients.py
+++ b/src/mailman/rules/max_recipients.py
@@ -18,9 +18,9 @@
"""The maximum number of recipients rule."""
from email.utils import getaddresses
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/max_size.py b/src/mailman/rules/max_size.py
index 8911e97fd..c5c492347 100644
--- a/src/mailman/rules/max_size.py
+++ b/src/mailman/rules/max_size.py
@@ -17,9 +17,9 @@
"""The maximum message size rule."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/moderation.py b/src/mailman/rules/moderation.py
index 20b238eab..b52ecff3e 100644
--- a/src/mailman/rules/moderation.py
+++ b/src/mailman/rules/moderation.py
@@ -19,13 +19,13 @@
import re
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.action import Action
from mailman.interfaces.bans import IBanManager
from mailman.interfaces.member import MemberRole
from mailman.interfaces.rules import IRule
from mailman.interfaces.usermanager import IUserManager
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/rules/news_moderation.py b/src/mailman/rules/news_moderation.py
index 63a7e93b0..8d0fe3402 100644
--- a/src/mailman/rules/news_moderation.py
+++ b/src/mailman/rules/news_moderation.py
@@ -17,10 +17,10 @@
"""The news moderation rule."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.nntp import NewsgroupModeration
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/rules/no_subject.py b/src/mailman/rules/no_subject.py
index 4b53067a5..f3eba625a 100644
--- a/src/mailman/rules/no_subject.py
+++ b/src/mailman/rules/no_subject.py
@@ -17,9 +17,9 @@
"""The no-Subject header rule."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
@@ -34,5 +34,7 @@ class NoSubject:
def check(self, mlist, msg, msgdata):
"""See `IRule`."""
- subject = msg.get('subject', '').strip()
+ # Convert the header value to a str because it may be an
+ # email.header.Header instance.
+ subject = str(msg.get('subject', '')).strip()
return subject == ''
diff --git a/src/mailman/rules/suspicious.py b/src/mailman/rules/suspicious.py
index f349a313e..049df0a61 100644
--- a/src/mailman/rules/suspicious.py
+++ b/src/mailman/rules/suspicious.py
@@ -20,9 +20,9 @@
import re
import logging
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
@@ -87,6 +87,8 @@ def has_matching_bounce_header(mlist, msg):
"""
for header, cre, line in _parse_matching_header_opt(mlist):
for value in msg.get_all(header, []):
- if cre.search(value):
+ # Convert the header value to a str because it may be an
+ # email.header.Header instance.
+ if cre.search(str(value)):
return True
return False
diff --git a/src/mailman/rules/tests/test_no_subject.py b/src/mailman/rules/tests/test_no_subject.py
new file mode 100644
index 000000000..0155e25ee
--- /dev/null
+++ b/src/mailman/rules/tests/test_no_subject.py
@@ -0,0 +1,48 @@
+# Copyright (C) 2016 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test the `no_subject` header rule."""
+
+import unittest
+
+from email.header import Header
+from mailman.app.lifecycle import create_list
+from mailman.email.message import Message
+from mailman.rules import no_subject
+from mailman.testing.layers import ConfigLayer
+
+
+class TestNoSubject(unittest.TestCase):
+ """Test the no_subject rule."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._rule = no_subject.NoSubject()
+
+ def test_header_instance_empty(self):
+ msg = Message()
+ msg['Subject'] = Header('')
+ result = self._rule.check(self._mlist, msg, {})
+ self.assertTrue(result)
+
+ def test_header_instance_not_empty(self):
+ msg = Message()
+ msg['Subject'] = Header('Test subject')
+ result = self._rule.check(self._mlist, msg, {})
+ self.assertFalse(result)
diff --git a/src/mailman/rules/tests/test_suspicious.py b/src/mailman/rules/tests/test_suspicious.py
new file mode 100644
index 000000000..441fb0b48
--- /dev/null
+++ b/src/mailman/rules/tests/test_suspicious.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2016 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test the `suspicious` rule."""
+
+
+import unittest
+
+from email.header import Header
+from mailman.app.lifecycle import create_list
+from mailman.email.message import Message
+from mailman.rules import suspicious
+from mailman.testing.layers import ConfigLayer
+
+
+class TestSuspicious(unittest.TestCase):
+ """Test the suspicious rule."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._rule = suspicious.SuspiciousHeader()
+
+ def test_header_instance(self):
+ msg = Message()
+ msg['From'] = Header('user@example.com')
+ self._mlist.bounce_matching_headers = 'from: spam@example.com'
+ result = self._rule.check(self._mlist, msg, {})
+ self.assertFalse(result)
diff --git a/src/mailman/rules/truth.py b/src/mailman/rules/truth.py
index 9883a0e60..224ceeaad 100644
--- a/src/mailman/rules/truth.py
+++ b/src/mailman/rules/truth.py
@@ -17,9 +17,9 @@
"""A rule which always matches."""
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.rules import IRule
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/runners/archive.py b/src/mailman/runners/archive.py
index 23b7b164d..073f72d52 100644
--- a/src/mailman/runners/archive.py
+++ b/src/mailman/runners/archive.py
@@ -23,12 +23,12 @@ import logging
from datetime import datetime
from email.utils import mktime_tz, parsedate_tz
from lazr.config import as_timedelta
-from mailman import public
from mailman.config import config
from mailman.core.runner import Runner
from mailman.interfaces.archiver import ClobberDate
from mailman.interfaces.mailinglist import IListArchiverSet
from mailman.utilities.datetime import RFC822_DATE_FMT, now
+from public import public
log = logging.getLogger('mailman.archiver')
diff --git a/src/mailman/runners/bounce.py b/src/mailman/runners/bounce.py
index 4150dc9b5..40ea840e7 100644
--- a/src/mailman/runners/bounce.py
+++ b/src/mailman/runners/bounce.py
@@ -20,10 +20,10 @@
import logging
from flufl.bounce import all_failures, scan_message
-from mailman import public
from mailman.app.bounces import ProbeVERP, StandardVERP, maybe_forward
from mailman.core.runner import Runner
from mailman.interfaces.bounce import BounceContext, IBounceProcessor
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/runners/command.py b/src/mailman/runners/command.py
index ba10988e3..a52dd541d 100644
--- a/src/mailman/runners/command.py
+++ b/src/mailman/runners/command.py
@@ -30,13 +30,13 @@ from email.errors import HeaderParseError
from email.header import decode_header, make_header
from email.iterators import typed_subpart_iterator
from io import StringIO
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.runner import Runner
from mailman.email.message import UserNotification
from mailman.interfaces.command import ContinueProcessing, IEmailResults
from mailman.interfaces.languages import ILanguageManager
+from public import public
from zope.component import getUtility
from zope.interface import implementer
diff --git a/src/mailman/runners/digest.py b/src/mailman/runners/digest.py
index 4971965fa..284056e3a 100644
--- a/src/mailman/runners/digest.py
+++ b/src/mailman/runners/digest.py
@@ -27,7 +27,6 @@ from email.mime.message import MIMEMessage
from email.mime.text import MIMEText
from email.utils import formatdate, getaddresses, make_msgid
from io import StringIO
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.runner import Runner
@@ -37,6 +36,7 @@ from mailman.interfaces.member import DeliveryMode, DeliveryStatus
from mailman.interfaces.template import ITemplateLoader
from mailman.utilities.mailbox import Mailbox
from mailman.utilities.string import expand, oneline, wrap
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/runners/incoming.py b/src/mailman/runners/incoming.py
index 62b12dab1..9461e59bc 100644
--- a/src/mailman/runners/incoming.py
+++ b/src/mailman/runners/incoming.py
@@ -27,12 +27,12 @@ immediately.
"""
from contextlib import suppress
-from mailman import public
from mailman.core.chains import process
from mailman.core.runner import Runner
from mailman.database.transaction import transaction
from mailman.interfaces.address import ExistingAddressError
from mailman.interfaces.usermanager import IUserManager
+from public import public
from zope.component import getUtility
diff --git a/src/mailman/runners/lmtp.py b/src/mailman/runners/lmtp.py
index 21fb44c5e..25d531da4 100644
--- a/src/mailman/runners/lmtp.py
+++ b/src/mailman/runners/lmtp.py
@@ -37,13 +37,10 @@ so that the peer mail server can provide better diagnostics.
import email
import socket
import logging
-import aiosmtpd
-import aiosmtpd.smtp
from aiosmtpd.controller import Controller
from aiosmtpd.lmtp import LMTP
from email.utils import parseaddr
-from mailman import public
from mailman.config import config
from mailman.core.runner import Runner
from mailman.database.transaction import transactional
@@ -51,6 +48,7 @@ from mailman.email.message import Message
from mailman.interfaces.listmanager import IListManager
from mailman.utilities.datetime import now
from mailman.utilities.email import add_message_hash
+from public import public
from zope.component import getUtility
@@ -93,9 +91,6 @@ ERR_502 = '502 Error: command HELO not implemented'
ERR_550 = '550 Requested action not taken: mailbox unavailable'
ERR_550_MID = '550 No Message-ID header provided'
-# XXX Blech
-aiosmtpd.smtp.__version__ = 'GNU Mailman LMTP runner 2.0'
-
def split_recipient(address):
"""Split an address into listname, subaddress and domain parts.
@@ -218,7 +213,9 @@ class LMTPHandler:
class LMTPController(Controller):
def factory(self):
- return LMTP(self.handler)
+ server = LMTP(self.handler)
+ server.__ident__ = 'GNU Mailman LMTP runner 2.0'
+ return server
def make_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
diff --git a/src/mailman/runners/nntp.py b/src/mailman/runners/nntp.py
index b125fe4f9..38f67c453 100644
--- a/src/mailman/runners/nntp.py
+++ b/src/mailman/runners/nntp.py
@@ -24,10 +24,10 @@ import logging
import nntplib
from io import StringIO
-from mailman import public
from mailman.config import config
from mailman.core.runner import Runner
from mailman.interfaces.nntp import NewsgroupModeration
+from public import public
COMMA = ','
diff --git a/src/mailman/runners/outgoing.py b/src/mailman/runners/outgoing.py
index 3f21e3813..61b6e0b99 100644
--- a/src/mailman/runners/outgoing.py
+++ b/src/mailman/runners/outgoing.py
@@ -22,7 +22,6 @@ import logging
from datetime import datetime
from lazr.config import as_boolean, as_timedelta
-from mailman import public
from mailman.config import config
from mailman.core.runner import Runner
from mailman.interfaces.bounce import BounceContext, IBounceProcessor
@@ -32,6 +31,7 @@ from mailman.interfaces.pending import IPendings
from mailman.interfaces.subscriptions import ISubscriptionService
from mailman.utilities.datetime import now
from mailman.utilities.modules import find_name
+from public import public
from uuid import UUID
from zope.component import getUtility
diff --git a/src/mailman/runners/pipeline.py b/src/mailman/runners/pipeline.py
index 3ec7499f2..caa68763c 100644
--- a/src/mailman/runners/pipeline.py
+++ b/src/mailman/runners/pipeline.py
@@ -22,9 +22,9 @@ through the 'preparation pipeline'. This pipeline adds, deletes and modifies
headers, calculates message recipients, and more.
"""
-from mailman import public
from mailman.core.pipelines import process
from mailman.core.runner import Runner
+from public import public
@public
diff --git a/src/mailman/runners/rest.py b/src/mailman/runners/rest.py
index 037b6adf8..dd7eae245 100644
--- a/src/mailman/runners/rest.py
+++ b/src/mailman/runners/rest.py
@@ -21,9 +21,9 @@ import signal
import logging
import threading
-from mailman import public
from mailman.core.runner import Runner
from mailman.rest.wsgiapp import make_server
+from public import public
log = logging.getLogger('mailman.http')
diff --git a/src/mailman/runners/retry.py b/src/mailman/runners/retry.py
index f1af4f73c..2be89e8b0 100644
--- a/src/mailman/runners/retry.py
+++ b/src/mailman/runners/retry.py
@@ -19,9 +19,9 @@
import time
-from mailman import public
from mailman.config import config
from mailman.core.runner import Runner
+from public import public
@public
diff --git a/src/mailman/runners/virgin.py b/src/mailman/runners/virgin.py
index a69d07bf7..50ef3dcce 100644
--- a/src/mailman/runners/virgin.py
+++ b/src/mailman/runners/virgin.py
@@ -23,9 +23,9 @@ to go through some minimal processing before they can be sent out to the
recipient.
"""
-from mailman import public
from mailman.core.pipelines import process
from mailman.core.runner import Runner
+from public import public
@public
diff --git a/src/mailman/styles/base.py b/src/mailman/styles/base.py
index 7226d762a..02a17d54d 100644
--- a/src/mailman/styles/base.py
+++ b/src/mailman/styles/base.py
@@ -24,7 +24,6 @@ methods in your compositional derived class.
from datetime import timedelta
-from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.action import Action, FilterAction
from mailman.interfaces.archiver import ArchivePolicy
@@ -34,6 +33,7 @@ from mailman.interfaces.digests import DigestFrequency
from mailman.interfaces.mailinglist import (
Personalization, ReplyToMunging, SubscriptionPolicy)
from mailman.interfaces.nntp import NewsgroupModeration
+from public import public
@public
diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py
index 2df075a6f..c7632fe8e 100644
--- a/src/mailman/styles/default.py
+++ b/src/mailman/styles/default.py
@@ -17,11 +17,11 @@
"""Application of list styles to new and existing lists."""
-from mailman import public
from mailman.interfaces.styles import IStyle
from mailman.styles.base import (
Announcement, BasicOperation, Bounces, Discussion, Identity, Moderation,
Public)
+from public import public
from zope.interface import implementer
diff --git a/src/mailman/styles/manager.py b/src/mailman/styles/manager.py
index 1b3130581..ae60dc3c6 100644
--- a/src/mailman/styles/manager.py
+++ b/src/mailman/styles/manager.py
@@ -17,11 +17,11 @@
"""Style manager."""
-from mailman import public
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
from mailman.interfaces.styles import (
DuplicateStyleError, IStyle, IStyleManager)
from mailman.utilities.modules import find_components
+from public import public
from zope.component import getUtility
from zope.interface import implementer
from zope.interface.verify import verifyObject
diff --git a/src/mailman/testing/documentation.py b/src/mailman/testing/documentation.py
index 29629fe1b..97e30e900 100644
--- a/src/mailman/testing/documentation.py
+++ b/src/mailman/testing/documentation.py
@@ -22,12 +22,12 @@ distributions. doctest discovery currently requires file system traversal.
"""
from inspect import isfunction, ismethod
-from mailman import public
from mailman.app.lifecycle import create_list
from mailman.config import config
from mailman.testing.helpers import (
call_api, get_queue_messages, specialized_message_from_string, subscribe)
from mailman.testing.layers import SMTPLayer
+from public import public
DOT = '.'
diff --git a/src/mailman/testing/flake8.py b/src/mailman/testing/flake8.py
deleted file mode 100644
index 68bd37761..000000000
--- a/src/mailman/testing/flake8.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# Copyright (C) 2016 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Flake8 extensions for Mailman coding style."""
-
-
-from ast import NodeVisitor
-from collections import namedtuple
-from enum import Enum
-
-
-class ImportType(Enum):
- non_from = 0
- from_import = 1
-
-
-ImportRecord = namedtuple('ImportRecord', 'itype lineno colno, module, names')
-
-
-NONFROM_FOLLOWS_FROM = 'B401 Non-from import follows from-import'
-NONFROM_MULTIPLE_NAMES = 'B402 Multiple names on non-from import'
-NONFROM_SHORTER_FOLLOWS = 'B403 Shorter non-from import follows longer'
-NONFROM_ALPHA_UNSORTED = (
- 'B404 Same-length non-from imports not sorted alphabetically')
-NONFROM_EXTRA_BLANK_LINE = (
- 'B405 Unexpected blank line since last non-from import')
-NONFROM_DOTTED_UNSORTED = (
- 'B406 Dotted non-from import not sorted alphabetically')
-
-FROMIMPORT_MISSING_BLANK_LINE = (
- 'B411 Expected one blank line since last non-from import')
-FROMIMPORT_ALPHA_UNSORTED = 'B412 from-import not sorted alphabetically'
-FROMIMPORT_MULTIPLE = 'B413 Multiple from-imports of same module'
-FROMIMPORT_NAMES_UNSORTED = (
- 'B414 from-imported names are not sorted alphabetically')
-
-
-class ImportVisitor(NodeVisitor):
- def __init__(self):
- self.imports = []
-
- def visit_Import(self, node):
- if node.col_offset != 0:
- # Ignore nested imports.
- return
- names = [alias.name for alias in node.names]
- self.imports.append(
- ImportRecord(ImportType.non_from, node.lineno, node.col_offset,
- None, names))
-
- def visit_ImportFrom(self, node):
- if node.col_offset != 0:
- # Ignore nested imports.
- return
- names = [alias.name for alias in node.names]
- self.imports.append(
- ImportRecord(ImportType.from_import, node.lineno, node.col_offset,
- node.module, names))
-
-
-class ImportOrder:
- name = 'flufl-import-order'
- version = '0.1'
-
- def __init__(self, tree, filename):
- self.tree = tree
- self.filename = filename
-
- def _error(self, record, error):
- code, space, text = error.partition(' ')
- return (record.lineno, record.colno,
- '{} {}'.format(code, text), ImportOrder)
-
- def run(self):
- visitor = ImportVisitor()
- visitor.visit(self.tree)
- last_import = None
- for record in visitor.imports:
- if last_import is None:
- last_import = record
- continue
- if record.itype is ImportType.non_from:
- if len(record.names) != 1:
- yield self._error(record, NONFROM_MULTIPLE_NAMES)
- if last_import.itype is ImportType.from_import:
- yield self._error(record, NONFROM_FOLLOWS_FROM)
- # Shorter imports should always precede longer import *except*
- # when they are dotted imports and everything but the last
- # path component are the same. In that case, they should be
- # sorted alphabetically.
- last_name = last_import.names[0]
- this_name = record.names[0]
- if '.' in last_name and '.' in this_name:
- last_parts = last_name.split('.')
- this_parts = this_name.split('.')
- if (last_parts[:-1] == this_parts[:-1] and
- last_parts[-1] > this_parts[-1]):
- yield self._error(record, NONFROM_DOTTED_UNSORTED)
- elif len(last_name) > len(this_name):
- yield self._error(record, NONFROM_SHORTER_FOLLOWS)
- # It's also possible that the imports are the same length, in
- # which case they must be sorted alphabetically.
- if (len(last_import.names[0]) == len(record.names[0]) and
- last_import.names[0] > record.names[0]):
- yield self._error(record, NONFROM_ALPHA_UNSORTED)
- if last_import.lineno + 1 != record.lineno:
- yield self._error(record, NONFROM_DOTTED_UNSORTED)
- else:
- assert record.itype is ImportType.from_import
- if (last_import.itype is ImportType.non_from and
- record.lineno != last_import.lineno + 2):
- yield self._error(record, FROMIMPORT_MISSING_BLANK_LINE)
- if last_import.itype is ImportType.non_from:
- last_import = record
- continue
- if last_import.module > record.module:
- yield self._error(record, FROMIMPORT_ALPHA_UNSORTED)
- # All imports from the same module should show up in the same
- # multiline import.
- if last_import.module == record.module:
- yield self._error(record, FROMIMPORT_MULTIPLE)
- # Check the sort order of the imported names.
- if sorted(record.names) != record.names:
- yield self._error(record, FROMIMPORT_NAMES_UNSORTED)
- # How to check for no blank lines between from imports?
- # Update the last import.
- last_import = record
diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py
index 2ce6956b7..233b03cf8 100644
--- a/src/mailman/testing/helpers.py
+++ b/src/mailman/testing/helpers.py
@@ -35,7 +35,6 @@ from contextlib import contextmanager, suppress
from email import message_from_string
from httplib2 import Http
from lazr.config import as_timedelta
-from mailman import public
from mailman.bin.master import Loop as Master
from mailman.config import config
from mailman.database.transaction import transaction
@@ -46,6 +45,7 @@ from mailman.interfaces.styles import IStyleManager
from mailman.interfaces.usermanager import IUserManager
from mailman.runners.digest import DigestRunner
from mailman.utilities.mailbox import Mailbox
+from public import public
from unittest import mock
from urllib.error import HTTPError
from urllib.parse import urlencode
@@ -568,3 +568,11 @@ def hackenv(envar, new_value):
del os.environ[envar]
else:
os.environ[envar] = old_value
+
+
+def nose2_start_test_run_callback(plugin):
+ from mailman.testing.layers import ConfigLayer, MockAndMonkeyLayer
+ MockAndMonkeyLayer.testing_mode = True
+ if (plugin.stderr or
+ len(os.environ.get('MM_VERBOSE_TESTLOG', '').strip()) > 0):
+ ConfigLayer.stderr = True
diff --git a/src/mailman/testing/i18n.py b/src/mailman/testing/i18n.py
index 2031be307..ade8584b1 100644
--- a/src/mailman/testing/i18n.py
+++ b/src/mailman/testing/i18n.py
@@ -20,8 +20,8 @@
from contextlib import closing
from flufl.i18n import registry
from gettext import GNUTranslations, NullTranslations
-from mailman import public
from pkg_resources import resource_stream
+from public import public
class TestingStrategy:
diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py
index 3157809e6..67fb4f5e1 100644
--- a/src/mailman/testing/layers.py
+++ b/src/mailman/testing/layers.py
@@ -32,7 +32,6 @@ import datetime
import tempfile
from lazr.config import as_boolean
-from mailman import public
from mailman.config import config
from mailman.core import initialize
from mailman.core.initialize import INHIBIT_CONFIG_FILE
@@ -44,6 +43,7 @@ from mailman.testing.helpers import (
from mailman.testing.mta import ConnectionCountingController
from mailman.utilities.string import expand
from pkg_resources import resource_string as resource_bytes
+from public import public
from textwrap import dedent
from zope.component import getUtility
diff --git a/src/mailman/testing/mta.py b/src/mailman/testing/mta.py
index 81e4b8a62..d94466428 100644
--- a/src/mailman/testing/mta.py
+++ b/src/mailman/testing/mta.py
@@ -24,8 +24,8 @@ import smtplib
from aiosmtpd.controller import Controller
from aiosmtpd.handlers import Message as MessageHandler
from aiosmtpd.smtp import SMTP
-from mailman import public
from mailman.interfaces.mta import IMailTransportAgentLifecycle
+from public import public
from queue import Empty, Queue
from zope.interface import implementer
diff --git a/src/mailman/testing/nose.py b/src/mailman/testing/nose.py
deleted file mode 100644
index bbd361390..000000000
--- a/src/mailman/testing/nose.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright (C) 2013-2016 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""nose2 test infrastructure."""
-
-import os
-import re
-import doctest
-import importlib
-
-from mailman import public
-from mailman.testing.documentation import setup, teardown
-from mailman.testing.layers import ConfigLayer, MockAndMonkeyLayer, SMTPLayer
-from nose2.events import Plugin
-from pkg_resources import resource_filename
-
-
-DOT = '.'
-FLAGS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
-TOPDIR = os.path.dirname(resource_filename('mailman', '__init__.py'))
-
-
-@public
-class NosePlugin(Plugin):
- configSection = 'mailman'
-
- def __init__(self):
- super().__init__()
- self.patterns = []
- self.stderr = False
- def set_stderr(ignore): # noqa: E306
- self.stderr = True
- self.addArgument(self.patterns, 'P', 'pattern',
- 'Add a test matching pattern')
- self.addFlag(set_stderr, 'E', 'stderr',
- 'Enable stderr logging to sub-runners')
-
- def startTestRun(self, event):
- MockAndMonkeyLayer.testing_mode = True
- if (self.stderr or
- len(os.environ.get('MM_VERBOSE_TESTLOG', '').strip()) > 0):
- ConfigLayer.stderr = True
-
- def getTestCaseNames(self, event):
- if len(self.patterns) == 0:
- # No filter patterns, so everything should be tested.
- return
- # Does the pattern match the fully qualified class name?
- for pattern in self.patterns:
- full_class_name = '{}.{}'.format(
- event.testCase.__module__, event.testCase.__name__)
- if re.search(pattern, full_class_name):
- # Don't suppress this test class.
- return
- names = filter(event.isTestMethod, dir(event.testCase))
- for name in names:
- full_test_name = '{}.{}.{}'.format(
- event.testCase.__module__,
- event.testCase.__name__,
- name)
- for pattern in self.patterns:
- if re.search(pattern, full_test_name):
- break
- else:
- event.excludedNames.append(name)
-
- def handleFile(self, event):
- path = event.path[len(TOPDIR)+1:]
- if len(self.patterns) > 0:
- for pattern in self.patterns:
- if re.search(pattern, path):
- break
- else:
- # Skip this doctest.
- return
- base, ext = os.path.splitext(path)
- if ext != '.rst':
- return
- # Look to see if the package defines a test layer, otherwise use the
- # default layer. First turn the file system path into a dotted Python
- # module path.
- parent = os.path.dirname(path)
- dotted = 'mailman.' + DOT.join(parent.split(os.path.sep))
- try:
- module = importlib.import_module(dotted)
- except ImportError:
- layer = SMTPLayer
- else:
- layer = getattr(module, 'layer', SMTPLayer)
- test = doctest.DocFileTest(
- path, package='mailman',
- optionflags=FLAGS,
- setUp=setup,
- tearDown=teardown)
- test.layer = layer
- # Suppress the extra "Doctest: ..." line.
- test.shortDescription = lambda: None
- event.extraTests.append(test)
-
- # def startTest(self, event):
- # import sys; print('vvvvv', event.test, file=sys.stderr)
-
- # def stopTest(self, event):
- # import sys; print('^^^^^', event.test, file=sys.stderr)
diff --git a/src/mailman/testing/testing.cfg b/src/mailman/testing/testing.cfg
index 022f9f289..8b6a48c36 100644
--- a/src/mailman/testing/testing.cfg
+++ b/src/mailman/testing/testing.cfg
@@ -65,7 +65,7 @@ max_restarts: 1
max_restarts: 1
[archiver.prototype]
-enable: yes
+enable: no
[archiver.mail_archive]
enable: yes
diff --git a/src/mailman/utilities/datetime.py b/src/mailman/utilities/datetime.py
index 9bb772b3f..2915080e8 100644
--- a/src/mailman/utilities/datetime.py
+++ b/src/mailman/utilities/datetime.py
@@ -24,8 +24,8 @@ instrumented for testing purposes.
import datetime
-from mailman import public
from mailman.testing import layers
+from public import public
# Python always sets the locale to 'C' locale unless the user explicitly calls
diff --git a/src/mailman/utilities/email.py b/src/mailman/utilities/email.py
index e870117ac..546a7de61 100644
--- a/src/mailman/utilities/email.py
+++ b/src/mailman/utilities/email.py
@@ -19,7 +19,7 @@
from base64 import b32encode
from hashlib import sha1
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/utilities/filesystem.py b/src/mailman/utilities/filesystem.py
index e89f2abb8..7dcf2bb80 100644
--- a/src/mailman/utilities/filesystem.py
+++ b/src/mailman/utilities/filesystem.py
@@ -20,7 +20,7 @@
import os
from contextlib import suppress
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/utilities/i18n.py b/src/mailman/utilities/i18n.py
index 1df8ede7e..a658c231b 100644
--- a/src/mailman/utilities/i18n.py
+++ b/src/mailman/utilities/i18n.py
@@ -21,11 +21,11 @@ import os
import sys
from itertools import product
-from mailman import public
from mailman.config import config
from mailman.core.constants import system_preferences
from mailman.interfaces.errors import MailmanError
from pkg_resources import resource_filename
+from public import public
@public
diff --git a/src/mailman/utilities/importer.py b/src/mailman/utilities/importer.py
index 00c30c9f0..c8348a681 100644
--- a/src/mailman/utilities/importer.py
+++ b/src/mailman/utilities/importer.py
@@ -23,7 +23,6 @@ import sys
import logging
import datetime
-from mailman import public
from mailman.config import config
from mailman.handlers.decorate import decorate_template
from mailman.interfaces.action import Action, FilterAction
@@ -44,6 +43,7 @@ from mailman.interfaces.template import ITemplateManager
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.filesystem import makedirs
from mailman.utilities.i18n import search
+from public import public
from sqlalchemy import Boolean
from zope.component import getUtility
@@ -336,7 +336,7 @@ def import_config_pck(mlist, config_dict):
for line_pattern in line_patterns.splitlines():
if len(line_pattern.strip()) == 0:
continue
- for sep in (': ', ':.', ':'):
+ for sep in (': ', ':.*', ':.', ':'):
header, sep, pattern = line_pattern.partition(sep)
if sep:
# We found it.
diff --git a/src/mailman/utilities/interact.py b/src/mailman/utilities/interact.py
index fec980b80..48f3ae358 100644
--- a/src/mailman/utilities/interact.py
+++ b/src/mailman/utilities/interact.py
@@ -22,7 +22,8 @@ import sys
import code
from contextlib import suppress
-from mailman import public
+from inspect import signature
+from public import public
DEFAULT_BANNER = object()
@@ -67,4 +68,10 @@ def interact(upframe=True, banner=DEFAULT_BANNER, overrides=None):
Python %s on %s
Type "help", "copyright", "credits" or "license" for more information.''' % (
sys.version, sys.platform)
- interp.interact(banner)
+ # Python 3.6 added an exitmsg keyword but we don't currently support
+ # configuring it. For consistency between Python 3.6 and earlier
+ # versions, suppress the exit message if possible.
+ kws = dict(banner=banner)
+ if 'exitmsg' in signature(interp.interact).parameters:
+ kws['exitmsg'] = ''
+ interp.interact(**kws)
diff --git a/src/mailman/utilities/mailbox.py b/src/mailman/utilities/mailbox.py
index b799babea..19146e036 100644
--- a/src/mailman/utilities/mailbox.py
+++ b/src/mailman/utilities/mailbox.py
@@ -23,8 +23,9 @@
# get its size. MMDF is slightly more sane than mbox; it's primary advantage
# for us is that it does no 'From' mangling.
# mangling.
+
from mailbox import MMDF
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/utilities/modules.py b/src/mailman/utilities/modules.py
index b16aa45e5..83063a3f0 100644
--- a/src/mailman/utilities/modules.py
+++ b/src/mailman/utilities/modules.py
@@ -20,8 +20,8 @@
import os
import sys
-from mailman import public
from pkg_resources import resource_filename, resource_listdir
+from public import public
@public
diff --git a/src/mailman/utilities/options.py b/src/mailman/utilities/options.py
index 1c0064260..9e1e698a7 100644
--- a/src/mailman/utilities/options.py
+++ b/src/mailman/utilities/options.py
@@ -21,12 +21,12 @@ import os
import sys
from copy import copy
-from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.initialize import initialize
from mailman.version import MAILMAN_VERSION
from optparse import Option, OptionParser, OptionValueError
+from public import public
def check_unicode(option, opt, value):
diff --git a/src/mailman/utilities/passwords.py b/src/mailman/utilities/passwords.py
index 5597e2556..7bf18b93a 100644
--- a/src/mailman/utilities/passwords.py
+++ b/src/mailman/utilities/passwords.py
@@ -17,10 +17,10 @@
"""A wrapper around passlib."""
-from mailman import public
from mailman.config.config import load_external
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
from passlib.context import CryptContext
+from public import public
class PasswordContext:
diff --git a/src/mailman/utilities/protocols.py b/src/mailman/utilities/protocols.py
index 5f447c465..43d43a8bc 100644
--- a/src/mailman/utilities/protocols.py
+++ b/src/mailman/utilities/protocols.py
@@ -19,10 +19,10 @@
import requests
-from mailman import public
from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.listmanager import IListManager
from mailman.utilities.i18n import TemplateNotFoundError, find
+from public import public
from urllib.error import URLError
from urllib.parse import urlparse
from zope.component import getUtility
diff --git a/src/mailman/utilities/queries.py b/src/mailman/utilities/queries.py
index e27ae9a17..cd6542270 100644
--- a/src/mailman/utilities/queries.py
+++ b/src/mailman/utilities/queries.py
@@ -18,7 +18,7 @@
"""Some helpers for queries."""
from collections.abc import Sequence
-from mailman import public
+from public import public
@public
diff --git a/src/mailman/utilities/string.py b/src/mailman/utilities/string.py
index 2694877ee..fecadc444 100644
--- a/src/mailman/utilities/string.py
+++ b/src/mailman/utilities/string.py
@@ -21,8 +21,8 @@ import logging
from email.errors import HeaderParseError
from email.header import decode_header, make_header
-from mailman import public
from mailman.config import config
+from public import public
from string import Template, whitespace
from textwrap import TextWrapper, dedent
diff --git a/src/mailman/utilities/tests/test_import.py b/src/mailman/utilities/tests/test_import.py
index ca3a4afb7..62985545f 100644
--- a/src/mailman/utilities/tests/test_import.py
+++ b/src/mailman/utilities/tests/test_import.py
@@ -65,6 +65,7 @@ def list_to_string(data):
class TestBasicImport(unittest.TestCase):
layer = ConfigLayer
+ maxDiff = None
def setUp(self):
self._mlist = create_list('blank@example.com')
@@ -322,12 +323,12 @@ class TestBasicImport(unittest.TestCase):
SubscriptionPolicy.confirm_then_moderate)
def test_header_matches(self):
- # This test contail real cases of header_filter_rules
+ # This test containes real cases of header_filter_rules.
self._pckdict['header_filter_rules'] = [
('X\\-Spam\\-Status\\: Yes.*', 3, False),
('^X-Spam-Status: Yes\r\n\r\n', 2, False),
('^X-Spam-Level: \\*\\*\\*.*$', 3, False),
- ('^X-Spam-Level:.\\*\\*\r\n^X-Spam:.\\Yes', 3, False),
+ ('^X-Spam-Level:.\\*\\*\r\n^X-Spam:.Yes', 3, False),
('Subject: \\[SPAM\\].*', 3, False),
('^Subject: .*loan.*', 3, False),
('Original-Received: from *linkedin.com*\r\n', 3, False),
@@ -336,6 +337,7 @@ class TestBasicImport(unittest.TestCase):
('^Subject: dev-\r\n^Subject: staging-', 3, False),
('from: .*info@aolanchem.com\r\nfrom: .*@jw-express.com',
2, False),
+ ('^Subject:.*\\Wwas:\\W', 3, False),
('^Received: from smtp-.*\\.fedoraproject\\.org\r\n'
'^Received: from mx.*\\.redhat.com\r\n'
'^Resent-date:\r\n'
@@ -362,7 +364,7 @@ class TestBasicImport(unittest.TestCase):
('x-spam-status', 'Yes', 'reject'),
('x-spam-level', '\\*\\*\\*.*$', 'discard'),
('x-spam-level', '\\*\\*', 'discard'),
- ('x-spam', '\\Yes', 'discard'),
+ ('x-spam', 'Yes', 'discard'),
('subject', '\\[SPAM\\].*', 'discard'),
('subject', '.*loan.*', 'discard'),
('original-received', 'from *linkedin.com*', 'discard'),
@@ -372,6 +374,7 @@ class TestBasicImport(unittest.TestCase):
('subject', 'staging-', 'discard'),
('from', '.*info@aolanchem.com', 'reject'),
('from', '.*@jw-express.com', 'reject'),
+ ('subject', '\\Wwas:\\W', 'discard'),
('received', 'from smtp-.*\\.fedoraproject\\.org', 'hold'),
('received', 'from mx.*\\.redhat.com', 'hold'),
('resent-date', '.*', 'hold'),
diff --git a/src/mailman/utilities/tests/test_modules.py b/src/mailman/utilities/tests/test_modules.py
index 8e144e60b..d34a99910 100644
--- a/src/mailman/utilities/tests/test_modules.py
+++ b/src/mailman/utilities/tests/test_modules.py
@@ -67,7 +67,7 @@ class TestModuleImports(unittest.TestCase):
Path(init_file).touch()
with open(good_file, 'w', encoding='utf-8') as fp:
print("""\
-from mailman import public
+from public import public
from mailman.interfaces.styles import IStyle
from zope.interface import implementer
@@ -80,7 +80,7 @@ class GoodStyle:
""", file=fp)
with open(bad_file, 'w', encoding='utf-8') as fp:
print("""\
-from mailman import public
+from public import public
from mailman.interfaces.styles import IStyle
from zope.interface import implementer
diff --git a/src/mailman/utilities/uid.py b/src/mailman/utilities/uid.py
index 4389bcd92..9abf92e90 100644
--- a/src/mailman/utilities/uid.py
+++ b/src/mailman/utilities/uid.py
@@ -29,10 +29,10 @@ import hashlib
from contextlib import suppress
from flufl.lock import Lock
-from mailman import public
from mailman.config import config
from mailman.model.uid import UID
from mailman.testing import layers
+from public import public
class _PredictableIDGenerator: