diff options
Diffstat (limited to 'src/mailman/testing')
| -rw-r--r-- | src/mailman/testing/documentation.py | 2 | ||||
| -rw-r--r-- | src/mailman/testing/flake8.py | 141 | ||||
| -rw-r--r-- | src/mailman/testing/helpers.py | 10 | ||||
| -rw-r--r-- | src/mailman/testing/i18n.py | 2 | ||||
| -rw-r--r-- | src/mailman/testing/layers.py | 2 | ||||
| -rw-r--r-- | src/mailman/testing/mta.py | 2 | ||||
| -rw-r--r-- | src/mailman/testing/nose.py | 118 |
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) |
