summaryrefslogtreecommitdiff
path: root/src/mailman/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/testing')
-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
7 files changed, 13 insertions, 264 deletions
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)