diff --git a/mypy/myunit/__init__.py b/mypy/myunit/__init__.py index 6ffa3293929f..fa4000266849 100644 --- a/mypy/myunit/__init__.py +++ b/mypy/myunit/__init__.py @@ -1,371 +1 @@ -import importlib -import os -import sys -import re -import tempfile -import time -import traceback - -from typing import List, Tuple, Any, Callable, Union, cast - - -# TODO remove global state -is_verbose = False -is_quiet = False -patterns = [] # type: List[str] -times = [] # type: List[Tuple[float, str]] -APPEND_TESTCASES = '' -UPDATE_TESTCASES = False - - -class AssertionFailure(Exception): - """Exception used to signal skipped test cases.""" - def __init__(self, s: str = None) -> None: - if s: - super().__init__(s) - else: - super().__init__() - - -class SkipTestCaseException(Exception): pass - - -def assert_true(b: bool, msg: str = None) -> None: - if not b: - raise AssertionFailure(msg) - - -def assert_false(b: bool, msg: str = None) -> None: - if b: - raise AssertionFailure(msg) - - -def good_repr(obj: object) -> str: - if isinstance(obj, str): - if obj.count('\n') > 1: - bits = ["'''\\"] - for line in obj.split('\n'): - # force repr to use ' not ", then cut it off - bits.append(repr('"' + line)[2:-1]) - bits[-1] += "'''" - return '\n'.join(bits) - return repr(obj) - - -def assert_equal(a: object, b: object, fmt: str = '{} != {}') -> None: - if a != b: - raise AssertionFailure(fmt.format(good_repr(a), good_repr(b))) - - -def assert_not_equal(a: object, b: object, fmt: str = '{} == {}') -> None: - if a == b: - raise AssertionFailure(fmt.format(good_repr(a), good_repr(b))) - - -def assert_raises(typ: type, *rest: Any) -> None: - """Usage: assert_raises(exception class[, message], function[, args]) - - Call function with the given arguments and expect an exception of the given - type. - - TODO use overloads for better type checking - """ - # Parse arguments. - msg = None # type: str - if isinstance(rest[0], str) or rest[0] is None: - msg = rest[0] - rest = rest[1:] - f = rest[0] - args = [] # type: List[Any] - if len(rest) > 1: - args = rest[1] - assert len(rest) <= 2 - - # Perform call and verify the exception. - try: - f(*args) - except Exception as e: - assert_type(typ, e) - if msg: - assert_equal(e.args[0], msg, 'Invalid message {}, expected {}') - else: - raise AssertionFailure('No exception raised') - - -def assert_type(typ: type, value: object) -> None: - if type(value) != typ: - raise AssertionFailure('Invalid type {}, expected {}'.format( - typename(type(value)), typename(typ))) - - -def fail() -> None: - raise AssertionFailure() - - -class TestCase: - def __init__(self, name: str, suite: 'Suite' = None, - func: Callable[[], None] = None) -> None: - self.func = func - self.name = name - self.suite = suite - self.old_cwd = None # type: str - self.tmpdir = None # type: tempfile.TemporaryDirectory - - def run(self) -> None: - if self.func: - self.func() - - def set_up(self) -> None: - self.old_cwd = os.getcwd() - self.tmpdir = tempfile.TemporaryDirectory(prefix='mypy-test-', - dir=os.path.abspath('tmp-test-dirs')) - os.chdir(self.tmpdir.name) - os.mkdir('tmp') - if self.suite: - self.suite.set_up() - - def tear_down(self) -> None: - if self.suite: - self.suite.tear_down() - os.chdir(self.old_cwd) - self.tmpdir.cleanup() - self.old_cwd = None - self.tmpdir = None - - -class Suite: - def __init__(self) -> None: - self.prefix = typename(type(self)) + '.' - # Each test case is either a TestCase object or (str, function). - self._test_cases = [] # type: List[Any] - self.init() - - def set_up(self) -> None: - pass - - def tear_down(self) -> None: - pass - - def init(self) -> None: - for m in dir(self): - if m.startswith('test'): - t = getattr(self, m) - if isinstance(t, Suite): - self.add_test((m + '.', t)) - else: - self.add_test(TestCase(m, self, getattr(self, m))) - - def add_test(self, test: Union[TestCase, - Tuple[str, Callable[[], None]], - Tuple[str, 'Suite']]) -> None: - self._test_cases.append(test) - - def cases(self) -> List[Any]: - return self._test_cases[:] - - def skip(self) -> None: - raise SkipTestCaseException() - - -def add_suites_from_module(suites: List[Suite], mod_name: str) -> None: - mod = importlib.import_module(mod_name) - got_suite = False - for suite in mod.__dict__.values(): - if isinstance(suite, type) and issubclass(suite, Suite) and suite is not Suite: - got_suite = True - suites.append(cast(Callable[[], Suite], suite)()) - if not got_suite: - # Sanity check in case e.g. it uses unittest instead of a myunit. - # The codecs tests do since they need to be python2-compatible. - sys.exit('Test module %s had no test!' % mod_name) - - -class ListSuite(Suite): - def __init__(self, suites: List[Suite]) -> None: - for suite in suites: - mod_name = type(suite).__module__.replace('.', '_') - mod_name = mod_name.replace('mypy_', '') - mod_name = mod_name.replace('test_', '') - mod_name = mod_name.strip('_').replace('__', '_') - type_name = type(suite).__name__ - name = 'test_%s_%s' % (mod_name, type_name) - setattr(self, name, suite) - super().__init__() - - -def main(args: List[str] = None) -> None: - global patterns, is_verbose, is_quiet - global APPEND_TESTCASES, UPDATE_TESTCASES - if not args: - args = sys.argv[1:] - is_verbose = False - is_quiet = False - suites = [] # type: List[Suite] - patterns = [] - i = 0 - while i < len(args): - a = args[i] - if a == '-v': - is_verbose = True - elif a == '-q': - is_quiet = True - elif a == '-u': - APPEND_TESTCASES = '.new' - UPDATE_TESTCASES = True - elif a == '-i': - APPEND_TESTCASES = '' - UPDATE_TESTCASES = True - elif a == '-m': - i += 1 - if i == len(args): - sys.exit('-m requires an argument') - add_suites_from_module(suites, args[i]) - elif not a.startswith('-'): - patterns.append(a) - else: - sys.exit('Usage: python -m mypy.myunit [-v] [-q] [-u | -i]' - + ' -m test.module [-m test.module ...] [filter ...]') - i += 1 - if len(patterns) == 0: - patterns.append('*') - if not suites: - sys.exit('At least one -m argument is required') - - t = ListSuite(suites) - num_total, num_fail, num_skip = run_test_recursive(t, 0, 0, 0, '', 0) - - skip_msg = '' - if num_skip > 0: - skip_msg = ', {} skipped'.format(num_skip) - - if num_fail == 0: - if not is_quiet: - print('%d test cases run%s, all passed.' % (num_total, skip_msg)) - print('*** OK ***') - else: - sys.stderr.write('%d/%d test cases failed%s.\n' % (num_fail, - num_total, - skip_msg)) - sys.stderr.write('*** FAILURE ***\n') - sys.exit(1) - - -def run_test_recursive(test: Any, num_total: int, num_fail: int, num_skip: int, - prefix: str, depth: int) -> Tuple[int, int, int]: - """The first argument may be TestCase, Suite or (str, Suite).""" - if isinstance(test, TestCase): - name = prefix + test.name - for pattern in patterns: - if match_pattern(name, pattern): - match = True - break - else: - match = False - if match: - is_fail, is_skip = run_single_test(name, test) - if is_fail: num_fail += 1 - if is_skip: num_skip += 1 - num_total += 1 - else: - suite = None # type: Suite - suite_prefix = '' - if isinstance(test, list) or isinstance(test, tuple): - suite = test[1] - suite_prefix = test[0] - else: - suite = test - suite_prefix = test.prefix - - for stest in suite.cases(): - new_prefix = prefix - if depth > 0: - new_prefix = prefix + suite_prefix - num_total, num_fail, num_skip = run_test_recursive( - stest, num_total, num_fail, num_skip, new_prefix, depth + 1) - return num_total, num_fail, num_skip - - -def run_single_test(name: str, test: Any) -> Tuple[bool, bool]: - if is_verbose: - sys.stderr.write(name) - sys.stderr.flush() - - time0 = time.time() - test.set_up() # FIX: check exceptions - exc_traceback = None # type: Any - try: - test.run() - except Exception: - exc_type, exc_value, exc_traceback = sys.exc_info() - test.tear_down() # FIX: check exceptions - times.append((time.time() - time0, name)) - - if exc_traceback: - if isinstance(exc_value, SkipTestCaseException): - if is_verbose: - sys.stderr.write(' (skipped)\n') - return False, True - else: - handle_failure(name, exc_type, exc_value, exc_traceback) - return True, False - elif is_verbose: - sys.stderr.write('\n') - - return False, False - - -def handle_failure(name, exc_type, exc_value, exc_traceback) -> None: - # Report failed test case. - if is_verbose: - sys.stderr.write('\n\n') - msg = '' - if exc_value.args and exc_value.args[0]: - msg = ': ' + str(exc_value) - else: - msg = '' - sys.stderr.write('Traceback (most recent call last):\n') - tb = traceback.format_tb(exc_traceback) - tb = clean_traceback(tb) - for s in tb: - sys.stderr.write(s) - exception = typename(exc_type) - sys.stderr.write('{}{}\n\n'.format(exception, msg)) - sys.stderr.write('{} failed\n\n'.format(name)) - - -def typename(t: type) -> str: - if '.' in str(t): - return str(t).split('.')[-1].rstrip("'>") - else: - return str(t)[8:-2] - - -def match_pattern(s: str, p: str) -> bool: - if len(p) == 0: - return len(s) == 0 - elif p[0] == '*': - if len(p) == 1: - return True - else: - for i in range(len(s) + 1): - if match_pattern(s[i:], p[1:]): - return True - return False - elif len(s) == 0: - return False - else: - return s[0] == p[0] and match_pattern(s[1:], p[1:]) - - -def clean_traceback(tb: List[str]) -> List[str]: - # Remove clutter from the traceback. - start = 0 - for i, s in enumerate(tb): - if '\n test.run()\n' in s or '\n self.func()\n' in s: - start = i + 1 - tb = tb[start:] - for f in ['assert_equal', 'assert_not_equal', 'assert_type', - 'assert_raises', 'assert_true']: - if tb != [] and ', in {}\n'.format(f) in tb[-1]: - tb = tb[:-1] - return tb +# This page intentionally left blank diff --git a/mypy/myunit/__main__.py b/mypy/myunit/__main__.py index 34098d40648d..de26b70e84d2 100644 --- a/mypy/myunit/__main__.py +++ b/mypy/myunit/__main__.py @@ -4,6 +4,6 @@ Usually used as a slave by runtests.py, but can be used directly. """ -from mypy.myunit import main +from mypy.myunit.main import main main() diff --git a/mypy/myunit/assertions.py b/mypy/myunit/assertions.py new file mode 100644 index 000000000000..f59413b6a90d --- /dev/null +++ b/mypy/myunit/assertions.py @@ -0,0 +1,30 @@ +def fail(msg: str = None) -> None: + from mypy.myunit.errors import AssertionFailure + raise AssertionFailure(msg) + + +def assert_true(b: bool, msg: str = None) -> None: + if not b: + fail(msg) + + +def assert_false(b: bool, msg: str = None) -> None: + if b: + fail(msg) + + +def _good_repr(obj: object) -> str: + if isinstance(obj, str): + if obj.count('\n') > 1: + bits = ["'''\\"] + for line in obj.split('\n'): + # force repr to use ' not ", then cut it off + bits.append(repr('"' + line)[2:-1]) + bits[-1] += "'''" + return '\n'.join(bits) + return repr(obj) + + +def assert_equal(a: object, b: object, fmt: str = '{} != {}') -> None: + if a != b: + fail(fmt.format(_good_repr(a), _good_repr(b))) diff --git a/mypy/myunit/errors.py b/mypy/myunit/errors.py new file mode 100644 index 000000000000..fc06d2a5bed6 --- /dev/null +++ b/mypy/myunit/errors.py @@ -0,0 +1,7 @@ +class MyunitException(Exception): pass + + +class AssertionFailure(MyunitException): pass + + +class SkipTestCaseException(MyunitException): pass diff --git a/mypy/myunit/ick.py b/mypy/myunit/ick.py new file mode 100644 index 000000000000..3c7ff591b79a --- /dev/null +++ b/mypy/myunit/ick.py @@ -0,0 +1,6 @@ +"""Ick, mutable globals! +""" + +# TODO remove global state +APPEND_TESTCASES = '' +UPDATE_TESTCASES = False diff --git a/mypy/myunit/main.py b/mypy/myunit/main.py new file mode 100644 index 000000000000..22a1d6255291 --- /dev/null +++ b/mypy/myunit/main.py @@ -0,0 +1,90 @@ +from typing import Callable, List, cast + +import importlib +import sys + +from mypy.myunit.suite import Suite +from mypy.myunit import ick +from mypy.myunit.run import run_test_recursive +from mypy.myunit import run + + +def add_suites_from_module(suites: List[Suite], mod_name: str) -> None: + mod = importlib.import_module(mod_name) + got_suite = False + for suite in mod.__dict__.values(): + if isinstance(suite, type) and issubclass(suite, Suite) and suite is not Suite: + got_suite = True + suites.append(cast(Callable[[], Suite], suite)()) + if not got_suite: + # Sanity check in case e.g. it uses unittest instead of a myunit. + # The codecs tests do since they need to be python2-compatible. + sys.exit('Test module %s had no test!' % mod_name) + + +class ListSuite(Suite): + def __init__(self, suites: List[Suite]) -> None: + for suite in suites: + mod_name = type(suite).__module__.replace('.', '_') + mod_name = mod_name.replace('mypy_', '') + mod_name = mod_name.replace('test_', '') + mod_name = mod_name.strip('_').replace('__', '_') + type_name = type(suite).__name__ + name = 'test_%s_%s' % (mod_name, type_name) + setattr(self, name, suite) + super().__init__() + + +def main(args: List[str] = None) -> None: + if not args: + args = sys.argv[1:] + run.is_verbose = False + run.is_quiet = False + suites = [] # type: List[Suite] + run.patterns = [] + i = 0 + while i < len(args): + a = args[i] + if a == '-v': + run.is_verbose = True + elif a == '-q': + run.is_quiet = True + elif a == '-u': + ick.APPEND_TESTCASES = '.new' + ick.UPDATE_TESTCASES = True + elif a == '-i': + ick.APPEND_TESTCASES = '' + ick.UPDATE_TESTCASES = True + elif a == '-m': + i += 1 + if i == len(args): + sys.exit('-m requires an argument') + add_suites_from_module(suites, args[i]) + elif not a.startswith('-'): + run.patterns.append(a) + else: + sys.exit('Usage: python -m mypy.myunit [-v] [-q] [-u | -i]' + + ' -m test.module [-m test.module ...] [filter ...]') + i += 1 + if len(run.patterns) == 0: + run.patterns.append('*') + if not suites: + sys.exit('At least one -m argument is required') + + t = ListSuite(suites) + num_total, num_fail, num_skip = run_test_recursive(t, 0, 0, 0, '', 0) + + skip_msg = '' + if num_skip > 0: + skip_msg = ', {} skipped'.format(num_skip) + + if num_fail == 0: + if not run.is_quiet: + print('%d test cases run%s, all passed.' % (num_total, skip_msg)) + print('*** OK ***') + else: + sys.stderr.write('%d/%d test cases failed%s.\n' % (num_fail, + num_total, + skip_msg)) + sys.stderr.write('*** FAILURE ***\n') + sys.exit(1) diff --git a/mypy/myunit/run.py b/mypy/myunit/run.py new file mode 100644 index 000000000000..4e21f5d15d4c --- /dev/null +++ b/mypy/myunit/run.py @@ -0,0 +1,123 @@ +from typing import Any, List, Tuple, Union, cast + +import sys +import traceback + +from mypy.myunit.errors import SkipTestCaseException +from mypy.myunit.suite import Suite, TestCase, TestUnion, typename + +# TODO remove global state +is_verbose = False +is_quiet = False +patterns = [] # type: List[str] + + +def run_test_recursive(test: Union[Suite, TestUnion], + num_total: int, num_fail: int, num_skip: int, + prefix: str, depth: int) -> Tuple[int, int, int]: + if isinstance(test, TestCase): + name = prefix + test.name + for pattern in patterns: + if match_pattern(name, pattern): + match = True + break + else: + match = False + if match: + is_fail, is_skip = run_single_test(name, test) + if is_fail: num_fail += 1 + if is_skip: num_skip += 1 + num_total += 1 + else: + suite = None # type: Suite + suite_prefix = '' + if isinstance(test, tuple): + suite_prefix, suite = cast(Tuple[str, Suite], test) + else: + suite = cast(Suite, test) + suite_prefix = suite.prefix + + for stest in suite.cases(): + new_prefix = prefix + if depth > 0: + new_prefix = prefix + suite_prefix + num_total, num_fail, num_skip = run_test_recursive( + stest, num_total, num_fail, num_skip, new_prefix, depth + 1) + return num_total, num_fail, num_skip + + +def run_single_test(name: str, test: TestCase) -> Tuple[bool, bool]: + if is_verbose: + sys.stderr.write(name) + sys.stderr.flush() + + test.set_up() # FIX: check exceptions + exc_traceback = None # type: Any + try: + test.run() + except Exception: + exc_type, exc_value, exc_traceback = sys.exc_info() + test.tear_down() # FIX: check exceptions + + if exc_traceback: + if isinstance(exc_value, SkipTestCaseException): + if is_verbose: + sys.stderr.write(' (skipped)\n') + return False, True + else: + handle_failure(name, exc_type, exc_value, exc_traceback) + return True, False + elif is_verbose: + sys.stderr.write('\n') + + return False, False + + +def handle_failure(name, exc_type, exc_value, exc_traceback) -> None: + # Report failed test case. + if is_verbose: + sys.stderr.write('\n\n') + msg = '' + if exc_value.args and exc_value.args[0]: + msg = ': ' + str(exc_value) + else: + msg = '' + sys.stderr.write('Traceback (most recent call last):\n') + tb = traceback.format_tb(exc_traceback) + tb = clean_traceback(tb) + for s in tb: + sys.stderr.write(s) + exception = typename(exc_type) + sys.stderr.write('{}{}\n\n'.format(exception, msg)) + sys.stderr.write('{} failed\n\n'.format(name)) + + +def match_pattern(s: str, p: str) -> bool: + if len(p) == 0: + return len(s) == 0 + elif p[0] == '*': + if len(p) == 1: + return True + else: + for i in range(len(s) + 1): + if match_pattern(s[i:], p[1:]): + return True + return False + elif len(s) == 0: + return False + else: + return s[0] == p[0] and match_pattern(s[1:], p[1:]) + + +def clean_traceback(tb: List[str]) -> List[str]: + # Remove clutter from the traceback. + start = 0 + for i, s in enumerate(tb): + if '\n test.run()\n' in s or '\n self.func()\n' in s: + start = i + 1 + tb = tb[start:] + for f in ['assert_equal', 'assert_not_equal', 'assert_type', + 'assert_raises', 'assert_true']: + if tb != [] and ', in {}\n'.format(f) in tb[-1]: + tb = tb[:-1] + return tb diff --git a/mypy/myunit/suite.py b/mypy/myunit/suite.py new file mode 100644 index 000000000000..fe2d1b94a4c4 --- /dev/null +++ b/mypy/myunit/suite.py @@ -0,0 +1,79 @@ +from typing import Callable, List, Tuple, Union + +import os +import tempfile + +from mypy.myunit.errors import SkipTestCaseException + + +class TestCase: + def __init__(self, name: str, suite: 'Suite' = None, + func: Callable[[], None] = None) -> None: + self.func = func + self.name = name + self.suite = suite + self.old_cwd = None # type: str + self.tmpdir = None # type: tempfile.TemporaryDirectory + + def run(self) -> None: + if self.func: + self.func() + + def set_up(self) -> None: + self.old_cwd = os.getcwd() + self.tmpdir = tempfile.TemporaryDirectory(prefix='mypy-test-', + dir=os.path.abspath('tmp-test-dirs')) + os.chdir(self.tmpdir.name) + os.mkdir('tmp') + if self.suite: + self.suite.set_up() + + def tear_down(self) -> None: + if self.suite: + self.suite.tear_down() + os.chdir(self.old_cwd) + self.tmpdir.cleanup() + self.old_cwd = None + self.tmpdir = None + + +TestUnion = Union[TestCase, Tuple[str, 'Suite']] + + +class Suite: + def __init__(self) -> None: + self.prefix = typename(type(self)) + '.' + self._test_cases = [] # type: List[TestUnion] + self.init() + + def set_up(self) -> None: + pass + + def tear_down(self) -> None: + pass + + def init(self) -> None: + for m in dir(self): + if m.startswith('test'): + t = getattr(self, m) + if isinstance(t, Suite): + self.add_test((m + '.', t)) + else: + assert callable(t), '%s.%s is %s' % (type(self).__name__, m, type(t).__name__) + self.add_test(TestCase(m, self, t)) + + def add_test(self, test: TestUnion) -> None: + self._test_cases.append(test) + + def cases(self) -> List[TestUnion]: + return self._test_cases[:] + + def skip(self) -> None: + raise SkipTestCaseException() + + +def typename(t: type) -> str: + if '.' in str(t): + return str(t).split('.')[-1].rstrip("'>") + else: + return str(t)[8:-2] diff --git a/mypy/test/data.py b/mypy/test/data.py index 73e6b9db35bf..bedb76995259 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -8,7 +8,8 @@ from typing import Callable, List, Tuple -from mypy.myunit import TestCase, SkipTestCaseException +from mypy.myunit.errors import SkipTestCaseException +from mypy.myunit.suite import TestCase def parse_test_cases( diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index b6b1e5a850cf..9fbefea2997e 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -5,7 +5,7 @@ from typing import List, Dict, Tuple from mypy import defaults -from mypy.myunit import AssertionFailure +from mypy.myunit.errors import AssertionFailure from mypy.test import config diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 4fc83b1411f0..1033ea4fd1cd 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -7,8 +7,8 @@ from typing import Tuple from mypy import build -import mypy.myunit # for mutable globals (ick!) -from mypy.myunit import Suite +from mypy.myunit import ick # for mutable globals (ick!) +from mypy.myunit.suite import Suite from mypy.test.config import test_temp_dir, test_data_prefix from mypy.test.data import parse_test_cases from mypy.test.helpers import ( @@ -78,8 +78,8 @@ def run_test(self, testcase): except CompileError as e: a = normalize_error_messages(e.messages) - if testcase.output != a and mypy.myunit.UPDATE_TESTCASES: - update_testcase_output(testcase, a, mypy.myunit.APPEND_TESTCASES) + if testcase.output != a and ick.UPDATE_TESTCASES: + update_testcase_output(testcase, a, ick.APPEND_TESTCASES) assert_string_arrays_equal( testcase.output, a, diff --git a/mypy/test/testdocstring.py b/mypy/test/testdocstring.py index 9a6b67220007..75d7711fb056 100644 --- a/mypy/test/testdocstring.py +++ b/mypy/test/testdocstring.py @@ -1,6 +1,7 @@ """Test cases for finding type annotations in docstrings.""" -from mypy.myunit import Suite, assert_equal +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.docstring import parse_docstring, scrubtype diff --git a/mypy/test/testinfer.py b/mypy/test/testinfer.py index 58d3b0b3a661..6c56a1d94228 100644 --- a/mypy/test/testinfer.py +++ b/mypy/test/testinfer.py @@ -2,7 +2,8 @@ import typing -from mypy.myunit import Suite, assert_equal, assert_true +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.checkexpr import map_actuals_to_formals from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, ARG_NAMED from mypy.types import AnyType, TupleType diff --git a/mypy/test/testlex.py b/mypy/test/testlex.py index 9a38c5d7677f..e374506e4ceb 100644 --- a/mypy/test/testlex.py +++ b/mypy/test/testlex.py @@ -2,7 +2,8 @@ import typing -from mypy.myunit import Suite, assert_equal +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.lex import lex diff --git a/mypy/test/testparse.py b/mypy/test/testparse.py index 56b7523ad4cd..f3f0752ab0ba 100644 --- a/mypy/test/testparse.py +++ b/mypy/test/testparse.py @@ -7,7 +7,8 @@ import typing from mypy import defaults -from mypy.myunit import Suite, AssertionFailure +from mypy.myunit.errors import AssertionFailure +from mypy.myunit.suite import Suite from mypy.test.helpers import assert_string_arrays_equal from mypy.test.data import parse_test_cases from mypy.test import config diff --git a/mypy/test/testpythoneval.py b/mypy/test/testpythoneval.py index 07a4a0dc4f47..3d165becc7e0 100644 --- a/mypy/test/testpythoneval.py +++ b/mypy/test/testpythoneval.py @@ -17,7 +17,8 @@ import typing -from mypy.myunit import Suite, SkipTestCaseException +from mypy.myunit.errors import SkipTestCaseException +from mypy.myunit.suite import Suite from mypy.test.config import test_data_prefix, test_temp_dir from mypy.test.data import parse_test_cases from mypy.test.helpers import assert_string_arrays_equal diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index 3a9c14bccce3..3cd51be61d07 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -5,7 +5,7 @@ from typing import Dict, List from mypy import build -from mypy.myunit import Suite +from mypy.myunit.suite import Suite from mypy.test.helpers import assert_string_arrays_equal, testfile_pyversion from mypy.test.data import parse_test_cases from mypy.test.config import test_data_prefix, test_temp_dir diff --git a/mypy/test/testsolve.py b/mypy/test/testsolve.py index b84bb1714f50..f5d9e15e2840 100644 --- a/mypy/test/testsolve.py +++ b/mypy/test/testsolve.py @@ -2,10 +2,11 @@ import typing -from mypy.myunit import Suite, assert_equal +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.constraints import SUPERTYPE_OF, SUBTYPE_OF, Constraint from mypy.solve import solve_constraints -from mypy.typefixture import TypeFixture +from mypy.test.typefixture import TypeFixture class SolveSuite(Suite): diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 893659d2f6cf..ddfbdd2e741b 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -9,7 +9,9 @@ import typing -from mypy.myunit import Suite, AssertionFailure, assert_equal +from mypy.myunit.assertions import * +from mypy.myunit.errors import AssertionFailure +from mypy.myunit.suite import Suite from mypy.test.helpers import assert_string_arrays_equal from mypy.test.data import parse_test_cases from mypy.test import config @@ -94,11 +96,11 @@ def test_infer_sig_from_docstring(self): class StubgenPythonSuite(Suite): - test_data_files = ['stubgen.test'] + data_files = ['stubgen.test'] def cases(self): c = [] - for path in self.test_data_files: + for path in self.data_files: c += parse_test_cases(os.path.join(config.test_data_prefix, path), test_stubgen) return c diff --git a/mypy/test/testsubtypes.py b/mypy/test/testsubtypes.py index e8a4121c7682..2e106039e13d 100644 --- a/mypy/test/testsubtypes.py +++ b/mypy/test/testsubtypes.py @@ -1,7 +1,8 @@ -from mypy.myunit import Suite, assert_true +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.nodes import CONTRAVARIANT, INVARIANT, COVARIANT from mypy.subtypes import is_subtype -from mypy.typefixture import TypeFixture, InterfaceTypeFixture +from mypy.test.typefixture import TypeFixture, InterfaceTypeFixture class SubtypingSuite(Suite): diff --git a/mypy/test/testtransform.py b/mypy/test/testtransform.py index eaab12cb1de8..bb7a413aa882 100644 --- a/mypy/test/testtransform.py +++ b/mypy/test/testtransform.py @@ -5,7 +5,7 @@ from typing import Dict, List from mypy import build -from mypy.myunit import Suite +from mypy.myunit.suite import Suite from mypy.test.helpers import assert_string_arrays_equal, testfile_pyversion from mypy.test.data import parse_test_cases from mypy.test.config import test_data_prefix, test_temp_dir diff --git a/mypy/test/testtypegen.py b/mypy/test/testtypegen.py index dc1961544238..32f7e9275bda 100644 --- a/mypy/test/testtypegen.py +++ b/mypy/test/testtypegen.py @@ -6,7 +6,7 @@ import typing from mypy import build -from mypy.myunit import Suite +from mypy.myunit.suite import Suite from mypy.test import config from mypy.test.data import parse_test_cases from mypy.test.helpers import assert_string_arrays_equal diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index ec0c3ef8bafb..aaed7c87a78d 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -2,9 +2,8 @@ from typing import List -from mypy.myunit import ( - Suite, assert_equal, assert_true, assert_false -) +from mypy.myunit.assertions import * +from mypy.myunit.suite import Suite from mypy.erasetype import erase_type from mypy.expandtype import expand_type from mypy.join import join_types @@ -16,7 +15,7 @@ from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, CONTRAVARIANT, INVARIANT, COVARIANT from mypy.replacetvars import replace_type_vars from mypy.subtypes import is_subtype, is_more_precise, is_proper_subtype -from mypy.typefixture import TypeFixture, InterfaceTypeFixture +from mypy.test.typefixture import TypeFixture, InterfaceTypeFixture class TypesSuite(Suite): diff --git a/mypy/typefixture.py b/mypy/test/typefixture.py similarity index 100% rename from mypy/typefixture.py rename to mypy/test/typefixture.py diff --git a/runtests.py b/runtests.py index 462fa1491369..4cd6b3234b23 100755 --- a/runtests.py +++ b/runtests.py @@ -205,8 +205,8 @@ def add_myunit(driver: Driver) -> None: mod = file_to_module(f) if '.codec.test.' in mod: # myunit is Python3 only. - driver.add_python_mod('unittest %s' % mod, 'unittest', mod) - driver.add_python2('unittest %s' % mod, '-m', 'unittest', mod) + driver.add_python_mod('unittest %s' % mod, 'unittest', '-q', mod) + driver.add_python2('unittest %s' % mod, '-m', 'unittest', '-q', mod) elif mod == 'mypy.test.testpythoneval': # Run Python evaluation integration tests separetely since they are much slower # than proper unit tests. @@ -326,6 +326,8 @@ def main() -> None: # empty string is a substring of all names if not whitelist: whitelist.append('') + if not arglist: + arglist.append('-q') driver = Driver(whitelist=whitelist, blacklist=blacklist, arglist=arglist, verbosity=verbosity, xfail=[]) diff --git a/scripts/myunit b/scripts/myunit index 43fce063f5a2..a8a67b87d4f0 100755 --- a/scripts/myunit +++ b/scripts/myunit @@ -4,6 +4,6 @@ Usually used as a slave by runtests.py, but can be used directly. """ -from mypy.myunit import main +from mypy.myunit.main import main main() diff --git a/setup.cfg b/setup.cfg index 4818cec154a6..0d28dd19e8f1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,4 +7,5 @@ exclude = mypy/codec/*,mypy/test/data/lib-stub/*,mypy/test/data/fixtures/* # F401: unused identifiers (useless, as it doesn't see inside # type: comments) # W601: has_key() deprecated (false positives) # E701: multiple statements on one line (colon) (we use this for classes with empty body) -ignore = E251,E128,F401,W601,E701 +# F403: 'from foo import *' used; unable to detect undefined names (mypy checks this better) +ignore = E251,E128,F401,W601,E701,F403