summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/languages/language.py2
-rw-r--r--src/mailman/tests/test_configfile.py13
-rw-r--r--src/mailman/utilities/datetime.py27
-rw-r--r--src/mailman/utilities/email.py11
-rw-r--r--src/mailman/utilities/filesystem.py12
-rw-r--r--src/mailman/utilities/i18n.py16
-rw-r--r--src/mailman/utilities/importer.py30
-rw-r--r--src/mailman/utilities/interact.py12
-rw-r--r--src/mailman/utilities/mailbox.py8
-rw-r--r--src/mailman/utilities/modules.py22
-rw-r--r--src/mailman/utilities/options.py13
-rw-r--r--src/mailman/utilities/passwords.py9
-rw-r--r--src/mailman/utilities/queries.py7
-rw-r--r--src/mailman/utilities/string.py18
-rw-r--r--src/mailman/utilities/tests/test_email.py9
-rw-r--r--src/mailman/utilities/tests/test_import.py149
-rw-r--r--src/mailman/utilities/tests/test_passwords.py6
-rw-r--r--src/mailman/utilities/tests/test_queries.py5
-rw-r--r--src/mailman/utilities/tests/test_string.py6
-rw-r--r--src/mailman/utilities/tests/test_templates.py36
-rw-r--r--src/mailman/utilities/tests/test_uid.py8
-rw-r--r--src/mailman/utilities/tests/test_wrap.py6
-rw-r--r--src/mailman/utilities/uid.py12
-rw-r--r--tox.ini2
24 files changed, 152 insertions, 287 deletions
diff --git a/src/mailman/languages/language.py b/src/mailman/languages/language.py
index 2b58180ed..014852c5c 100644
--- a/src/mailman/languages/language.py
+++ b/src/mailman/languages/language.py
@@ -31,7 +31,7 @@ class Language:
def __init__(self, code, charset, description):
self.code = code
self.charset = charset
- self.description = description
+ self.description = description
def __str__(self):
return '<Language [{0.code}] {0.description}>'.format(self)
diff --git a/src/mailman/tests/test_configfile.py b/src/mailman/tests/test_configfile.py
index 5b146e5d2..79adcdd3e 100644
--- a/src/mailman/tests/test_configfile.py
+++ b/src/mailman/tests/test_configfile.py
@@ -17,13 +17,6 @@
"""Test configuration file searching."""
-__all__ = [
- 'TestConfigFileBase',
- 'TestConfigFileSearch',
- 'TestConfigFileSearchWithChroot',
- ]
-
-
import os
import sys
import shutil
@@ -34,7 +27,6 @@ from contextlib import contextmanager
from mailman.core.initialize import search_for_configuration_file
-
# Here are a couple of context managers that make our tests easier to read.
@contextmanager
def fakedirs(path):
@@ -82,7 +74,6 @@ def argv0(new_argv0):
sys.argv[0] = old_argv0
-
class TestConfigFileBase(unittest.TestCase):
"""Common test infrastructure."""
@@ -106,7 +97,6 @@ class TestConfigFileBase(unittest.TestCase):
return os.path.join(self._root, path)
-
class TestConfigFileSearch(TestConfigFileBase):
"""Test various aspects of searching for configuration files.
@@ -128,7 +118,6 @@ class TestConfigFileSearch(TestConfigFileBase):
self.assertEqual(found, config_file)
-
class TestConfigFileSearchWithChroot(TestConfigFileBase):
"""Like `TestConfigFileSearch` but with a special os.path.exists()."""
@@ -140,7 +129,7 @@ class TestConfigFileSearchWithChroot(TestConfigFileBase):
# system that we can write to and test is to hack os.path.exists() to
# prepend a temporary directory onto the path it tests.
self._os_path_exists = os.path.exists
- def exists(path):
+ def exists(path): # flake8: noqa
# Strip off the leading slash, otherwise we'll end up with path.
return self._os_path_exists(self._make_fake(path))
os.path.exists = exists
diff --git a/src/mailman/utilities/datetime.py b/src/mailman/utilities/datetime.py
index 56a5a146c..ba7ce9de2 100644
--- a/src/mailman/utilities/datetime.py
+++ b/src/mailman/utilities/datetime.py
@@ -22,19 +22,9 @@ datetime.datetime.now() and datetime.date.today(). These are better
instrumented for testing purposes.
"""
-__all__ = [
- 'DateFactory',
- 'RFC822_DATE_FMT',
- 'UTC',
- 'factory',
- 'now',
- 'today',
- 'utc',
- ]
-
-
import datetime
+from mailman import public
from mailman.testing import layers
@@ -43,26 +33,31 @@ from mailman.testing import layers
# no library better do it either!) this will safely give us expected RFC 5322
# Date headers.
RFC822_DATE_FMT = '%a, %d %b %Y %H:%M:%S %z'
+__all__ = ['RFC822_DATE_FMT']
-
# Definition of UTC timezone, taken from
# http://docs.python.org/library/datetime.html
ZERO = datetime.timedelta(0)
+
+@public
class UTC(datetime.tzinfo):
def utcoffset(self, dt):
return ZERO
+
def tzname(self, dt):
return 'UTC'
+
def dst(self, dt):
return ZERO
+
utc = UTC()
+__all__.append('utc')
_missing = object()
-
class DateFactory:
"""A factory for today() and now() that works with testing."""
@@ -107,3 +102,9 @@ factory.reset()
today = factory.today
now = factory.now
layers.MockAndMonkeyLayer.register_reset(factory.reset)
+
+__all__.extend([
+ 'factory',
+ 'now',
+ 'today',
+ ])
diff --git a/src/mailman/utilities/email.py b/src/mailman/utilities/email.py
index 546187f2a..e870117ac 100644
--- a/src/mailman/utilities/email.py
+++ b/src/mailman/utilities/email.py
@@ -17,18 +17,12 @@
"""Email helpers."""
-__all__ = [
- 'add_message_hash',
- 'split_email',
- ]
-
-
from base64 import b32encode
from hashlib import sha1
+from mailman import public
-
-
+@public
def split_email(address):
"""Split an email address into a user name and domain.
@@ -45,6 +39,7 @@ def split_email(address):
return local_part, domain.split('.')
+@public
def add_message_hash(msg):
"""Add a Message-ID-Hash header derived from Message-ID.
diff --git a/src/mailman/utilities/filesystem.py b/src/mailman/utilities/filesystem.py
index a20672f95..e8935b92c 100644
--- a/src/mailman/utilities/filesystem.py
+++ b/src/mailman/utilities/filesystem.py
@@ -17,17 +17,13 @@
"""Filesystem utilities."""
-__all__ = [
- 'makedirs',
- 'umask',
- ]
-
-
import os
import errno
+from mailman import public
+
-
+@public
class umask:
"""Manage the umask for the with statement."""
@@ -46,7 +42,7 @@ class umask:
return False
-
+@public
def makedirs(path, mode=0o2775):
"""Create a directory hierarchy, ensuring permissions.
diff --git a/src/mailman/utilities/i18n.py b/src/mailman/utilities/i18n.py
index 3999af869..e289a92be 100644
--- a/src/mailman/utilities/i18n.py
+++ b/src/mailman/utilities/i18n.py
@@ -17,18 +17,11 @@
"""i18n template search and interpolation."""
-__all__ = [
- 'TemplateNotFoundError',
- 'find',
- 'make',
- 'search',
- ]
-
-
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.core.i18n import _
@@ -37,7 +30,7 @@ from mailman.utilities.string import expand, wrap as wrap_text
from pkg_resources import resource_filename
-
+@public
class TemplateNotFoundError(MailmanError):
"""The named template was not found."""
@@ -48,7 +41,7 @@ class TemplateNotFoundError(MailmanError):
return self.template_file
-
+@public
def search(template_file, mlist=None, language=None):
"""Generator that provides file system search order.
@@ -132,7 +125,7 @@ def search(template_file, mlist=None, language=None):
yield os.path.join(templates_dir, 'en', template_file)
-
+@public
def find(template_file, mlist=None, language=None, _trace=False):
"""Use Mailman's internal template search order to find a template.
@@ -168,6 +161,7 @@ def find(template_file, mlist=None, language=None, _trace=False):
raise TemplateNotFoundError(template_file)
+@public
def make(template_file, mlist=None, language=None, wrap=True,
_trace=False, **kw):
"""Locate and 'make' a template file.
diff --git a/src/mailman/utilities/importer.py b/src/mailman/utilities/importer.py
index 3d1a8b82f..acd673c7d 100644
--- a/src/mailman/utilities/importer.py
+++ b/src/mailman/utilities/importer.py
@@ -17,12 +17,6 @@
"""Importer routines."""
-__all__ = [
- 'Import21Error',
- 'import_config_pck',
- ]
-
-
import os
import re
import sys
@@ -30,6 +24,7 @@ import codecs
import logging
import datetime
+from mailman import public
from mailman.config import config
from mailman.handlers.decorate import decorate, decorate_template
from mailman.interfaces.action import Action, FilterAction
@@ -57,12 +52,11 @@ from zope.component import getUtility
log = logging.getLogger('mailman.error')
-
+@public
class Import21Error(MailmanError):
"""An import from a Mailman 2.1 list failed."""
-
def bytes_to_str(value):
# Convert a string to unicode when the encoding is not declared.
if not isinstance(value, bytes):
@@ -94,7 +88,6 @@ def list_members_to_unicode(value):
return [bytes_to_str(item) for item in value]
-
def filter_action_mapping(value):
# The filter_action enum values have changed. In Mailman 2.1 the order
# was 'Discard', 'Reject', 'Forward to List Owner', 'Preserve'. In MM3
@@ -137,17 +130,16 @@ def action_to_chain(value):
# a jump to a terminal chain.
return {
0: None,
- #1: 'approve',
+ # 1: 'approve',
2: 'reject',
3: 'discard',
- #4: 'subscribe',
- #5: 'unsubscribe',
+ # 4: 'subscribe',
+ # 5: 'unsubscribe',
6: 'accept',
7: 'hold',
}[value]
-
def check_language_code(code):
if code is None:
return None
@@ -168,7 +160,6 @@ enabled: yes
return code
-
# Attributes in Mailman 2 which have a different type in Mailman 3. Some
# types (e.g. bools) are autodetected from their SA column types.
TYPES = dict(
@@ -233,7 +224,7 @@ EXCLUDES = set((
))
-
+@public
def import_config_pck(mlist, config_dict):
"""Apply a config.pck configuration dictionary to a mailing list.
@@ -431,7 +422,7 @@ def import_config_pck(mlist, config_dict):
text = text.decode('utf-8', 'replace')
for oldph, newph in convert_placeholders:
text = text.replace(oldph, newph)
- default_value, default_text = defaults.get(newvar, (None, None))
+ default_value, default_text = defaults.get(newvar, (None, None))
if not text and not (default_value or default_text):
# Both are empty, leave it.
continue
@@ -448,8 +439,8 @@ def import_config_pck(mlist, config_dict):
'with value "{}"'.format(text),
file=sys.stderr)
continue
- if (expanded_text and default_text
- and expanded_text.strip() == default_text.strip()):
+ if (expanded_text and default_text and
+ expanded_text.strip() == default_text.strip()):
# Keep the default.
continue
# Write the custom value to the right file.
@@ -494,7 +485,6 @@ def import_config_pck(mlist, config_dict):
mlist.send_welcome_message = send_welcome_message
-
def import_roster(mlist, config_dict, members, role, action=None):
"""Import members lists from a config.pck configuration dictionary.
@@ -562,7 +552,7 @@ def import_roster(mlist, config_dict, members, role, action=None):
if email in config_dict.get('usernames', {}):
address.display_name = \
bytes_to_str(config_dict['usernames'][email])
- user.display_name = \
+ user.display_name = \
bytes_to_str(config_dict['usernames'][email])
if email in config_dict.get('passwords', {}):
user.password = config.password_context.encrypt(
diff --git a/src/mailman/utilities/interact.py b/src/mailman/utilities/interact.py
index 03df69855..609fe78fb 100644
--- a/src/mailman/utilities/interact.py
+++ b/src/mailman/utilities/interact.py
@@ -17,19 +17,17 @@
"""Provide an interactive prompt, mimicking the Python interpreter."""
-__all__ = [
- 'interact',
- ]
-
-
import os
import sys
import code
+from mailman import public
+
+
DEFAULT_BANNER = ''
-
+@public
def interact(upframe=True, banner=DEFAULT_BANNER, overrides=None):
"""Start an interactive interpreter prompt.
@@ -54,7 +52,7 @@ def interact(upframe=True, banner=DEFAULT_BANNER, overrides=None):
interp = code.InteractiveConsole(namespace)
# Try to import the readline module, but don't worry if it's unavailable.
try:
- import readline
+ import readline # flake8: noqa
except ImportError:
pass
# Mimic the real interactive interpreter's loading of any $PYTHONSTARTUP
diff --git a/src/mailman/utilities/mailbox.py b/src/mailman/utilities/mailbox.py
index e3630a1ff..b799babea 100644
--- a/src/mailman/utilities/mailbox.py
+++ b/src/mailman/utilities/mailbox.py
@@ -17,11 +17,6 @@
"""MMDF helper for digests."""
-__all__ = [
- 'Mailbox',
- ]
-
-
# Use a single file format for the digest mailbox because this makes it easier
# to calculate the current size of the mailbox. This way, we don't have to
# carry around or store the size of the mailbox, we can just stat the file to
@@ -29,9 +24,10 @@ __all__ = [
# for us is that it does no 'From' mangling.
# mangling.
from mailbox import MMDF
+from mailman import public
-
+@public
class Mailbox(MMDF):
"""A mailbox that interoperates with the 'with' statement."""
diff --git a/src/mailman/utilities/modules.py b/src/mailman/utilities/modules.py
index 4a506321e..88639a881 100644
--- a/src/mailman/utilities/modules.py
+++ b/src/mailman/utilities/modules.py
@@ -17,22 +17,14 @@
"""Package and module utilities."""
-__all__ = [
- 'call_name',
- 'expand_path',
- 'find_components',
- 'find_name',
- 'scan_module',
- ]
-
-
import os
import sys
+from mailman import public
from pkg_resources import resource_filename, resource_listdir
-
+@public
def find_name(dotted_name):
"""Import and return the named object in package space.
@@ -46,7 +38,7 @@ def find_name(dotted_name):
return getattr(sys.modules[package_path], object_name)
-
+@public
def call_name(dotted_name, *args, **kws):
"""Imports and calls the named object in package space.
@@ -63,7 +55,7 @@ def call_name(dotted_name, *args, **kws):
return named_callable(*args, **kws)
-
+@public
def scan_module(module, interface):
"""Return all the items in a module that conform to an interface.
@@ -83,7 +75,7 @@ def scan_module(module, interface):
yield component
-
+@public
def find_components(package, interface):
"""Find components which conform to a given interface.
@@ -101,7 +93,7 @@ def find_components(package, interface):
basename, extension = os.path.splitext(filename)
if extension != '.py':
continue
- module_name = '{0}.{1}'.format(package, basename)
+ module_name = '{}.{}'.format(package, basename)
__import__(module_name, fromlist='*')
module = sys.modules[module_name]
if not hasattr(module, '__all__'):
@@ -109,7 +101,7 @@ def find_components(package, interface):
yield from scan_module(module, interface)
-
+@public
def expand_path(url):
"""Expand a python: path, returning the absolute file system path."""
# Is the context coming from a file system or Python path?
diff --git a/src/mailman/utilities/options.py b/src/mailman/utilities/options.py
index 96d37fb36..1c0064260 100644
--- a/src/mailman/utilities/options.py
+++ b/src/mailman/utilities/options.py
@@ -17,15 +17,11 @@
"""Common argument parsing."""
-__all__ = [
- 'Options',
- ]
-
-
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
@@ -33,7 +29,6 @@ from mailman.version import MAILMAN_VERSION
from optparse import Option, OptionParser, OptionValueError
-
def check_unicode(option, opt, value):
"""Check that the value is a unicode string."""
if not isinstance(value, bytes):
@@ -42,14 +37,14 @@ def check_unicode(option, opt, value):
return value.decode(sys.getdefaultencoding())
except UnicodeDecodeError:
raise OptionValueError(
- 'option {0}: Cannot decode: {1}'.format(opt, value))
+ 'option {}: Cannot decode: {}'.format(opt, value))
def check_yesno(option, opt, value):
"""Check that the value is 'yes' or 'no'."""
value = value.lower()
if value not in ('yes', 'no', 'y', 'n'):
- raise OptionValueError('option {0}: invalid: {1}'.format(opt, value))
+ raise OptionValueError('option {}: invalid: {}'.format(opt, value))
return value[0] == 'y'
@@ -85,7 +80,7 @@ class SafeOptionParser(OptionParser):
return OptionParser.add_option(self, *new_args, **kwargs)
-
+@public
class Options:
"""Common argument parser."""
diff --git a/src/mailman/utilities/passwords.py b/src/mailman/utilities/passwords.py
index a0135187a..5597e2556 100644
--- a/src/mailman/utilities/passwords.py
+++ b/src/mailman/utilities/passwords.py
@@ -17,17 +17,12 @@
"""A wrapper around passlib."""
-__all__ = [
- 'handle_ConfigurationUpdatedEvent',
- ]
-
-
+from mailman import public
from mailman.config.config import load_external
from mailman.interfaces.configuration import ConfigurationUpdatedEvent
from passlib.context import CryptContext
-
class PasswordContext:
def __init__(self, config):
"""Create a password context for hashing and verification.
@@ -66,7 +61,7 @@ class PasswordContext:
return self._context.verify_and_update(password, hashed)
-
+@public
def handle_ConfigurationUpdatedEvent(event):
if isinstance(event, ConfigurationUpdatedEvent):
# Just reset the password context.
diff --git a/src/mailman/utilities/queries.py b/src/mailman/utilities/queries.py
index 1a35e35fe..e27ae9a17 100644
--- a/src/mailman/utilities/queries.py
+++ b/src/mailman/utilities/queries.py
@@ -17,14 +17,11 @@
"""Some helpers for queries."""
-__all__ = [
- 'QuerySequence',
- ]
-
-
from collections.abc import Sequence
+from mailman import public
+@public
class QuerySequence(Sequence):
"""A simple wrapper class around database query results.
diff --git a/src/mailman/utilities/string.py b/src/mailman/utilities/string.py
index bf32016de..8394aa5e6 100644
--- a/src/mailman/utilities/string.py
+++ b/src/mailman/utilities/string.py
@@ -17,17 +17,11 @@
"""String utilities."""
-__all__ = [
- 'expand',
- 'oneline',
- 'wrap',
- ]
-
-
import logging
from email.errors import HeaderParseError
from email.header import decode_header, make_header
+from mailman import public
from string import Template, whitespace
from textwrap import TextWrapper, dedent
@@ -38,7 +32,7 @@ NL = '\n'
log = logging.getLogger('mailman.error')
-
+@public
def expand(template, substitutions, template_class=Template):
"""Expand string template with substitutions.
@@ -54,7 +48,7 @@ def expand(template, substitutions, template_class=Template):
return template_class(template).safe_substitute(substitutions)
-
+@public
def oneline(s, cset='us-ascii', in_unicode=False):
"""Decode a header string in one line and convert into specified charset.
@@ -81,7 +75,7 @@ def oneline(s, cset='us-ascii', in_unicode=False):
return EMPTYSTRING.join(s.splitlines())
-
+@public
def wrap(text, column=70, honor_leading_ws=True):
"""Wrap and fill the text to the specified column.
@@ -156,8 +150,8 @@ def wrap(text, column=70, honor_leading_ws=True):
if ch not in whitespace:
break
leading_ws = paragraph[:i]
- iwrapper.initial_indent=leading_ws
- iwrapper.subsequent_indent=leading_ws
+ iwrapper.initial_indent = leading_ws
+ iwrapper.subsequent_indent = leading_ws
paragraph_text = dedent(paragraph_text)
wrapped_paragraphs.append(iwrapper.fill(paragraph_text))
add_paragraph_break = True
diff --git a/src/mailman/utilities/tests/test_email.py b/src/mailman/utilities/tests/test_email.py
index d5bc5a560..36ffa7535 100644
--- a/src/mailman/utilities/tests/test_email.py
+++ b/src/mailman/utilities/tests/test_email.py
@@ -17,12 +17,6 @@
"""Testing functions in the email utilities."""
-__all__ = [
- 'TestEmail',
- 'TestMessageIDHash',
- ]
-
-
import unittest
from mailman.interfaces.messages import IMessageStore
@@ -33,7 +27,6 @@ from mailman.utilities.email import add_message_hash, split_email
from zope.component import getUtility
-
class TestEmail(unittest.TestCase):
"""Testing functions in the email utilities."""
@@ -119,9 +112,7 @@ Message-ID: aardvark>
self.assertEqual(hash32, '5KH3RA7ZM4VM6XOZXA7AST2XN2X4S3WY')
-
class TestMessageIDHash(unittest.TestCase):
-
layer = ConfigLayer
def setUp(self):
diff --git a/src/mailman/utilities/tests/test_import.py b/src/mailman/utilities/tests/test_import.py
index 68a005760..637f78585 100644
--- a/src/mailman/utilities/tests/test_import.py
+++ b/src/mailman/utilities/tests/test_import.py
@@ -17,17 +17,6 @@
"""Tests for config.pck imports."""
-__all__ = [
- 'TestArchiveImport',
- 'TestBasicImport',
- 'TestConvertToURI',
- 'TestFilterActionImport',
- 'TestMemberActionImport',
- 'TestPreferencesImport',
- 'TestRosterImport',
- ]
-
-
import os
import unittest
@@ -61,7 +50,6 @@ from unittest import mock
from zope.component import getUtility
-
NL = '\n'
@@ -74,7 +62,6 @@ def list_to_string(data):
return NL.join(data).encode('utf-8')
-
class TestBasicImport(unittest.TestCase):
layer = ConfigLayer
@@ -148,9 +135,9 @@ class TestBasicImport(unittest.TestCase):
self.assertEqual(self._mlist.autoresponse_owner_text, '')
def test_administrativia(self):
- self._mlist.administrivia = None
- self._import()
- self.assertTrue(self._mlist.administrivia)
+ self._mlist.administrivia = None
+ self._import()
+ self.assertTrue(self._mlist.administrivia)
def test_filter_pass_renames(self):
# mime_types -> types
@@ -164,8 +151,9 @@ class TestBasicImport(unittest.TestCase):
self.assertEqual(list(self._mlist.filter_extensions),
['exe', 'bat', 'cmd', 'com', 'pif',
'scr', 'vbs', 'cpl'])
- self.assertEqual(list(self._mlist.pass_types),
- ['multipart/mixed', 'multipart/alternative', 'text/plain'])
+ self.assertEqual(
+ list(self._mlist.pass_types),
+ ['multipart/mixed', 'multipart/alternative', 'text/plain'])
self.assertEqual(list(self._mlist.pass_extensions), [])
def test_process_bounces(self):
@@ -249,7 +237,7 @@ class TestBasicImport(unittest.TestCase):
def test_acceptable_aliases_as_list(self):
# In some versions of the pickle, this can be a list, not a string
# (seen in the wild).
- aliases = [b'alias1@example.com', b'alias2@exemple.com' ]
+ aliases = [b'alias1@example.com', b'alias2@exemple.com']
self._pckdict['acceptable_aliases'] = aliases
self._import()
alias_set = IAcceptableAliasSet(self._mlist)
@@ -368,40 +356,40 @@ class TestBasicImport(unittest.TestCase):
self._import()
self.assertListEqual(
[(hm.header, hm.pattern, hm.chain)
- for hm in self._mlist.header_matches ], [
- ('x-spam-status', 'Yes.*', 'discard'),
- ('x-spam-status', 'Yes', 'reject'),
- ('x-spam-level', '\\*\\*\\*.*$', 'discard'),
- ('x-spam-level', '\\*\\*', 'discard'),
- ('x-spam', '\\Yes', 'discard'),
- ('subject', '\\[SPAM\\].*', 'discard'),
- ('subject', '.*loan.*', 'discard'),
- ('original-received', 'from *linkedin.com*', 'discard'),
- ('x-git-module', 'rhq.*git', 'accept'),
- ('approved', 'verysecretpassword', 'accept'),
- ('subject', 'dev-', 'discard'),
- ('subject', 'staging-', 'discard'),
- ('from', '.*info@aolanchem.com', 'reject'),
- ('from', '.*@jw-express.com', 'reject'),
- ('received', 'from smtp-.*\\.fedoraproject\\.org', 'hold'),
- ('received', 'from mx.*\\.redhat.com', 'hold'),
- ('resent-date', '.*', 'hold'),
- ('resent-from', '.*', 'hold'),
- ('resent-message-id', '.*', 'hold'),
- ('resent-to', '.*', 'hold'),
- ('subject', '[^mtv]', 'hold'),
- ('received', 'from fedorahosted\\.org.*by fedorahosted\\.org',
- 'accept'),
- ('received',
- 'from hosted.*\\.fedoraproject.org.*by '
- 'hosted.*\\.fedoraproject\\.org', 'accept'),
- ('received',
- 'from hosted.*\\.fedoraproject.org.*by '
- 'fedoraproject\\.org', 'accept'),
- ('received',
- 'from hosted.*\\.fedoraproject.org.*by '
- 'fedorahosted\\.org', 'accept'),
- ])
+ for hm in self._mlist.header_matches], [
+ ('x-spam-status', 'Yes.*', 'discard'),
+ ('x-spam-status', 'Yes', 'reject'),
+ ('x-spam-level', '\\*\\*\\*.*$', 'discard'),
+ ('x-spam-level', '\\*\\*', 'discard'),
+ ('x-spam', '\\Yes', 'discard'),
+ ('subject', '\\[SPAM\\].*', 'discard'),
+ ('subject', '.*loan.*', 'discard'),
+ ('original-received', 'from *linkedin.com*', 'discard'),
+ ('x-git-module', 'rhq.*git', 'accept'),
+ ('approved', 'verysecretpassword', 'accept'),
+ ('subject', 'dev-', 'discard'),
+ ('subject', 'staging-', 'discard'),
+ ('from', '.*info@aolanchem.com', 'reject'),
+ ('from', '.*@jw-express.com', 'reject'),
+ ('received', 'from smtp-.*\\.fedoraproject\\.org', 'hold'),
+ ('received', 'from mx.*\\.redhat.com', 'hold'),
+ ('resent-date', '.*', 'hold'),
+ ('resent-from', '.*', 'hold'),
+ ('resent-message-id', '.*', 'hold'),
+ ('resent-to', '.*', 'hold'),
+ ('subject', '[^mtv]', 'hold'),
+ ('received', 'from fedorahosted\\.org.*by fedorahosted\\.org',
+ 'accept'),
+ ('received',
+ 'from hosted.*\\.fedoraproject.org.*by '
+ 'hosted.*\\.fedoraproject\\.org', 'accept'),
+ ('received',
+ 'from hosted.*\\.fedoraproject.org.*by '
+ 'fedoraproject\\.org', 'accept'),
+ ('received',
+ 'from hosted.*\\.fedoraproject.org.*by '
+ 'fedorahosted\\.org', 'accept'),
+ ])
loglines = error_log.read().strip()
self.assertEqual(len(loglines), 0)
@@ -484,7 +472,6 @@ class TestBasicImport(unittest.TestCase):
error_log.readline())
-
class TestArchiveImport(unittest.TestCase):
"""Test conversion of the archive policies.
@@ -537,7 +524,6 @@ class TestArchiveImport(unittest.TestCase):
self._do_test(dict(archive=True), ArchivePolicy.private)
-
class TestFilterActionImport(unittest.TestCase):
# The mlist.filter_action enum values have changed. In Mailman 2.1 the
# order was 'Discard', 'Reject', 'Forward to List Owner', 'Preserve'.
@@ -565,7 +551,6 @@ class TestFilterActionImport(unittest.TestCase):
self._do_test(3, FilterAction.preserve)
-
class TestMemberActionImport(unittest.TestCase):
# The mlist.default_member_action and mlist.default_nonmember_action enum
# values are different in Mailman 2.1; they have been merged into a
@@ -637,7 +622,6 @@ class TestMemberActionImport(unittest.TestCase):
self._do_test(dict(default_nonmember_action=Action.discard))
-
class TestConvertToURI(unittest.TestCase):
# The following values were plain text, and are now URIs in Mailman 3:
# - welcome_message_uri
@@ -673,9 +657,10 @@ class TestConvertToURI(unittest.TestCase):
import_config_pck(self._mlist, self._pckdict)
newattr = getattr(self._mlist, newvar)
text = decorate(self._mlist, newattr)
- self.assertEqual(text, 'TEST VALUE',
- 'Old variable %s was not properly imported to %s'
- % (oldvar, newvar))
+ self.assertEqual(
+ text, 'TEST VALUE',
+ 'Old variable %s was not properly imported to %s'
+ % (oldvar, newvar))
def test_substitutions(self):
test_text = ('UNIT TESTING %(real_name)s mailing list\n'
@@ -712,8 +697,9 @@ class TestConvertToURI(unittest.TestCase):
old_value = getattr(self._mlist, newvar)
import_config_pck(self._mlist, self._pckdict)
new_value = getattr(self._mlist, newvar)
- self.assertEqual(old_value, new_value,
- 'Default value was not preserved for %s' % newvar)
+ self.assertEqual(
+ old_value, new_value,
+ 'Default value was not preserved for %s' % newvar)
def test_keep_default_if_fqdn_changed(self):
# Use case: importing the old a@ex.com into b@ex.com. We can't check
@@ -729,7 +715,8 @@ class TestConvertToURI(unittest.TestCase):
with mock.patch('sys.stderr'):
import_config_pck(self._mlist, self._pckdict)
new_value = getattr(self._mlist, newvar)
- self.assertEqual(old_value, new_value,
+ self.assertEqual(
+ old_value, new_value,
'Default value was not preserved for %s' % newvar)
def test_unicode(self):
@@ -758,7 +745,7 @@ class TestConvertToURI(unittest.TestCase):
text = decorate(self._mlist, self._mlist.footer_uri)
self.assertEqual(text, 'NEW-VALUE')
-
+
class TestRosterImport(unittest.TestCase):
"""Test that rosters are imported correctly."""
@@ -776,22 +763,23 @@ class TestRosterImport(unittest.TestCase):
'dave@example.com': b'dave@ExampLe.Com',
},
'passwords': {
- 'anne@example.com' : b'annepass',
- 'bob@example.com' : b'bobpass',
+ 'anne@example.com': b'annepass',
+ 'bob@example.com': b'bobpass',
'cindy@example.com': b'cindypass',
- 'dave@example.com' : b'davepass',
+ 'dave@example.com': b'davepass',
},
'language': {
- 'anne@example.com' : b'fr',
- 'bob@example.com' : b'de',
+ 'anne@example.com': b'fr',
+ 'bob@example.com': b'de',
'cindy@example.com': b'es',
- 'dave@example.com' : b'it',
+ 'dave@example.com': b'it',
},
- 'usernames': { # Usernames are unicode strings in the pickle
- 'anne@example.com' : 'Anne',
- 'bob@example.com' : 'Bob',
+ # Usernames are unicode strings in the pickle
+ 'usernames': {
+ 'anne@example.com': 'Anne',
+ 'bob@example.com': 'Bob',
'cindy@example.com': 'Cindy',
- 'dave@example.com' : 'Dave',
+ 'dave@example.com': 'Dave',
},
'owner': [
'anne@example.com',
@@ -878,9 +866,11 @@ class TestRosterImport(unittest.TestCase):
self.assertIsNotNone(user, 'User %s was not imported' % addr)
self.assertIsNotNone(address, 'Address %s was not imported' % addr)
display_name = self._pckdict['usernames'][addr]
- self.assertEqual(user.display_name, display_name,
+ self.assertEqual(
+ user.display_name, display_name,
'The display name was not set for User %s' % addr)
- self.assertEqual(address.display_name, display_name,
+ self.assertEqual(
+ address.display_name, display_name,
'The display name was not set for Address %s' % addr)
def test_owner(self):
@@ -907,7 +897,7 @@ class TestRosterImport(unittest.TestCase):
'Address fred@ was wrongly added to the members list')
def test_password(self):
- #self.anne.password = config.password_context.encrypt('abc123')
+ # self.anne.password = config.password_context.encrypt('abc123')
import_config_pck(self._mlist, self._pckdict)
for name in ('anne', 'bob', 'cindy', 'dave'):
addr = '%s@example.com' % name
@@ -920,7 +910,7 @@ class TestRosterImport(unittest.TestCase):
def test_same_user(self):
# Adding the address of an existing User must not create another user.
user = self._usermanager.create_user('anne@example.com', 'Anne')
- user.register('bob@example.com') # secondary email
+ user.register('bob@example.com') # secondary email
import_config_pck(self._mlist, self._pckdict)
member = self._mlist.members.get_member('bob@example.com')
self.assertEqual(member.user, user)
@@ -1023,7 +1013,6 @@ class TestRosterImport(unittest.TestCase):
self.assertTrue(all(addr.startswith('^') for addr in list_prop))
-
class TestPreferencesImport(unittest.TestCase):
"""Preferences get imported too."""
@@ -1124,7 +1113,7 @@ class TestPreferencesImport(unittest.TestCase):
def test_no_moderate(self):
# If option flag Moderate is not set, action is accept
- self._pckdict['member_moderation_action'] = 1 # reject
+ self._pckdict['member_moderation_action'] = 1 # reject
self._do_test(0, dict(moderation_action=Action.accept))
def test_multiple_options(self):
diff --git a/src/mailman/utilities/tests/test_passwords.py b/src/mailman/utilities/tests/test_passwords.py
index 326e1ac08..15f307007 100644
--- a/src/mailman/utilities/tests/test_passwords.py
+++ b/src/mailman/utilities/tests/test_passwords.py
@@ -17,11 +17,6 @@
"""Testing the password utility."""
-__all__ = [
- 'TestPasswords',
- ]
-
-
import os
import unittest
@@ -30,7 +25,6 @@ from mailman.testing.helpers import configuration
from mailman.testing.layers import ConfigLayer
-
class TestPasswords(unittest.TestCase):
layer = ConfigLayer
diff --git a/src/mailman/utilities/tests/test_queries.py b/src/mailman/utilities/tests/test_queries.py
index 39ab7de61..e5b0a7836 100644
--- a/src/mailman/utilities/tests/test_queries.py
+++ b/src/mailman/utilities/tests/test_queries.py
@@ -17,11 +17,6 @@
"""Test queries."""
-__all__ = [
- 'TestQueries',
- ]
-
-
import unittest
from mailman.utilities.queries import QuerySequence
diff --git a/src/mailman/utilities/tests/test_string.py b/src/mailman/utilities/tests/test_string.py
index ea3b94ee4..14beead0a 100644
--- a/src/mailman/utilities/tests/test_string.py
+++ b/src/mailman/utilities/tests/test_string.py
@@ -17,17 +17,11 @@
"""Test the string utilities."""
-__all__ = [
- 'TestString',
- ]
-
-
import unittest
from mailman.utilities import string
-
class TestString(unittest.TestCase):
def test_oneline_bogus_charset(self):
self.assertEqual(string.oneline('foo', 'bogus'), 'foo')
diff --git a/src/mailman/utilities/tests/test_templates.py b/src/mailman/utilities/tests/test_templates.py
index f4b581b90..9fb0aaa16 100644
--- a/src/mailman/utilities/tests/test_templates.py
+++ b/src/mailman/utilities/tests/test_templates.py
@@ -17,13 +17,6 @@
"""Testing i18n template search and interpolation."""
-__all__ = [
- 'TestFind',
- 'TestMake',
- 'TestSearchOrder',
- ]
-
-
import os
import shutil
import tempfile
@@ -38,7 +31,6 @@ from pkg_resources import resource_filename
from zope.component import getUtility
-
class TestSearchOrder(unittest.TestCase):
"""Test internal search order for language templates."""
@@ -51,7 +43,7 @@ class TestSearchOrder(unittest.TestCase):
[mailman]
default_language: fr
[paths.testing]
- var_dir: {0}
+ var_dir: {}
""".format(self.var_dir))
self.addCleanup(config.pop, 'no template dir')
self.mlist = create_list('l@example.com')
@@ -85,7 +77,7 @@ class TestSearchOrder(unittest.TestCase):
def test_fully_specified_search_order(self):
search_order = self._stripped_search_order('foo.txt', self.mlist, 'it')
# For convenience.
- def nexteq(path):
+ def nexteq(path): # flake8: noqa
self.assertEqual(next(search_order), path)
# 1: Use the given language argument
nexteq('/v/templates/lists/l.example.com/it/foo.txt')
@@ -115,7 +107,7 @@ class TestSearchOrder(unittest.TestCase):
def test_no_language_argument_search_order(self):
search_order = self._stripped_search_order('foo.txt', self.mlist)
# For convenience.
- def nexteq(path):
+ def nexteq(path): # flakeq: noqa
self.assertEqual(next(search_order), path)
# 1: Use mlist.preferred_language
nexteq('/v/templates/lists/l.example.com/de/foo.txt')
@@ -140,7 +132,7 @@ class TestSearchOrder(unittest.TestCase):
def test_no_mailing_list_argument_search_order(self):
search_order = self._stripped_search_order('foo.txt', language='it')
# For convenience.
- def nexteq(path):
+ def nexteq(path): # flake8: noqa
self.assertEqual(next(search_order), path)
# 1: Use the given language argument
nexteq('/v/templates/site/it/foo.txt')
@@ -156,7 +148,7 @@ class TestSearchOrder(unittest.TestCase):
def test_no_optional_arguments_search_order(self):
search_order = self._stripped_search_order('foo.txt')
# For convenience.
- def nexteq(path):
+ def nexteq(path): # flake8: noqa
self.assertEqual(next(search_order), path)
# 1: Use the site's default language
nexteq('/v/templates/site/fr/foo.txt')
@@ -168,7 +160,6 @@ class TestSearchOrder(unittest.TestCase):
nexteq('/m/templates/en/foo.txt')
-
class TestFind(unittest.TestCase):
"""Test template search."""
@@ -176,10 +167,12 @@ class TestFind(unittest.TestCase):
def setUp(self):
self.var_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.var_dir)
config.push('template config', """\
[paths.testing]
- var_dir: {0}
+ var_dir: {}
""".format(self.var_dir))
+ self.addCleanup(config.pop, 'template config')
# The following MUST happen AFTER the push() above since pushing a new
# config also clears out the language manager.
getUtility(ILanguageManager).add('xx', 'utf-8', 'Xlandia')
@@ -187,7 +180,7 @@ class TestFind(unittest.TestCase):
self.mlist.preferred_language = 'xx'
self.fp = None
# Populate the template directories with a few fake templates.
- def write(text, path):
+ def write(text, path): # flake8: noqa
os.makedirs(os.path.dirname(path))
with open(path, 'w') as fp:
fp.write(text)
@@ -206,8 +199,6 @@ class TestFind(unittest.TestCase):
def tearDown(self):
if self.fp is not None:
self.fp.close()
- config.pop('template config')
- shutil.rmtree(self.var_dir)
def test_find_site_template(self):
filename, self.fp = find('site.txt', language='xx')
@@ -230,7 +221,6 @@ class TestFind(unittest.TestCase):
self.assertEqual(cm.exception.template_file, 'missing.txt')
-
class TestMake(unittest.TestCase):
"""Test template interpolation."""
@@ -238,10 +228,12 @@ class TestMake(unittest.TestCase):
def setUp(self):
self.var_dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.var_dir)
config.push('template config', """\
[paths.testing]
- var_dir: {0}
+ var_dir: {}
""".format(self.var_dir))
+ self.addCleanup(config.pop, 'template config')
# The following MUST happen AFTER the push() above since pushing a new
# config also clears out the language manager.
getUtility(ILanguageManager).add('xx', 'utf-8', 'Xlandia')
@@ -269,10 +261,6 @@ It has $howmany substitutions.
It will not be wrapped.
""", file=fp)
- def tearDown(self):
- config.pop('template config')
- shutil.rmtree(self.var_dir)
-
def test_no_substitutions(self):
self.assertEqual(make('nosub.txt', self.mlist), """\
This is a global template. It has no substitutions. It will be
diff --git a/src/mailman/utilities/tests/test_uid.py b/src/mailman/utilities/tests/test_uid.py
index dce63caf3..0ee53a211 100644
--- a/src/mailman/utilities/tests/test_uid.py
+++ b/src/mailman/utilities/tests/test_uid.py
@@ -17,11 +17,6 @@
"""Test the uid module."""
-__all__ = [
- 'TestUID',
- ]
-
-
import os
import uuid
import unittest
@@ -33,7 +28,6 @@ from mailman.utilities import uid
from unittest.mock import patch
-
class TestUID(unittest.TestCase):
layer = ConfigLayer
@@ -60,7 +54,7 @@ class TestUID(unittest.TestCase):
def test_uid_record_try_again(self):
called = False
- def record_second(ignore):
+ def record_second(ignore): # flake8: noqa
nonlocal called
if not called:
called = True
diff --git a/src/mailman/utilities/tests/test_wrap.py b/src/mailman/utilities/tests/test_wrap.py
index bcb44eece..f34627694 100644
--- a/src/mailman/utilities/tests/test_wrap.py
+++ b/src/mailman/utilities/tests/test_wrap.py
@@ -17,17 +17,11 @@
"""Test text wrapping."""
-__all__ = [
- 'TestWrap',
- ]
-
-
import unittest
from mailman.utilities.string import wrap
-
class TestWrap(unittest.TestCase):
"""Test text wrapping."""
diff --git a/src/mailman/utilities/uid.py b/src/mailman/utilities/uid.py
index e49b3d8dd..cef0ebc87 100644
--- a/src/mailman/utilities/uid.py
+++ b/src/mailman/utilities/uid.py
@@ -21,12 +21,6 @@ Use these functions to create unique ids rather than inlining calls to hashlib
and whatnot. These are better instrumented for testing purposes.
"""
-__all__ = [
- 'UIDFactory',
- 'TokenFactory',
- ]
-
-
import os
import time
import uuid
@@ -34,12 +28,12 @@ import random
import hashlib
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
-
class _PredictableIDGenerator:
"""Base class factory.
@@ -119,7 +113,7 @@ class _PredictableIDGenerator:
fp.write('1')
-
+@public
class UIDFactory(_PredictableIDGenerator):
"""A factory for unique ids."""
@@ -143,7 +137,7 @@ class UIDFactory(_PredictableIDGenerator):
return uuid.UUID(int=uid)
-
+@public
class TokenFactory(_PredictableIDGenerator):
def __init__(self):
diff --git a/tox.ini b/tox.ini
index b5c501246..b1166bdc1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -32,4 +32,4 @@ rc = --rcfile={[coverage]rcfile}
[flake8]
max-line-length = 79
-exclude = src/mailman/compat/*.py \ No newline at end of file
+exclude = src/mailman/compat/*.py