summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman/testing/documentation.py12
-rw-r--r--src/mailman/testing/helpers.py66
-rw-r--r--src/mailman/testing/i18n.py10
-rw-r--r--src/mailman/testing/layers.py27
-rw-r--r--src/mailman/testing/mta.py11
-rw-r--r--src/mailman/testing/nose.py20
6 files changed, 47 insertions, 99 deletions
diff --git a/src/mailman/testing/documentation.py b/src/mailman/testing/documentation.py
index ccc34de1f..f3a6e335a 100644
--- a/src/mailman/testing/documentation.py
+++ b/src/mailman/testing/documentation.py
@@ -21,13 +21,8 @@ Note that doctest extraction does not currently work for zip file
distributions. doctest discovery currently requires file system traversal.
"""
-__all__ = [
- 'setup',
- 'teardown'
- ]
-
-
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, specialized_message_from_string
@@ -38,7 +33,6 @@ DOT = '.'
COMMASPACE = ', '
-
def stop():
"""Call into pdb.set_trace()"""
# Do the import here so that you get the wacky special hacked pdb instead
@@ -138,7 +132,7 @@ def dump_json(url, data=None, method=None, username=None, password=None):
print('{}: {}'.format(key, value))
-
+@public
def setup(testobj):
"""Test setup."""
# In general, I don't like adding convenience functions, since I think
@@ -159,7 +153,7 @@ def setup(testobj):
testobj.globs['cleanups'] = []
-
+@public
def teardown(testobj):
for cleanup in testobj.globs['cleanups']:
if isfunction(cleanup) or ismethod(cleanup):
diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py
index e0d46cd20..302198396 100644
--- a/src/mailman/testing/helpers.py
+++ b/src/mailman/testing/helpers.py
@@ -17,28 +17,6 @@
"""Various test helpers."""
-__all__ = [
- 'LogFileMark',
- 'TestableMaster',
- 'call_api',
- 'chdir',
- 'configuration',
- 'digest_mbox',
- 'event_subscribers',
- 'get_lmtp_client',
- 'get_nntp_server',
- 'get_queue_messages',
- 'make_digest_messages',
- 'make_testable_runner',
- 'reset_the_world',
- 'set_preferred',
- 'specialized_message_from_string',
- 'subscribe',
- 'temporary_db',
- 'wait_for_webservice',
- ]
-
-
import os
import json
import time
@@ -57,6 +35,7 @@ from contextlib import contextmanager
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
@@ -77,7 +56,7 @@ from zope.component import getUtility
NL = '\n'
-
+@public
def make_testable_runner(runner_class, name=None, predicate=None):
"""Create a runner that runs until its queue is empty.
@@ -115,13 +94,13 @@ def make_testable_runner(runner_class, name=None, predicate=None):
return EmptyingRunner(name)
-
class _Bag:
def __init__(self, **kws):
for key, value in kws.items():
setattr(self, key, value)
+@public
def get_queue_messages(queue_name, sort_on=None, expected_count=None):
"""Return and clear all the messages in the given queue.
@@ -147,7 +126,7 @@ def get_queue_messages(queue_name, sort_on=None, expected_count=None):
return messages
-
+@public
def digest_mbox(mlist):
"""The mailing list's pending digest as a mailbox.
@@ -158,8 +137,8 @@ def digest_mbox(mlist):
return Mailbox(path)
-
# Remember, Master is mailman.bin.master.Loop.
+@public
class TestableMaster(Master):
"""A testable master loop watcher."""
@@ -228,7 +207,6 @@ class TestableMaster(Master):
yield from self._started_kids
-
class LMTP(smtplib.SMTP):
"""Like a normal SMTP client, but for LMTP."""
def lhlo(self, name=''):
@@ -238,12 +216,13 @@ class LMTP(smtplib.SMTP):
return code, msg
+@public
def get_lmtp_client(quiet=False):
"""Return a connected LMTP client."""
# It's possible the process has started but is not yet accepting
# connections. Wait a little while.
lmtp = LMTP()
- #lmtp.debuglevel = 1
+ # lmtp.debuglevel = 1
until = datetime.datetime.now() + as_timedelta(config.devmode.wait)
while datetime.datetime.now() < until:
try:
@@ -261,7 +240,7 @@ def get_lmtp_client(quiet=False):
raise RuntimeError('Connection refused')
-
+@public
def get_nntp_server(cleanups):
"""Create and start an NNTP server mock.
@@ -272,14 +251,14 @@ def get_nntp_server(cleanups):
cleanups.append(patcher.stop)
nntpd = server_class()
# A class for more convenient access to the posted message.
- class NNTPProxy:
+ class NNTPProxy: # flake8: noqa
def get_message(self):
args = nntpd.post.call_args
return specialized_message_from_string(args[0][0].read())
return NNTPProxy()
-
+@public
def wait_for_webservice():
"""Wait for the REST server to start serving requests."""
until = datetime.datetime.now() + as_timedelta(config.devmode.wait)
@@ -298,6 +277,7 @@ def wait_for_webservice():
raise RuntimeError('Connection refused')
+@public
def call_api(url, data=None, method=None, username=None, password=None):
"""'Call a URL with a given HTTP method and return the resulting object.
@@ -351,7 +331,7 @@ def call_api(url, data=None, method=None, username=None, password=None):
return json.loads(content), response
-
+@public
@contextmanager
def event_subscribers(*subscribers):
"""Temporarily extend the Zope event subscribers list.
@@ -368,7 +348,7 @@ def event_subscribers(*subscribers):
event.subscribers[:] = old_subscribers
-
+@public
class configuration:
"""A decorator/context manager for temporarily setting configurations."""
@@ -410,7 +390,7 @@ class configuration:
return wrapper
-
+@public
@contextmanager
def temporary_db(db):
real_db = config.db
@@ -421,7 +401,7 @@ def temporary_db(db):
config.db = real_db
-
+@public
class chdir:
"""A context manager for temporary directory changing."""
def __init__(self, directory):
@@ -438,16 +418,16 @@ class chdir:
return False
-
+@public
def subscribe(mlist, first_name, role=MemberRole.member, email=None):
"""Helper for subscribing a sample person to a mailing list.
Returns the newly created member object.
"""
user_manager = getUtility(IUserManager)
- email = ('{0}person@example.com'.format(first_name[0].lower())
+ email = ('{}person@example.com'.format(first_name[0].lower())
if email is None else email)
- full_name = '{0} Person'.format(first_name)
+ full_name = '{} Person'.format(first_name)
with transaction():
person = user_manager.get_user(email)
if person is None:
@@ -464,7 +444,7 @@ def subscribe(mlist, first_name, role=MemberRole.member, email=None):
return roster.get_member(email)
-
+@public
def reset_the_world():
"""Reset everything:
@@ -504,7 +484,7 @@ def reset_the_world():
config.chains['header-match'].flush()
-
+@public
def specialized_message_from_string(unicode_text):
"""Parse text into a message object.
@@ -523,7 +503,7 @@ def specialized_message_from_string(unicode_text):
return message
-
+@public
class LogFileMark:
def __init__(self, log_name):
self._log = logging.getLogger(log_name)
@@ -541,7 +521,7 @@ class LogFileMark:
return fp.read()
-
+@public
def make_digest_messages(mlist, msg=None):
if msg is None:
msg = specialized_message_from_string("""\
@@ -562,7 +542,7 @@ message triggering a digest
runner.run()
-
+@public
def set_preferred(user):
# Avoid circular imports.
from mailman.utilities.datetime import now
diff --git a/src/mailman/testing/i18n.py b/src/mailman/testing/i18n.py
index 92189302c..2031be307 100644
--- a/src/mailman/testing/i18n.py
+++ b/src/mailman/testing/i18n.py
@@ -17,19 +17,13 @@
"""Internationalization for the tests."""
-__all__ = [
- 'TestingStrategy',
- 'initialize',
- ]
-
-
from contextlib import closing
from flufl.i18n import registry
from gettext import GNUTranslations, NullTranslations
+from mailman import public
from pkg_resources import resource_stream
-
class TestingStrategy:
"""A strategy that finds catalogs in the testing directory."""
@@ -44,7 +38,7 @@ class TestingStrategy:
return GNUTranslations(fp)
-
+@public
def initialize():
"""Install a global underscore function for testing purposes."""
# Avoid circular imports.
diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py
index 494aeb35a..c282689d1 100644
--- a/src/mailman/testing/layers.py
+++ b/src/mailman/testing/layers.py
@@ -24,16 +24,6 @@
# the full test run. For now, I'll ignore that, but I do want to eventually
# get rid of the layers and use something like testresources or some such.
-__all__ = [
- 'ConfigLayer',
- 'LMTPLayer',
- 'MockAndMonkeyLayer',
- 'RESTLayer',
- 'SMTPLayer',
- 'is_testing',
- ]
-
-
import os
import sys
import shutil
@@ -42,6 +32,7 @@ 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
@@ -61,7 +52,7 @@ TEST_TIMEOUT = datetime.timedelta(seconds=5)
NL = '\n'
-
+@public
class MockAndMonkeyLayer:
"""Layer for mocking and monkey patching for testing."""
@@ -81,7 +72,7 @@ class MockAndMonkeyLayer:
cls._resets.append(reset)
-
+@public
class ConfigLayer(MockAndMonkeyLayer):
"""Layer for pushing and popping test configurations."""
@@ -120,11 +111,11 @@ class ConfigLayer(MockAndMonkeyLayer):
[mailman]
layout: testing
[paths.testing]
- var_dir: {0}
+ var_dir: {}
[devmode]
testing: yes
[mta]
- configuration: {1}
+ configuration: {}
""".format(cls.var_dir, postfix_cfg))
# Read the testing config and push it.
more = resource_bytes('mailman.testing', 'testing.cfg')
@@ -228,7 +219,7 @@ class ConfigLayer(MockAndMonkeyLayer):
cls.root_directory = directory
-
+@public
class SMTPLayer(ConfigLayer):
"""Layer for starting, stopping, and accessing a test SMTP server."""
@@ -260,7 +251,7 @@ class SMTPLayer(ConfigLayer):
cls.smtpd.clear()
-
+@public
class LMTPLayer(ConfigLayer):
"""Layer for starting, stopping, and accessing a test LMTP server."""
@@ -289,7 +280,7 @@ class LMTPLayer(ConfigLayer):
pass
-
+@public
class RESTLayer(SMTPLayer):
"""Layer for starting, stopping, and accessing the test REST layer."""
@@ -308,7 +299,7 @@ class RESTLayer(SMTPLayer):
cls.server = None
-
+@public
def is_testing():
"""Return a 'testing' flag for use with the predictable factories.
diff --git a/src/mailman/testing/mta.py b/src/mailman/testing/mta.py
index 9642803e2..c1327f428 100644
--- a/src/mailman/testing/mta.py
+++ b/src/mailman/testing/mta.py
@@ -17,15 +17,11 @@
"""Fake MTA for testing purposes."""
-__all__ = [
- 'FakeMTA',
- ]
-
-
import logging
from lazr.smtptest.controller import QueueController
from lazr.smtptest.server import Channel, QueueServer
+from mailman import public
from mailman.interfaces.mta import IMailTransportAgentLifecycle
from queue import Empty, Queue
from zope.interface import implementer
@@ -34,7 +30,7 @@ from zope.interface import implementer
log = logging.getLogger('lazr.smtptest')
-
+@public
@implementer(IMailTransportAgentLifecycle)
class FakeMTA:
"""Fake MTA for testing purposes."""
@@ -49,7 +45,6 @@ class FakeMTA:
pass
-
class StatisticsChannel(Channel):
"""A channel that can answers to the fake STAT command."""
@@ -134,7 +129,6 @@ class StatisticsChannel(Channel):
super().found_terminator()
-
class ConnectionCountingServer(QueueServer):
"""Count the number of SMTP connections opened."""
@@ -210,7 +204,6 @@ class ConnectionCountingServer(QueueServer):
self._oob_queue.put(arg)
-
class ConnectionCountingController(QueueController):
"""Count the number of SMTP connections opened."""
diff --git a/src/mailman/testing/nose.py b/src/mailman/testing/nose.py
index c969f087d..0a5608c7a 100644
--- a/src/mailman/testing/nose.py
+++ b/src/mailman/testing/nose.py
@@ -17,16 +17,12 @@
"""nose2 test infrastructure."""
-__all__ = [
- 'NosePlugin',
- ]
-
-
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
@@ -38,7 +34,7 @@ FLAGS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
TOPDIR = os.path.dirname(resource_filename('mailman', '__init__.py'))
-
+@public
class NosePlugin(Plugin):
configSection = 'mailman'
@@ -46,7 +42,7 @@ class NosePlugin(Plugin):
super().__init__()
self.patterns = []
self.stderr = False
- def set_stderr(ignore):
+ def set_stderr(ignore): # flake8: noqa
self.stderr = True
self.addArgument(self.patterns, 'P', 'pattern',
'Add a test matching pattern')
@@ -55,7 +51,7 @@ class NosePlugin(Plugin):
def startTestRun(self, event):
MockAndMonkeyLayer.testing_mode = True
- if ( self.stderr or
+ if (self.stderr or
len(os.environ.get('MM_VERBOSE_TESTLOG', '').strip()) > 0):
ConfigLayer.stderr = True
@@ -115,8 +111,8 @@ class NosePlugin(Plugin):
test.shortDescription = lambda: None
event.extraTests.append(test)
- ## def startTest(self, event):
- ## import sys; print('vvvvv', event.test, file=sys.stderr)
+ # 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)
+ # def stopTest(self, event):
+ # import sys; print('^^^^^', event.test, file=sys.stderr)