diff options
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): @@ -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 |
