From 22c472452d13ecaf091b71e0393593f5c1e21439 Mon Sep 17 00:00:00 2001 From: Pytype Team Date: Mon, 30 Mar 2020 11:50:41 -0700 Subject: [PATCH 01/11] Fix a documentation snippet demonstrating the usage with mixins. PiperOrigin-RevId: 303789067 --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 5addcbfb6..5911508f3 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -127,7 +127,7 @@ class LoggerMixin(LoggerMixinInterface): def log(self, msg: str): self._log.print(f"{self.name()}: {msg}") -class Person(Logger): +class Person(LoggerMixinInterface): ... # Other initialization def name(self): return self._name From b8fdc568ff51696b0f2cab8f400574e7b987b780 Mon Sep 17 00:00:00 2001 From: rechen Date: Mon, 30 Mar 2020 12:35:25 -0700 Subject: [PATCH 02/11] Cleanup: use "regex" instead of "regexp". assertRegexpMatches is deprecated in favor of assertRegex in Python 3, and assertRaisesRegexp was renamed to assertRaisesRegex in 3.2. Just for consistency, I also changed all other references to "regexp" I could find. Lastly, fixes two g-missing-super-call lint warnings. PiperOrigin-RevId: 303799439 --- pytype/abstract_test.py | 7 +++-- pytype/directors_test.py | 4 ++- pytype/pytd/parse/parser_constants.py | 2 +- pytype/pytd/parse/preconditions_test.py | 5 ++-- pytype/pytd/pytd_utils_test.py | 10 +++---- pytype/pytd/serialize_ast_test.py | 2 +- pytype/tests/test_utils.py | 26 +++++++++---------- .../analyze_project/pytype_runner_test.py | 7 ++--- 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/pytype/abstract_test.py b/pytype/abstract_test.py index e53664584..11789e8e9 100644 --- a/pytype/abstract_test.py +++ b/pytype/abstract_test.py @@ -119,7 +119,7 @@ def test_call_wrong_argcount(self): self.assertEqual(self._node, node) self.assertIsInstance(abstract_utils.get_atomic_value(result), abstract.Unsolvable) - self.assertRegexpMatches(str(self._vm.errorlog), "missing-parameter") + six.assertRegex(self, str(self._vm.errorlog), "missing-parameter") def test_call_wrong_keywords(self): self._vm.push_frame(frame_state.SimpleFrame()) @@ -130,9 +130,8 @@ def test_call_wrong_keywords(self): self.assertEqual(self._node, node) self.assertIsInstance(abstract_utils.get_atomic_value(result), abstract.Unsolvable) - self.assertRegexpMatches( - str(self._vm.errorlog), - r"foo.*isinstance.*\[wrong-keyword-args\]") + six.assertRegex(self, str(self._vm.errorlog), + r"foo.*isinstance.*\[wrong-keyword-args\]") def test_is_instance(self): def check(expected, left, right): diff --git a/pytype/directors_test.py b/pytype/directors_test.py index f022ca592..e8eb00d56 100644 --- a/pytype/directors_test.py +++ b/pytype/directors_test.py @@ -3,6 +3,7 @@ from pytype import directors from pytype import errors +import six import unittest _TEST_FILENAME = "my_file.py" @@ -99,6 +100,7 @@ class DirectorTest(unittest.TestCase): @classmethod def setUpClass(cls): + super(DirectorTest, cls).setUpClass() # Invoking the _error_name decorator will register the name as a valid # error name. for name in ["test-error", "test-other-error"]: @@ -296,7 +298,7 @@ def check_warning(message_regex, text): error = list(self._errorlog)[0] self.assertEqual(_TEST_FILENAME, error._filename) self.assertEqual(1, error.lineno) - self.assertRegexpMatches(str(error), message_regex) + six.assertRegex(self, str(error), message_regex) check_warning("Unknown pytype directive.*disalbe.*", "# pytype: disalbe=test-error") diff --git a/pytype/pytd/parse/parser_constants.py b/pytype/pytd/parse/parser_constants.py index 81e656b9d..295ce86cf 100644 --- a/pytype/pytd/parse/parser_constants.py +++ b/pytype/pytd/parse/parser_constants.py @@ -49,7 +49,7 @@ 'yield', ] -# parser.t_NAME's regexp allows a few extra characters in the name. +# parser.t_NAME's regex allows a few extra characters in the name. # A less-pedantic RE is r'[-~]'. # See visitors._EscapedName and parser.PyLexer.t_NAME BACKTICK_NAME = re.compile(r'[-]|^~') diff --git a/pytype/pytd/parse/preconditions_test.py b/pytype/pytd/parse/preconditions_test.py index fdf30976e..b1dc2b3c7 100644 --- a/pytype/pytd/parse/preconditions_test.py +++ b/pytype/pytd/parse/preconditions_test.py @@ -29,7 +29,7 @@ class SubClass(BaseClass): class PreconditionsTest(unittest.TestCase): def assertError(self, regex, condition, value): - self.assertRaisesRegexp( + self.assertRaisesRegex( preconditions.PreconditionError, regex, condition.check, value) def testClassNamePrecondition(self): @@ -69,6 +69,7 @@ def testIsInstancePrecondition(self): class CallCheckerTest(unittest.TestCase): def setUp(self): + super(CallCheckerTest, self).setUp() self.checker = preconditions.CallChecker([ ("x", preconditions._ClassNamePrecondition("int")), ("s", preconditions._ClassNamePrecondition("str"))]) @@ -77,7 +78,7 @@ def testAllowedTypes(self): self.assertEqual({"int", "str"}, self.checker.allowed_types()) def assertError(self, regex, *args, **kwargs): - self.assertRaisesRegexp( + self.assertRaisesRegex( preconditions.PreconditionError, regex, self.checker.check, *args, **kwargs) diff --git a/pytype/pytd/pytd_utils_test.py b/pytype/pytd/pytd_utils_test.py index 2cd4ad505..b6f336769 100644 --- a/pytype/pytd/pytd_utils_test.py +++ b/pytype/pytd/pytd_utils_test.py @@ -457,10 +457,10 @@ def testASTdiff(self): self.assertEqual(normalize(pytd_utils.ASTdiff(tree1, tree1)), src1) self.assertEqual(normalize(pytd_utils.ASTdiff(tree2, tree2)), src2) diff_pattern = r"(?s)- b.*\+ b" - self.assertRegexpMatches(normalize(pytd_utils.ASTdiff(tree1, tree2)), - diff_pattern) - self.assertRegexpMatches(normalize(pytd_utils.ASTdiff(tree2, tree1)), - diff_pattern) + six.assertRegex(self, normalize(pytd_utils.ASTdiff(tree1, tree2)), + diff_pattern) + six.assertRegex(self, normalize(pytd_utils.ASTdiff(tree2, tree1)), + diff_pattern) class TestDataFiles(parser_test_base.ParserTest): @@ -477,7 +477,7 @@ def testGetPredefinedFileBasic(self): def testGetPredefinedFileThrows(self): # smoke test, only checks that it does throw - with self.assertRaisesRegexp( + with self.assertRaisesRegex( IOError, r"File not found|Resource not found|No such file or directory"): pytd_utils.GetPredefinedFile(self.BUILTINS, "-this-file-does-not-exist") diff --git a/pytype/pytd/serialize_ast_test.py b/pytype/pytd/serialize_ast_test.py index e43bcd46f..a5cae88a0 100644 --- a/pytype/pytd/serialize_ast_test.py +++ b/pytype/pytd/serialize_ast_test.py @@ -89,7 +89,7 @@ def testNodeIndexVisitorUsage(self): serialized_ast.class_type_nodes)[1:]) loaded_ast = serialize_ast.ProcessAst(serialized_ast, module_map) - with self.assertRaisesRegexp( + with self.assertRaisesRegex( ValueError, "Unresolved class: '__builtin__.NoneType'"): loaded_ast.Visit(visitors.VerifyLookup()) diff --git a/pytype/tests/test_utils.py b/pytype/tests/test_utils.py index 7c5e4172b..c329d3fef 100644 --- a/pytype/tests/test_utils.py +++ b/pytype/tests/test_utils.py @@ -210,18 +210,18 @@ def assert_expected_errors(self, expected_errors): for error in self.unique_sorted_errors(): almost_matches = set() for (pattern, count) in expected_errors.items(): - line, name, regexp = self._parse_expected_error(pattern) + line, name, regex = self._parse_expected_error(pattern) # We should only call this function after resolving marks assert isinstance(line, int), "Unresolved mark %s" % line if line == error.lineno and name == error.name: - if not regexp or re.search(regexp, error.message, flags=re.DOTALL): + if not regex or re.search(regex, error.message, flags=re.DOTALL): if count == 1: del expected_errors[pattern] else: expected_errors[pattern] -= 1 break else: - almost_matches.add(regexp) + almost_matches.add(regex) else: self.print_to_stderr() if almost_matches: @@ -244,9 +244,9 @@ def make_expected_errors(self, expected_errors): expected.append((line, error)) for pattern in expected_errors: - line, name, regexp = self._parse_expected_error(pattern) + line, name, regex = self._parse_expected_error(pattern) line = self.marks.get(line, line) - expected.append((line, name, regexp)) + expected.append((line, name, regex)) return expected @@ -254,27 +254,27 @@ def increment_line_numbers(self, expected_errors): """Adjust line numbers to account for an ANNOTATIONS_IMPORT line.""" incremented_expected_errors = [] for pattern in expected_errors: - line, name, regexp = self._parse_expected_error(pattern) + line, name, regex = self._parse_expected_error(pattern) # We should only call this function after resolving marks assert isinstance(line, int), "Unresolved mark %s" % line # Increments the expected line number of the error. line += 1 # Increments line numbers in the text of the expected error message. - regexp = re.sub( - r"line (\d+)", lambda m: "line %d" % (int(m.group(1)) + 1), regexp) + regex = re.sub( + r"line (\d+)", lambda m: "line %d" % (int(m.group(1)) + 1), regex) incremented_expected_error = (line, name) - if regexp: - incremented_expected_error += (regexp,) + if regex: + incremented_expected_error += (regex,) incremented_expected_errors.append(incremented_expected_error) return incremented_expected_errors def _parse_expected_error(self, pattern): assert 2 <= len(pattern) <= 3, ( - "Bad expected error format. Use: (, [, ])") + "Bad expected error format. Use: (, [, ])") line = pattern[0] name = pattern[1] - regexp = pattern[2] if len(pattern) > 2 else "" - return line, name, regexp + regex = pattern[2] if len(pattern) > 2 else "" + return line, name, regex def _parse_comments(self, src): # Strip out the "google type annotations" line if we have added it - we diff --git a/pytype/tools/analyze_project/pytype_runner_test.py b/pytype/tools/analyze_project/pytype_runner_test.py index 3ec3f302a..f3599b608 100644 --- a/pytype/tools/analyze_project/pytype_runner_test.py +++ b/pytype/tools/analyze_project/pytype_runner_test.py @@ -8,6 +8,7 @@ from pytype import module_utils from pytype.tools.analyze_project import parse_args from pytype.tools.analyze_project import pytype_runner +import six import unittest @@ -375,13 +376,13 @@ def test_write(self): # Check that the lines cycle through these patterns. for i, line in enumerate(preamble): if not i % 3: - self.assertRegexpMatches(line, r'rule \w*') + six.assertRegex(self, line, r'rule \w*') elif i % 3 == 1: expected = r' command = {} .* \$in'.format( ' '.join(pytype_runner.PYTYPE_SINGLE)) - self.assertRegexpMatches(line, expected) + six.assertRegex(self, line, expected) else: - self.assertRegexpMatches(line, r' description = \w* \$module') + six.assertRegex(self, line, r' description = \w* \$module') class TestNinjaBuildStatement(TestBase): From f01905b530ff0893a5e695d77b81a1558714525b Mon Sep 17 00:00:00 2001 From: rechen Date: Mon, 30 Mar 2020 18:07:29 -0700 Subject: [PATCH 03/11] Do expected error checking in (Check|Infer)WithErrors. Now that we have comment-based error checking, I really wanted to be able to insert expected errors into test code and have them checked without needing to call a separate assert method afterwards. This CL: * Fixes a couple cases where errors were reported in a non-deterministic order, so that a mark can always be associated with the right error. * Has CheckWithErrors and InferWithErrors call assert_errors_match_expected() on the errorlog. * Forbids adding expected error comments to Check, Infer, and InferFromFile, so that we don't accidentally use one of these methods and have our expected errors silently ignored. * Replaces assertErrorLogIs and assertErrorsMatch with an assertErrorRegexes method that only has to be called when we want to check marks. * Makes some simplifications to the line number handling and error matching code that are possible because of the removal of assertErrorLogIs. On its own, this CL does not pass tests; a follow-up will migrate all uses of assertErrorLogIs over to assertErrorRegexes. I'll wait until both CLs have been reviewed, then submit them in quick succession. PiperOrigin-RevId: 303863481 --- pytype/abstract.py | 5 +- pytype/annotations_util.py | 8 +- pytype/tests/CMakeLists.txt | 1 + pytype/tests/test_base.py | 39 +++++---- pytype/tests/test_base_test.py | 112 +++++++++++++++++++++--- pytype/tests/test_utils.py | 154 ++++++++++++++------------------- 6 files changed, 202 insertions(+), 117 deletions(-) diff --git a/pytype/abstract.py b/pytype/abstract.py index 055b15c89..7431f3ae0 100644 --- a/pytype/abstract.py +++ b/pytype/abstract.py @@ -2491,7 +2491,7 @@ def update_sig(method): if nitem in self.template: raise abstract_utils.GenericTypeError( self, ("Generic class [%s] and its nested generic class [%s] " - "cannot use same type variable %s.") + "cannot use the same type variable %s.") % (self.full_name, cls.full_name, item.name)) self._load_all_formal_type_parameters() # Throw exception if there is error @@ -3010,7 +3010,8 @@ def _inner_cls_check(self, last_frame): inner_cls_types = value.collect_inner_cls_types() inner_cls_types.update([(value, item.with_module(None)) for item in value.template]) - for cls, item in inner_cls_types: + # Report errors in a deterministic order. + for cls, item in sorted(inner_cls_types, key=lambda typ: typ[1].name): if item in all_type_parameters: self.vm.errorlog.invalid_annotation( self.vm.simple_stack(self.get_first_opcode()), item, diff --git a/pytype/annotations_util.py b/pytype/annotations_util.py index e208ef51e..ca15b9f16 100644 --- a/pytype/annotations_util.py +++ b/pytype/annotations_util.py @@ -1,5 +1,7 @@ """Utilities for inline type annotations.""" +import sys + from pytype import abstract from pytype import abstract_utils from pytype import mixin @@ -157,7 +159,11 @@ def convert_annotations_list(self, node, annotations_list): def convert_class_annotations(self, node, raw_annotations): """Convert a name -> raw_annot dict to annotations.""" annotations = {} - for name, t in raw_annotations.items(): + raw_items = raw_annotations.items() + if sys.version_info.major == 2: + # Make sure annotation errors are reported in a deterministic order. + raw_items = sorted(raw_items) + for name, t in raw_items: # Don't use the parameter name, since it's often something unhelpful # like `0`. annot = self._process_one_annotation( diff --git a/pytype/tests/CMakeLists.txt b/pytype/tests/CMakeLists.txt index 4b99ebecc..34fd13064 100644 --- a/pytype/tests/CMakeLists.txt +++ b/pytype/tests/CMakeLists.txt @@ -18,6 +18,7 @@ py_test( test_base_test.py DEPS .test_base + pytype.utils ) py_test( diff --git a/pytype/tests/test_base.py b/pytype/tests/test_base.py index 13ba05531..52b2bdbbd 100644 --- a/pytype/tests/test_base.py +++ b/pytype/tests/test_base.py @@ -1,13 +1,13 @@ """Common methods for tests of analyze.py.""" import logging +import re import sys import textwrap from pytype import analyze from pytype import config from pytype import directors -from pytype import errors from pytype import load_pytd from pytype import utils from pytype.pyi import parser @@ -52,7 +52,10 @@ def _Wrapper(self, code, *args, **kwargs): def _IncrementLineNumbersPy2(func): def _Wrapper(self, errorlog, expected_errors): if self.options.python_version == (2, 7): - expected_errors = errorlog.increment_line_numbers(expected_errors) + for mark in expected_errors: + expected_errors[mark] = re.sub( + r"line (\d+)", + lambda m: "line %d" % (int(m.group(1)) + 1), expected_errors[mark]) return func(self, errorlog, expected_errors) return _Wrapper @@ -169,20 +172,21 @@ def ConfigureOptions(self, **kwargs): python_exe=utils.get_python_exe(self.options.python_version)) # For historical reasons (byterun), this method name is snakecase: - # TODO(kramm): Rename this function. # pylint: disable=invalid-name def Check(self, code, pythonpath=(), skip_repeat_calls=True, report_errors=True, filename=None, quick=False, **kwargs): """Run an inference smoke test for the given code.""" self.ConfigureOptions(skip_repeat_calls=skip_repeat_calls, pythonpath=pythonpath, quick=quick) - errorlog = errors.ErrorLog() try: src = "" if six.PY3: src = textwrap.dedent(code) else: src = textwrap.dedent(code.decode("utf-8")) + errorlog = test_utils.TestErrorLog(code) + if errorlog.expected: + self.fail("Cannot assert errors with Check(); use CheckWithErrors()") analyze.check_types( src, filename, loader=self.loader, errorlog=errorlog, options=self.options, **kwargs) @@ -211,19 +215,26 @@ def InferWithErrors(self, code, deep=True, pythonpath=(), unit.Visit(visitors.VerifyVisitor()) unit = optimize.Optimize(unit, builtins_pytd, lossy=False, use_abcs=False, max_union=7, remove_mutable=False) - return pytd_utils.CanonicalOrdering(unit), kwargs["errorlog"] + errorlog = kwargs["errorlog"] + errorlog.assert_errors_match_expected() + return pytd_utils.CanonicalOrdering(unit), errorlog def CheckWithErrors(self, code, deep=True, pythonpath=(), analyze_annotated=True, quick=False, **kwargs): kwargs.update( self._SetUpErrorHandling(code, pythonpath, analyze_annotated, quick)) analyze.check_types(filename="", deep=deep, **kwargs) - return kwargs["errorlog"] + errorlog = kwargs["errorlog"] + errorlog.assert_errors_match_expected() + return errorlog def InferFromFile(self, filename, pythonpath): with open(filename, "r") as fi: code = fi.read() - errorlog = errors.ErrorLog() + errorlog = test_utils.TestErrorLog(code) + if errorlog.expected: + self.fail( + "Cannot assert errors with InferFromFile(); use InferWithErrors()") self.ConfigureOptions( module_name=load_pytd.get_module_name(filename, pythonpath), pythonpath=pythonpath) @@ -329,12 +340,8 @@ def assertIsIdentity(self, func): self.assertEqual(param1.type, sig.return_type, "Not identity: %r" % pytd_utils.Print(func)) - def assertErrorsMatch(self, errorlog, expected_errors): - expected = errorlog.make_expected_errors(expected_errors) - self.assertErrorLogIs(errorlog, expected) - - def assertErrorLogIs(self, errorlog, expected_errors): - errorlog.assert_expected_errors(expected_errors) + def assertErrorRegexes(self, errorlog, expected_errors): + errorlog.assert_error_regexes(expected_errors) def _Pickle(self, ast, module_name): assert module_name @@ -383,7 +390,9 @@ def _InferAndVerify( module_name=module_name, quick=quick, use_pickled_files=True, pythonpath=[""] if (not pythonpath and imports_map) else pythonpath, imports_map=imports_map, analyze_annotated=analyze_annotated) - errorlog = errors.ErrorLog() + errorlog = test_utils.TestErrorLog(src) + if errorlog.expected: + self.fail("Cannot assert errors with Infer(); use InferWithErrors()") unit, builtins_pytd = analyze.infer_types( src, errorlog, self.options, loader=self.loader, **kwargs) unit.Visit(visitors.VerifyVisitor()) @@ -427,7 +436,7 @@ def assertTypesMatchPytd(self, ty, pytd_src): CheckWithErrors = _AddAnnotationsImportPy2(CheckWithErrors) Infer = _AddAnnotationsImportPy2(Infer) InferWithErrors = _AddAnnotationsImportPy2(InferWithErrors) - assertErrorLogIs = _IncrementLineNumbersPy2(assertErrorLogIs) + assertErrorRegexes = _IncrementLineNumbersPy2(assertErrorRegexes) class TargetIndependentTest(BaseTest): diff --git a/pytype/tests/test_base_test.py b/pytype/tests/test_base_test.py index 42f26df2e..18b6a63de 100644 --- a/pytype/tests/test_base_test.py +++ b/pytype/tests/test_base_test.py @@ -1,31 +1,123 @@ """Tests for our test framework.""" +from pytype import file_utils +from pytype import utils from pytype.tests import test_base -import six +from pytype.tests import test_utils class ErrorLogTest(test_base.TargetIndependentTest): + def _lineno(self, line): + if self.options.python_version == (2, 7) and utils.USE_ANNOTATIONS_BACKPORT: + return line + 1 + return line + def test_error_comments(self): err = self.CheckWithErrors("""\ a = 10 # a random comment - b = "hello" # .mark - c = a + b # some-error - d = a + b # .another_mark + b = "hello" + 3 # unsupported-operands[.mark] + c = (10).foo # attribute-error + d = int(int) # wrong-arg-types[.another_mark] + """) + self.assertEqual( + {mark: (e.lineno, e.name) for mark, e in err.marks.items()}, + {".mark": (self._lineno(2), "unsupported-operands"), + ".another_mark": (self._lineno(4), "wrong-arg-types")}) + self.assertEqual(err.expected, { + self._lineno(2): [("unsupported-operands", ".mark")], + self._lineno(3): [("attribute-error", None)], + self._lineno(4): [("wrong-arg-types", ".another_mark")]}) + + def test_multiple_errors_one_line(self): + err = self.CheckWithErrors("""\ + x = (10).foo, "hello".foo # attribute-error[e1] # attribute-error[e2] """) - six.assertCountEqual(self, err.marks.keys(), [".mark", ".another_mark"]) - self.assertEqual(err.marks[".mark"], 2) - six.assertCountEqual(self, err.expected.keys(), [3]) - six.assertCountEqual(self, err.expected[3], "some-error") + line = self._lineno(1) + self.assertEqual(err.expected, {line: [("attribute-error", "e1"), + ("attribute-error", "e2")]}) + self.assertCountEqual(err.marks, ["e1", "e2"]) + self.assertIn("on int", err.marks["e1"].message) + self.assertIn("on str", err.marks["e2"].message) + + def test_populate_marks(self): + # Test that assert_error_regexes populates self.marks if not already done. + errorlog = test_utils.TestErrorLog("x = 0") + self.assertIsNone(errorlog.marks) + self.assertErrorRegexes(errorlog, {}) + self.assertIsNotNone(errorlog.marks) + + def test_duplicate_mark(self): + with self.assertRaises(AssertionError) as ctx: + self.CheckWithErrors("x = 0 # attribute-error[e] # attribute-error[e]") + self.assertEqual(str(ctx.exception), "Mark e already used") def test_error_matching(self): err = self.CheckWithErrors("""\ a = 10 b = "hello" c = a + b # unsupported-operands - d = a.foo() # .mark + d = a.foo() # attribute-error[.mark] """) - self.assertErrorsMatch(err, [(".mark", "attribute-error", ".*foo.*")]) + self.assertErrorRegexes(err, {".mark": ".*foo.*"}) + + def test_mismatched_error(self): + with self.assertRaises(AssertionError) as ctx: + self.CheckWithErrors("(10).foo # wrong-arg-types") + self.assertIn("Error does not match", str(ctx.exception)) + + def test_unexpected_error(self): + with self.assertRaises(AssertionError) as ctx: + self.CheckWithErrors("""\ + (10).foo # attribute-error + "hello".foo + """) + self.assertIn("Unexpected error", str(ctx.exception)) + + def test_leftover_error(self): + with self.assertRaises(AssertionError) as ctx: + self.CheckWithErrors("x = 0 # attribute-error") + self.assertIn("Errors not found", str(ctx.exception)) + + def test_misspelled_leftover_error(self): + with self.assertRaises(AssertionError) as ctx: + self.CheckWithErrors("x = 0 # misspelled-error") + self.assertIn("Errors not found", str(ctx.exception)) + + def test_mismatched_regex(self): + err = self.CheckWithErrors("(10).foo # attribute-error[e]") + with self.assertRaises(AssertionError) as ctx: + self.assertErrorRegexes(err, {"e": r"does not match error message"}) + self.assertIn("Bad error message", str(ctx.exception)) + + def test_missing_regex(self): + err = self.CheckWithErrors("(10).foo # attribute-error[e]") + with self.assertRaises(AssertionError) as ctx: + self.assertErrorRegexes(err, {}) + self.assertEqual(str(ctx.exception), "No regex for mark e") + + def test_leftover_regex(self): + err = self.CheckWithErrors("x = 0") + with self.assertRaises(AssertionError) as ctx: + self.assertErrorRegexes(err, {"e": ""}) + self.assertEqual(str(ctx.exception), "Marks not found in code: e") + + def test_bad_check(self): + with self.assertRaises(AssertionError) as ctx: + self.Check("name_error # name-error") + self.assertIn("Cannot assert errors", str(ctx.exception)) + + def test_bad_infer(self): + with self.assertRaises(AssertionError) as ctx: + self.Infer("name_error # name-error") + self.assertIn("Cannot assert errors", str(ctx.exception)) + + def test_bad_infer_from_file(self): + with file_utils.Tempdir() as d: + d.create_file("some_file.py", "name_error # name-error") + with self.assertRaises(AssertionError) as ctx: + self.InferFromFile(filename=d["some_file.py"], pythonpath=[]) + self.assertIn("Cannot assert errors", str(ctx.exception)) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_utils.py b/pytype/tests/test_utils.py index c329d3fef..ee20cd10b 100644 --- a/pytype/tests/test_utils.py +++ b/pytype/tests/test_utils.py @@ -1,6 +1,7 @@ """Utility class and function for tests.""" import collections +import itertools import re import subprocess import tokenize @@ -187,8 +188,8 @@ class TestErrorLog(errors.ErrorLog): holding parsed comment directives. Attributes: - marks: { mark_name : line number } - expected: { line number : expected error code } + marks: { mark_name : errors.Error object } + expected: { line number : sequence of expected error codes and mark names } Also adds an assertion matcher to match self.errors against a list of expected errors of the form [(line number, error code, message regex)]. @@ -196,104 +197,79 @@ class TestErrorLog(errors.ErrorLog): See tests/test_base_test.py for usage examples. """ - MARK_RE = re.compile(r"^[.]\w+$") - ERROR_RE = re.compile(r"^\w[\w-]+\w$") + ERROR_RE = re.compile(r"^(?P(\w+-)+\w+)(\[(?P.+)\])?$") def __init__(self, src): super(TestErrorLog, self).__init__() - self.marks, self.expected = self._parse_comments(src) + self.marks = None # set by assert_errors_match_expected() + self.expected = self._parse_comments(src) - def assert_expected_errors(self, expected_errors): - expected_errors = collections.Counter(expected_errors) - # This is O(|errorlog| * |expected_errors|), which is okay because error - # lists in tests are short. - for error in self.unique_sorted_errors(): - almost_matches = set() - for (pattern, count) in expected_errors.items(): - line, name, regex = self._parse_expected_error(pattern) - # We should only call this function after resolving marks - assert isinstance(line, int), "Unresolved mark %s" % line - if line == error.lineno and name == error.name: - if not regex or re.search(regex, error.message, flags=re.DOTALL): - if count == 1: - del expected_errors[pattern] - else: - expected_errors[pattern] -= 1 - break - else: - almost_matches.add(regex) - else: - self.print_to_stderr() - if almost_matches: - raise AssertionError("Bad error message: expected %r, got %r" % ( - almost_matches.pop(), error.message)) - else: - raise AssertionError("Unexpected error:\n%s" % error) - if expected_errors: + def _fail(self, msg): + if self.marks: self.print_to_stderr() - leftover_errors = [ - self._parse_expected_error(pattern) for pattern in expected_errors] - raise AssertionError("Errors not found:\n" + "\n".join( - "Line %d: %r [%s]" % (e[0], e[2], e[1]) for e in leftover_errors)) - - def make_expected_errors(self, expected_errors): - """Rewrite expected_errors, resolving marks and adding comments.""" - expected = [] - - for line, error in self.expected.items(): - expected.append((line, error)) + raise AssertionError(msg) + + def assert_errors_match_expected(self): + # TODO(rechen): The sorted() call can be removed once we stop supporting + # host Python 2, since dictionaries preserve insertion order in Python 3.6+. + expected_errors = itertools.chain.from_iterable( + [(line, code, mark) for (code, mark) in errors] + for line, errors in sorted(self.expected.items())) + self.marks = {} + + def _format_error(line, code, mark=None): + formatted = "Line %d: %s" % (line, code) + if mark: + formatted += "[%s]" % mark + return formatted - for pattern in expected_errors: - line, name, regex = self._parse_expected_error(pattern) - line = self.marks.get(line, line) - expected.append((line, name, regex)) - - return expected - - def increment_line_numbers(self, expected_errors): - """Adjust line numbers to account for an ANNOTATIONS_IMPORT line.""" - incremented_expected_errors = [] - for pattern in expected_errors: - line, name, regex = self._parse_expected_error(pattern) - # We should only call this function after resolving marks - assert isinstance(line, int), "Unresolved mark %s" % line - # Increments the expected line number of the error. - line += 1 - # Increments line numbers in the text of the expected error message. - regex = re.sub( - r"line (\d+)", lambda m: "line %d" % (int(m.group(1)) + 1), regex) - incremented_expected_error = (line, name) - if regex: - incremented_expected_error += (regex,) - incremented_expected_errors.append(incremented_expected_error) - return incremented_expected_errors - - def _parse_expected_error(self, pattern): - assert 2 <= len(pattern) <= 3, ( - "Bad expected error format. Use: (, [, ])") - line = pattern[0] - name = pattern[1] - regex = pattern[2] if len(pattern) > 2 else "" - return line, name, regex + for error in self.unique_sorted_errors(): + try: + line, code, mark = next(expected_errors) + except StopIteration: + self._fail("Unexpected error:\n%s" % error) + if line != error.lineno or code != error.name: + self._fail("Error does not match:\nExpected: %s\nActual: %s" % + (_format_error(line, code, mark), + _format_error(error.lineno, error.name))) + elif mark: + self.marks[mark] = error + leftover_errors = [_format_error(*error) for error in expected_errors] + if leftover_errors: + self._fail("Errors not found:\n" + "\n".join(leftover_errors)) + + def assert_error_regexes(self, expected_regexes): + if self.marks is None: + self.assert_errors_match_expected() # populates self.marks + for mark, error in self.marks.items(): + try: + regex = expected_regexes.pop(mark) + except KeyError: + self._fail("No regex for mark %s" % mark) + if not re.search(regex, error.message, flags=re.DOTALL): + self._fail("Bad error message for mark %s: expected %r, got %r" % + (mark, regex, error.message)) + if expected_regexes: + self._fail("Marks not found in code: %s" % ", ".join(expected_regexes)) def _parse_comments(self, src): - # Strip out the "google type annotations" line if we have added it - we - # already have an assertion in test_base that this is not added manually. - offset = -1 if ANNOTATIONS_IMPORT in src else 0 - src = six.moves.StringIO(src) - marks = {} - expected = {} + expected = collections.defaultdict(list) + used_marks = set() for tok, s, (line, _), _, _ in tokenize.generate_tokens(src.readline): - line = line + offset if tok == tokenize.COMMENT: - comment = s.lstrip("# ").rstrip() - if self.MARK_RE.match(comment): - assert comment not in marks, "Mark %s already used" % comment - marks[comment] = line - elif self.ERROR_RE.match(comment): - expected[line] = comment - return marks, expected + for comment in s.split("#"): + comment = comment.strip() + match = self.ERROR_RE.match(comment) + if not match: + continue + mark = match.group("mark") + if mark: + if mark in used_marks: + self._fail("Mark %s already used" % mark) + used_marks.add(mark) + expected[line].append((match.group("code"), mark)) + return expected class Py2Opcodes(object): From 57c88d75a2435d078cc1b2575e85f935c518b5a5 Mon Sep 17 00:00:00 2001 From: rechen Date: Mon, 30 Mar 2020 18:15:36 -0700 Subject: [PATCH 04/11] Migrate all uses of assertErrorLogIs to assertErrorRegexes. PiperOrigin-RevId: 303864672 --- pytype/tests/py2/test_abc.py | 13 +- pytype/tests/py2/test_attributes.py | 8 +- pytype/tests/py2/test_builtins.py | 5 +- pytype/tests/py2/test_decorators.py | 4 +- pytype/tests/py2/test_errors.py | 22 +- pytype/tests/py2/test_list.py | 9 +- pytype/tests/py2/test_namedtuple.py | 16 +- pytype/tests/py2/test_pyi.py | 17 +- pytype/tests/py2/test_reingest.py | 4 +- pytype/tests/py2/test_slots.py | 11 +- pytype/tests/py2/test_super.py | 9 +- pytype/tests/py2/test_typevar.py | 24 +- pytype/tests/py3/test_abc.py | 4 +- pytype/tests/py3/test_annotations.py | 212 +++--- pytype/tests/py3/test_anystr.py | 11 +- pytype/tests/py3/test_async_generators.py | 34 +- pytype/tests/py3/test_attr.py | 10 +- pytype/tests/py3/test_attributes.py | 22 +- pytype/tests/py3/test_builtins.py | 60 +- pytype/tests/py3/test_checker.py | 58 +- pytype/tests/py3/test_classes.py | 18 +- pytype/tests/py3/test_coroutine.py | 57 +- pytype/tests/py3/test_dataclasses.py | 20 +- pytype/tests/py3/test_decorators.py | 5 +- pytype/tests/py3/test_dict.py | 10 +- pytype/tests/py3/test_errors.py | 186 +++-- pytype/tests/py3/test_exceptions.py | 3 +- pytype/tests/py3/test_functions.py | 79 +- pytype/tests/py3/test_generators.py | 16 +- pytype/tests/py3/test_generic.py | 152 ++-- pytype/tests/py3/test_list.py | 19 +- pytype/tests/py3/test_match.py | 112 ++- pytype/tests/py3/test_methods.py | 18 +- pytype/tests/py3/test_namedtuple.py | 18 +- pytype/tests/py3/test_overload.py | 31 +- pytype/tests/py3/test_protocols.py | 68 +- pytype/tests/py3/test_recovery.py | 17 +- pytype/tests/py3/test_reingest.py | 8 +- pytype/tests/py3/test_slots.py | 5 +- pytype/tests/py3/test_stdlib.py | 4 +- pytype/tests/py3/test_super.py | 14 +- pytype/tests/py3/test_tracebacks.py | 4 +- pytype/tests/py3/test_tuple.py | 46 +- pytype/tests/py3/test_type_comments.py | 5 +- pytype/tests/py3/test_typevar.py | 90 +-- pytype/tests/py3/test_typing.py | 202 +++--- pytype/tests/py3/test_typing_namedtuple.py | 46 +- pytype/tests/py3/test_variable_annotations.py | 39 +- pytype/tests/test_abc.py | 19 +- pytype/tests/test_attr.py | 41 +- pytype/tests/test_attributes.py | 78 +- pytype/tests/test_basic.py | 27 +- pytype/tests/test_builtins1.py | 9 +- pytype/tests/test_builtins2.py | 19 +- pytype/tests/test_builtins3.py | 36 +- pytype/tests/test_calls.py | 26 +- pytype/tests/test_classes.py | 47 +- pytype/tests/test_cmp.py | 28 +- pytype/tests/test_compile_to_pyc.py | 11 +- pytype/tests/test_containers.py | 12 +- pytype/tests/test_decorators.py | 16 +- pytype/tests/test_dict.py | 4 +- pytype/tests/test_disables.py | 23 +- pytype/tests/test_errors.py | 673 ++++++++---------- pytype/tests/test_exceptions.py | 31 +- pytype/tests/test_flow.py | 4 +- pytype/tests/test_functions.py | 89 +-- pytype/tests/test_future_overlay.py | 7 +- pytype/tests/test_import.py | 55 +- pytype/tests/test_list.py | 5 +- pytype/tests/test_namedtuple.py | 48 +- pytype/tests/test_operators.py | 8 +- pytype/tests/test_pyi.py | 26 +- pytype/tests/test_quick.py | 4 +- pytype/tests/test_recovery.py | 24 +- pytype/tests/test_reingest.py | 6 +- pytype/tests/test_slots.py | 99 +-- pytype/tests/test_special_builtins.py | 4 +- pytype/tests/test_splits.py | 10 +- pytype/tests/test_super.py | 38 +- pytype/tests/test_tracebacks.py | 42 +- pytype/tests/test_tuple.py | 13 +- pytype/tests/test_type_comments.py | 138 ++-- pytype/tests/test_typevar.py | 85 +-- pytype/tests/test_typing.py | 48 +- pytype/tests/test_typing_namedtuple.py | 85 +-- pytype/tests/test_unions.py | 9 +- pytype/tests/test_utils.py | 4 +- 88 files changed, 1650 insertions(+), 2146 deletions(-) diff --git a/pytype/tests/py2/test_abc.py b/pytype/tests/py2/test_abc.py index e396f67f2..0b4dc280c 100644 --- a/pytype/tests/py2/test_abc.py +++ b/pytype/tests/py2/test_abc.py @@ -7,15 +7,14 @@ class AbstractMethodTests(test_base.TargetPython27FeatureTest): """Tests for @abc.abstractmethod.""" def test_name_error(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import abc class Example(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def foo(self): - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(6, "name-error", r"name_error")]) def test_instantiate_abstract_class(self): _, errors = self.InferWithErrors("""\ @@ -25,9 +24,9 @@ class Example(object): @abc.abstractmethod def foo(self): pass - Example() # line 7 + Example() # not-instantiable[e] """) - self.assertErrorLogIs(errors, [(7, "not-instantiable", r"Example.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Example.*foo"}) def test_multiple_inheritance_implementation(self): self.Check(""" @@ -59,9 +58,9 @@ def foo(self): pass class Foo(X, Interface): pass - Foo().foo() # line 11 + Foo().foo() # not-instantiable[e] """) - self.assertErrorLogIs(errors, [(11, "not-instantiable", r"Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo.*foo"}) def test_multiple_inheritance_builtins(self): self.Check(""" diff --git a/pytype/tests/py2/test_attributes.py b/pytype/tests/py2/test_attributes.py index b48803837..dcbc0be3d 100644 --- a/pytype/tests/py2/test_attributes.py +++ b/pytype/tests/py2/test_attributes.py @@ -19,9 +19,9 @@ class A(object): values = 42 args = {A() if __random__ else True: ""} for x, y in sorted(args.iteritems()): - x.values # line 5 + x.values # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"'values' on bool")]) + self.assertErrorRegexes(errors, {"e": r"'values' on bool"}) def testTypeParameterInstanceSetAttr(self): ty = self.Infer(""" @@ -63,9 +63,9 @@ def testIter(self): errors = self.CheckWithErrors("""\ def f(): x = None - return [y for y in x] + return [y for y in x] # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"__iter__.*None")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*None"}) @test_base.skip("Needs vm._get_iter() to iterate over individual bindings.") def testMetaclassIter(self): diff --git a/pytype/tests/py2/test_builtins.py b/pytype/tests/py2/test_builtins.py index e9eddb389..4c1164cb9 100644 --- a/pytype/tests/py2/test_builtins.py +++ b/pytype/tests/py2/test_builtins.py @@ -349,10 +349,9 @@ def testIterItems(self): def testIntInit(self): _, errors = self.InferWithErrors("""\ - int(0, 1) # line 8: expected str or unicode, got int for first arg + int(0, 1) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Union\[str, unicode\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[str, unicode\].*int"}) def testAddStrAndBytearray(self): ty = self.Infer(""" diff --git a/pytype/tests/py2/test_decorators.py b/pytype/tests/py2/test_decorators.py index c8f401978..bb9347587 100644 --- a/pytype/tests/py2/test_decorators.py +++ b/pytype/tests/py2/test_decorators.py @@ -14,9 +14,9 @@ def decorate(cls): @decorate class Foo(object): def Hello(self): - return self.Goodbye() # line 6 + return self.Goodbye() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(6, "attribute-error", r"Goodbye")]) + self.assertErrorRegexes(errors, {"e": r"Goodbye"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_errors.py b/pytype/tests/py2/test_errors.py index cda165a2d..6e771c585 100644 --- a/pytype/tests/py2/test_errors.py +++ b/pytype/tests/py2/test_errors.py @@ -9,27 +9,27 @@ class ErrorTest(test_base.TargetPython27FeatureTest): def testProtocolMismatch(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", "__iter__, next") - ]) + self.assertErrorRegexes(errors, {"e": r"__iter__, next"}) def testProtocolMismatchPartial(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __iter__(self): return self - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 4, "wrong-arg-types", r"\n\s*next\s*$")]) # `next` on its own line + self.assertErrorRegexes( + errors, {"e": r"\n\s*next\s*$"}) # `next` on its own line def testGetSlice(self): - errors = self.CheckWithErrors("def f(): v = []; return v[:'foo']") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"slicing.*List.*str.*__getslice__ on List.*Optional\[int\]")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; return v[:'foo'] # unsupported-operands[e] + """) + self.assertErrorRegexes( + errors, + {"e": r"slicing.*List.*str.*__getslice__ on List.*Optional\[int\]"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_list.py b/pytype/tests/py2/test_list.py index f58dfc088..b62512840 100644 --- a/pytype/tests/py2/test_list.py +++ b/pytype/tests/py2/test_list.py @@ -18,8 +18,8 @@ def test_getslice_slot(self): g = a[2:None] h = a[None:2] i = a[None:None] - j = a[int:str] - k = a["s":] + j = a[int:str] # unsupported-operands[e1] + k = a["s":] # unsupported-operands[e2] l = a[1:-1] m = a[0:0] n = a[1:1] @@ -41,9 +41,8 @@ def test_getslice_slot(self): m = ... # type: List[nothing] n = ... # type: List[nothing] """) - self.assertErrorLogIs(errors, [ - (10, "unsupported-operands", r"__getslice__ on List"), - (11, "unsupported-operands", r"__getslice__ on List")]) + self.assertErrorRegexes(errors, { + "e1": r"__getslice__ on List", "e2": r"__getslice__ on List"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_namedtuple.py b/pytype/tests/py2/test_namedtuple.py index e1336c4ba..d7c07d8c2 100644 --- a/pytype/tests/py2/test_namedtuple.py +++ b/pytype/tests/py2/test_namedtuple.py @@ -23,18 +23,14 @@ def test_calls(self): """) def test_bad_call(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple() - collections.namedtuple("_") - collections.namedtuple("_", "", True, True, True) - collections.namedtuple("_", "", True, verbose=True) + collections.namedtuple() # missing-parameter + collections.namedtuple("_") # missing-parameter + collections.namedtuple("_", "", True, True, True) # wrong-arg-count + collections.namedtuple( + "_", "", True, verbose=True) # duplicate-keyword-argument """) - self.assertErrorLogIs(errorlog, - [(2, "missing-parameter"), - (3, "missing-parameter"), - (4, "wrong-arg-count"), - (5, "duplicate-keyword-argument")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_pyi.py b/pytype/tests/py2/test_pyi.py index 392028cd4..1dcb1448c 100644 --- a/pytype/tests/py2/test_pyi.py +++ b/pytype/tests/py2/test_pyi.py @@ -35,8 +35,10 @@ def get_varargs(x: int, *args: T, z: int, **kws: int) -> T: ... v1 = a.get_varargs(1, *l1) v2 = a.get_varargs(1, *l2, z=5) v3 = a.get_varargs(1, True, 2.0, z=5) - v4 = a.get_varargs(1, 2j, "foo", z=5) # bad: conflicting args types - v5 = a.get_varargs(1, *None) # bad: None not iterable + # bad: conflicting args types + v4 = a.get_varargs(1, 2j, "foo", z=5) # wrong-arg-types[e1] + # bad: None not iterable + v5 = a.get_varargs(1, *None) # wrong-arg-types[e2] """, deep=True, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any @@ -53,8 +55,7 @@ def get_varargs(x: int, *args: T, z: int, **kws: int) -> T: ... r"Actually passed: \(x, _, _2: str, \.\.\.\)") msg2 = (r"Expected: \(x, \*args: Iterable, \.\.\.\).*" r"Actually passed: \(x, args: None\)") - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", msg1), - (9, "wrong-arg-types", msg2)]) + self.assertErrorRegexes(errors, {"e1": msg1, "e2": msg2}) # TODO(sivachandra): Make this a target independent test after # after b/78785264 is fixed. @@ -69,11 +70,12 @@ def get_kwargs(x: int, *args: int, z: int, **kws: T) -> T: ... import a d1 = None # type: dict[int, int] d2 = None # type: Mapping[str, Union[str, complex]] - v1 = a.get_kwargs(1, 2, 3, z=5, **d1) # bad: K must be str + # bad: K must be str + v1 = a.get_kwargs(1, 2, 3, z=5, **d1) # wrong-arg-types[e1] v2 = a.get_kwargs(1, 2, 3, z=5, **d2) v3 = a.get_kwargs(1, 2, 3, z=5, v=0, u=3j) # bad: conflicting kwargs types - v4 = a.get_kwargs(1, 2, 3, z=5, v="", u=3j) + v4 = a.get_kwargs(1, 2, 3, z=5, v="", u=3j) # wrong-arg-types[e2] """, deep=True, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any, Mapping @@ -89,8 +91,7 @@ def get_kwargs(x: int, *args: int, z: int, **kws: T) -> T: ... r"Actually passed: \(x, _, _, z, kws: Dict\[int, int\]\)") msg2 = (r"Expected: \(x, _, _, u, v: complex, \.\.\.\).*" r"Actually passed: \(x, _, _, u, v: str, \.\.\.\)") - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", msg1), - (9, "wrong-arg-types", msg2)]) + self.assertErrorRegexes(errors, {"e1": msg1, "e2": msg2}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_reingest.py b/pytype/tests/py2/test_reingest.py index 7da3d2717..b541ffece 100644 --- a/pytype/tests/py2/test_reingest.py +++ b/pytype/tests/py2/test_reingest.py @@ -24,10 +24,10 @@ def foo(self): d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.Foo() + foo.Foo() # not-instantiable[e] foo.Bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_slots.py b/pytype/tests/py2/test_slots.py index 125c83611..a12232e05 100644 --- a/pytype/tests/py2/test_slots.py +++ b/pytype/tests/py2/test_slots.py @@ -7,24 +7,23 @@ class SlotsTest(test_base.TargetPython27FeatureTest): """Tests for __slots__.""" def testBuiltinAttr(self): - _, errors = self.InferWithErrors("""\ - buffer("foo").bar = 16 + self.InferWithErrors("""\ + buffer("foo").bar = 16 # not-writable """) - self.assertErrorLogIs(errors, [(1, "not-writable")]) def testSlotWithBytes(self): - _ = self.Check("""\ + self.Check("""\ class Foo(object): __slots__ = (b"x",) """) def testSlotWithUnicode(self): errors = self.CheckWithErrors("""\ - class Foo(object): + class Foo(object): # bad-slots[e] __slots__ = (u"fo\\xf6", u"b\\xe4r", "baz") Foo().baz = 3 """) - self.assertErrorLogIs(errors, [(1, "bad-slots", r"fo\\xc3\\xb6")]) + self.assertErrorRegexes(errors, {"e": r"fo\\xc3\\xb6"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_super.py b/pytype/tests/py2/test_super.py index 2b8b92cd1..c5c5f0d30 100644 --- a/pytype/tests/py2/test_super.py +++ b/pytype/tests/py2/test_super.py @@ -12,14 +12,13 @@ def testSuperMissingArg(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls): - return super(cls).__new__(cls) + return super(cls).__new__(cls) # wrong-arg-types[e1] class Bar(object): def __new__(cls): - return super().__new__(cls) + return super().__new__(cls) # wrong-arg-count[e2] """) - self.assertErrorLogIs(errors, [ - (3, "wrong-arg-types", r"Type\[super\].*Type\[Foo\]"), - (6, "wrong-arg-count", r"2.*0")]) + self.assertErrorRegexes( + errors, {"e1": r"Type\[super\].*Type\[Foo\]", "e2": r"2.*0"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_typevar.py b/pytype/tests/py2/test_typevar.py index fc3b447e0..e1d5b661e 100644 --- a/pytype/tests/py2/test_typevar.py +++ b/pytype/tests/py2/test_typevar.py @@ -9,7 +9,7 @@ class Test(test_base.TargetPython27FeatureTest): def testUseConstraintsFromPyi(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ from typing import AnyStr, TypeVar T = TypeVar("T", int, float) def f(x: T) -> T: ... @@ -17,25 +17,23 @@ def g(x: AnyStr) -> AnyStr: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f("") - foo.g(0) + foo.f("") # wrong-arg-types[e1] + foo.g(0) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"Union\[float, int\].*str"), - (3, "wrong-arg-types", r"Union\[str, unicode\].*int")]) + self.assertErrorRegexes(errors, { + "e1": r"Union\[float, int\].*str", + "e2": r"Union\[str, unicode\].*int"}) def testExtraArguments(self): # TODO(b/78905523): Make this a target-independent test. _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", extra_arg=42) - S = TypeVar("S", *__any_object__) - U = TypeVar("U", **__any_object__) + T = TypeVar("T", extra_arg=42) # invalid-typevar[e1] + S = TypeVar("S", *__any_object__) # invalid-typevar[e2] + U = TypeVar("U", **__any_object__) # invalid-typevar[e3] """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"extra_arg"), - (3, "invalid-typevar", r"\*args"), - (4, "invalid-typevar", r"\*\*kwargs")]) + self.assertErrorRegexes(errors, { + "e1": r"extra_arg", "e2": r"\*args", "e3": r"\*\*kwargs"}) def testSimplifyArgsAndKwargs(self): # TODO(b/78905523): Make this a target-independent test. diff --git a/pytype/tests/py3/test_abc.py b/pytype/tests/py3/test_abc.py index a0ad0dd34..692362565 100644 --- a/pytype/tests/py3/test_abc.py +++ b/pytype/tests/py3/test_abc.py @@ -63,7 +63,7 @@ class Bar(Foo): @property def foo(self): return super(Bar, self).foo - v1 = Foo().foo + v1 = Foo().foo # not-instantiable[e] v2 = Bar().foo """) self.assertTypesMatchPytd(ty, """ @@ -77,7 +77,7 @@ class Bar(Foo): class Foo(metaclass=abc.ABCMeta): foo = ... # type: Any """) - self.assertErrorLogIs(errors, [(10, "not-instantiable", r"Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_annotations.py b/pytype/tests/py3/test_annotations.py index f995c2c7a..14cf2a0c3 100644 --- a/pytype/tests/py3/test_annotations.py +++ b/pytype/tests/py3/test_annotations.py @@ -63,9 +63,9 @@ def testCallError(self): s = {1} def foo(x: int): s.intersection(x) - foo(3.0) + foo(3.0) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: int.*x: float")]) + self.assertErrorRegexes(errors, {"e": r"x: int.*x: float"}) def testAmbiguousArg(self): self.Check("""\ @@ -84,9 +84,9 @@ def g(y, z): def testInnerError(self): _, errors = self.InferWithErrors("""\ def foo(x: int): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) def testList(self): ty = self.Infer(""" @@ -170,45 +170,40 @@ def f(c: calendar.Calendar) -> int: ... def testAmbiguousAnnotation(self): _, errors = self.InferWithErrors("""\ - def foo(x: int if __random__ else float): + def foo(x: int if __random__ else float): # invalid-annotation[e1] return x - def foo(x: "int if __random__ else float"): + def foo(x: "int if __random__ else float"): # invalid-annotation[e2] return x """) - self.assertErrorLogIs(errors, { - (1, "invalid-annotation", r"float or int.*x.*constant"), - # For a late annotation, we print the string literal, which is why - # the types below are not in alphabetical order. - (3, "invalid-annotation", r"int.*float.*x.*constant")}) + self.assertErrorRegexes(errors, { + "e1": r"float or int.*x.*constant", + # For a late annotation, we print the string literal, which is why the + # types below are not in alphabetical order. + "e2": r"int.*float.*x.*constant"}) def testBadStringAnnotation(self): _, errors = self.InferWithErrors("""\ - def foo(x: str()): + def foo(x: str()): # invalid-annotation[e] return x """) - self.assertErrorLogIs(errors, { - (1, "invalid-annotation", r"x.*constant")}) + self.assertErrorRegexes(errors, {"e": r"x.*constant"}) def testBadReturn(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x: str, y: str) -> int: - return "foo" + return "foo" # bad-return-type """) - self.assertErrorLogIs(errors, { - (2, "bad-return-type")}) def testMultipleReturns(self): _, errors = self.InferWithErrors("""\ def foo(x: str, y: str) -> int: if x: - return "foo" + return "foo" # bad-return-type[e1] else: - return 3j + return 3j # bad-return-type[e2] """) - self.assertErrorLogIs(errors, { - (3, "bad-return-type", r"Expected.*int.*Actual.*str"), - (5, "bad-return-type", r"Expected.*int.*Actual.*complex") - }) + self.assertErrorRegexes(errors, {"e1": r"Expected.*int.*Actual.*str", + "e2": r"Expected.*int.*Actual.*complex"}) def testAmbiguousReturn(self): _, errors = self.InferWithErrors("""\ @@ -217,12 +212,10 @@ def foo(x: str) -> int: y = "foo" else: y = 3j - return y + return y # bad-return-type[e] """) - self.assertErrorLogIs(errors, { - (6, "bad-return-type", - r"Expected.*int.*Actual.*Union(?=.*complex).*str"), - }) + self.assertErrorRegexes( + errors, {"e": r"Expected.*int.*Actual.*Union(?=.*complex).*str"}) def testDefaultReturn(self): ty = self.Infer("""\ @@ -279,73 +272,56 @@ def f(x) -> None: ... """) def testDict(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Dict, List def keys(d: Dict[str, int]): return keys({"foo": 3}) keys({}) # ok - keys({3: 3}) # not allowed + keys({3: 3}) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testSequence(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Sequence def f(s: Sequence): return s f([1,2,3]) f((1,2,3)) - f({1,2,3}) - f(1) + f({1,2,3}) # wrong-arg-types + f(1) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testOptional(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Optional def f(s: Optional[int]): return s f(1) f(None) - f("foo") + f("foo") # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testSet(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Set def f(d: Set[str]): return f({"foo"}) # ok f(set()) # ok - f({}) # not allowed, {} isn't a set - f({3}) # not allowed + f({}) # {} isn't a set # wrong-arg-types + f({3}) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testFrozenSet(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import FrozenSet def f(d: FrozenSet[str]): return f(frozenset(["foo"])) # ok f(frozenset()) # ok - f(frozenset([3])) # not allowed + f(frozenset([3])) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testGenericAndTypeVar(self): self.assertNoCrash(self.Check, """\ @@ -385,13 +361,13 @@ class B(object): def testWithoutForwardDecl(self): _, errorlog = self.InferWithErrors("""\ - def f(a) -> Bar: + def f(a) -> Bar: # name-error[e] return Bar() class Bar(object): pass """) - self.assertErrorLogIs(errorlog, [(1, "name-error", r"Bar")]) + self.assertErrorRegexes(errorlog, {"e": r"Bar"}) def testInvalidForwardDecl(self): self.Check(""" @@ -402,25 +378,24 @@ class Foo(object): pass """) _, errorlog = self.InferWithErrors("""\ - def f(a: "Foo"): + def f(a: "Foo"): # name-error[e] return B() class B(object): pass """) - self.assertErrorLogIs(errorlog, [(1, "name-error", r"Foo")]) + self.assertErrorRegexes(errorlog, {"e": r"Foo"}) def testForwardDeclBadReturn(self): _, errorlog = self.InferWithErrors("""\ def f() -> "Foo": - return 1 + return 1 # bad-return-type[e] class Foo(object): pass """) # Error message along the lines: No attribute 'bar' on Foo - self.assertErrorLogIs( - errorlog, [(2, "bad-return-type", r"return type.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"return type.*int"}) def testConfusingForwardDecl(self): _, errorlog = self.InferWithErrors("""\ @@ -436,20 +411,18 @@ def bar(self): return 2 def g(): - return f().bar() + return f().bar() # attribute-error[e] """) # Error message along the lines: No attribute 'bar' on Foo - self.assertErrorLogIs( - errorlog, [(13, "attribute-error", r"\'bar\'.*Foo")]) + self.assertErrorRegexes(errorlog, {"e": r"\'bar\'.*Foo"}) def testReturnTypeError(self): _, errors = self.InferWithErrors("""\ class FooBar(object): pass def f() -> FooBar: - return 3 + return 3 # bad-return-type[e] """, deep=True) - self.assertErrorLogIs(errors, [( - 3, "bad-return-type", r"Expected: FooBar")]) + self.assertErrorRegexes(errors, {"e": r"Expected: FooBar"}) def testUnknownArgument(self): with file_utils.Tempdir() as d: @@ -477,7 +450,7 @@ def foo(): } labels['baz'] = bar( - labels['baz']) + labels['baz']) # wrong-arg-types[e] def bar(path: str, **kwargs): return path @@ -488,7 +461,7 @@ def foo() -> None def bar(path: str, **kwargs) -> str """) error = r"Actually passed:.*path: None" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testBadCallWithKwarg(self): ty, errors = self.InferWithErrors("""\ @@ -498,7 +471,7 @@ def foo(): } labels['baz'] = bar( - labels['baz'], x=42) + labels['baz'], x=42) # wrong-arg-types[e] def bar(path: str, **kwargs): return path @@ -509,7 +482,7 @@ def foo() -> None def bar(path: str, **kwargs) -> str """) error = r"Actually passed:.*path: None" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testSkipFunctionsWithAnnotations(self): ty = self.Infer("""\ @@ -567,13 +540,13 @@ def func(x: Union[Container1, Container2]): """) def testImpreciseAnnotation(self): - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ from typing import Union class A: pass class B: x = 42 def f(v: Union[A, B]): - return v.x + return v.x # attribute-error[e] f(A()) """) self.assertTypesMatchPytd(ty, """ @@ -583,7 +556,7 @@ class B: x = ... # type: int def f(v: Union[A, B]) -> int: ... """) - self.assertErrorLogIs(errors, [(7, "attribute-error", "x.*A")]) + self.assertErrorRegexes(errors, {"e": r"x.*A"}) def testTuple(self): ty = self.Infer(""" @@ -627,16 +600,16 @@ def g(x: Union["int"]): def testAmbiguousInnerAnnotation(self): _, errors = self.InferWithErrors("""\ from typing import List, Union - def f(x: List[int if __random__ else str]): + def f(x: List[int if __random__ else str]): # invalid-annotation[e1] pass - def g(x: Union[int if __random__ else str]): + def g(x: Union[int if __random__ else str]): # invalid-annotation[e2] pass def h(x: List[Union[int, str]]): # okay pass """) - self.assertErrorLogIs(errors, [ - (2, "invalid-annotation", r"List\[int\] or List\[str\].*constant"), - (4, "invalid-annotation", r"int or str.*constant")]) + self.assertErrorRegexes(errors, { + "e1": r"List\[int\] or List\[str\].*constant", + "e2": r"int or str.*constant"}) def testKwargs(self): ty, errors = self.InferWithErrors("""\ @@ -650,8 +623,8 @@ def h() -> Dict[float, int]: f("", y=42) f("", **{}) f("", **{"y": 42}) - f("", **g()) - f("", **h()) + f("", **g()) # wrong-arg-types[e1] + f("", **h()) # wrong-arg-types[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Dict @@ -663,8 +636,7 @@ def h() -> Dict[float, int] r"Actually passed.*Dict\[str, float\]") error2 = (r"Expected.*Mapping\[str, int\].*" r"Actually passed.*Dict\[float, int\]") - self.assertErrorLogIs(errors, [(11, "wrong-arg-types", error1), - (12, "wrong-arg-types", error2)]) + self.assertErrorRegexes(errors, {"e1": error1, "e2": error2}) @test_base.skip("Types not checked due to function.Args.simplify") def testSimplifiedVarargsAndKwargs(self): @@ -673,14 +645,12 @@ def f(x, *args: int): pass def g(x, **kwargs: int): pass - f("", 42.0) - g("", y=42.0) - g("", **{"y": 42.0}) + f("", 42.0) # wrong-arg-types[e1] + g("", y=42.0) # wrong-arg-types[e2] + g("", **{"y": 42.0}) # wrong-arg-types[e3] """) error = r"Expected.*int.*Actually passed.*float" - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", error), - (6, "wrong-arg-types", error), - (7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e1": error, "e2": error, "e3": error}) def testUseVarargsAndKwargs(self): ty = self.Infer(""" @@ -722,7 +692,7 @@ def f() -> Union[A, None]: pass def g() -> List[None]: return [None] - v1 = f().x # line 8 + v1 = f().x # attribute-error[e] v2 = g()[0] """, deep=False) self.assertTypesMatchPytd(ty, """ @@ -734,7 +704,7 @@ def g() -> List[None]: ... v1 = ... # type: int v2 = ... # type: None """) - self.assertErrorLogIs(errors, [(8, "attribute-error", r"x.*None")]) + self.assertErrorRegexes(errors, {"e": r"x.*None"}) def testMatchLateAnnotation(self): _, errors = self.InferWithErrors("""\ @@ -742,34 +712,33 @@ class A(object): def f(self, x: "A"): pass def f(): - A().f(42) + A().f(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", r"A.*int")]) + self.assertErrorRegexes(errors, {"e": r"A.*int"}) def testRecursiveForwardReference(self): _, errors = self.InferWithErrors("""\ class A(object): def __init__(self, x: "A"): self.foo = x.foo - f(x) + f(x) # wrong-arg-types[e1] def method1(self): self.foo def method2(self): - self.bar + self.bar # attribute-error[e2] def f(x: int): pass """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*A"), - (8, "attribute-error", r"bar")]) + self.assertErrorRegexes(errors, {"e1": r"int.*A", "e2": r"bar"}) def testModuleLevelForwardReferenceError(self): errors = self.CheckWithErrors("""\ class A(object): def f(self, x: "A"): pass - A().f(42) + A().f(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"A.*int")]) + self.assertErrorRegexes(errors, {"e": r"A.*int"}) def testReturnAnnotation1(self): ty = self.Infer(""" @@ -923,9 +892,9 @@ def g(x: int) -> int: ... def testEllipsis(self): ty, errors = self.InferWithErrors("""\ from typing import Dict, Tuple - def f(x: ...): pass + def f(x: ...): pass # invalid-annotation[e1] def g(x: Tuple[str, ...]): pass - def h(x: Dict[..., int]): pass + def h(x: Dict[..., int]): pass # invalid-annotation[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict, Tuple @@ -933,9 +902,8 @@ def f(x) -> None: ... def g(x: Tuple[str, ...]) -> None: ... def h(x: Dict[Any, int]) -> None: ... """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*x"), - (4, "invalid-annotation", r"Ellipsis.*Dict")]) + self.assertErrorRegexes( + errors, {"e1": r"Ellipsis.*x", "e2": r"Ellipsis.*Dict"}) def testCustomContainer(self): with file_utils.Tempdir() as d: @@ -952,13 +920,12 @@ def __init__(self, x: T2): def f(x: foo.Foo[int]): pass f(foo.Foo(42)) - f(foo.Foo("")) + f(foo.Foo("")) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Foo\[int\].*Foo\[str\]")]) + self.assertErrorRegexes(errors, {"e": r"Foo\[int\].*Foo\[str\]"}) def testNoImplicitOptional(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ from typing import Optional, Union def f1(x: str = None): pass @@ -968,10 +935,10 @@ def f3(x: Union[str, None] = None): pass def f4(x: Union[str, int] = None): pass - f1(None) + f1(None) # wrong-arg-types f2(None) f3(None) - f4(None) + f4(None) # wrong-arg-types """) self.assertTypesMatchPytd(ty, """ from typing import Optional, Union @@ -980,8 +947,6 @@ def f2(x: Optional[str] = ...) -> None: ... def f3(x: Optional[str] = ...) -> None: ... def f4(x: Union[str, int] = ...) -> None: ... """) - self.assertErrorLogIs(errors, [(10, "wrong-arg-types"), - (13, "wrong-arg-types")]) def testInferReturn(self): ty = self.Infer(""" @@ -1007,11 +972,10 @@ def testRecursiveTypeAlias(self): errors = self.CheckWithErrors("""\ from typing import List, Union Foo = Union[str, List['Foo']] - def f(x: Foo): + def f(x: Foo): # not-supported-yet[e] pass """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet", - r"Recursive.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Recursive.*Foo"}) def testFullyQuotedAnnotation(self): self.Check(""" @@ -1034,25 +998,23 @@ def f(x: List[Callable[[int], str]]) -> None: ... """) def testLateAnnotationNonNameError(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): pass - def f(x: "Foo.Bar"): + def f(x: "Foo.Bar"): # attribute-error pass """) - self.assertErrorLogIs(errors, [(3, "attribute-error")]) def testKeepContainerWithError(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ from typing import Dict - def f(x: "Dict[str, int.error]"): + def f(x: "Dict[str, int.error]"): # attribute-error pass """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict def f(x: Dict[str, Any]) -> None: ... """) - self.assertErrorLogIs(errors, [(2, "attribute-error")]) class TestAnnotationsPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_anystr.py b/pytype/tests/py3/test_anystr.py index 63177cd69..a07a63dc4 100644 --- a/pytype/tests/py3/test_anystr.py +++ b/pytype/tests/py3/test_anystr.py @@ -80,7 +80,7 @@ def testUseAnyStrConstraints(self): def f(x: AnyStr, y: AnyStr) -> AnyStr: return __any_object__ v1 = f(__any_object__, u"") # ok - v2 = f(__any_object__, 42) + v2 = f(__any_object__, 42) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, TypeVar @@ -89,19 +89,18 @@ def f(x: AnyStr, y: AnyStr) -> AnyStr: ... v1 = ... # type: str v2 = ... # type: Any """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testConstraintMismatch(self): _, errors = self.InferWithErrors("""\ from typing import AnyStr def f(x: AnyStr, y: AnyStr): ... f("", "") # ok - f("", b"") + f("", b"") # wrong-arg-types[e] f(b"", b"") # ok """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", - r"Expected.*y: str.*Actual.*y: bytes")]) + self.assertErrorRegexes( + errors, {"e": r"Expected.*y: str.*Actual.*y: bytes"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_async_generators.py b/pytype/tests/py3/test_async_generators.py index e2fd72ac8..3d4faca96 100644 --- a/pytype/tests/py3/test_async_generators.py +++ b/pytype/tests/py3/test_async_generators.py @@ -78,28 +78,25 @@ def testAnnotationError(self): from typing import AsyncGenerator, AsyncIterator, AsyncIterable, Any, Union async def gen1() -> AsyncGenerator[bool, int]: - yield 1 + yield 1 # bad-return-type[e1] async def gen2() -> AsyncIterator[bool]: - yield 1 + yield 1 # bad-return-type[e2] async def gen3() -> AsyncIterable[bool]: - yield 1 + yield 1 # bad-return-type[e3] - async def gen4() -> int: + async def gen4() -> int: # invalid-annotation[e4] yield 1 async def fun(): g = gen1() - await g.asend("str") + await g.asend("str") # wrong-arg-types[e5] """) - self.assertErrorLogIs(errors, [ - (4, "bad-return-type", r"bool.*int"), - (7, "bad-return-type", r"bool.*int"), - (10, "bad-return-type", r"bool.*int"), - (12, "invalid-annotation", - r"AsyncGenerator.*AsyncIterable.*AsyncIterator"), - (17, "wrong-arg-types", r"int.*str"),]) + self.assertErrorRegexes(errors, { + "e1": r"bool.*int", "e2": r"bool.*int", "e3": r"bool.*int", + "e4": r"AsyncGenerator.*AsyncIterable.*AsyncIterator", + "e5": r"int.*str"}) def testMatchBaseClassError(self): errors = self.CheckWithErrors("""\ @@ -134,16 +131,15 @@ def f6(x: AsyncGenerator[bool, Any]): pass f1(gen()) - f2(gen()) + f2(gen()) # wrong-arg-types[e1] f3(gen()) - f4(gen()) + f4(gen()) # wrong-arg-types[e2] f5(gen()) - f6(gen()) + f6(gen()) # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (32, "wrong-arg-types", r"bool.*Union\[int, str\]"), - (34, "wrong-arg-types", r"bool.*Union\[int, str\]"), - (36, "wrong-arg-types", r"bool.*Union\[int, str\]"),]) + self.assertErrorRegexes(errors, { + "e1": r"bool.*Union\[int, str\]", "e2": r"bool.*Union\[int, str\]", + "e3": r"bool.*Union\[int, str\]"}) def testProtocol(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_attr.py b/pytype/tests/py3/test_attr.py index 688e75bf2..beb5d300b 100644 --- a/pytype/tests/py3/test_attr.py +++ b/pytype/tests/py3/test_attr.py @@ -81,13 +81,12 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s - class Foo(object): + class Foo(object): # invalid-annotation x : int = attr.ib(type=str) """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation")]) def test_defaults_with_annotation(self): ty = self.Infer(""" @@ -218,14 +217,13 @@ def foo(cls) -> None: ... """) def test_bad_default_param_order(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s(auto_attribs=True) - class Foo(object): + class Foo(object): # invalid-function-definition x: int = 10 y: str """) - self.assertErrorLogIs(err, [(4, "invalid-function-definition")]) def test_subclass_auto_attribs(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_attributes.py b/pytype/tests/py3/test_attributes.py index c78771962..e38d3f18d 100644 --- a/pytype/tests/py3/test_attributes.py +++ b/pytype/tests/py3/test_attributes.py @@ -10,9 +10,9 @@ def testExplicitNone(self): errors = self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testClosure(self): self.Check(""" @@ -30,14 +30,13 @@ def testOverwriteGlobal(self): from typing import Optional d = ... # type: Optional[dict] if d: - formatter = lambda x: d.get(x, '') # line 4 + formatter = lambda x: d.get(x, '') # attribute-error[e] else: formatter = lambda x: '' d = None formatter('key') # line 8 """) - self.assertErrorLogIs( - errors, [(4, "attribute-error", r"get.*None.*traceback.*line 8")]) + self.assertErrorRegexes(errors, {"e": r"get.*None.*traceback.*line 8"}) class TestAttributes(test_base.TargetPython3BasicTest): @@ -47,9 +46,9 @@ def testAttrOnOptional(self): errors = self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testErrorInAny(self): errors = self.CheckWithErrors("""\ @@ -57,10 +56,9 @@ def testErrorInAny(self): def f(x: Any): if __random__: x = 42 - x.upper() # line 5 + x.upper() # attribute-error[e] """) - self.assertErrorLogIs( - errors, [(5, "attribute-error", r"upper.*int.*Union\[Any, int\]")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int.*Union\[Any, int\]"}) class TestAttributesPython3FeatureTest(test_base.TargetPython3FeatureTest): @@ -79,9 +77,9 @@ class A(object): values = 42 args = {A() if __random__ else True: ""} for x, y in sorted(args.items()): - x.values # line 5 + x.values # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"'values' on bool")]) + self.assertErrorRegexes(errors, {"e": r"'values' on bool"}) def testTypeParameterInstanceSetAttr(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_builtins.py b/pytype/tests/py3/test_builtins.py index 207c6e3de..5b0e28040 100644 --- a/pytype/tests/py3/test_builtins.py +++ b/pytype/tests/py3/test_builtins.py @@ -115,18 +115,16 @@ def testBuiltins(self): """) def testUnicode(self): - errors = self.CheckWithErrors("""\ - unicode("foo") + self.CheckWithErrors("""\ + unicode("foo") # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testBytesIteration(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): for x in bytes(): - return bytes() + x + return bytes() + x # unsupported-operands """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands")]) def test_inplace_division(self): self.Check("""\ @@ -140,18 +138,14 @@ def test_inplace_division(self): """) def test_removed_dict_methods(self): - errors = self.CheckWithErrors("""\ - {}.iteritems - {}.iterkeys - {}.itervalues - {}.viewitems - {}.viewkeys - {}.viewvalues - """) - self.assertErrorLogIs( - errors, [(1, "attribute-error"), (2, "attribute-error"), - (3, "attribute-error"), (4, "attribute-error"), - (5, "attribute-error"), (6, "attribute-error")]) + self.CheckWithErrors("""\ + {}.iteritems # attribute-error + {}.iterkeys # attribute-error + {}.itervalues # attribute-error + {}.viewitems # attribute-error + {}.viewkeys # attribute-error + {}.viewvalues # attribute-error + """) def test_dict_views(self): self.Check(""" @@ -424,21 +418,19 @@ def testItems(self): def testIntInit(self): _, errors = self.InferWithErrors("""\ - int(0, 1) # line 8: expected str or unicode, got int for first arg + int(0, 1) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testRemovedBuiltins(self): - errors = self.CheckWithErrors("""\ - long - {}.has_key + self.CheckWithErrors("""\ + long # name-error + {}.has_key # attribute-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (2, "attribute-error")]) def testRange(self): - ty, errors = self.InferWithErrors("""\ - xrange(3) + ty, _ = self.InferWithErrors("""\ + xrange(3) # name-error v = range(3) v[0] v[:] @@ -450,7 +442,6 @@ def testRange(self): y: int z: int """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testCreateStr(self): self.Check(""" @@ -569,8 +560,7 @@ def testOSErrorSubclasses(self): def testRawInput(self): # Removed in Python 3: - errors = self.CheckWithErrors("raw_input") - self.assertErrorLogIs(errors, [(1, "name-error")]) + self.CheckWithErrors("raw_input # name-error") def testClear(self): # new in Python 3 @@ -630,20 +620,18 @@ def testMinMax(self): """) def testStrIsNotInt(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import SupportsInt def f(x: SupportsInt): pass - f("") + f("") # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types")]) def testStrIsNotFloat(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import SupportsFloat def f(x: SupportsFloat): pass - f("") + f("") # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_checker.py b/pytype/tests/py3/test_checker.py index 19cb8ba81..8eecee850 100644 --- a/pytype/tests/py3/test_checker.py +++ b/pytype/tests/py3/test_checker.py @@ -22,19 +22,18 @@ class X(object): def __init__(self, val: "X"): pass def f(): - X(42) + X(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errorlog, [(5, "wrong-arg-types", r"X.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"X.*int"}) def testBadReturnTypeInline(self): errorlog = self.CheckWithErrors("""\ from typing import List def f() -> List[int]: - return [object()] + return [object()] # bad-return-type[e] f()[0] += 1 """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"List\[int\].*List\[object\]")]) + self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[object\]"}) def testUseVarargsAndKwargs(self): self.Check("""\ @@ -89,50 +88,46 @@ def testBadDictValue(self): errorlog = self.CheckWithErrors("""\ from typing import Dict def f() -> Dict[str, int]: - return {"x": 42.0} + return {"x": 42.0} # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", r"int.*float")]) + self.assertErrorRegexes(errorlog, {"e": r"int.*float"}) def testInstanceAsAnnotation(self): errorlog = self.CheckWithErrors("""\ def f(): pass - def g(x: f): + def g(x: f): # invalid-annotation[e1] pass - def h(x: 3): + def h(x: 3): # invalid-annotation[e2] pass """) - self.assertErrorLogIs(errorlog, [(3, "invalid-annotation", - r"instance of Callable.*x"), - (5, "invalid-annotation", - r"3.*x")]) + self.assertErrorRegexes( + errorlog, {"e1": r"instance of Callable.*x", "e2": r"3.*x"}) def testBadGenerator(self): errorlog = self.CheckWithErrors("""\ from typing import Generator def f() -> Generator[str, None, None]: for i in range(3): - yield i + yield i # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(4, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"str.*int"}) def testMultipleParameterBindings(self): errorlog = self.CheckWithErrors("""\ from typing import List def f(x) -> List[int]: - return ["", x] + return ["", x] # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"List\[int\].*List\[str\]")]) + self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[str\]"}) def testNoParamBinding(self): errorlog = self.CheckWithErrors("""\ def f() -> None: x = [] - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"None.*List\[nothing\]")]) + self.assertErrorRegexes(errorlog, {"e": r"None.*List\[nothing\]"}) def testAttributeInIncompleteInstance(self): errorlog = self.CheckWithErrors("""\ @@ -140,30 +135,31 @@ def testAttributeInIncompleteInstance(self): class Foo(object): def __init__(self, other: "List[Foo]"): self.x = other[0].x # okay - self.y = other.y # No "y" on List[Foo] - self.z = Foo.z # No "z" on Type[Foo] + # No "y" on List[Foo] + self.y = other.y # attribute-error[e1] + # No "z" on Type[Foo] + self.z = Foo.z # attribute-error[e2] """) - self.assertErrorLogIs(errorlog, [(5, "attribute-error", r"y.*List\[Foo\]"), - (6, "attribute-error", r"z.*Type\[Foo\]")]) + self.assertErrorRegexes(errorlog, {"e1": r"y.*List\[Foo\]", + "e2": r"z.*Type\[Foo\]"}) def testBadGetItem(self): errorlog = self.CheckWithErrors("""\ def f(x: int): - return x[0] + return x[0] # unsupported-operands[e] """) - self.assertErrorLogIs(errorlog, [(2, "unsupported-operands", r"int.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"int.*int"}) def testBadAnnotationContainer(self): errorlog = self.CheckWithErrors("""\ class A(object): pass - def f(x: int[str]): + def f(x: int[str]): # not-indexable[e1] pass - def g(x: A[str]): + def g(x: A[str]): # not-indexable[e2] pass """) - self.assertErrorLogIs(errorlog, [(3, "not-indexable", r"Generic"), - (5, "not-indexable", r"Generic")]) + self.assertErrorRegexes(errorlog, {"e1": r"Generic", "e2": r"Generic"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_classes.py b/pytype/tests/py3/test_classes.py index 16e2a2860..e3dda37f1 100644 --- a/pytype/tests/py3/test_classes.py +++ b/pytype/tests/py3/test_classes.py @@ -70,9 +70,9 @@ def __init__(self, x): def Create(self, x: MyType): self.x = x def Convert(self): - self.y + self.y # attribute-error[e] """) - self.assertErrorLogIs(errors, [(9, "attribute-error", r"y.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"y.*Foo"}) def testRecursiveConstructorSubclass(self): self.Check(""" @@ -169,17 +169,16 @@ def __init__(self, obj: Sequence): pass class Y(X): def __init__(self, obj: int): - X.__init__(self, obj) # line 7 + X.__init__(self, obj) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", r"Sequence.*int")]) + self.assertErrorRegexes(errors, {"e": r"Sequence.*int"}) def testParameterizedClassBinaryOperator(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Sequence def f(x: Sequence[str], y: Sequence[str]) -> None: - a = x + y + a = x + y # unsupported-operands """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands")]) def testInstanceAttribute(self): ty = self.Infer(""" @@ -415,13 +414,12 @@ def bar(cls): def testPy2Metaclass(self): errors = self.CheckWithErrors("""\ import abc - class Foo(object): + class Foo(object): # ignored-metaclass[e] __metaclass__ = abc.ABCMeta @abc.abstractmethod def f(self) -> int: ... """) - self.assertErrorLogIs( - errors, [(2, "ignored-metaclass", r"abc\.ABCMeta.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"abc\.ABCMeta.*Foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_coroutine.py b/pytype/tests/py3/test_coroutine.py index c1348ea1b..c859f0d32 100644 --- a/pytype/tests/py3/test_coroutine.py +++ b/pytype/tests/py3/test_coroutine.py @@ -71,7 +71,7 @@ def caller() -> Coroutine[Any, Any, Union[int, str]]: ... def testNativeCoroutineError(self): errors = self.CheckWithErrors("""\ async def f1() -> str: - return 1 + return 1 # bad-return-type[e1] async def f2() -> int: return 1 @@ -84,13 +84,11 @@ def f4(x: str): async def caller(): f4(await f1()) - f4(await f2()) - f4(await f3()) + f4(await f2()) # wrong-arg-types[e2] + f4(await f3()) # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (2, "bad-return-type", r"str.*int"), - (15, "wrong-arg-types", r"str.*int"), - (16, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes( + errors, {"e1": r"str.*int", "e2": r"str.*int", "e3": r"str.*int"}) def testGeneratorBasedCoroutinePyi(self): ty = self.Infer(""" @@ -149,13 +147,12 @@ def f3(x, y: str): pass async def caller(): - x = await f1() + x = await f1() # bad-return-type[e1] y = await f2() - f3(x, y) + f3(x, y) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [ - (17, "bad-return-type", r"Awaitable.*int"), - (19, "wrong-arg-types", r"y: str.*y: int")]) + self.assertErrorRegexes( + errors, {"e1": r"Awaitable.*int", "e2": r"y: str.*y: int"}) def testAwaitablePyi(self): ty = self.Infer(""" @@ -220,10 +217,9 @@ class A(object): pass async def fun(): - await A() + await A() # bad-return-type[e] """) - self.assertErrorLogIs(errors, [ - (5, "bad-return-type", r"Awaitable.*A")]) + self.assertErrorRegexes(errors, {"e": r"Awaitable.*A"}) def testAsyncForPyi(self): ty = self.Infer(""" @@ -298,21 +294,19 @@ async def __anext__(self): async def caller(): res = [] - async for i in Iter1(): + async for i in Iter1(): # attribute-error[e1] res.append(i) - async for i in Iter2(): + async for i in Iter2(): # attribute-error[e2] res.append(i) - async for i in Iter3(): + async for i in Iter3(): # bad-return-type[e3] res.append(i) async for i in Iter4(): res.append(i) return res """) - self.assertErrorLogIs(errors, [ - (36, "attribute-error", r"No attribute.*__aiter__"), - (38, "attribute-error", r"No attribute.*__anext__"), - (40, "bad-return-type", r"Awaitable.*Union\[int, str]"), - ]) + self.assertErrorRegexes(errors, {"e1": r"No attribute.*__aiter__", + "e2": r"No attribute.*__anext__", + "e3": r"Awaitable.*Union\[int, str\]"}) def testAsyncWithPyi(self): ty = self.Infer(""" @@ -355,6 +349,7 @@ def log(s: _T0) -> Coroutine[Any, Any, _T0]: ... """) def testAsyncWithError(self): + # pylint: disable=anomalous-backslash-in-string errors = self.CheckWithErrors("""\ class AsyncCtx1(object): pass @@ -367,15 +362,15 @@ def __aexit__(self, exc_type, exc, tb): return "str" async def caller(): - async with AsyncCtx1() as var1, AsyncCtx2() as var2: - pass + ctx1 = AsyncCtx1() + ctx2 = AsyncCtx2() + async with ctx1 as var1: # attribute-error[e1] # attribute-error[e2] + async with ctx2 as var2: # bad-return-type[e3] + pass # bad-return-type[e4] """) - self.assertErrorLogIs(errors, [ - (12, "attribute-error", r"No attribute.*__aexit__"), - (12, "attribute-error", r"No attribute.*__aenter__"), - (12, "bad-return-type", r"Awaitable.*AsyncCtx2"), - (13, "bad-return-type", r"Awaitable.*str"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"No attribute.*__aexit__", "e2": r"No attribute.*__aenter__", + "e3": r"Awaitable.*AsyncCtx2", "e4": r"Awaitable.*str"}) def testLoadPyi(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/py3/test_dataclasses.py b/pytype/tests/py3/test_dataclasses.py index 3e812f420..94dd59d2c 100644 --- a/pytype/tests/py3/test_dataclasses.py +++ b/pytype/tests/py3/test_dataclasses.py @@ -135,31 +135,28 @@ def __init__(self, x: bool = ..., y: List[int] = ...) -> None: ... """) def test_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = 10 """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_field_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = dataclasses.field(default=10) """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_factory_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = dataclasses.field(default_factory=set) """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_field_no_init(self): ty = self.Infer(""" @@ -194,14 +191,13 @@ def __init__(self, x: bool, y: int) -> None: ... """) def test_bad_default_param_order(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # invalid-function-definition x: int = 10 y: str """) - self.assertErrorLogIs(err, [(4, "invalid-function-definition")]) def test_any(self): self.Check(""" diff --git a/pytype/tests/py3/test_decorators.py b/pytype/tests/py3/test_decorators.py index f21339cec..9166f54fc 100644 --- a/pytype/tests/py3/test_decorators.py +++ b/pytype/tests/py3/test_decorators.py @@ -7,15 +7,14 @@ class DecoratorsTest(test_base.TargetPython3BasicTest): """Test decorators.""" def testAnnotatedSuperCallUnderBadDecorator(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class Foo(object): def Run(self) -> None: ... class Bar(Foo): - @bad_decorator # line 4 + @bad_decorator # name-error def Run(self): return super(Bar, self).Run() """) - self.assertErrorLogIs(errors, [(4, "name-error", r"bad_decorator")]) def testReplaceSelfToStarArg(self): # Without decorator, `self` will be in `signature.param_names`. diff --git a/pytype/tests/py3/test_dict.py b/pytype/tests/py3/test_dict.py index 2f89f742b..49540fb1a 100644 --- a/pytype/tests/py3/test_dict.py +++ b/pytype/tests/py3/test_dict.py @@ -21,16 +21,15 @@ def foo(x: Union[int, None]) -> Any """) def testObjectInDict(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Any, Dict def objectIsStr() -> Dict[str, Any]: - return {object(): ""} + return {object(): ""} # bad-return-type """) - self.assertErrorLogIs(errors, [(3, "bad-return-type")]) def testBigConcreteDict(self): # Test that we don't timeout. - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Dict, Tuple, Union # A concrete dictionary with lots of concrete keys and a complicated # value type. @@ -50,9 +49,8 @@ def testBigConcreteDict(self): def f() -> Dict[Union[str, Tuple[str, None]], ValueType]: return d def g() -> Dict[int, int]: - return d # line 20 + return d # bad-return-type """) - self.assertErrorLogIs(errorlog, [(20, "bad-return-type")]) def testDictOfTuple(self): # utils.deep_variable_product(group_dict) generates a lot of combinations. diff --git a/pytype/tests/py3/test_errors.py b/pytype/tests/py3/test_errors.py index 6293dc2aa..678bb45c8 100644 --- a/pytype/tests/py3/test_errors.py +++ b/pytype/tests/py3/test_errors.py @@ -18,39 +18,36 @@ def f(x: int): else: i = 1 x = (3.14, "") - f(x[i]) + f(x[i]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Actually passed:.*Union\[float, str\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actually passed:.*Union\[float, str\]"}) def testInvalidAnnotations(self): _, errors = self.InferWithErrors("""\ from typing import Dict, List, Union def f1(x: Dict): # okay pass - def f2(x: Dict[str]): + def f2(x: Dict[str]): # invalid-annotation[e1] pass - def f3(x: List[int, str]): + def f3(x: List[int, str]): # invalid-annotation[e2] pass - def f4(x: Union): + def f4(x: Union): # invalid-annotation[e3] pass """) - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", r"typing.Dict\[_K, _V].*2.*1"), - (6, "invalid-annotation", r"typing.List\[_T].*1.*2"), - (8, "invalid-annotation", r"Union.*x")]) + self.assertErrorRegexes(errors, {"e1": r"typing.Dict\[_K, _V].*2.*1", + "e2": r"typing.List\[_T].*1.*2", + "e3": r"Union.*x"}) def testPrintUnsolvable(self): _, errors = self.InferWithErrors("""\ from typing import List - def f(x: List[nonsense], y: str, z: float): + def f(x: List[nonsense], y: str, z: float): # name-error pass - f({nonsense}, "", "") + f({nonsense}, "", "") # name-error # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "name-error", r"nonsense"), - (4, "name-error", r"nonsense"), - (4, "wrong-arg-types", r"Expected:.*x: list.*Actual.*x: set")]) + self.assertErrorRegexes( + errors, {"e": r"Expected:.*x: list.*Actual.*x: set"}) def testPrintUnionOfContainers(self): _, errors = self.InferWithErrors("""\ @@ -60,75 +57,72 @@ def f(x: str): x = dict else: x = [float] - f(x) + f(x) # wrong-arg-types[e] """) error = r"Actual.*Union\[List\[Type\[float\]\], Type\[dict\]\]" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testWrongBrackets(self): _, errors = self.InferWithErrors("""\ from typing import List - def f(x: List(str)): + def f(x: List(str)): # not-callable[e] pass """) - self.assertErrorLogIs(errors, [(2, "not-callable", r"List")]) + self.assertErrorRegexes(errors, {"e": r"List"}) def testInterpreterClassPrinting(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass def f(x: str): pass - f(Foo()) + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"str.*Foo"}) def testPrintDictAndTuple(self): _, errors = self.InferWithErrors("""\ from typing import Tuple tup = None # type: Tuple[int, ...] dct = None # type: dict[str, int] - def f1(x: (int, str)): # line 4 + def f1(x: (int, str)): # invalid-annotation[e1] pass - def f2(x: tup): # line 6 + def f2(x: tup): # invalid-annotation[e2] pass - def g1(x: {"a": 1}): # line 8 + def g1(x: {"a": 1}): # invalid-annotation[e3] pass - def g2(x: dct): # line 10 + def g2(x: dct): # invalid-annotation[e4] pass """) - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", r"(int, str).*Not a type"), - (6, "invalid-annotation", - r"instance of Tuple\[int, \.\.\.\].*Not a type"), - (8, "invalid-annotation", r"{'a': '1'}.*Not a type"), - (10, "invalid-annotation", r"instance of Dict\[str, int\].*Not a type") - ]) + self.assertErrorRegexes(errors, { + "e1": r"(int, str).*Not a type", + "e2": r"instance of Tuple\[int, \.\.\.\].*Not a type", + "e3": r"{'a': '1'}.*Not a type", + "e4": r"instance of Dict\[str, int\].*Not a type"}) def testMoveUnionInward(self): _, errors = self.InferWithErrors("""\ - def f() -> str: + def f() -> str: # invalid-annotation[e] y = "hello" if __random__ else 42 yield y """) - self.assertErrorLogIs(errors, [( - 1, "invalid-annotation", r"Generator, Iterable or Iterator")]) + self.assertErrorRegexes(errors, {"e": r"Generator, Iterable or Iterator"}) def testInnerClassError(self): _, errors = self.InferWithErrors("""\ def f(x: str): pass def g(): class Foo(object): pass - f(Foo()) + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: str.*x: Foo")]) + self.assertErrorRegexes(errors, {"e": r"x: str.*x: Foo"}) def testInnerClassError2(self): _, errors = self.InferWithErrors("""\ def f(): class Foo(object): pass def g(x: Foo): pass - g("") + g("") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: Foo.*x: str")]) + self.assertErrorRegexes(errors, {"e": r"x: Foo.*x: str"}) def testCleanNamedtupleNames(self): # Make sure the namedtuple renaming in _pytd_print correctly extracts type @@ -140,54 +134,44 @@ def testCleanNamedtupleNames(self): W = collections.namedtuple("W", "abc def ghi abc", rename=True) def bar(x: str): return x - bar(X(1,2,3,4)) # 7 - bar(Y()) # 8 - bar(W(1,2,3,4)) # 9 - bar({1: 2}.__iter__()) # 10 + bar(X(1,2,3,4)) # wrong-arg-types[e1] + bar(Y()) # wrong-arg-types[e2] + bar(W(1,2,3,4)) # wrong-arg-types[e3] + bar({1: 2}.__iter__()) # wrong-arg-types[e4] if __random__: a = X(1,2,3,4) else: a = 1 - bar(a) # 15 + bar(a) # wrong-arg-types[e5] """) - self.assertErrorLogIs(errors, - [(7, "wrong-arg-types", r"`X`"), - (8, "wrong-arg-types", r"`Z`"), - (9, "wrong-arg-types", r"`W`"), - (10, "wrong-arg-types", r"`dictionary-keyiterator`"), - (15, "wrong-arg-types", r"Union\[int, `X`\]") - ]) + self.assertErrorRegexes(errors, { + "e1": r"`X`", "e2": r"`Z`", "e3": r"`W`", + "e4": r"`dictionary-keyiterator`", "e5": r"Union\[int, `X`\]"}) def testArgumentOrder(self): _, errors = self.InferWithErrors("""\ def g(f: str, a, b, c, d, e,): pass - g(a=1, b=2, c=3, d=4, e=5, f=6) + g(a=1, b=2, c=3, d=4, e=5, f=6) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", - r"Expected.*f: str, \.\.\..*Actual.*f: int, \.\.\.")] - ) + self.assertErrorRegexes(errors, { + "e": r"Expected.*f: str, \.\.\..*Actual.*f: int, \.\.\."}) def testConversionOfGeneric(self): - _, errors = self.InferWithErrors(""" + self.InferWithErrors("""\ import os def f() -> None: - return os.walk("/tmp") + return os.walk("/tmp") # bad-return-type """) - self.assertErrorLogIs(errors, [ - (4, "bad-return-type") - ]) def testInnerClass(self): _, errors = self.InferWithErrors("""\ def f() -> int: class Foo(object): pass - return Foo() # line 4 + return Foo() # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(4, "bad-return-type", r"int.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"int.*Foo"}) def testNestedProtoClass(self): with file_utils.Tempdir() as d: @@ -200,14 +184,13 @@ class Foo: errors = self.CheckWithErrors("""\ import foo_bar def f(x: foo_bar.Foo.Bar): ... - f(42) + f(42) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(3, "wrong-arg-types", r"foo_bar\.Foo\.Bar")]) + self.assertErrorRegexes(errors, {"e": r"foo_bar\.Foo\.Bar"}) def testStaticmethodInError(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ class A(object): @staticmethod def t(a: str) -> None: ... @@ -217,12 +200,10 @@ def t(a: str) -> None: ... import foo def f(x: Callable[[int], None], y: int) -> None: return x(y) - f(foo.A.t, 1) + f(foo.A.t, 1) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, - [(5, "wrong-arg-types", - r"Actually passed: \(x: Callable\[\[str\], None\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actually passed: \(x: Callable\[\[str\], None\]"}) def testGeneratorSend(self): errors = self.CheckWithErrors("""\ @@ -234,26 +215,25 @@ def f(x) -> Generator[Any, int, Any]: yield "1" x = f(2) - x.send("123") + x.send("123") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(9, "wrong-arg-types", - r"\(self, value: int\)")]) + self.assertErrorRegexes(errors, {"e": r"\(self, value: int\)"}) def testGeneratorIteratorRetType(self): errors = self.CheckWithErrors("""\ from typing import Iterator def f() -> Iterator[str]: - yield 1 + yield 1 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def testGeneratorIterableRetType(self): errors = self.CheckWithErrors("""\ from typing import Iterable def f() -> Iterable[str]: - yield 1 + yield 1 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class InPlaceOperationsTest(test_base.TargetPython3BasicTest): @@ -266,11 +246,10 @@ def __%s__(self, x: "A"): return None def f(): v = A() - v %s 3 # line 6 + v %s 3 # unsupported-operands[e] """ % (op, symbol)) - self.assertErrorLogIs(errors, [ - (6, "unsupported-operands", - r"%s.*A.*int.*__%s__ on A.*A" % (re.escape(symbol), op))]) + self.assertErrorRegexes(errors, { + "e": r"%s.*A.*int.*__%s__ on A.*A" % (re.escape(symbol), op)}) def testISub(self): self._testOp("isub", "-=") @@ -287,10 +266,10 @@ def __itruediv__(self, x: "A"): return None def f(): v = A() - v /= 3 # line 8 + v /= 3 # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [ - (8, "unsupported-operands", r"\/\=.*A.*int.*__i(true)?div__ on A.*A")]) + self.assertErrorRegexes( + errors, {"e": r"\/\=.*A.*int.*__i(true)?div__ on A.*A"}) def testIMod(self): self._testOp("imod", "%=") @@ -323,40 +302,40 @@ class ErrorTestPy3(test_base.TargetPython3FeatureTest): def testProtocolMismatch(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", "__iter__, __next__") - ]) + self.assertErrorRegexes(errors, {"e": r"__iter__, __next__"}) def testProtocolMismatchPartial(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __iter__(self): return self - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 4, "wrong-arg-types", r"\n\s*__next__\s*$")]) # `next` on its own line + self.assertErrorRegexes( + errors, {"e": r"\n\s*__next__\s*$"}) # `next` on its own line def testGeneratorSendRetType(self): _, errors = self.InferWithErrors("""\ from typing import Generator def f() -> Generator[int, str, int]: x = yield 1 - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(4, "bad-return-type", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) class MatrixOperationsTest(test_base.TargetPython3FeatureTest): """Test matrix operations.""" def testMatMul(self): - errors = self.CheckWithErrors("def f(): return 'foo' @ 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\@.*str.*int.*'__matmul__' on str.*'__rmatmul__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): + return 'foo' @ 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\@.*str.*int.*'__matmul__' on str.*'__rmatmul__' on int"}) def testIMatMul(self): errors = self.CheckWithErrors("""\ @@ -365,10 +344,9 @@ def __imatmul__(self, x: "A"): pass def f(): v = A() - v @= 3 # line 6 + v @= 3 # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [ - (6, "unsupported-operands", r"\@.*A.*int.*__imatmul__ on A.*A")]) + self.assertErrorRegexes(errors, {"e": r"\@.*A.*int.*__imatmul__ on A.*A"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_exceptions.py b/pytype/tests/py3/test_exceptions.py index c9f9de5f9..97e3de9d9 100644 --- a/pytype/tests/py3/test_exceptions.py +++ b/pytype/tests/py3/test_exceptions.py @@ -18,8 +18,7 @@ def test_raise_exception_from(self): def test_exception_message(self): # This attribute was removed in Python 3. - errors = self.CheckWithErrors("ValueError().message") - self.assertErrorLogIs(errors, [(1, "attribute-error")]) + self.CheckWithErrors("ValueError().message # attribute-error") def test_suppress_context(self): self.Check("ValueError().__suppress_context__") diff --git a/pytype/tests/py3/test_functions.py b/pytype/tests/py3/test_functions.py index 1ad2c39b7..ed6e8f18a 100644 --- a/pytype/tests/py3/test_functions.py +++ b/pytype/tests/py3/test_functions.py @@ -11,9 +11,9 @@ def test_error(self): errors = self.CheckWithErrors("""\ def f(x: int): def g(): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", "upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) class TestClosuresPy3(test_base.TargetPython3FeatureTest): @@ -37,16 +37,15 @@ def f(a: int) -> Optional[str] """) def test_closures_delete_deref(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): x = "hello" def g(): nonlocal x # force x to be stored in a closure cell x = 10 del x - return x + return x # name-error """) - self.assertErrorLogIs(errors, [(7, "name-error")]) def test_nonlocal(self): ty = self.Infer("""\ @@ -63,16 +62,15 @@ def f() -> int """) def test_nonlocal_delete_deref(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): x = True def g(): nonlocal x del x g() - return x + return x # name-error """) - self.assertErrorLogIs(errors, [(7, "name-error")]) def test_reuse_after_delete_deref(self): ty = self.Infer("""\ @@ -95,13 +93,13 @@ def f(): a = 1 def g(x: int) -> int: a # makes sure g is a closure - return "hello" + return "hello" # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(5, "bad-return-type", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_filter_before_delete(self): # TODO(b/117463644): Remove the disable on line 7. - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): if x is None: @@ -111,9 +109,8 @@ def nested(): print(x.upper()) # pytype: disable=name-error del x nested() - return x # line 10 + return x # name-error """) - self.assertErrorLogIs(errors, [(10, "name-error")]) class PreciseReturnTest(test_base.TargetPython3BasicTest): @@ -127,26 +124,26 @@ def test_interpreter_return(self): ty, errors = self.InferWithErrors("""\ def f(x: str) -> str: return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ def f(x: str) -> str: ... x: str """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_unknown_return(self): ty, errors = self.InferWithErrors("""\ def f(x: str): return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any def f(x: str) -> str: ... x: Any """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_overload(self): ty, errors = self.InferWithErrors("""\ @@ -155,7 +152,7 @@ def test_interpreter_overload(self): def f(x: str) -> str: ... def f(x): return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import overload @@ -163,7 +160,7 @@ def f(x): def f(x: str) -> str: ... x: str """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class TestFunctions(test_base.TargetPython3BasicTest): @@ -238,24 +235,20 @@ def f( """) def test_typecheck_varargs(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(*args: int) -> int: return args[0] - f(*['value']) - f(1, 'hello', 'world') + f(*['value']) # wrong-arg-types + f(1, 'hello', 'world') # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types"), - (4, "wrong-arg-types")]) def test_typecheck_kwargs(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(**kwargs: int) -> int: return len(kwargs.values()) - f(**{'arg': 'value'}) - f(arg='value', arg2=3) - """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types"), - (4, "wrong-arg-types")]) + f(**{'arg': 'value'}) # wrong-arg-types + f(arg='value', arg2=3) # wrong-arg-types + """) def test_pass_func_to_complex_func(self): # This test gets an unsolvable binding added to the variable containing the @@ -304,14 +297,11 @@ def text_varargs_errors(self): errors = self.CheckWithErrors("""\ def foo(x: str, *y: int): pass - foo(*[1, 2, 3]) + foo(*[1, 2, 3]) # wrong-arg-types[e1] def bar(*z: int): - foo(*z) + foo(*z) # wrong-arg-types[e2] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", "str.*int"), - (5, "wrong-arg-types", "str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) def test_varargs_in_pyi(self): with file_utils.Tempdir() as d: @@ -332,9 +322,9 @@ def f(x: int, *args): ... errors = self.CheckWithErrors("""\ import foo def g(*args): - foo.f("", *args) + foo.f("", *args) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) class TestFunctionsPython3Feature(test_base.TargetPython3FeatureTest): @@ -597,9 +587,9 @@ def test_varargs_with_missing_kwonly(self): def foo(x: int, *args: int, z: int) -> None: pass - foo(1, 2, 5) + foo(1, 2, 5) # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(4, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) def test_multiple_varargs_packs(self): self.Check(""" @@ -619,14 +609,11 @@ def text_multiple_varargs_packs_errors(self): errors = self.CheckWithErrors("""\ def foo(x: str, *y: int): pass - foo(*[1, 2, 3], *[4, 5, 6]) + foo(*[1, 2, 3], *[4, 5, 6]) # wrong-arg-types[e1] def bar(*z: int): - foo(*z, *z) + foo(*z, *z) # wrong-arg-types[e2] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", "str.*int"), - (5, "wrong-arg-types", "str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_generators.py b/pytype/tests/py3/test_generators.py index 60bc4f4a7..b785ce4e1 100644 --- a/pytype/tests/py3/test_generators.py +++ b/pytype/tests/py3/test_generators.py @@ -33,9 +33,9 @@ def testNoReturn(self): _, errors = self.InferWithErrors("""\ from typing import Generator def f() -> Generator[str, None, None]: - yield 42 + yield 42 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class GeneratorFeatureTest(test_base.TargetPython3FeatureTest): @@ -97,17 +97,15 @@ def func1() -> Generator[int, int, int]: x = yield 5 return x - def func2() -> Generator[int, int]: + def func2() -> Generator[int, int]: # invalid-annotation[e1] x = yield 5 - def func3() -> Generator[int]: + def func3() -> Generator[int]: # invalid-annotation[e2] yield 5 """) - self.assertErrorLogIs(errors, [ - (7, "invalid-annotation", - r"typing.Generator\[_T, _T2, _V].*3.*2"), - (10, "invalid-annotation", - r"typing.Generator\[_T, _T2, _V].*3.*1")]) + self.assertErrorRegexes(errors, { + "e1": r"typing.Generator\[_T, _T2, _V].*3.*2", + "e2": r"typing.Generator\[_T, _T2, _V].*3.*1"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_generic.py b/pytype/tests/py3/test_generic.py index 07cdcd212..3ecfe4a5d 100644 --- a/pytype/tests/py3/test_generic.py +++ b/pytype/tests/py3/test_generic.py @@ -11,22 +11,21 @@ def testGenericTypeParamsError(self): _, errors = self.InferWithErrors("""\ from typing import Generic - class A(Generic[int]): + class A(Generic[int]): # invalid-annotation[e] pass """) - self.assertErrorLogIs(errors, [ - (3, "invalid-annotation", "Parameters.*Generic.*must.*type variables")]) + self.assertErrorRegexes( + errors, {"e": r"Parameters.*Generic.*must.*type variables"}) def testMroError(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Generic, Iterator, Generator, TypeVar T = TypeVar('T') - class A(Generic[T], Iterator[T], Generator): + class A(Generic[T], Iterator[T], Generator): # mro-error pass """) - self.assertErrorLogIs(errors, [(5, "mro-error")]) def testTemplateOrderError(self): _, errors = self.InferWithErrors("""\ @@ -60,13 +59,12 @@ def func(self, x: K1, y: K2): A = ClassA[int, str, int, int]() B = ClassB[int, str, int, int]() - A.func(5, "5") # Error + A.func(5, "5") # wrong-arg-types[e1] A.func("5", 5) # OK B.func(5, "5") # OK - B.func("5", 5) # Error + B.func("5", 5) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(31, "wrong-arg-types", r"str.*int"), - (34, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"int.*str"}) def testTypeErasureError(self): _, errors = self.InferWithErrors("""\ @@ -82,25 +80,23 @@ def __init__(self, x: T = None, y: S = None): def fun(self, x: T, y: S): pass - o1 = MyClass[str, str]() + o1 = MyClass[str, str]() # bad-concrete-type[e1] o2 = MyClass[int, int]() - o2.fun("5", 5) - o2.fun(5, "5") + o2.fun("5", 5) # wrong-arg-types[e2] + o2.fun(5, "5") # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (13, "bad-concrete-type", r"Union\[float, int\].*str"), - (15, "wrong-arg-types", r"x: int.*x: str"), - (16, "wrong-arg-types", r"y: int.*y: str")]) + self.assertErrorRegexes(errors, {"e1": r"Union\[float, int\].*str", + "e2": r"x: int.*x: str", + "e3": r"y: int.*y: str"}) def testInhericPlainGenericError(self): _, errors = self.InferWithErrors("""\ from typing import Generic - class A(Generic): + class A(Generic): # invalid-annotation[e] pass """) - self.assertErrorLogIs( - errors, [(3, "invalid-annotation", r"Cannot inherit.*plain Generic")]) + self.assertErrorRegexes(errors, {"e": r"Cannot inherit.*plain Generic"}) def testGenericWithDupTypeError(self): with file_utils.Tempdir() as d: @@ -111,10 +107,9 @@ def testGenericWithDupTypeError(self): class A(Generic[T, T]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", "Duplicate.*T.*a.A")]) + self.assertErrorRegexes(errors, {"e": r"Duplicate.*T.*a.A"}) def testMultiGenericError(self): with file_utils.Tempdir() as d: @@ -126,11 +121,10 @@ def testMultiGenericError(self): class A(Generic[T], Generic[V]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", - r"Cannot inherit.*Generic.*multiple times")]) + self.assertErrorRegexes( + errors, {"e": r"Cannot inherit.*Generic.*multiple times"}) def testGenericWithTypeMissError(self): with file_utils.Tempdir() as d: @@ -142,10 +136,10 @@ def testGenericWithTypeMissError(self): class A(Dict[K, V], Generic[K]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", r"V.*are not listed in Generic.*a.A")]) + self.assertErrorRegexes( + errors, {"e": r"V.*are not listed in Generic.*a.A"}) def testClassInFuncError(self): _, errors = self.InferWithErrors("""\ @@ -155,15 +149,14 @@ def testClassInFuncError(self): S = TypeVar('S') def func(x: T, y: S) -> Union[T, S]: - class InnerCls1(Generic[T]): + class InnerCls1(Generic[T]): # invalid-annotation[e1] # invalid-annotation[e2] class InnerCls2(Generic[S]): pass return x + y """) - self.assertErrorLogIs( - errors, [(7, "invalid-annotation", r"func.*InnerCls1.*T"), - (7, "invalid-annotation", r"func.*InnerCls2.*S")]) + self.assertErrorRegexes(errors, {"e1": r"func.*InnerCls2.*S", + "e2": r"func.*InnerCls1.*T"}) def testClassInClassError(self): _, errors = self.InferWithErrors("""\ @@ -172,7 +165,7 @@ def testClassInClassError(self): T = TypeVar('T', int, float, str) S = TypeVar('S') - class MyClass(Generic[T, S]): + class MyClass(Generic[T, S]): # invalid-annotation[e1] def __init__(self, x: T = None, y: S = None): pass @@ -182,14 +175,13 @@ def f(self, x: T, y: S): class InnerClass1(Iterator[T]): pass - class A(Generic[T]): + class A(Generic[T]): # invalid-annotation[e2] class B(Generic[S]): class C(Generic[T]): pass """) - self.assertErrorLogIs(errors, [ - (6, "invalid-annotation", r"MyClass.*InnerClass1.*T"), - (16, "invalid-annotation", r"A.*C.*T")]) + self.assertErrorRegexes(errors, {"e1": r"MyClass.*InnerClass1.*T", + "e2": r"A.*C.*T"}) def testSignatureTypeParam(self): _, errors = self.InferWithErrors("""\ @@ -205,18 +197,17 @@ def __init__(self, x: T = None, y: S = None): def func1(self, x: T, y: S): pass - def func2(self, x: V): pass + def func2(self, x: V): pass # invalid-annotation[e1] - def func1(x: S): pass + def func1(x: S): pass # invalid-annotation[e2] def func2(x: S) -> S: return x def func3(x: T): pass """) - self.assertErrorLogIs( - errors, [(13, "invalid-annotation", r"Invalid type annotation 'V'"), - (15, "invalid-annotation", r"Invalid type annotation 'S'")]) + self.assertErrorRegexes(errors, {"e1": r"Invalid type annotation 'V'", + "e2": r"Invalid type annotation 'S'"}) def testPyiOutput(self): ty = self.Infer(""" @@ -292,11 +283,11 @@ def testSignatureTypeError(self): V = TypeVar('V') class MyClass(Generic[T]): - def __init__(self, x: T, y: V): + def __init__(self, x: T, y: V): # invalid-annotation[e] pass """) - self.assertErrorLogIs(errors, [ - (7, "invalid-annotation", r"V.*Appears only once in the signature")]) + self.assertErrorRegexes( + errors, {"e": r"V.*Appears only once in the signature"}) def testTypeParameterWithoutSubstitution(self): with file_utils.Tempdir() as d: @@ -361,14 +352,12 @@ def fun3(self, x: T, y: S): pass o = C[int, int]() - o.fun1("5", "5") - o.fun2("5", "5") - o.fun3("5", "5") + o.fun1("5", "5") # wrong-arg-types[e1] + o.fun2("5", "5") # wrong-arg-types[e2] + o.fun3("5", "5") # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (23, "wrong-arg-types", r"int.*str"), - (24, "wrong-arg-types", r"int.*str"), - (25, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes( + errors, {"e1": r"int.*str", "e2": r"int.*str", "e3": r"int.*str"}) def testFuncMatchForPytdClassError(self): with file_utils.Tempdir() as d: @@ -396,14 +385,12 @@ def fun3(self, x: T, y: S): ... o = a.C[int, int]() - o.fun1("5", "5") - o.fun2("5", "5") - o.fun3("5", "5") + o.fun1("5", "5") # wrong-arg-types[e1] + o.fun2("5", "5") # wrong-arg-types[e2] + o.fun3("5", "5") # wrong-arg-types[e3] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types", r"int.*str"), - (6, "wrong-arg-types", r"int.*str"), - (7, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes( + errors, {"e1": r"int.*str", "e2": r"int.*str", "e3": r"int.*str"}) def testTypeRenamingError(self): _, errors = self.InferWithErrors("""\ @@ -416,19 +403,18 @@ def testTypeRenamingError(self): W = TypeVar('W') class A(Generic[T]): pass - class B(A[V]): pass + class B(A[V]): pass # not-supported-yet[e1] class C(Generic[V]): pass class D(C[T]): pass - class E(D[S]): pass + class E(D[S]): pass # not-supported-yet[e2] class F(Generic[U]): pass - class G(F[W]): pass + class G(F[W]): pass # not-supported-yet[e3] """) - self.assertErrorLogIs(errors, [ - (10, "not-supported-yet", r"Renaming TypeVar `T`.*"), - (14, "not-supported-yet", r"Renaming TypeVar `T`.*"), - (17, "not-supported-yet", r"Renaming TypeVar `U`.*")]) + self.assertErrorRegexes(errors, {"e1": r"Renaming TypeVar `T`.*", + "e2": r"Renaming TypeVar `T`.*", + "e3": r"Renaming TypeVar `U`.*"}) def testTypeParameterConflictError(self): ty, errors = self.InferWithErrors("""\ @@ -443,9 +429,9 @@ class A(Generic[T]): pass class B(A[V]): pass class D(B[S], A[U]): pass - class E(D[int, str]): pass + class E(D[int, str]): pass # invalid-annotation[e1] - d = D[int, str]() + d = D[int, str]() # invalid-annotation[e2] e = E() """) self.assertTypesMatchPytd(ty, """ @@ -471,9 +457,8 @@ class D(B[S], A[U]): class E(Any): pass """) - self.assertErrorLogIs(errors, [ - (12, "invalid-annotation", r"Conflicting value for TypeVar"), - (14, "invalid-annotation", r"Conflicting value for TypeVar")]) + self.assertErrorRegexes(errors, {"e1": r"Conflicting value for TypeVar", + "e2": r"Conflicting value for TypeVar"}) def testUnboundTypeParameterError(self): _, errors = self.InferWithErrors("""\ @@ -484,10 +469,9 @@ def testUnboundTypeParameterError(self): class A(Generic[T]): pass class B(A): pass - class D(B, A[U]): pass + class D(B, A[U]): pass # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [ - (8, "invalid-annotation", r"Conflicting value for TypeVar D.U")]) + self.assertErrorRegexes(errors, {"e": r"Conflicting value for TypeVar D.U"}) def testSelfTypeParameter(self): # The purpose is to verify there is no infinite recursion @@ -535,11 +519,10 @@ class DictC(collections.OrderedDict, DictB): d2 = DictA() d3 = DictC() x = d1["123"] - y = d2["123"] - z = d3["123"] + y = d2["123"] # unsupported-operands[e1] + z = d3["123"] # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [(16, "unsupported-operands", r"str.*int"), - (17, "unsupported-operands", r"str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) def testNoSelfAnnot(self): self.Check(""" @@ -556,10 +539,9 @@ def testIllegalSelfAnnot(self): T = TypeVar('T') class Foo(Generic[T]): def __init__(self: 'Foo', children: List['Foo[Any]']): - pass + pass # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(5, "invalid-annotation", r"self.*__init__")]) + self.assertErrorRegexes(errors, {"e": r"self.*__init__"}) def testParameterizedForwardReference(self): ty = self.Infer(""" @@ -583,12 +565,12 @@ def testBadParameterizedForwardReference(self): from typing import Generic, TypeVar T = TypeVar('T') - v = None # type: "Foo[int, str]" + v = None # type: "Foo[int, str]" # invalid-annotation[e] class Foo(Generic[T]): pass """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation", r"1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testRecursiveClass(self): self.Check("""\ diff --git a/pytype/tests/py3/test_list.py b/pytype/tests/py3/test_list.py index b45ca56fe..f583e35ee 100644 --- a/pytype/tests/py3/test_list.py +++ b/pytype/tests/py3/test_list.py @@ -10,16 +10,15 @@ class ListTestBasic(test_base.TargetPython3BasicTest): def test_repeated_add(self): # At the time of this writing, this test completes in <5s. If it takes # significantly longer, there's been a performance regression. - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import List, Text, Tuple def f() -> Tuple[List[Text]]: x = ( ['' % __any_object__, ''] + [''] + [''] + [''.format()] + [''] + [['' % __any_object__, '', '']] ) - return ([__any_object__] + [''] + x,) + return ([__any_object__] + [''] + x,) # bad-return-type """) - self.assertErrorLogIs(errors, [(7, "bad-return-type")]) class ListTest(test_base.TargetPython3FeatureTest): @@ -64,12 +63,12 @@ def test_byte_unpack_ex(self): """) def test_getitem_slot(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ a = [1, '2', 3, 4] p = a[1] q = 1 if __random__ else 2 r = a[q] - s = a["s"] + s = a["s"] # unsupported-operands t = a[-1] """) self.assertTypesMatchPytd(ty, """\ @@ -81,14 +80,13 @@ def test_getitem_slot(self): s = ... # type: Any t = ... # type: int """) - self.assertErrorLogIs(errors, [(5, "unsupported-operands")]) @test_base.skip("Requires more precise slice objects") def test_getitem_slice(self): # Python 3 uses __getitem__ with slice objects instead of __getslice__. # Pytype doesn't support slice objects well, so a lot of results here are # imprecise. It also means wrong-arg-types won't be detected. - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ a = [1, '2', 3, 4] b = a[:] c = 1 if __random__ else 2 @@ -98,8 +96,8 @@ def test_getitem_slice(self): g = a[2:None] h = a[None:2] i = a[None:None] - j = a[int:str] - k = a["s":] + j = a[int:str] # wrong-arg-types + k = a["s":] # wrong-arg-types m = a[1:-1] n = a[0:0] o = a[1:1] @@ -123,9 +121,6 @@ def test_getitem_slice(self): o = ... # type: List[nothing] p = ... # type: List[str] """) - self.assertErrorLogIs(errors, [ - (10, "wrong-arg-types"), - (11, "wrong-arg-types")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_match.py b/pytype/tests/py3/test_match.py index 0fcc9353b..c998976e5 100644 --- a/pytype/tests/py3/test_match.py +++ b/pytype/tests/py3/test_match.py @@ -20,11 +20,10 @@ def f(x: Callable[[], int]): ... def g(x: Callable[[], str]): ... f(foo.bar) # ok - g(foo.bar) + g(foo.bar) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"\(x: Callable\[\[\], str\]\).*" - r"\(x: Callable\[\[\], bool\]\)")]) + self.assertErrorRegexes(errors, { + "e": r"\(x: Callable\[\[\], str\]\).*\(x: Callable\[\[\], bool\]\)"}) def testPyTDFunctionAgainstCallableWithTypeParameters(self): with file_utils.Tempdir() as d: @@ -44,22 +43,19 @@ def f2(x: Callable[[T_constrained], T_constrained]): ... f1(foo.f1) # ok f1(foo.f2) # ok - f1(foo.f3) + f1(foo.f3) # wrong-arg-types[e1] f2(foo.f1) # ok - f2(foo.f2) - f2(foo.f3) + f2(foo.f2) # wrong-arg-types[e2] + f2(foo.f3) # wrong-arg-types[e3] """, pythonpath=[d.path]) expected = r"Callable\[\[Union\[bool, int\]\], Union\[bool, int\]\]" - self.assertErrorLogIs(errors, [ - (11, "wrong-arg-types", - r"Expected.*Callable\[\[str\], str\].*" - r"Actual.*Callable\[\[int\], str\]"), - (13, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], bool\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (14, "wrong-arg-types", - r"Expected.*" + expected + ".*" - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, { + "e1": (r"Expected.*Callable\[\[str\], str\].*" + r"Actual.*Callable\[\[int\], str\]"), + "e2": (r"Expected.*Callable\[\[bool\], bool\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e3": (r"Expected.*" + expected + ".*" + r"Actual.*Callable\[\[int\], str\]")}) def testInterpreterFunctionAgainstCallable(self): _, errors = self.InferWithErrors("""\ @@ -70,11 +66,11 @@ def g1(x: int) -> bool: def g2(x: str) -> int: return __any_object__ f(g1) # ok - f(g2) + f(g2) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], int\].*" - r"Actual.*Callable\[\[str\], int\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[bool\], int\].*" + r"Actual.*Callable\[\[str\], int\]")}) def testBoundInterpreterFunctionAgainstCallable(self): _, errors = self.InferWithErrors("""\ @@ -91,20 +87,18 @@ def f2(x: Callable[[A, bool], int]): ... def f3(x: Callable[[bool], str]): ... f1(bound) # ok - f2(bound) - f3(bound) - f1(unbound) + f2(bound) # wrong-arg-types[e1] + f3(bound) # wrong-arg-types[e2] + f1(unbound) # wrong-arg-types[e3] f2(unbound) # ok """) - self.assertErrorLogIs(errors, [(14, "wrong-arg-types", - r"Expected.*Callable\[\[A, bool\], int\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (15, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], str\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (16, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], int\].*" - r"Actual.*Callable\[\[Any, int\], bool\]")]) + self.assertErrorRegexes(errors, { + "e1": (r"Expected.*Callable\[\[A, bool\], int\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e2": (r"Expected.*Callable\[\[bool\], str\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e3": (r"Expected.*Callable\[\[bool\], int\].*" + r"Actual.*Callable\[\[Any, int\], bool\]")}) def testCallableParameters(self): with file_utils.Tempdir() as d: @@ -149,11 +143,11 @@ def f(x: Callable[[int], Any]): pass def g1(x: int=0): pass def g2(x: str=""): pass f(g1) # ok - f(g2) + f(g2) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"Expected.*Callable\[\[int\], Any\].*" - r"Actual.*Callable\[\[str\], Any\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[int\], Any\].*" + r"Actual.*Callable\[\[str\], Any\]")}) def testCallableInstanceAgainstCallableWithTypeParameters(self): _, errors = self.InferWithErrors("""\ @@ -161,14 +155,14 @@ def testCallableInstanceAgainstCallableWithTypeParameters(self): T = TypeVar("T") def f(x: Callable[[T], T]): ... def g() -> Callable[[int], str]: return __any_object__ - f(g()) + f(g()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*Callable\[\[str\], str\].*" - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[str\], str\].*" + r"Actual.*Callable\[\[int\], str\]")}) def testFunctionWithTypeParameterReturnAgainstCallable(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Callable, AnyStr, TypeVar T = TypeVar("T") def f(x: Callable[..., AnyStr]): ... @@ -176,9 +170,8 @@ def g1(x: AnyStr) -> AnyStr: return x def g2(x: T) -> T: return x f(g1) # ok - f(g2) + f(g2) # wrong-arg-types """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types")]) def testUnionInTypeParameter(self): with file_utils.Tempdir() as d: @@ -208,20 +201,16 @@ def bar(self, x: Dict[Tuple[AnyStr], AnyStr]): ... """) def testFormalType(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import AnyStr, List, NamedTuple def f(x: str): pass - f(AnyStr) + f(AnyStr) # invalid-typevar def g(x: List[str]): pass - g([AnyStr]) - H = NamedTuple("H", [('a', AnyStr)]) + g([AnyStr]) # invalid-typevar + H = NamedTuple("H", [('a', AnyStr)]) # invalid-typevar """) - self.assertErrorLogIs(errors, [ - (4, "invalid-typevar"), - (7, "invalid-typevar"), - (8, "invalid-typevar")]) def testTypeVarWithBound(self): _, errors = self.InferWithErrors("""\ @@ -232,10 +221,9 @@ def f(x: T1) -> T1: return __any_object__ def g(x: Callable[[T2], T2]) -> None: pass - g(f) # line 8 + g(f) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Expected.*T2.*Actual.*T1")]) + self.assertErrorRegexes(errors, {"e": r"Expected.*T2.*Actual.*T1"}) def testCallableBaseClass(self): with file_utils.Tempdir() as d: @@ -279,11 +267,10 @@ def f(x: AnyStr) -> AnyStr: return x def g(f: Callable[[IntVar], Any], x: IntVar): pass - g(f, 0) + g(f, 0) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Callable\[\[IntVar\], Any\].*Callable\[\[AnyStr\], AnyStr\]")]) + self.assertErrorRegexes(errors, { + "e": r"Callable\[\[IntVar\], Any\].*Callable\[\[AnyStr\], AnyStr\]"}) def testAnyStrAgainstMultipleParamCallable(self): # Callable[[T], T] needs to accept any argument, so AnyStr cannot match it. @@ -294,11 +281,10 @@ def f(x: AnyStr) -> AnyStr: return x def g(f: Callable[[T], T]): pass - g(f) + g(f) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Callable\[\[T\], T\].*Callable\[\[AnyStr\], AnyStr\]")]) + self.assertErrorRegexes(errors, { + "e": r"Callable\[\[T\], T\].*Callable\[\[AnyStr\], AnyStr\]"}) class MatchTestPy3(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_methods.py b/pytype/tests/py3/test_methods.py index e0e415a2d..4fd78fb20 100644 --- a/pytype/tests/py3/test_methods.py +++ b/pytype/tests/py3/test_methods.py @@ -4,7 +4,7 @@ class TestMethods(test_base.TargetPython3BasicTest): - """Tests for class methods""" + """Tests for class methods.""" def testFunctionInit(self): ty = self.Infer(""" @@ -19,39 +19,39 @@ def testAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(x: int): - pass + pass # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*x")]) + self.assertErrorRegexes(errors, {"e": r"int.*x"}) def testLateAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(x: "X"): - pass + pass # invalid-annotation[e] class X(object): pass """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"X.*x")]) + self.assertErrorRegexes(errors, {"e": r"X.*x"}) def testAttributeWithAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self: int): - self.x = 3 + self.x = 3 # invalid-annotation[e] def foo(self): return self.x """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*self")]) + self.assertErrorRegexes(errors, {"e": r"int.*self"}) def testAttributeWithAnnotatedSelfAndFunctionInit(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self: int): - self.x = 3 + self.x = 3 # invalid-annotation[e] def __init__(self: int): pass """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*self")]) + self.assertErrorRegexes(errors, {"e": r"int.*self"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_namedtuple.py b/pytype/tests/py3/test_namedtuple.py index 145f427b4..a3a4dc1e4 100644 --- a/pytype/tests/py3/test_namedtuple.py +++ b/pytype/tests/py3/test_namedtuple.py @@ -23,20 +23,14 @@ class NamedtupleTestsPy3(test_base.TargetPython3FeatureTest): def test_bad_call(self): """The last two arguments are kwonly in 3.6.""" - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple() - collections.namedtuple("_") - collections.namedtuple("_", "", True) - collections.namedtuple("_", "", True, True) - collections.namedtuple("_", "", True, True, True) + collections.namedtuple() # missing-parameter + collections.namedtuple("_") # missing-parameter + collections.namedtuple("_", "", True) # wrong-arg-count + collections.namedtuple("_", "", True, True) # wrong-arg-count + collections.namedtuple("_", "", True, True, True) # wrong-arg-count """) - self.assertErrorLogIs(errorlog, - [(2, "missing-parameter"), - (3, "missing-parameter"), - (4, "wrong-arg-count"), - (5, "wrong-arg-count"), - (6, "wrong-arg-count")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_overload.py b/pytype/tests/py3/test_overload.py index 11f755f7e..fea30006e 100644 --- a/pytype/tests/py3/test_overload.py +++ b/pytype/tests/py3/test_overload.py @@ -25,9 +25,9 @@ def test_bad_implementation(self): def f(x: int) -> str: pass def f(x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(6, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_bad_call(self): errors = self.CheckWithErrors("""\ @@ -37,9 +37,9 @@ def f(x: int) -> int: pass def f(x): return x - f("") + f("") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_sub_return(self): ty = self.Infer(""" @@ -81,9 +81,9 @@ def f(x: int) -> int: def f(x: str) -> int: pass def f(x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(9, "bad-return-type", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_multiple_overload_bad_call(self): errors = self.CheckWithErrors("""\ @@ -96,11 +96,10 @@ def f(x: int, y: str) -> str: pass def f(x, y=None): return x if y is None else y - f("") - f(0, 0) + f("") # wrong-arg-types[e1] + f(0, 0) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(10, "wrong-arg-types", r"int.*str"), - (11, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"int.*str", "e2": r"str.*int"}) def test_pyi(self): src = """ @@ -133,9 +132,9 @@ def g() -> Callable: ... import foo foo.f(0) # ok foo.f("") # ok - foo.f(0.0) # error + foo.f(0.0) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*float")]) + self.assertErrorRegexes(errors, {"e": r"int.*float"}) def test_method_bad_implementation(self): errors = self.CheckWithErrors("""\ @@ -148,9 +147,9 @@ def f(self, x: int) -> int: def f(self, x: str) -> int: pass def f(self, x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(10, "bad-return-type", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_method_pyi(self): src = """ @@ -182,9 +181,9 @@ def test_call_overload(self): @overload def f(x: int) -> int: pass - f(0) + f(0) # not-callable[e] """) - self.assertErrorLogIs(errors, [(5, "not-callable", r"overload")]) + self.assertErrorRegexes(errors, {"e": r"overload"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_protocols.py b/pytype/tests/py3/test_protocols.py index 629517091..ce4cedf3a 100644 --- a/pytype/tests/py3/test_protocols.py +++ b/pytype/tests/py3/test_protocols.py @@ -35,10 +35,10 @@ def test_check_protocol_error(self): def f(x: protocols.SupportsAbs): return x.__abs__() - f(["foo"]) + f(["foo"]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"\(x: SupportsAbs\).*\(x: List\[str\]\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: SupportsAbs\).*\(x: List\[str\]\)"}) def test_check_iterator_error(self): _, errors = self.InferWithErrors("""\ @@ -50,10 +50,9 @@ def next(self) -> str: return '' def __iter__(self): return self - f(Foo()) # line 9 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"Iterator\[int\].*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Iterator\[int\].*Foo"}) def test_check_protocol_match_unknown(self): self.Check("""\ @@ -96,10 +95,10 @@ def f(x: Iterable[int]): pass foo = Foo() - f(foo) + f(foo) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(11, "wrong-arg-types", - r"\(x: Iterable\[int\]\).*\(x: Foo\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: Iterable\[int\]\).*\(x: Foo\)"}) def test_check_parameterized_protocol_multi_signature(self): self.Check("""\ @@ -132,10 +131,10 @@ def f(x: Sequence[int]): pass foo = Foo() - f(foo) + f(foo) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(13, "wrong-arg-types", - r"\(x: Sequence\[int\]\).*\(x: Foo\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: Sequence\[int\]\).*\(x: Foo\)"}) def test_construct_dict_with_protocol(self): self.Check(""" @@ -266,10 +265,9 @@ def next(self): return __any_object__ def f(x: Iterator[int]): pass - f(Foo()) # line 9 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"Iterator\[int\].*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Iterator\[int\].*Foo"}) def test_reversible(self): self.Check(""" @@ -320,10 +318,9 @@ def test_list_hash(self): from typing import Hashable def f(x: Hashable): pass - f([]) # line 4 + f([]) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(4, "wrong-arg-types", r"Hashable.*List.*__hash__")]) + self.assertErrorRegexes(errors, {"e": r"Hashable.*List.*__hash__"}) def test_hash_constant(self): errors = self.CheckWithErrors("""\ @@ -332,10 +329,9 @@ class Foo(object): __hash__ = None def f(x: Hashable): pass - f(Foo()) # line 6 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(6, "wrong-arg-types", r"Hashable.*Foo.*__hash__")]) + self.assertErrorRegexes(errors, {"e": r"Hashable.*Foo.*__hash__"}) def test_generic_callable(self): with file_utils.Tempdir() as d: @@ -401,12 +397,12 @@ class NotAppendable(object): pass def f(x: Appendable): pass - f(42) # error - f(NotAppendable()) # error + f(42) # wrong-arg-types[e1] + f(NotAppendable()) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [ - (9, "wrong-arg-types", r"Appendable.*int.*append"), - (10, "wrong-arg-types", r"Appendable.*NotAppendable.*append")]) + self.assertErrorRegexes(errors, { + "e1": r"Appendable.*int.*append", + "e2": r"Appendable.*NotAppendable.*append"}) def test_reingest_custom_protocol(self): ty = self.Infer(""" @@ -443,12 +439,12 @@ class NotAppendable(object): pass def f(x: foo.Appendable): pass - f(42) # error - f(NotAppendable()) # error + f(42) # wrong-arg-types[e1] + f(NotAppendable()) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types", r"Appendable.*int.*append"), - (7, "wrong-arg-types", r"Appendable.*NotAppendable.*append")]) + self.assertErrorRegexes(errors, { + "e1": r"Appendable.*int.*append", + "e2": r"Appendable.*NotAppendable.*append"}) def test_reingest_custom_protocol_inherit_method(self): ty = self.Infer(""" @@ -470,10 +466,9 @@ def remove(self): def f(x: Mutable): pass f([]) # ok - f(NotMutable()) # error + f(NotMutable()) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (8, "wrong-arg-types", r"Mutable.*NotMutable.*append")]) + self.assertErrorRegexes(errors, {"e": r"Mutable.*NotMutable.*append"}) def test_reingest_custom_protocol_implement_method(self): ty = self.Infer(""" @@ -513,13 +508,12 @@ def test_check_method_body(self): from typing_extensions import Protocol class Countable(Protocol): def count(self) -> int: - ... + ... # bad-return-type[e] class MyCountable(Countable): def count(self): return super(MyCountable, self).count() """) - self.assertErrorLogIs( - errors, [(4, "bad-return-type", r"int.*None.*line 7")]) + self.assertErrorRegexes(errors, {"e": r"int.*None.*line 7"}) class ProtocolsTestPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_recovery.py b/pytype/tests/py3/test_recovery.py index d2f7a8e60..1709b945c 100644 --- a/pytype/tests/py3/test_recovery.py +++ b/pytype/tests/py3/test_recovery.py @@ -7,20 +7,15 @@ class RecoveryTests(test_base.TargetPython3BasicTest): """Tests for recovering after errors.""" def testFunctionWithUnknownDecorator(self): - _, errors = self.InferWithErrors("""\ - from nowhere import decorator + self.InferWithErrors("""\ + from nowhere import decorator # import-error @decorator def f(): - name_error + name_error # name-error @decorator def g(x: int) -> None: - x.upper() + x.upper() # attribute-error """, deep=True) - self.assertErrorLogIs(errors, [ - (1, "import-error"), - (4, "name-error"), - (7, "attribute-error"), - ]) def testComplexInit(self): """Test that we recover when __init__ triggers a utils.TooComplexError.""" @@ -37,10 +32,10 @@ def __init__(self, string_ref: AnyStr = None, type_ref: AnyStr = None) -> None: pass - def foo(self, x: other_module.X) -> None: # line 13 + def foo(self, x: other_module.X) -> None: # name-error[e] pass """, deep=True) - self.assertErrorLogIs(errors, [(13, "name-error", r"other_module")]) + self.assertErrorRegexes(errors, {"e": r"other_module"}) class RecoveryTestsPython3(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_reingest.py b/pytype/tests/py3/test_reingest.py index a8a7089ab..78eaab9f2 100644 --- a/pytype/tests/py3/test_reingest.py +++ b/pytype/tests/py3/test_reingest.py @@ -18,9 +18,9 @@ def f(x: T) -> T: return x d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.f("") + foo.f("") # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"float.*str")]) + self.assertErrorRegexes(errors, {"e": r"float.*str"}) def testDefaultArgumentType(self): foo = self.Infer(""" @@ -56,10 +56,10 @@ def foo(self): d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.Foo() + foo.Foo() # not-instantiable[e] foo.Bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_slots.py b/pytype/tests/py3/test_slots.py index f0c39d834..b585b88a5 100644 --- a/pytype/tests/py3/test_slots.py +++ b/pytype/tests/py3/test_slots.py @@ -14,11 +14,10 @@ class Foo(object): """) def testSlotWithBytes(self): - errors = self.CheckWithErrors("""\ - class Foo(object): + self.CheckWithErrors("""\ + class Foo(object): # bad-slots __slots__ = (b"x",) """) - self.assertErrorLogIs(errors, [(1, "bad-slots")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_stdlib.py b/pytype/tests/py3/test_stdlib.py index d67c8918a..aa1ae3fe9 100644 --- a/pytype/tests/py3/test_stdlib.py +++ b/pytype/tests/py3/test_stdlib.py @@ -17,9 +17,9 @@ def testCollectionsDeque(self): def f1(x: Deque): ... def f2(x: int): ... f1(collections.deque()) - f2(collections.deque()) # line 6 + f2(collections.deque()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", r"int.*deque")]) + self.assertErrorRegexes(errors, {"e": r"int.*deque"}) def testCollectionsDequeInit(self): ty = self.Infer("""\ diff --git a/pytype/tests/py3/test_super.py b/pytype/tests/py3/test_super.py index 47bfe7115..bad37fa94 100644 --- a/pytype/tests/py3/test_super.py +++ b/pytype/tests/py3/test_super.py @@ -66,24 +66,20 @@ def call_inner(a) -> int """) def test_super_without_args_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ class A(object): def m(self): pass class B(A): def m(self): def f(): - super().m() + super().m() # invalid-super-call[e1] f() def func(x: int): - super().m() + super().m() # invalid-super-call[e2] """) - self.assertErrorLogIs( - errors, - [(8, "invalid-super-call", - r".*Missing 'self' argument.*"), - (11, "invalid-super-call", - r".*Missing __class__ closure.*")]) + self.assertErrorRegexes(errors, {"e1": r".*Missing 'self' argument.*", + "e2": r".*Missing __class__ closure.*"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_tracebacks.py b/pytype/tests/py3/test_tracebacks.py index cca593b4f..d2922d793 100644 --- a/pytype/tests/py3/test_tracebacks.py +++ b/pytype/tests/py3/test_tracebacks.py @@ -9,10 +9,10 @@ class TracebackTest(test_base.TargetPython3BasicTest): def test_build_class(self): errors = self.CheckWithErrors("""\ class Foo(object): - def f(self, x: Bar): + def f(self, x: Bar): # name-error[e] pass """) - self.assertErrorLogIs(errors, [(2, "name-error", r"Bar.*not defined$")]) + self.assertErrorRegexes(errors, {"e": r"Bar.*not defined$"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_tuple.py b/pytype/tests/py3/test_tuple.py index 1e44a54da..0e4326dad 100644 --- a/pytype/tests/py3/test_tuple.py +++ b/pytype/tests/py3/test_tuple.py @@ -59,11 +59,11 @@ def f(x: Tuple[str, ...]): pass def g(y: Tuple[str]): pass - f((42,)) - f(tuple([42])) + f((42,)) # wrong-arg-types[e1] + f(tuple([42])) # wrong-arg-types[e2] f(("", "")) # okay - g((42,)) - g(("", "")) + g((42,)) # wrong-arg-types[e3] + g(("", "")) # wrong-arg-types[e4] g(("",)) # okay g(tuple([""])) # okay """) @@ -72,15 +72,11 @@ def g(y: Tuple[str]): tuple_int = r"Tuple\[int\]" tuple_ints = r"Tuple\[int, \.\.\.\]" tuple_str_str = r"Tuple\[str, str\]" - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"%s.*%s" % (x, tuple_int)), - (7, "wrong-arg-types", - r"%s.*%s" % (x, tuple_ints)), - (9, "wrong-arg-types", - r"%s.*%s" % (y, tuple_int)), - (10, "wrong-arg-types", - r"%s.*%s" % (y, tuple_str_str)) - ]) + self.assertErrorRegexes(errors, { + "e1": r"%s.*%s" % (x, tuple_int), + "e2": r"%s.*%s" % (x, tuple_ints), + "e3": r"%s.*%s" % (y, tuple_int), + "e4": r"%s.*%s" % (y, tuple_str_str)}) def testInlineTuple(self): with file_utils.Tempdir() as d: @@ -113,17 +109,16 @@ def f(x: Type[Tuple[int, str]]): pass def g(x: Tuple[int, str]): pass - f(type(("", 1))) - g(("", 1)) - g(foo.A()) + f(type(("", 1))) # wrong-arg-types[e1] + g(("", 1)) # wrong-arg-types[e2] + g(foo.A()) # wrong-arg-types[e3] """, pythonpath=[d.path]) expected = r"Tuple\[int, str\]" actual = r"Tuple\[str, int\]" - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Type\[%s\].*Type\[%s\]" % (expected, actual)), - (8, "wrong-arg-types", r"%s.*%s" % (expected, actual)), - (9, "wrong-arg-types", r"%s.*foo\.A" % expected)]) + self.assertErrorRegexes(errors, { + "e1": r"Type\[%s\].*Type\[%s\]" % (expected, actual), + "e2": r"%s.*%s" % (expected, actual), + "e3": r"%s.*foo\.A" % expected}) def testTupleCombinationExplosion(self): self.Check(""" @@ -154,9 +149,9 @@ class Bar(tuple): ... from typing import Tuple import bar def foo() -> Tuple[bar.Bar, bar.Bar]: - return bar.Bar(None, None) # line 4 + return bar.Bar(None, None) # wrong-arg-count[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "wrong-arg-count", "1.*3")]) + self.assertErrorRegexes(errors, {"e": r"1.*3"}) class TupleTestPython3Feature(test_base.TargetPython3FeatureTest): @@ -180,10 +175,9 @@ def __getitem__(self, pos: int) -> int or str or complex def testBadUnpackingWithSlurp(self): _, errors = self.InferWithErrors("""\ - a, *b, c = (1,) + a, *b, c = (1,) # bad-unpacking[e] """) - self.assertErrorLogIs( - errors, [(1, "bad-unpacking", "1 value.*3 variables")]) + self.assertErrorRegexes(errors, {"e": r"1 value.*3 variables"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_type_comments.py b/pytype/tests/py3/test_type_comments.py index bb6c41993..aee187d82 100644 --- a/pytype/tests/py3/test_type_comments.py +++ b/pytype/tests/py3/test_type_comments.py @@ -7,12 +7,11 @@ class FunctionCommentWithAnnotationsTest(test_base.TargetPython3BasicTest): """Tests for type comments that require annotations.""" def testFunctionTypeCommentPlusAnnotations(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x: int) -> float: - # type: (int) -> float + # type: (int) -> float # redundant-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "redundant-function-type-comment")]) def testListComprehensionComments(self): ty = self.Infer("""\ diff --git a/pytype/tests/py3/test_typevar.py b/pytype/tests/py3/test_typevar.py index 44f2eecaa..5f28b4f7a 100644 --- a/pytype/tests/py3/test_typevar.py +++ b/pytype/tests/py3/test_typevar.py @@ -70,15 +70,12 @@ def testImportTypeVarNameChange(self): """) _, errors = self.InferWithErrors("""\ # This is illegal: A TypeVar("T") needs to be stored under the name "T". - from a import T as T2 + from a import T as T2 # invalid-typevar[e1] from a import X - Y = X + Y = X # invalid-typevar[e2] def f(x: T2) -> T2: ... """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", "T.*T2"), - (4, "invalid-typevar", "X.*Y"), - ]) + self.assertErrorRegexes(errors, {"e1": r"T.*T2", "e2": r"X.*Y"}) def testMultipleSubstitution(self): ty = self.Infer("""\ @@ -124,24 +121,22 @@ def testBadSubstitution(self): S = TypeVar("S") T = TypeVar("T") def f1(x: S) -> List[S]: - return {x} + return {x} # bad-return-type[e1] def f2(x: S) -> S: return 42 # no error because never called def f3(x: S) -> S: - return 42 + return 42 # bad-return-type[e2] # bad-return-type[e3] def f4(x: S, y: T, z: T) -> List[S]: - return [y] + return [y] # bad-return-type[e4] f3("") f3(16) # ok f3(False) f4(True, 3.14, 0) f4("hello", "world", "domination") # ok """) - self.assertErrorLogIs(errors, [ - (5, "bad-return-type", r"List\[S\].*set"), - (9, "bad-return-type", r"str.*int"), - (9, "bad-return-type", r"bool.*int"), - (11, "bad-return-type", r"List\[bool\].*List\[Union\[float, int\]\]")]) + self.assertErrorRegexes(errors, { + "e1": r"List\[S\].*set", "e2": r"str.*int", "e3": r"bool.*int", + "e4": r"List\[bool\].*List\[Union\[float, int\]\]"}) def testUseConstraints(self): ty, errors = self.InferWithErrors("""\ @@ -149,7 +144,7 @@ def testUseConstraints(self): T = TypeVar("T", int, float) def f(x: T) -> T: return __any_object__ - v = f("") + v = f("") # wrong-arg-types[e] w = f(True) # ok u = f(__any_object__) # ok """) @@ -161,8 +156,7 @@ def f(x: T) -> T: ... w = ... # type: bool u = ... # type: int or float """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Union\[float, int\].*str")]) + self.assertErrorRegexes(errors, {"e": r"Union\[float, int\].*str"}) def testTypeParameterType(self): ty = self.Infer("""\ @@ -184,10 +178,10 @@ def testPrintNestedTypeParameter(self): from typing import List, TypeVar T = TypeVar("T", int, float) def f(x: List[T]): ... - f([""]) + f([""]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (4, "wrong-arg-types", r"List\[Union\[float, int\]\].*List\[str\]")]) + self.assertErrorRegexes(errors, { + "e": r"List\[Union\[float, int\]\].*List\[str\]"}) def testConstraintSubtyping(self): _, errors = self.InferWithErrors("""\ @@ -195,10 +189,9 @@ def testConstraintSubtyping(self): T = TypeVar("T", int, float) def f(x: T, y: T): ... f(True, False) # ok - f(True, 42) + f(True, 42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*y: bool.*Actual.*y: int")]) + self.assertErrorRegexes(errors, {"e": r"Expected.*y: bool.*Actual.*y: int"}) def testFilterValue(self): _, errors = self.InferWithErrors("""\ @@ -207,11 +200,11 @@ def testFilterValue(self): def f(x: T, y: T): ... x = 3 x = 42.0 - f(x, 3) + f(x, 3) # wrong-arg-types[e] f(x, 42.0) # ok """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"Expected.*y: float.*Actual.*y: int")]) + self.assertErrorRegexes( + errors, {"e": r"Expected.*y: float.*Actual.*y: int"}) def testFilterClass(self): self.Check("""\ @@ -254,36 +247,31 @@ def testEnforceNonConstrainedTypeVar(self): T = TypeVar("T") def f(x: T, y: T): ... f(42, True) # ok - f(42, "") + f(42, "") # wrong-arg-types[e1] f(42, 16j) # ok f(object(), 42) # ok f(42, object()) # ok - f(42.0, "") + f(42.0, "") # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*y: int.*Actual.*y: str"), - (9, "wrong-arg-types", - r"Expected.*y: float.*Actual.*y: str")]) + self.assertErrorRegexes(errors, { + "e1": r"Expected.*y: int.*Actual.*y: str", + "e2": r"Expected.*y: float.*Actual.*y: str"}) def testUselessTypeVar(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Tuple, TypeVar T = TypeVar("T") S = TypeVar("S", int, float) - def f1(x: T): ... - def f2() -> T: ... - def f3(x: Tuple[T]): ... + def f1(x: T): ... # invalid-annotation + def f2() -> T: ... # invalid-annotation + def f3(x: Tuple[T]): ... # invalid-annotation def f4(x: Tuple[T, T]): ... # ok def f5(x: S): ... # ok - def f6(x: "U"): ... + def f6(x: "U"): ... # invalid-annotation def f7(x: T, y: "T"): ... # ok def f8(x: "U") -> "U": ... # ok U = TypeVar("U") """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation"), - (5, "invalid-annotation"), - (6, "invalid-annotation"), - (9, "invalid-annotation")]) def testUseBound(self): ty, errors = self.InferWithErrors("""\ @@ -295,7 +283,7 @@ def f(x: T) -> T: v2 = f(True) # ok v3 = f(42) # ok v4 = f(3.14) # ok - v5 = f("") + v5 = f("") # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, TypeVar @@ -307,8 +295,7 @@ def f(x: T) -> T v4 = ... # type: float v5 = ... # type: Any """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"x: float.*x: str")]) + self.assertErrorRegexes(errors, {"e": r"x: float.*x: str"}) def testBadReturn(self): self.assertNoCrash(self.Check, """\ @@ -325,10 +312,9 @@ def testOptionalTypeVar(self): from typing import Optional, TypeVar T = TypeVar("T", bound=str) def f() -> Optional[T]: - return 42 if __random__ else None + return 42 if __random__ else None # bad-return-type[e] """, deep=True) - self.assertErrorLogIs( - errors, [(4, "bad-return-type", r"Optional\[T\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Optional\[T\].*int"}) def testUnicodeLiterals(self): ty = self.Infer(""" @@ -421,12 +407,12 @@ def g(x: AnyStr) -> AnyStr: ... # pylint: enable=g-backslash-continuation _, errors = self.InferWithErrors("""\ import foo - foo.f("") - foo.g(0) + foo.f("") # wrong-arg-types[e1] + foo.g(0) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"Union\[float, int\].*str"), - (3, "wrong-arg-types", r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, { + "e1": r"Union\[float, int\].*str", + "e2": r"Union\[bytes, str\].*int"}) def testSubprocess(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_typing.py b/pytype/tests/py3/test_typing.py index 443e7e075..af34aceae 100644 --- a/pytype/tests/py3/test_typing.py +++ b/pytype/tests/py3/test_typing.py @@ -20,8 +20,8 @@ def _test_match(self, arg, annotation, disables=""): self.Check(self._TEMPLATE % locals()) def _test_no_match(self, arg, annotation, disables=""): - _, errors = self.InferWithErrors(self._TEMPLATE % locals()) - self.assertNotEqual(0, len(errors)) + code = (self._TEMPLATE % locals()).rstrip() + " # wrong-arg-types" + self.InferWithErrors(code) def test_list_match(self): self._test_match("[1, 2, 3]", "typing.List") @@ -51,7 +51,7 @@ class Foo: def f1(foo: Type[Foo]): return foo.x def f2(foo: Type[Foo]): - return foo.y # bad + return foo.y # attribute-error[e] def f3(foo: Type[Foo]): return foo.mro() def f4(foo: Type[Foo]): @@ -61,7 +61,7 @@ def f4(foo: Type[Foo]): v3 = f3(Foo) v4 = f4(Foo) """) - self.assertErrorLogIs(errors, [(7, "attribute-error", r"y.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"y.*Foo"}) self.assertTypesMatchPytd(ty, """ from typing import Any, Type class Foo: @@ -86,13 +86,13 @@ def f1(x: Type[Union[int, Foo]]): # differently. See get_attribute() in attribute.py. x.bar def f2(x: Union[Type[int], Type[Foo]]): - x.bar + x.bar # attribute-error[e] f1(x) def f3(x: Type[Union[int, Foo]]): f1(x) f2(x) """) - self.assertErrorLogIs(errors, [(9, "attribute-error", "bar.*int")]) + self.assertErrorRegexes(errors, {"e": r"bar.*int"}) def test_use_type_alias(self): with file_utils.Tempdir() as d: @@ -131,19 +131,19 @@ def f1(x: Callable[[int, str], bool]): ... def f2(x: Callable[..., bool]): ... def f3(x: Callable[[], bool]): ... - def g1(x: Callable[int, bool]): ... # bad: _ARGS not a list + def g1(x: Callable[int, bool]): ... # _ARGS not a list # invalid-annotation[e1] lst = [int] if __random__ else [str] - def g2(x: Callable[lst, bool]): ... # bad: _ARGS ambiguous + def g2(x: Callable[lst, bool]): ... # _ARGS ambiguous # invalid-annotation[e2] # invalid-annotation[e3] # bad: _RET ambiguous - def g3(x: Callable[[], bool if __random__ else str]): ... + def g3(x: Callable[[], bool if __random__ else str]): ... # invalid-annotation[e4] # bad: _ARGS[0] ambiguous - def g4(x: Callable[[int if __random__ else str], bool]): ... + def g4(x: Callable[[int if __random__ else str], bool]): ... # invalid-annotation[e5] lst = None # type: list[int] - def g5(x: Callable[lst, bool]): ... # bad: _ARGS not a constant - def g6(x: Callable[[42], bool]): ... # bad: _ARGS[0] not a type - def g7(x: Callable[[], bool, int]): ... # bad: Too many params - def g8(x: Callable[Any, bool]): ... # bad: Any is not allowed - def g9(x: Callable[[]]) -> None: ... + def g5(x: Callable[lst, bool]): ... # _ARGS not a constant # invalid-annotation[e6] + def g6(x: Callable[[42], bool]): ... # _ARGS[0] not a type # invalid-annotation[e7] + def g7(x: Callable[[], bool, int]): ... # Too many params # invalid-annotation[e8] + def g8(x: Callable[Any, bool]): ... # Any is not allowed # invalid-annotation[e9] + def g9(x: Callable[[]]) -> None: ... # invalid-annotation[e10] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Callable, List, Type @@ -163,32 +163,28 @@ def g7(x: Callable[[], bool]) -> None: ... def g8(x: Callable[Any, bool]) -> None: ... def g9(x: Callable[[], Any]) -> None: ... """) - self.assertErrorLogIs(errors, [ - (8, "invalid-annotation", - r"'int'.*must be a list of argument types or ellipsis"), - (10, "invalid-annotation", r"\[int\] or \[str\].*Must be constant"), - (10, "invalid-annotation", - r"'Any'.*must be a list of argument types or ellipsis"), - (12, "invalid-annotation", r"bool or str.*Must be constant"), - (14, "invalid-annotation", r"int or str.*Must be constant"), - (16, "invalid-annotation", - r"instance of List\[int\].*Must be constant"), - (17, "invalid-annotation", r"instance of int"), - (18, "invalid-annotation", r"Callable.*Expected 2.*got 3"), - (19, "invalid-annotation", - r"'Any'.*must be a list of argument types or ellipsis"), - (20, "invalid-annotation", r"Callable\[_ARGS, _RET].*2.*1"),]) + self.assertErrorRegexes(errors, { + "e1": r"'int'.*must be a list of argument types or ellipsis", + "e2": r"\[int\] or \[str\].*Must be constant", + "e3": r"'Any'.*must be a list of argument types or ellipsis", + "e4": r"bool or str.*Must be constant", + "e5": r"int or str.*Must be constant", + "e6": r"instance of List\[int\].*Must be constant", + "e7": r"instance of int", + "e8": r"Callable.*Expected 2.*got 3", + "e9": r"'Any'.*must be a list of argument types or ellipsis", + "e10": r"Callable\[_ARGS, _RET].*2.*1"}) def test_callable_bad_args(self): ty, errors = self.InferWithErrors("""\ from typing import Callable lst1 = [str] lst1[0] = int - def g1(x: Callable[lst1, bool]): ... # line 4 + def g1(x: Callable[lst1, bool]): ... # invalid-annotation[e1] lst2 = [str] while __random__: lst2.append(int) - def g2(x: Callable[lst2, bool]): ... # line 8 + def g2(x: Callable[lst2, bool]): ... # invalid-annotation[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Callable, List, Type, Union @@ -200,11 +196,11 @@ def g2(x: Callable[..., bool]) -> None: ... # For the first error, it would be more precise to say [str or int], since # the mutation is simple enough that we could keep track of the change to # the constant, but we don't do that yet. - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", - r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant"), - (8, "invalid-annotation", - r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant"),]) + self.assertErrorRegexes(errors, { + "e1": (r"instance of List\[Type\[Union\[int, str\]\]\].*" + r"Must be constant"), + "e2": r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant" + }) def test_generics(self): with file_utils.Tempdir() as d: @@ -276,10 +272,10 @@ def test_callable_call(self): ty, errors = self.InferWithErrors("""\ from typing import Callable f = ... # type: Callable[[int], str] - v1 = f() + v1 = f() # wrong-arg-count[e1] v2 = f(True) # ok - v3 = f(42.0) - v4 = f(1, 2) + v3 = f(42.0) # wrong-arg-types[e2] + v4 = f(1, 2) # wrong-arg-count[e3] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Callable @@ -289,16 +285,15 @@ def test_callable_call(self): v3 = ... # type: Any v4 = ... # type: Any """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*0"), - (5, "wrong-arg-types", "int.*float"), - (6, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes( + errors, {"e1": r"1.*0", "e2": r"int.*float", "e3": r"1.*2"}) def test_callable_call_with_type_parameters(self): ty, errors = self.InferWithErrors("""\ from typing import Callable, TypeVar T = TypeVar("T") def f(g: Callable[[T, T], T], y, z): - return g(y, z) + return g(y, z) # wrong-arg-types[e] v1 = f(__any_object__, 42, 3.14) # ok v2 = f(__any_object__, 42, "hello world") """, deep=True) @@ -309,7 +304,7 @@ def f(g: Callable[[T, T], T], y, z): ... v1 = ... # type: int or float v2 = ... # type: Any """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_callable_call_with_return_only(self): ty = self.Infer(""" @@ -327,15 +322,13 @@ def test_callable_call_with_varargs_and_kwargs(self): _, errors = self.InferWithErrors("""\ from typing import Callable f = ... # type: Callable[[], int] - f(x=3) - f(*(42,)) - f(**{"x": "hello", "y": "world"}) - f(*(42,), **{"hello": "world"}) + f(x=3) # wrong-keyword-args[e1] + f(*(42,)) # wrong-arg-count[e2] + f(**{"x": "hello", "y": "world"}) # wrong-keyword-args[e3] + f(*(42,), **{"hello": "world"}) # wrong-keyword-args[e4] """) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", r"x"), - (4, "wrong-arg-count", r"0.*1"), - (5, "wrong-keyword-args", r"x, y"), - (6, "wrong-keyword-args", r"hello")]) + self.assertErrorRegexes(errors, {"e1": r"x", "e2": r"0.*1", "e3": r"x, y", + "e4": r"hello"}) def test_callable_attribute(self): self.Check("""\ @@ -416,27 +409,23 @@ def func7(a: MySpecialA) -> A: ... """) def test_new_type_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ from typing import NewType MyInt = NewType('MyInt', int) MyStr = NewType('MyStr', str) def func1(i: MyInt) -> MyInt: return i def func2(i: int) -> MyInt: - return i + return i # bad-return-type[e1] def func3(s: MyStr) -> MyStr: return s - func1(123) - func3(MyStr(123)) - """) - self.assertErrorLogIs( - errors, - [(8, "bad-return-type", - r"Expected: MyInt\nActually returned: int"), - (11, "wrong-arg-types", - r".*Expected: \(i: MyInt\)\nActually passed: \(i: int\)"), - (12, "wrong-arg-types", - r".*Expected:.*val: str\)\nActually passed:.*val: int\)"),]) + func1(123) # wrong-arg-types[e2] + func3(MyStr(123)) # wrong-arg-types[e3] + """) + self.assertErrorRegexes(errors, { + "e1": r"Expected: MyInt\nActually returned: int", + "e2": r".*Expected: \(i: MyInt\)\nActually passed: \(i: int\)", + "e3": r".*Expected:.*val: str\)\nActually passed:.*val: int\)"}) def test_maybe_return(self): self.Check(""" @@ -470,50 +459,46 @@ def g() -> str: def test_union_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Union - MyUnion = Union[int, ...] + MyUnion = Union[int, ...] # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*Union")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*Union"}) def test_list_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import List - MyList = List[int, ...] + MyList = List[int, ...] # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*List")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*List"}) def test_multiple_ellipses(self): errors = self.CheckWithErrors("""\ from typing import Union - MyUnion = Union[..., int, ..., str, ...] + MyUnion = Union[..., int, ..., str, ...] # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [ - (2, "invalid-annotation", r"Ellipsis.*indices 0, 2, 4.*Union")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*indices 0, 2, 4.*Union"}) def test_bad_tuple_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Tuple - MyTuple1 = Tuple[..., ...] - MyTuple2 = Tuple[...] + MyTuple1 = Tuple[..., ...] # invalid-annotation[e1] + MyTuple2 = Tuple[...] # invalid-annotation[e2] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 0.*Tuple"), - (3, "invalid-annotation", r"Ellipsis.*index 0.*Tuple")]) + self.assertErrorRegexes(errors, {"e1": r"Ellipsis.*index 0.*Tuple", + "e2": r"Ellipsis.*index 0.*Tuple"}) def test_bad_callable_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Callable - MyCallable1 = Callable[..., ...] - MyCallable2 = Callable[[int], ...] - MyCallable3 = Callable[[...], int] - MyCallable4 = Callable[[int], int, int] + MyCallable1 = Callable[..., ...] # invalid-annotation[e1] + MyCallable2 = Callable[[int], ...] # invalid-annotation[e2] + MyCallable3 = Callable[[...], int] # invalid-annotation[e3] + MyCallable4 = Callable[[int], int, int] # invalid-annotation[e4] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*Callable"), - (3, "invalid-annotation", r"Ellipsis.*index 1.*Callable"), - (4, "invalid-annotation", r"Ellipsis.*index 0.*list"), - (5, "invalid-annotation", r"Callable\[_ARGS, _RET].*2.*3")]) + self.assertErrorRegexes(errors, { + "e1": r"Ellipsis.*index 1.*Callable", + "e2": r"Ellipsis.*index 1.*Callable", + "e3": r"Ellipsis.*index 0.*list", + "e4": r"Callable\[_ARGS, _RET].*2.*3"}) def test_optional_parameters(self): errors = self.CheckWithErrors("""\ @@ -522,16 +507,15 @@ def test_optional_parameters(self): def func1(x: Optional[int]): pass - def func2(x: Optional): + def func2(x: Optional): # invalid-annotation[e1] pass - def func3(x: Optional[int, float, str]): + def func3(x: Optional[int, float, str]): # invalid-annotation[e2] pass """) - self.assertErrorLogIs( - errors, [(6, "invalid-annotation", r"Not a type"), - (9, "invalid-annotation", - r"typing.Optional can only contain one type parameter")]) + self.assertErrorRegexes( + errors, {"e1": r"Not a type", + "e2": r"typing\.Optional can only contain one type parameter"}) def test_noreturn_parameters(self): errors = self.CheckWithErrors("""\ @@ -540,27 +524,25 @@ def test_noreturn_parameters(self): def func0() -> NoReturn: raise ValueError() - def func1() -> List[NoReturn]: + def func1() -> List[NoReturn]: # invalid-annotation[e1] raise ValueError() def func2(x) -> NoReturn: if x > 1: - raise ValueError() + raise ValueError() # bad-return-type[e2] - def func3(x: NoReturn): + def func3(x: NoReturn): # invalid-annotation[e3] pass - def func4(x: List[NoReturn]): + def func4(x: List[NoReturn]): # invalid-annotation[e4] pass - bad = None # type: NoReturn + bad = None # type: NoReturn # invalid-annotation[e5] """) - self.assertErrorLogIs( - errors, [(6, "invalid-annotation", r"NoReturn is not allowed"), - (11, "bad-return-type", r"NoReturn.*None"), - (13, "invalid-annotation", r"NoReturn is not allowed"), - (16, "invalid-annotation", r"NoReturn is not allowed"), - (19, "invalid-annotation", r"NoReturn is not allowed")]) + self.assertErrorRegexes(errors, { + "e1": r"NoReturn is not allowed", "e2": r"NoReturn.*None", + "e3": r"NoReturn is not allowed", "e4": r"NoReturn is not allowed", + "e5": r"NoReturn is not allowed"}) def test_SupportsComplex(self): self.Check("""\ @@ -575,7 +557,7 @@ class CounterTest(test_base.TargetPython3BasicTest): """Tests for typing.Counter.""" def test_counter_generic(self): - ty, errors = self.InferWithErrors(""" + ty, _ = self.InferWithErrors(""" import collections import typing def freqs(s: str) -> typing.Counter[str]: @@ -587,8 +569,8 @@ def freqs(s: str) -> typing.Counter[str]: x + y x | y x & y - x - z # line 13 error: unsupported-operands - x.most_common(1, 2, 3) # line 14 error: wrong-arg-count + x - z # unsupported-operands + x.most_common(1, 2, 3) # wrong-arg-count a = x.most_common() b = x.most_common(1) c = x.elements() @@ -614,8 +596,6 @@ def freqs(s: str) -> typing.Counter[str]: def freqs(s: str) -> Counter[str]: ... """) - self.assertErrorLogIs( - errors, [(13, "unsupported-operands"), (14, "wrong-arg-count")]) class TypingTestPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_typing_namedtuple.py b/pytype/tests/py3/test_typing_namedtuple.py index 603c5e736..d51f14c62 100644 --- a/pytype/tests/py3/test_typing_namedtuple.py +++ b/pytype/tests/py3/test_typing_namedtuple.py @@ -8,22 +8,19 @@ class NamedTupleTest(test_base.TargetPython3BasicTest): """Tests for the typing.NamedTuple overlay.""" def test_make(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing A = typing.NamedTuple("A", [("b", str), ("c", str)]) a = A._make(["hello", "world"]) b = A._make(["hello", "world"], len=len) - c = A._make([1, 2]) # Should fail - d = A._make(A) # Should fail + c = A._make([1, 2]) # wrong-arg-types + d = A._make(A) # wrong-arg-types def f(e: A) -> None: pass f(a) """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (6, "wrong-arg-types")]) def test_subclass(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing A = typing.NamedTuple("A", [("b", str), ("c", int)]) class B(A): @@ -36,15 +33,12 @@ def take_b(b: B) -> None: pass take_a(x) take_b(x) take_b(y) - take_b(A("", 0)) # Should fail - B() # Should fail + take_b(A("", 0)) # wrong-arg-types + B() # missing-parameter # _make and _replace should return instances of the subclass. take_b(B._make(["hello", 0])) take_b(y._replace(b="world")) """) - self.assertErrorLogIs(errors, [ - (13, "wrong-arg-types"), - (14, "missing-parameter")]) def test_callable_attribute(self): ty = self.Infer(""" @@ -59,13 +53,13 @@ def foo(x: X): def test_bare_union_attribute(self): ty, errors = self.InferWithErrors("""\ from typing import NamedTuple, Union - X = NamedTuple("X", [("x", Union)]) + X = NamedTuple("X", [("x", Union)]) # invalid-annotation[e] def foo(x: X): return x.x """) self.assertMultiLineEqual(pytd_utils.Print(ty.Lookup("foo")), "def foo(x: X) -> Any: ...") - self.assertErrorLogIs(errors, [(2, "invalid-annotation", r"Union.*x")]) + self.assertErrorRegexes(errors, {"e": r"Union.*x"}) class NamedTupleTestPy3(test_base.TargetPython3FeatureTest): @@ -124,22 +118,21 @@ def test_bad_call(self): _, errorlog = self.InferWithErrors("""\ from typing import NamedTuple E2 = NamedTuple('Employee2', [('name', str), ('id', int)], - birth=str, gender=bool) + birth=str, gender=bool) # invalid-namedtuple-arg[e1] # wrong-keyword-args[e2] """) - self.assertErrorLogIs(errorlog, [ - (3, "invalid-namedtuple-arg", "Either list of fields or keywords.*"), - (3, "wrong-keyword-args", ".*(birth, gender).*NamedTuple")]) + self.assertErrorRegexes(errorlog, { + "e1": r"Either list of fields or keywords.*", + "e2": r".*(birth, gender).*NamedTuple"}) def test_bad_attribute(self): _, errorlog = self.InferWithErrors("""\ from typing import NamedTuple - class SubCls(NamedTuple): + class SubCls(NamedTuple): # not-writable[e] def __init__(self): pass """) - self.assertErrorLogIs(errorlog, [ - (3, "not-writable", ".*'__init__'.*[SubCls]")]) + self.assertErrorRegexes(errorlog, {"e": r".*'__init__'.*[SubCls]"}) def test_bad_arg_count(self): _, errorlog = self.InferWithErrors("""\ @@ -149,23 +142,20 @@ class SubCls(NamedTuple): a: int b: int - cls1 = SubCls(5) + cls1 = SubCls(5) # missing-parameter[e] """) - self.assertErrorLogIs(errorlog, [ - (7, "missing-parameter", "Missing.*'b'.*__new__")]) + self.assertErrorRegexes(errorlog, {"e": r"Missing.*'b'.*__new__"}) def test_bad_arg_name(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import NamedTuple - class SubCls(NamedTuple): + class SubCls(NamedTuple): # invalid-namedtuple-arg _a: int b: int cls1 = SubCls(5) """) - self.assertErrorLogIs(errorlog, [ - (3, "invalid-namedtuple-arg")]) def test_namedtuple_class(self): self.Check("""\ diff --git a/pytype/tests/py3/test_variable_annotations.py b/pytype/tests/py3/test_variable_annotations.py index 74be589cb..a9b0706cb 100644 --- a/pytype/tests/py3/test_variable_annotations.py +++ b/pytype/tests/py3/test_variable_annotations.py @@ -23,13 +23,11 @@ def f(x: int) -> None: pass obj = foo.A() f(foo.x) - f(foo.y) + f(foo.y) # wrong-arg-types[e1] f(obj.a) - f(obj.b) + f(obj.b) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types", r"int.*List"), - (8, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e1": r"int.*List", "e2": r"int.*str"}) class VariableAnnotationsFeatureTest(test_base.TargetPython3FeatureTest): @@ -66,21 +64,19 @@ def testIllegalAnnotations(self): T = TypeVar('T') - a: "abc" = "1" - b: 123 = "2" - c: NoReturn = "3" + a: "abc" = "1" # name-error[e1] + b: 123 = "2" # invalid-annotation[e2] + c: NoReturn = "3" # invalid-annotation[e3] d: List[int] = [] - e: List[T] = [] - f: int if __random__ else str = 123 - h: NoReturn = None - """) - self.assertErrorLogIs(errors, [ - (5, "name-error", "Name \'abc\' is not defined"), - (6, "invalid-annotation", "Not a type"), - (7, "invalid-annotation", "NoReturn is not allowed"), - (9, "not-supported-yet", r"type parameter.*variable annotation"), - (10, "invalid-annotation", r"Type must be constant"), - (11, "invalid-annotation", r"NoReturn is not allowed")]) + e: List[T] = [] # not-supported-yet[e4] + f: int if __random__ else str = 123 # invalid-annotation[e5] + h: NoReturn = None # invalid-annotation[e6] + """) + self.assertErrorRegexes(errors, { + "e1": r"Name \'abc\' is not defined", "e2": r"Not a type", + "e3": r"NoReturn is not allowed", + "e4": r"type parameter.*variable annotation", + "e5": r"Type must be constant", "e6": r"NoReturn is not allowed"}) def testUninitializedClassAnnotation(self): ty = self.Infer(""" @@ -108,10 +104,9 @@ def testUninitializedModuleAnnotation(self): def testOverwriteAnnotationsDict(self): errors = self.CheckWithErrors("""\ __annotations__ = None - foo: int + foo: int # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(2, "unsupported-operands", r"None.*__setitem__")]) + self.assertErrorRegexes(errors, {"e": r"None.*__setitem__"}) def testShadowNone(self): ty = self.Infer(""" diff --git a/pytype/tests/test_abc.py b/pytype/tests/test_abc.py index 6b1a82006..1811989c2 100644 --- a/pytype/tests/test_abc.py +++ b/pytype/tests/test_abc.py @@ -17,21 +17,19 @@ def foo(self) -> None: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.Example() + foo.Example() # not-instantiable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", - r"foo\.Example.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Example.*foo"}) def test_stray_abstractmethod(self): _, errors = self.InferWithErrors("""\ import abc - class Example(object): + class Example(object): # ignored-abstractmethod[e] @abc.abstractmethod def foo(self): pass """) - self.assertErrorLogIs(errors, [(2, "ignored-abstractmethod", - r"foo.*Example")]) + self.assertErrorRegexes(errors, {"e": r"foo.*Example"}) def test_multiple_inheritance_implementation_pyi(self): with file_utils.Tempdir() as d: @@ -62,9 +60,9 @@ class Foo(X, Interface): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.Foo().foo() + foo.Foo().foo() # not-instantiable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) def test_abc_metaclass_from_decorator(self): with file_utils.Tempdir() as d: @@ -108,10 +106,9 @@ def test_misplaced_abstractproperty(self): @abc.abstractproperty class Example(object): pass - Example() + Example() # not-callable[e] """) - self.assertErrorLogIs(errors, - [(5, "not-callable", r"'abstractproperty' object")]) + self.assertErrorRegexes(errors, {"e": r"'abstractproperty' object"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_attr.py b/pytype/tests/test_attr.py index 7c0435ff3..1bf3ef6fb 100644 --- a/pytype/tests/test_attr.py +++ b/pytype/tests/test_attr.py @@ -140,24 +140,22 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s - class Foo(object): + class Foo(object): # invalid-annotation x = attr.ib(type=str) # type: int y = attr.ib(type=str, default="") # type: int Foo(x="") # should not report an error """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation")]) def test_bad_type(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s class Foo(object): - x = attr.ib(type=10) + x = attr.ib(type=10) # invalid-annotation """) - self.assertErrorLogIs(errors, [(5, "invalid-annotation")]) def test_name_mangling(self): # NOTE: Python itself mangles names starting with two underscores. @@ -276,21 +274,20 @@ def test_bad_factory(self): import attr @attr.s class Foo(object): - x = attr.ib(default=attr.Factory(42)) - y = attr.ib(factory=42) + x = attr.ib(default=attr.Factory(42)) # wrong-arg-types[e1] + y = attr.ib(factory=42) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"Callable.*int"), - (5, "wrong-arg-types", r"Callable.*int")]) + self.assertErrorRegexes(errors, {"e1": r"Callable.*int", + "e2": r"Callable.*int"}) def test_default_factory_clash(self): errors = self.CheckWithErrors("""\ import attr @attr.s class Foo(object): - x = attr.ib(default=None, factory=list) + x = attr.ib(default=None, factory=list) # duplicate-keyword-argument[e] """) - self.assertErrorLogIs( - errors, [(4, "duplicate-keyword-argument", r"default")]) + self.assertErrorRegexes(errors, {"e": r"default"}) def test_takes_self(self): ty = self.Infer(""" @@ -388,18 +385,17 @@ def test_init_bad_constant(self): import attr @attr.s class Foo(object): - x = attr.ib(init=0) + x = attr.ib(init=0) # wrong-arg-types[e] """) - self.assertErrorLogIs(err, [(4, "wrong-arg-types", r"bool.*int")]) + self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_init_bad_kwarg(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s class Foo: - x = attr.ib(init=__random__) # type: str + x = attr.ib(init=__random__) # type: str # not-supported-yet """) - self.assertErrorLogIs(err, [(5, "not-supported-yet")]) def test_class(self): self.assertNoCrash(self.Check, """ @@ -605,20 +601,19 @@ class Foo(object): def test_init_bad_constant(self): err = self.CheckWithErrors("""\ import attr - @attr.s(init=0) + @attr.s(init=0) # wrong-arg-types[e] class Foo: pass """) - self.assertErrorLogIs(err, [(2, "wrong-arg-types", r"bool.*int")]) + self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_bad_kwarg(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr - @attr.s(init=__random__) + @attr.s(init=__random__) # not-supported-yet class Foo: pass """) - self.assertErrorLogIs(err, [(3, "not-supported-yet")]) def test_depth(self): self.Check(""" diff --git a/pytype/tests/test_attributes.py b/pytype/tests/test_attributes.py index 5cd63d923..5b6719e8d 100644 --- a/pytype/tests/test_attributes.py +++ b/pytype/tests/test_attributes.py @@ -26,9 +26,9 @@ def testClassConstantError(self): errors = self.CheckWithErrors("""\ x = None class Foo(object): - x = x.upper() + x = x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMultiplePaths(self): errors = self.CheckWithErrors("""\ @@ -36,9 +36,9 @@ def testMultiplePaths(self): def f(): z = None if __random__ else x y = z - return y.upper() + return y.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testLateInitialization(self): ty = self.Infer(""" @@ -86,9 +86,9 @@ def testReturnValue(self): def f(): pass def g(): - return f().upper() + return f().upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMethodReturnValue(self): errors = self.CheckWithErrors("""\ @@ -96,9 +96,9 @@ class Foo(object): def f(self): pass def g(): - return Foo().f().upper() + return Foo().f().upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testPyiReturnValue(self): with file_utils.Tempdir() as d: @@ -106,18 +106,18 @@ def testPyiReturnValue(self): errors = self.CheckWithErrors("""\ import foo def g(): - return foo.f().upper() + return foo.f().upper() # attribute-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testPassThroughNone(self): errors = self.CheckWithErrors("""\ def f(x): return x def g(): - return f(None).upper() + return f(None).upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testShadowedLocalOrigin(self): self.Check(""" @@ -155,20 +155,19 @@ def g(): def testUnpackedNone(self): errors = self.CheckWithErrors("""\ _, a = 42, None - b = a.upper() + b = a.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testFunctionDefault(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self, v=None): - v.upper() + v.upper() # attribute-error[e] def f(): Foo() """) - self.assertErrorLogIs( - errors, [(3, "attribute-error", r"upper.*None.*traceback.*line 5")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None.*traceback.*line 5"}) def testKeepNoneReturn(self): ty = self.Infer(""" @@ -252,10 +251,9 @@ def testGetItem(self): errors = self.CheckWithErrors("""\ def f(): x = None - return x[0] + return x[0] # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(3, "unsupported-operands", r"item retrieval.*None.*int")]) + self.assertErrorRegexes(errors, {"e": r"item retrieval.*None.*int"}) def testIgnoreGetItem(self): self.Check(""" @@ -275,10 +273,9 @@ def testContains(self): errors = self.CheckWithErrors("""\ def f(): x = None - return 42 in x + return 42 in x # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(3, "unsupported-operands", r"'in'.*None.*int")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*None.*int"}) def testIgnoreContains(self): self.Check(""" @@ -500,13 +497,13 @@ def f(x) -> Any @test_base.skip("TODO(b/63407497): implement strict checking for __setitem__") def testUnionSetAttribute(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ class A(object): x = "Hello world" def f(i): t = A() l = [t] - l[i].x = 1 # line 6 + l[i].x = 1 # not-writable return l[i].x """) self.assertTypesMatchPytd(ty, """ @@ -515,7 +512,6 @@ class A(object): x = ... # type: str def f(i) -> Any """) - self.assertErrorLogIs(errors, [(6, "not-writable")]) def testSetClass(self): ty = self.Infer(""" @@ -591,9 +587,9 @@ def testHasDynamicAttributesClassAttr(self): errors = self.CheckWithErrors("""\ class Foo(object): _HAS_DYNAMIC_ATTRIBUTES = True - Foo.CONST + Foo.CONST # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", "CONST.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"CONST.*Foo"}) def testHasDynamicAttributesMetaclass(self): # Since class attributes of Foo are instance attributes for the metaclass, @@ -657,21 +653,19 @@ def testModuleTypeAttribute(self): """) def testAttrOnNone(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(arg): x = "foo" if arg else None if not x: - x.upper() + x.upper() # attribute-error """) - self.assertErrorLogIs(errors, [(4, "attribute-error")]) def testIteratorOnNone(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): pass - a, b = f() + a, b = f() # attribute-error """) - self.assertErrorLogIs(errors, [(3, "attribute-error")]) def testOverloadedBuiltin(self): self.Check(""" @@ -722,10 +716,10 @@ def __init__(self) -> None: ... def testBadIter(self): errors = self.CheckWithErrors("""\ v = [] if __random__ else 42 - for _ in v: + for _ in v: # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"__iter__.*int")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*int"}) def testBadGetItem(self): errors = self.CheckWithErrors("""\ @@ -733,11 +727,10 @@ class Foo(object): def __getitem__(self, x): return 0 v = Foo() if __random__ else 42 - for _ in v: # line 5 + for _ in v: # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(5, "attribute-error", - r"__iter__.*int.*Union\[Foo, int\]")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*int.*Union\[Foo, int\]"}) def testBadContains(self): errors = self.CheckWithErrors("""\ @@ -745,12 +738,11 @@ class Foo(object): def __iter__(self): return iter([]) v = Foo() if __random__ else 42 - if 42 in v: # line 5 + if 42 in v: # unsupported-operands[e] pass """) - self.assertErrorLogIs( - errors, [(5, "unsupported-operands", - r"'in'.*'Union\[Foo, int\]' and 'int'")]) + self.assertErrorRegexes( + errors, {"e": r"'in'.*'Union\[Foo, int\]' and 'int'"}) def testSubclassShadowing(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_basic.py b/pytype/tests/test_basic.py index 17ee2304e..493c7e63c 100644 --- a/pytype/tests/test_basic.py +++ b/pytype/tests/test_basic.py @@ -245,24 +245,22 @@ def test_attribute_inplace_ops(self): """) def test_deleting_names(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ g = 17 assert g == 17 del g - g + g # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) def test_deleting_local_names(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): l = 23 assert l == 23 del l - l + l # name-error f() """) - self.assertErrorLogIs(errors, [(5, "name-error")]) def test_import(self): self.Check("""\ @@ -317,9 +315,9 @@ def __init__(self, x): def meth(self, y): return self.x * y thing1 = Thing(2) - print(Thing.meth(14)) + print(Thing.meth(14)) # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(7, "missing-parameter", r"self")]) + self.assertErrorRegexes(errors, {"e": r"self"}) def test_calling_subclass_methods(self): self.Check("""\ @@ -345,9 +343,9 @@ def bar(self): return 9 st = SubThing() - print(st.foo()) + print(st.foo()) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(10, "attribute-error", r"foo.*SubThing")]) + self.assertErrorRegexes(errors, {"e": r"foo.*SubThing"}) def test_attribute_access(self): self.Check("""\ @@ -368,9 +366,9 @@ class Thing(object): def __init__(self): self.x = 23 t = Thing() - print(t.xyzzy) + print(t.xyzzy) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(6, "attribute-error", r"xyzzy.*Thing")]) + self.assertErrorRegexes(errors, {"e": r"xyzzy.*Thing"}) def test_staticmethods(self): self.Check("""\ @@ -488,15 +486,14 @@ def baz(): """) def test_delete_global(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ a = 3 def f(): global a del a f() - x = a + x = a # name-error """) - self.assertErrorLogIs(errors, [(6, "name-error")]) def test_string(self): self.Check("v = '\\xff'") diff --git a/pytype/tests/test_builtins1.py b/pytype/tests/test_builtins1.py index 05fc2c3ad..381d5760c 100644 --- a/pytype/tests/test_builtins1.py +++ b/pytype/tests/test_builtins1.py @@ -114,8 +114,8 @@ def t_testMax2(x, y) -> ? """) def testZipError(self): - errors = self.CheckWithErrors("zip([], [], [], 42)") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", "Iterable.*int")]) + errors = self.CheckWithErrors("zip([], [], [], 42) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Iterable.*int"}) def testDictDefaults(self): ty = self.Infer(""" @@ -316,9 +316,8 @@ def f(x) -> str """) def testOpenError(self): - src = "open(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)" - errors = self.CheckWithErrors(src) - self.assertErrorLogIs(errors, [(1, "wrong-arg-count")]) + src = "open(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) # wrong-arg-count" + self.CheckWithErrors(src) def testSignal(self): ty = self.Infer(""" diff --git a/pytype/tests/test_builtins2.py b/pytype/tests/test_builtins2.py index 6569594d2..5b9e646d2 100644 --- a/pytype/tests/test_builtins2.py +++ b/pytype/tests/test_builtins2.py @@ -349,9 +349,9 @@ def testReversed(self): x2 = reversed([42]) x3 = reversed((4, 2)) x4 = reversed("hello") - x5 = reversed({42}) - x6 = reversed(frozenset([42])) - x7 = reversed({True: 42}) + x5 = reversed({42}) # wrong-arg-types[e1] + x6 = reversed(frozenset([42])) # wrong-arg-types[e2] + x7 = reversed({True: 42}) # wrong-arg-types[e3] x8 = next(reversed([42])) x9 = list(reversed([42])) """) @@ -367,10 +367,9 @@ def testReversed(self): x8 = ... # type: int x9 = ... # type: List[int] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", r"Set\[int\]"), - (6, "wrong-arg-types", r"FrozenSet\[int\]"), - (7, "wrong-arg-types", - r"Dict\[bool, int\]")]) + self.assertErrorRegexes(errors, {"e1": r"Set\[int\]", + "e2": r"FrozenSet\[int\]", + "e3": r"Dict\[bool, int\]"}) def testStrJoin(self): ty = self.Infer(""" @@ -398,13 +397,11 @@ def testReduce(self): _, errors = self.InferWithErrors("""\ reduce(lambda x, y: x+y, [1,2,3]).real reduce(lambda x, y: x+y, ["foo"]).upper() - reduce(lambda x, y: 4, "foo").real + reduce(lambda x, y: 4, "foo").real # attribute-error[e] reduce(lambda x, y: 4, [], "foo").upper() reduce(lambda x, y: "s", [1,2,3], 0).upper() """) - self.assertErrorLogIs(errors, [ - (3, "attribute-error", "real.*str") - ]) + self.assertErrorRegexes(errors, {"e": r"real.*str"}) def testDictPopItem(self): ty = self.Infer(""" diff --git a/pytype/tests/test_builtins3.py b/pytype/tests/test_builtins3.py index e3c9ec948..06d51739d 100644 --- a/pytype/tests/test_builtins3.py +++ b/pytype/tests/test_builtins3.py @@ -66,12 +66,13 @@ def testNextFunction(self): """) def testImplicitTypeVarImport(self): - ty, errors = self.InferWithErrors("v = " + abstract_utils.T) + ty, _ = self.InferWithErrors("""\ + v = %s # name-error + """ % abstract_utils.T) self.assertTypesMatchPytd(ty, """ from typing import Any v = ... # type: Any """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testExplicitTypeVarImport(self): self.Check(""" @@ -128,9 +129,9 @@ def testIntInit(self): int("0", 10) int(u"0") int(u"0", 10) - int(0, 1, 2) # line 7: wrong argcount + int(0, 1, 2) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-count", r"1.*4")]) + self.assertErrorRegexes(errors, {"e": r"1.*4"}) def testNewlines(self): with file_utils.Tempdir() as d: @@ -206,21 +207,15 @@ def testBuiltins(self): """) def testSpecialBuiltinTypes(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ isinstance(1, int) - isinstance(1, "no") + isinstance(1, "no") # wrong-arg-types issubclass(int, object) - issubclass(0, 0) - issubclass(int, 0) + issubclass(0, 0) # wrong-arg-types + issubclass(int, 0) # wrong-arg-types hasattr(str, "upper") - hasattr(int, int) + hasattr(int, int) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types"), - (4, "wrong-arg-types"), - (5, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testUnpackList(self): ty = self.Infer(""" @@ -278,8 +273,8 @@ def testFromHex(self): """) def testNoneLength(self): - errors = self.CheckWithErrors("len(None)") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"Sized.*None")]) + errors = self.CheckWithErrors("len(None) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Sized.*None"}) def testSequenceLength(self): self.Check(""" @@ -351,8 +346,8 @@ def testInput(self): def testSetDefaultError(self): ty, errors = self.InferWithErrors("""\ x = {} - y = x.setdefault() - z = x.setdefault(1, 2, 3, *[]) + y = x.setdefault() # wrong-arg-count[e1] + z = x.setdefault(1, 2, 3, *[]) # wrong-arg-count[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict @@ -360,8 +355,7 @@ def testSetDefaultError(self): y = ... # type: Any z = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "wrong-arg-count", "2.*0"), - (3, "wrong-arg-count", "2.*3")]) + self.assertErrorRegexes(errors, {"e1": r"2.*0", "e2": r"2.*3"}) def testTuple(self): ty = self.Infer(""" diff --git a/pytype/tests/test_calls.py b/pytype/tests/test_calls.py index e319b30ce..34fc22670 100644 --- a/pytype/tests/test_calls.py +++ b/pytype/tests/test_calls.py @@ -24,22 +24,20 @@ def testMissing(self): d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1) + mod.foo(1) # missing-parameter """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter")]) def testExtraneous(self): with file_utils.Tempdir() as d: d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1, 2, 3) + mod.foo(1, 2, 3) # wrong-arg-count """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-count")]) def testMissingKwOnly(self): with file_utils.Tempdir() as d: @@ -48,20 +46,19 @@ def foo(x, y, *, z) -> int """) _, errors = self.InferWithErrors("""\ import mod - mod.foo(1, 2) + mod.foo(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) def testExtraKeyword(self): with file_utils.Tempdir() as d: d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1, 2, z=3) + mod.foo(1, 2, z=3) # wrong-keyword-args """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-keyword-args")]) def testVarArgsWithKwOnly(self): with file_utils.Tempdir() as d: @@ -79,12 +76,11 @@ def testVarArgsWithMissingKwOnly(self): d.create_file("mod.pyi", """ def foo(*args: int, z: int) -> int """) - _, errors = self.InferWithErrors( - """\ + _, errors = self.InferWithErrors("""\ import mod - mod.foo(1, 2, 3) + mod.foo(1, 2, 3) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_classes.py b/pytype/tests/test_classes.py index b691c65e7..a59eca1dc 100644 --- a/pytype/tests/test_classes.py +++ b/pytype/tests/test_classes.py @@ -215,9 +215,9 @@ def __init__(self, x, y, z): pass class Foo(Base): def __init__(self, x): - super(Foo, self).__init__() + super(Foo, self).__init__() # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(6, "missing-parameter", r"x")]) + self.assertErrorRegexes(errors, {"e": r"x"}) def testSuperInInit(self): ty = self.Infer(""" @@ -899,25 +899,24 @@ def f() -> C[int]: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f() + foo.f() # mro-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"C")]) + self.assertErrorRegexes(errors, {"e": r"C"}) def testCallParameterizedClass(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import List - List[str]() - """) - self.assertErrorLogIs(errors, [(2, "not-callable")]) + List[str]() # not-callable + """) def testErrorfulConstructors(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ class Foo(object): attr = 42 def __new__(cls): - return name_error + return name_error # name-error def __init__(self): - self.attribute_error + self.attribute_error # attribute-error self.instance_attr = self.attr def f(self): return self.instance_attr @@ -930,7 +929,6 @@ class Foo(object): def __new__(cls) -> Any: ... def f(self) -> int: ... """) - self.assertErrorLogIs(errors, [(4, "name-error"), (6, "attribute-error")]) def testNewFalse(self): ty = self.Infer("""\ @@ -1032,28 +1030,28 @@ def testSuperNewWrongArgCount(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls, x): - return super(Foo, cls).__new__(cls, x) + return super(Foo, cls).__new__(cls, x) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperInitWrongArgCount(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __init__(self, x): - super(Foo, self).__init__(x) + super(Foo, self).__init__(x) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperNewMissingParameter(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls, x): # Even when __init__ is defined, too few args is an error. - return super(Foo, cls).__new__() + return super(Foo, cls).__new__() # missing-parameter[e] def __init__(self, x): pass """, deep=True) - self.assertErrorLogIs(errors, [(4, "missing-parameter", r"cls.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"cls.*__new__"}) def testNewKwarg(self): _, errors = self.InferWithErrors("""\ @@ -1065,9 +1063,9 @@ def __init__(self): pass class Bar(object): def __new__(cls): - return super(Bar, cls).__new__(cls, x=42) # bad! + return super(Bar, cls).__new__(cls, x=42) # wrong-keyword-args[e] """, deep=True) - self.assertErrorLogIs(errors, [(9, "wrong-keyword-args", r"x.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"x.*__new__"}) def testInitKwarg(self): _, errors = self.InferWithErrors("""\ @@ -1079,9 +1077,9 @@ def __new__(cls): return super(Foo, cls).__new__(cls) class Bar(object): def __init__(self): - super(Bar, self).__init__(x=42) # bad! + super(Bar, self).__init__(x=42) # wrong-keyword-args[e] """, deep=True) - self.assertErrorLogIs(errors, [(9, "wrong-keyword-args", r"x.*__init__")]) + self.assertErrorRegexes(errors, {"e": r"x.*__init__"}) def testAliasInnerClass(self): ty = self.Infer(""" @@ -1130,14 +1128,13 @@ def testInstantiateWithAbstractDict(self): """) def testNotInstantiable(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): def __new__(cls): assert cls is not Foo, "not instantiable" def foo(self): - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(5, "name-error")]) def testMetaclassOnUnknownClass(self): self.Check(""" diff --git a/pytype/tests/test_cmp.py b/pytype/tests/test_cmp.py index ecbc1af20..297122b42 100644 --- a/pytype/tests/test_cmp.py +++ b/pytype/tests/test_cmp.py @@ -10,7 +10,7 @@ class InTest(test_base.TargetIndependentTest): def test_concrete(self): ty, errors = self.InferWithErrors("""\ def f(x, y): - return x in y + return x in y # unsupported-operands[e] f(1, [1]) f(1, [2]) f("x", "x") @@ -19,8 +19,7 @@ def f(x, y): f("y", object()) """, deep=False, show_library_calls=True) self.assertOnlyHasReturnType(ty.Lookup("f"), self.bool) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"'in'.*object")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*object"}) def test_deep(self): ty = self.Infer(""" @@ -50,12 +49,11 @@ def g() -> bool def test_none(self): _, errors = self.InferWithErrors("""\ x = None - if "" in x: - del x[""] + if "" in x: # unsupported-operands[e1] + del x[""] # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [ - (2, "unsupported-operands", r"'in'.*None"), - (3, "unsupported-operands", r"item deletion.*None")]) + self.assertErrorRegexes( + errors, {"e1": r"'in'.*None", "e2": r"item deletion.*None"}) class NotInTest(test_base.TargetIndependentTest): @@ -64,7 +62,7 @@ class NotInTest(test_base.TargetIndependentTest): def test_concrete(self): ty, errors = self.InferWithErrors("""\ def f(x, y): - return x not in y + return x not in y # unsupported-operands[e] f(1, [1]) f(1, [2]) f("x", "x") @@ -73,8 +71,7 @@ def f(x, y): f("y", object()) """, deep=False, show_library_calls=True) self.assertOnlyHasReturnType(ty.Lookup("f"), self.bool) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"'in'.*object")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*object"}) # "not in" maps to the inverse of __contains__ def test_overloaded(self): @@ -98,12 +95,11 @@ def g() -> bool def test_none(self): _, errors = self.InferWithErrors("""\ x = None - if "" not in x: - x[""] = 42 + if "" not in x: # unsupported-operands[e1] + x[""] = 42 # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [ - (2, "unsupported-operands", r"'in'.*None"), - (3, "unsupported-operands", r"item assignment.*None")]) + self.assertErrorRegexes( + errors, {"e1": r"'in'.*None", "e2": r"item assignment.*None"}) class IsTest(test_base.TargetIndependentTest): diff --git a/pytype/tests/test_compile_to_pyc.py b/pytype/tests/test_compile_to_pyc.py index 93af1f606..e98fdbf1f 100644 --- a/pytype/tests/test_compile_to_pyc.py +++ b/pytype/tests/test_compile_to_pyc.py @@ -5,6 +5,7 @@ class CompileToPycTest(test_base.TargetIndependentTest): + """Tests for compilation to bytecode.""" def testCompilationOfUnicodeSource(self): self.Check("print('←↑→↓')") @@ -14,20 +15,18 @@ def testCompilationOfUnicodeSourceWithEncoding(self): self.Check("#! my/python\n# encoding: utf-8\nprint('←↑→↓')") def testErrorLineNumbersWithEncoding1(self): - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ # coding: utf-8 def foo(): - return "1".hello + return "1".hello # attribute-error """) - self.assertErrorLogIs(errorlog, [(3, "attribute-error")]) def testErrorLineNumbersWithEncoding2(self): - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ #! /bin/python # coding: utf-8 def foo(): - return "1".hello + return "1".hello # attribute-error """) - self.assertErrorLogIs(errorlog, [(4, "attribute-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_containers.py b/pytype/tests/test_containers.py index 0b3dc9f30..85bbcf443 100644 --- a/pytype/tests/test_containers.py +++ b/pytype/tests/test_containers.py @@ -544,11 +544,11 @@ def testEqOperatorOnItemFromEmptyDict(self): """, deep=False) def testDict(self): - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ mymap = {'a': 3.14, 'b':1} a = mymap['a'] b1 = mymap['b'] - c = mymap['foobar'] + c = mymap['foobar'] # key-error[e] mymap[str()] = 3j b2 = mymap['b'] """, deep=True) @@ -560,9 +560,7 @@ def testDict(self): c = ... # type: Any b2 = ... # type: Union[int, float, complex] """) - self.assertErrorLogIs(errors, [ - (5, "key-error", "foobar") - ]) + self.assertErrorRegexes(errors, {"e": r"foobar"}) def testDictOrAny(self): self.Check(""" @@ -577,9 +575,9 @@ def testDictOrAny(self): def testDictGetItem(self): _, errors = self.InferWithErrors("""\ v = {} - v.__getitem__("a") + v.__getitem__("a") # key-error[e] """) - self.assertErrorLogIs(errors, [(2, "key-error", r"'a'")]) + self.assertErrorRegexes(errors, {"e": r"'a'"}) def testEmptyList(self): ty = self.Infer(""" diff --git a/pytype/tests/test_decorators.py b/pytype/tests/test_decorators.py index dd914c264..21c79c1a0 100644 --- a/pytype/tests/test_decorators.py +++ b/pytype/tests/test_decorators.py @@ -88,9 +88,9 @@ def __init__(self): self._bar = 1 def _SetBar(self, value): self._bar = value - bar = property(should_fail=_SetBar) + bar = property(should_fail=_SetBar) # wrong-keyword-args[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-keyword-args", r"should_fail")]) + self.assertErrorRegexes(errors, {"e": r"should_fail"}) def testFgetIsOptional(self): self.Check(""" @@ -302,12 +302,12 @@ def __call__(self, func): return func class Foo(object): @classmethod - @Decorate # forgot to instantiate Decorate + @Decorate # forgot to instantiate Decorate # wrong-arg-count[e] def bar(cls): pass Foo.bar() """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-count", r"Decorate.*1.*2")]) + self.assertErrorRegexes(errors, {"e": r"Decorate.*1.*2"}) def testUncallableInstanceAsDecorator(self): errors = self.CheckWithErrors("""\ @@ -315,13 +315,13 @@ class Decorate(object): pass # forgot to define __call__ class Foo(object): @classmethod - @Decorate # forgot to instantiate Decorate + @Decorate # forgot to instantiate Decorate # wrong-arg-count[e1] def bar(cls): pass - Foo.bar() + Foo.bar() # not-callable[e2] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-count", r"Decorate.*1.*2"), - (8, "not-callable", r"Decorate")]) + self.assertErrorRegexes( + errors, {"e1": r"Decorate.*1.*2", "e2": r"Decorate"}) def testAmbiguousClassMethod(self): self.Check("""\ diff --git a/pytype/tests/test_dict.py b/pytype/tests/test_dict.py index 2a9a543c2..7da5bea13 100644 --- a/pytype/tests/test_dict.py +++ b/pytype/tests/test_dict.py @@ -24,14 +24,14 @@ def testPop(self): def testBadPop(self): ty, errors = self.InferWithErrors("""\ d = {"a": 42} - v = d.pop("b") + v = d.pop("b") # key-error[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict d = ... # type: Dict[str, int] v = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "key-error", r"b")]) + self.assertErrorRegexes(errors, {"e": r"b"}) def testAmbiguousPop(self): ty = self.Infer(""" diff --git a/pytype/tests/test_disables.py b/pytype/tests/test_disables.py index b7d80f846..a0b7e269c 100644 --- a/pytype/tests/test_disables.py +++ b/pytype/tests/test_disables.py @@ -8,30 +8,27 @@ class DisableTest(test_base.TargetIndependentTest): def testInvalidDirective(self): _, errors = self.InferWithErrors("""\ - x = 1 # pytype: this is not a valid pytype directive. + x = 1 # pytype: this is not a valid pytype directive. # invalid-directive """) - self.assertErrorLogIs(errors, [(1, "invalid-directive")]) # Invalid directives are just a warning, so has_error() should still # return False. self.assertFalse(errors.has_error()) def testInvalidDisableErrorName(self): _, errors = self.InferWithErrors("""\ - x = 1 # pytype: disable=not-an-error. + x = 1 # pytype: disable=not-an-error. # invalid-directive[e] """) - self.assertErrorLogIs(errors, [(1, "invalid-directive", - r"Invalid error name.*not-an-error")]) + self.assertErrorRegexes(errors, {"e": r"Invalid error name.*not-an-error"}) # Invalid directives are just a warning, so has_error() should still # return False. self.assertFalse(errors.has_error()) def testDisableError(self): - _, errors = self.InferWithErrors("""\ - x = a + self.InferWithErrors("""\ + x = a # name-error x = b # pytype: disable=name-error - x = c + x = c # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (3, "name-error")]) def testOpenEndedDirective(self): """Test that disables in the middle of the file can't be left open-ended.""" @@ -47,16 +44,16 @@ class A(object): CONSTANT = 42 # pytype: disable=not-callable # ok (before first class/function def) def f(x): - # type: ignore # bad + # type: ignore # late-directive[e1] pass def g(): pass x = y # pytype: disable=name-error # ok (single line) # pytype: disable=attribute-error # ok (re-enabled) - # pytype: disable=wrong-arg-types # bad + # pytype: disable=wrong-arg-types # late-directive[e2] # pytype: enable=attribute-error """) - self.assertErrorLogIs(errors, [(12, "late-directive", "Type checking"), - (17, "late-directive", "wrong-arg-types")]) + self.assertErrorRegexes( + errors, {"e1": r"Type checking", "e2": r"wrong-arg-types"}) # late-directive is a warning self.assertFalse(errors.has_error()) diff --git a/pytype/tests/test_errors.py b/pytype/tests/test_errors.py index 886e101f9..89d1e6fde 100644 --- a/pytype/tests/test_errors.py +++ b/pytype/tests/test_errors.py @@ -11,25 +11,25 @@ def testDeduplicate(self): _, errors = self.InferWithErrors("""\ def f(x): y = 42 - y.foobar + y.foobar # attribute-error[e] f(3) f(4) """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"'foobar' on int$")]) + self.assertErrorRegexes(errors, {"e": r"'foobar' on int$"}) def testUnknownGlobal(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ def f(): - return foobar() + return foobar() # name-error[e] """) - self.assertErrorLogIs(errors, [(3, "name-error", r"foobar")]) + self.assertErrorRegexes(errors, {"e": r"foobar"}) def testInvalidAttribute(self): ty, errors = self.InferWithErrors("""\ class A(object): pass def f(): - (3).parrot + (3).parrot # attribute-error[e] return "foo" """) self.assertTypesMatchPytd(ty, """ @@ -38,86 +38,69 @@ class A(object): def f() -> str """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"parrot.*int")]) + self.assertErrorRegexes(errors, {"e": r"parrot.*int"}) def testImportError(self): - _, errors = self.InferWithErrors("""\ - import rumplestiltskin + self.InferWithErrors("""\ + import rumplestiltskin # import-error """) - self.assertErrorLogIs(errors, [(1, "import-error", r"rumplestiltskin")]) def testImportFromError(self): _, errors = self.InferWithErrors("""\ - from sys import foobar + from sys import foobar # import-error[e] """) - self.assertErrorLogIs(errors, [(1, "import-error", r"sys\.foobar")]) + self.assertErrorRegexes(errors, {"e": r"sys\.foobar"}) def testNameError(self): - _, errors = self.InferWithErrors("""\ - foobar + self.InferWithErrors("""\ + foobar # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error", r"foobar")]) def testWrongArgCount(self): _, errors = self.InferWithErrors("""\ - hex(1, 2, 3, 4) + hex(1, 2, 3, 4) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-count", r"expects 1.*got 4")]) + self.assertErrorRegexes(errors, {"e": r"expects 1.*got 4"}) def testWrongArgTypes(self): _, errors = self.InferWithErrors("""\ - hex(3j) + hex(3j) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"int.*complex")]) + self.assertErrorRegexes(errors, {"e": r"int.*complex"}) def testInterpreterFunctionNameInMsg(self): _, errors = self.InferWithErrors("""\ class A(list): pass - A.append(3) + A.append(3) # missing-parameter[e] """) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.append")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.append"}) def testPyTDFunctionNameInMsg(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", "class A(list): pass") _, errors = self.InferWithErrors("""\ import foo - foo.A.append(3) + foo.A.append(3) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.append")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.append"}) def testBuiltinFunctionNameInMsg(self): _, errors = self.InferWithErrors("""\ x = list - x += (1,2) + x += (1,2) # missing-parameter[e] """) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.__iadd__")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.__iadd__"}) def testRewriteBuiltinFunctionName(self): """Should rewrite `function __builtin__.len` to `built-in function len`.""" - _, errors = self.InferWithErrors("x = len(None)") - self.assertErrorLogIs( - errors, - [(1, "wrong-arg-types", r"Built-in function len")] - ) + _, errors = self.InferWithErrors("x = len(None) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Built-in function len"}) def testBoundMethodNameInMsg(self): _, errors = self.InferWithErrors("""\ - "".join(1) + "".join(1) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, - [(1, "wrong-arg-types", r"Function str.join")] - ) + self.assertErrorRegexes(errors, {"e": r"Function str\.join"}) def testNestedClassMethodNameIsMsg(self): errors = self.CheckWithErrors("""\ @@ -125,9 +108,9 @@ class A(object): class B(object): def f(self): pass - A.B().f("oops") + A.B().f("oops") # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-count", r"Function B.f")]) + self.assertErrorRegexes(errors, {"e": r"Function B.f"}) def testPrettyPrintWrongArgs(self): with file_utils.Tempdir() as d: @@ -136,18 +119,16 @@ def f(a: int, b: int, c: int, d: int, e: int): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(1, 2, 3, "four", 5) + foo.f(1, 2, 3, "four", 5) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", ("a, b, c, d: int, [.][.][.].*" - "a, b, c, d: str, [.][.][.]"))]) + self.assertErrorRegexes(errors, { + "e": r"a, b, c, d: int, [.][.][.].*a, b, c, d: str, [.][.][.]"}) def testInvalidBaseClass(self): - _, errors = self.InferWithErrors("""\ - class Foo(3): + self.InferWithErrors("""\ + class Foo(3): # base-class-error pass """) - self.assertErrorLogIs(errors, [(1, "base-class-error")]) def testInvalidIteratorFromImport(self): with file_utils.Tempdir() as d: @@ -155,33 +136,32 @@ def testInvalidIteratorFromImport(self): class Codec(object): def __init__(self) -> None: ... """) - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ import mod def f(): - for row in mod.Codec(): + for row in mod.Codec(): # attribute-error[e] pass """, pythonpath=[d.path]) error = r"No attribute.*__iter__.*on mod\.Codec" - self.assertErrorLogIs(errors, [(4, "attribute-error", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testInvalidIteratorFromClass(self): _, errors = self.InferWithErrors("""\ class A(object): pass def f(): - for row in A(): + for row in A(): # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"__iter__.*A")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*A"}) def testIterOnModule(self): errors = self.CheckWithErrors("""\ import sys - for _ in sys: + for _ in sys: # module-attr[e] pass """) - self.assertErrorLogIs( - errors, [(2, "module-attr", r"__iter__.*module 'sys'")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*module 'sys'"}) def testInheritFromGeneric(self): with file_utils.Tempdir() as d: @@ -193,10 +173,10 @@ class Bar(Foo[int]): ... """) _, errors = self.InferWithErrors("""\ import mod - chr(mod.Bar()) + chr(mod.Bar()) # wrong-arg-types[e] """, pythonpath=[d.path]) # "Line 3, in f: Can't retrieve item out of dict. Empty?" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"int.*mod\.Bar")]) + self.assertErrorRegexes(errors, {"e": r"int.*mod\.Bar"}) def testWrongKeywordArg(self): with file_utils.Tempdir() as d: @@ -206,10 +186,9 @@ def escape(x: str or int) -> str or int _, errors = self.InferWithErrors("""\ import mycgi def foo(s): - return mycgi.escape(s, quote=1) + return mycgi.escape(s, quote=1) # wrong-keyword-args[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", - r"quote.*mycgi\.escape")]) + self.assertErrorRegexes(errors, {"e": r"quote.*mycgi\.escape"}) def testMissingParameter(self): with file_utils.Tempdir() as d: @@ -218,21 +197,19 @@ def bar(xray, yankee, zulu) -> str """) _, errors = self.InferWithErrors("""\ import foo - foo.bar(1, 2) + foo.bar(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", - r"zulu.*foo\.bar")]) + self.assertErrorRegexes(errors, {"e": r"zulu.*foo\.bar"}) def testBadInheritance(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class X: pass class Bar(X): pass - class Baz(X, Bar): + class Baz(X, Bar): # mro-error pass """) - self.assertErrorLogIs(errors, [(5, "mro-error")]) def testBadCall(self): with file_utils.Tempdir() as d: @@ -241,24 +218,23 @@ def foo(x: int, y: str) -> str: ... """) _, errors = self.InferWithErrors("""\ import other - other.foo(1.2, []) + other.foo(1.2, []) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"\(x: int")]) + self.assertErrorRegexes(errors, {"e": r"\(x: int"}) def testCallUncallable(self): _, errors = self.InferWithErrors("""\ - 0() + 0() # not-callable[e] """) - self.assertErrorLogIs(errors, [(1, "not-callable", r"int")]) + self.assertErrorRegexes(errors, {"e": r"int"}) def testSuperError(self): _, errors = self.InferWithErrors("""\ class A(object): def __init__(self): - super(A, self, "foo").__init__() + super(A, self, "foo").__init__() # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def testAttributeError(self): with file_utils.Tempdir() as d: @@ -268,26 +244,23 @@ class Foo(object): def __getattr__(self, name): return "attr" def f(): - return Foo.foo # line 5 + return Foo.foo # attribute-error[e1] def g(x): if x: y = None else: y = 1 - return y.bar # line 11 + return y.bar # attribute-error[e2] # attribute-error[e3] def h(): return Foo().foo # No error import modfoo - modfoo.baz # line 15 + modfoo.baz # module-attr[e4] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (5, "attribute-error", r"No attribute 'foo' on Type\[Foo\]"), - (11, "attribute-error", - r"No attribute 'bar' on None\nIn Optional\[int\]"), - (11, "attribute-error", - r"No attribute 'bar' on int\nIn Optional\[int\]"), - (15, "module-attr", - "No attribute 'baz' on module 'modfoo'")]) + self.assertErrorRegexes(errors, { + "e1": r"No attribute 'foo' on Type\[Foo\]", + "e2": r"No attribute 'bar' on int\nIn Optional\[int\]", + "e3": r"No attribute 'bar' on None\nIn Optional\[int\]", + "e4": r"No attribute 'baz' on module 'modfoo'"}) def testAttributeErrorGetAttribute(self): _, errors = self.InferWithErrors("""\ @@ -297,15 +270,15 @@ def __getattribute__(self, name): def f(): return Foo().x # There should be no error on this line. def g(): - return Foo.x + return Foo.x # attribute-error[e] """) - self.assertErrorLogIs(errors, [(7, "attribute-error", r"x")]) + self.assertErrorRegexes(errors, {"e": r"x"}) def testNoneAttribute(self): _, errors = self.InferWithErrors("""\ - None.foo + None.foo # attribute-error[e] """) - self.assertErrorLogIs(errors, [(1, "attribute-error", r"foo")]) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testPyiType(self): with file_utils.Tempdir() as d: @@ -314,34 +287,33 @@ def f(x: list[int]) -> int: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f([""]) + foo.f([""]) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", - r"List\[int\].*List\[str\]")]) + self.assertErrorRegexes(errors, {"e": r"List\[int\].*List\[str\]"}) def testTooManyArgs(self): _, errors = self.InferWithErrors("""\ def f(): pass - f(3) + f(3) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", r"0.*1")]) + self.assertErrorRegexes(errors, {"e": r"0.*1"}) def testTooFewArgs(self): _, errors = self.InferWithErrors("""\ def f(x): pass - f() + f() # missing-parameter[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "missing-parameter", r"x.*f")]) + self.assertErrorRegexes(errors, {"e": r"x.*f"}) def testDuplicateKeyword(self): _, errors = self.InferWithErrors("""\ def f(x, y): pass - f(3, x=3) + f(3, x=3) # duplicate-keyword-argument[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "duplicate-keyword-argument", r"f.*x")]) + self.assertErrorRegexes(errors, {"e": r"f.*x"}) def testBadImport(self): with file_utils.Tempdir() as d: @@ -349,10 +321,9 @@ def testBadImport(self): def f() -> int: ... class f: ... """) - _, errors = self.InferWithErrors("""\ - import a + self.InferWithErrors("""\ + import a # pyi-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testBadImportDependency(self): with file_utils.Tempdir() as d: @@ -360,10 +331,9 @@ def testBadImportDependency(self): from b import X class Y(X): ... """) - _, errors = self.InferWithErrors("""\ - import a + self.InferWithErrors("""\ + import a # pyi-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testBadImportFrom(self): with file_utils.Tempdir() as d: @@ -373,9 +343,9 @@ class f: ... """) d.create_file("foo/__init__.pyi", "") _, errors = self.InferWithErrors("""\ - from foo import a + from foo import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"foo\.a")]) + self.assertErrorRegexes(errors, {"e": r"foo\.a"}) def testBadImportFromDependency(self): with file_utils.Tempdir() as d: @@ -385,9 +355,9 @@ class Y(X): ... """) d.create_file("foo/__init__.pyi", "") _, errors = self.InferWithErrors("""\ - from foo import a + from foo import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"foo\.a")]) + self.assertErrorRegexes(errors, {"e": r"foo\.a"}) def testBadContainer(self): with file_utils.Tempdir() as d: @@ -396,10 +366,9 @@ def testBadContainer(self): class A(SupportsInt[int]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", - r"SupportsInt is not a container")]) + self.assertErrorRegexes(errors, {"e": r"SupportsInt is not a container"}) def testBadTypeParameterOrder(self): with file_utils.Tempdir() as d: @@ -412,9 +381,9 @@ class B(Generic[K, V]): pass class C(A[K, V], B[V, K]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Illegal.*order.*a\.C")]) + self.assertErrorRegexes(errors, {"e": r"Illegal.*order.*a\.C"}) def testDuplicateTypeParameter(self): with file_utils.Tempdir() as d: @@ -424,9 +393,9 @@ def testDuplicateTypeParameter(self): class A(Generic[T, T]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"T")]) + self.assertErrorRegexes(errors, {"e": r"T"}) def testDuplicateGenericBaseClass(self): with file_utils.Tempdir() as d: @@ -437,9 +406,9 @@ def testDuplicateGenericBaseClass(self): class A(Generic[T], Generic[V]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"inherit.*Generic")]) + self.assertErrorRegexes(errors, {"e": r"inherit.*Generic"}) def testTypeParameterInModuleConstant(self): with file_utils.Tempdir() as d: @@ -449,9 +418,9 @@ def testTypeParameterInModuleConstant(self): x = ... # type: T """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a.*T.*a\.x")]) + self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.x"}) def testTypeParameterInClassAttribute(self): with file_utils.Tempdir() as d: @@ -464,9 +433,9 @@ class A(Generic[T]): _, errors = self.InferWithErrors("""\ import a def f(): - return a.A.x + return a.A.x # unbound-type-param[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "unbound-type-param", r"x.*A.*T")]) + self.assertErrorRegexes(errors, {"e": r"x.*A.*T"}) def testUnboundTypeParameterInInstanceAttribute(self): with file_utils.Tempdir() as d: @@ -477,9 +446,9 @@ class A(object): x = ... # type: T """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a.*T.*a\.A\.x")]) + self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.A\.x"}) def testPrintUnionArg(self): with file_utils.Tempdir() as d: @@ -488,35 +457,33 @@ def f(x: int or str) -> None """) _, errors = self.InferWithErrors("""\ import a - x = a.f(4.2) + x = a.f(4.2) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) pattern = r"Expected.*Union\[int, str\].*Actually passed" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", pattern)]) + self.assertErrorRegexes(errors, {"e": pattern}) def testPrintTypeArg(self): _, errors = self.InferWithErrors("""\ - hex(int) + hex(int) # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs( - errors, [(1, "wrong-arg-types", r"Actually passed.*Type\[int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actually passed.*Type\[int\]"}) def testDeleteFromSet(self): _, errors = self.InferWithErrors("""\ s = {1} - del s[1] + del s[1] # unsupported-operands[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "unsupported-operands", r"item deletion")]) + self.assertErrorRegexes(errors, {"e": r"item deletion"}) def testBadReference(self): ty, errors = self.InferWithErrors("""\ def main(): - x = foo + x = foo # name-error[e] for foo in []: pass return x """, deep=True) - self.assertErrorLogIs(errors, [(2, "name-error", r"foo")]) + self.assertErrorRegexes(errors, {"e": r"foo"}) # Make sure we recovered from the error and got the right return type self.assertTypesMatchPytd(ty, """ from typing import Any @@ -526,9 +493,9 @@ def main() -> Any def testSetIntAttribute(self): _, errors = self.InferWithErrors("""\ x = 42 - x.y = 42 + x.y = 42 # not-writable[e] """, deep=True) - self.assertErrorLogIs(errors, [(2, "not-writable", r"y.*int")]) + self.assertErrorRegexes(errors, {"e": r"y.*int"}) def testInvalidParametersOnMethod(self): with file_utils.Tempdir() as d: @@ -538,54 +505,42 @@ def __init__(self, x: int) -> None """) _, errors = self.InferWithErrors("""\ import a - x = a.A("") - x = a.A("", 42) - x = a.A(42, y="") - x = a.A(42, x=42) - x = a.A() + x = a.A("") # wrong-arg-types[e1] + x = a.A("", 42) # wrong-arg-count[e2] + x = a.A(42, y="") # wrong-keyword-args[e3] + x = a.A(42, x=42) # duplicate-keyword-argument[e4] + x = a.A() # missing-parameter[e5] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"A\.__init__"), - (3, "wrong-arg-count", r"A\.__init__"), - (4, "wrong-keyword-args", r"A\.__init__"), - (5, "duplicate-keyword-argument", - r"A\.__init__"), - (6, "missing-parameter", r"A\.__init__")]) + self.assertErrorRegexes(errors, { + "e1": r"A\.__init__", "e2": r"A\.__init__", "e3": r"A\.__init__", + "e4": r"A\.__init__", "e5": r"A\.__init__"}) def testDuplicateKeywords(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", """ def f(x, *args, y) -> None """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import foo foo.f(1, y=2) foo.f(1, 2, y=3) - foo.f(1, x=1) + foo.f(1, x=1) # duplicate-keyword-argument # foo.f(y=1, y=2) # caught by compiler """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (4, "duplicate-keyword-argument"), - ]) def testInvalidParametersDetails(self): _, errors = self.InferWithErrors("""\ - float(list()) - float(1, list(), foobar=str) - float(1, foobar=list()) - float(1, x="") - hex() + float(list()) # wrong-arg-types[e1] + float(1, list(), foobar=str) # wrong-arg-count[e2] + float(1, foobar=list()) # wrong-keyword-args[e3] + float(1, x="") # duplicate-keyword-argument[e4] + hex() # missing-parameter[e5] """) - self.assertErrorLogIs(errors, [ - (1, "wrong-arg-types", - r"Actually passed:.*self, x: List\[nothing\]"), - (2, "wrong-arg-count", r"Actually passed:.*self, x, " - r"_, foobar"), - (3, "wrong-keyword-args", - r"Actually passed:.*self, x, foobar"), - (4, "duplicate-keyword-argument", - r"Actually passed:.*self, x, x"), - (5, "missing-parameter", r"Actually passed: \(\)") - ]) + self.assertErrorRegexes(errors, { + "e1": r"Actually passed:.*self, x: List\[nothing\]", + "e2": r"_, foobar", "e3": r"Actually passed:.*self, x, foobar", + "e4": r"Actually passed:.*self, x, x", "e5": r"Actually passed: \(\)", + }) def testBadSuperClass(self): _, errors = self.InferWithErrors("""\ @@ -595,10 +550,9 @@ def f(self): class B(A): def f(self): - return super(self, B).f() # should be super(B, self) + return super(self, B).f() # should be super(B, self) # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", r"cls: type.*cls: B")]) + self.assertErrorRegexes(errors, {"e": r"cls: type.*cls: B"}) @test_base.skip("Need to type-check second argument to super") def testBadSuperInstance(self): @@ -607,10 +561,10 @@ class A(object): pass class B(A): def __init__(self): - super(B, A).__init__() # A cannot be the second argument to super + super(B, A).__init__() # A cannot be the second argument to super # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs( - errors, [(5, "wrong-arg-types", r"Type\[B\].*Type\[A\]")]) + self.assertErrorRegexes( + errors, {"e": r"Type\[B\].*Type\[A\]"}) def testBadNameImport(self): with file_utils.Tempdir() as d: @@ -619,10 +573,10 @@ def testBadNameImport(self): x = ... # type: typing.Rumpelstiltskin """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Rumpelstiltskin")]) + self.assertErrorRegexes(errors, {"e": r"Rumpelstiltskin"}) def testBadNameImportFrom(self): with file_utils.Tempdir() as d: @@ -631,10 +585,10 @@ def testBadNameImportFrom(self): x = ... # type: Rumpelstiltskin """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Rumpelstiltskin")]) + self.assertErrorRegexes(errors, {"e": r"Rumpelstiltskin"}) def testMatchType(self): with file_utils.Tempdir() as d: @@ -649,10 +603,10 @@ def f(x: Type[A]) -> bool import a x = a.f(a.A) y = a.f(a.B) - z = a.f(a.C) + z = a.f(a.C) # wrong-arg-types[e] """, pythonpath=[d.path], deep=True) error = r"Expected.*Type\[a\.A\].*Actual.*Type\[a\.C\]" - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) self.assertTypesMatchPytd(ty, """ from typing import Any a = ... # type: module @@ -672,10 +626,10 @@ def f(x: Type[A[int]]): ... """) _, errors = self.InferWithErrors("""\ import a - x = a.f(a.B) + x = a.f(a.B) # wrong-arg-types[e] """, pythonpath=[d.path], deep=True) expected_error = r"Expected.*Type\[a\.A\[int\]\].*Actual.*Type\[a\.B\]" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", expected_error)]) + self.assertErrorRegexes(errors, {"e": expected_error}) def testMROError(self): with file_utils.Tempdir() as d: @@ -688,9 +642,9 @@ class E(C, D): ... """) _, errors = self.InferWithErrors("""\ import a - x = a.E() + x = a.E() # mro-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"E")]) + self.assertErrorRegexes(errors, {"e": r"E"}) def testBadMRO(self): with file_utils.Tempdir() as d: @@ -699,10 +653,10 @@ class A(BaseException, ValueError): ... """) _, errors = self.InferWithErrors("""\ import a - class B(a.A): pass + class B(a.A): pass # mro-error[e] raise a.A() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"A")]) + self.assertErrorRegexes(errors, {"e": r"A"}) def testUnsolvableAsMetaclass(self): with file_utils.Tempdir() as d: @@ -718,9 +672,9 @@ class B(metaclass=A): ... import b class C(b.B): def __init__(self): - f = open(self.x, 'r') + f = open(self.x, 'r') # attribute-error[e] """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"x.*C")]) + self.assertErrorRegexes(errors, {"e": r"x.*C"}) def testDontTimeoutOnComplex(self): # Tests that we can solve a complex file without timing out. @@ -749,12 +703,10 @@ def testFailedFunctionCall(self): def f(x: str, y: int) -> bool def f(x: str) -> bool """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import a - x = a.f(0, "") + x = a.f(0, "") # wrong-arg-types """, pythonpath=[d.path]) - # Tests that [wrong-arg-types] rather than [wrong-arg-count] is reported - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"")]) def testNoncomputableMethod(self): with file_utils.Tempdir() as d: @@ -767,36 +719,34 @@ def copy(x: T) -> T class A(object): def __getattribute__(self, name): return a.copy(self) - x = A()() + x = A()() # not-callable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(5, "not-callable", r"A")]) + self.assertErrorRegexes(errors, {"e": r"A"}) def testBadTypeName(self): _, errors = self.InferWithErrors("""\ - X = type(3, (int, object), {"a": 1}) + X = type(3, (int, object), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"Actual.*int")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*int"}) def testBadTypeBases(self): _, errors = self.InferWithErrors("""\ - X = type("X", (42,), {"a": 1}) + X = type("X", (42,), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Tuple\[int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Tuple\[int\]"}) def testHalfBadTypeBases(self): _, errors = self.InferWithErrors("""\ - X = type("X", (42, object), {"a": 1}) + X = type("X", (42, object), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Tuple\[int, Type\[object\]\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actual.*Tuple\[int, Type\[object\]\]"}) def testBadTypeMembers(self): _, errors = self.InferWithErrors("""\ - X = type("X", (int, object), {0: 1}) + X = type("X", (int, object), {0: 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Dict\[int, int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Dict\[int, int\]"}) def testRecursion(self): with file_utils.Tempdir() as d: @@ -806,7 +756,7 @@ class B(A): ... """) ty, errors = self.InferWithErrors("""\ import a - v = a.A() + v = a.A() # recursion-error[e] x = v.x # No error because there is an Unsolvable in the MRO of a.A """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -815,30 +765,29 @@ class B(A): ... v = ... # type: a.A x = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "recursion-error", r"a\.A")]) + self.assertErrorRegexes(errors, {"e": r"a\.A"}) def testEmptyUnionOrOptional(self): with file_utils.Tempdir() as d: - d.create_file("f1.pyi", """\ + d.create_file("f1.pyi", """ def f(x: Union): ... """) - d.create_file("f2.pyi", """\ + d.create_file("f2.pyi", """ def f(x: Optional): ... """) _, errors = self.InferWithErrors("""\ - import f1 - import f2 + import f1 # pyi-error[e1] + import f2 # pyi-error[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"f1.*Union"), - (2, "pyi-error", r"f2.*Optional")]) + self.assertErrorRegexes( + errors, {"e1": r"f1.*Union", "e2": r"f2.*Optional"}) def testBadDictAttribute(self): _, errors = self.InferWithErrors("""\ x = {"a": 1} - y = x.a + y = x.a # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", - r"a.*Dict\[str, int\]")]) + self.assertErrorRegexes(errors, {"e": r"a.*Dict\[str, int\]"}) def testBadPyiDict(self): with file_utils.Tempdir() as d: @@ -847,31 +796,28 @@ def testBadPyiDict(self): x = ... # type: Dict[str, int, float] """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def testCallNone(self): - _, errors = self.InferWithErrors("""\ - None() + self.InferWithErrors("""\ + None() # not-callable """) - self.assertErrorLogIs(errors, [(1, "not-callable")]) def testInNone(self): - _, errors = self.InferWithErrors("""\ - 3 in None + self.InferWithErrors("""\ + 3 in None # unsupported-operands """) - self.assertErrorLogIs(errors, [(1, "unsupported-operands")]) def testNoAttrError(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ if __random__: y = 42 else: y = "foo" - y.upper + y.upper # attribute-error """) - self.assertErrorLogIs(errors, [(5, "attribute-error")]) def testAttrError(self): _, errors = self.InferWithErrors("""\ @@ -879,28 +825,26 @@ def testAttrError(self): y = 42 else: y = "foo" - y.upper + y.upper # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", "upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) def testPrintCallableInstance(self): _, errors = self.InferWithErrors("""\ from typing import Callable v = None # type: Callable[[int], str] - hex(v) + hex(v) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Callable\[\[int\], str\]"}) def testSameNameAndLine(self): _, errors = self.InferWithErrors("""\ def f(x): - return x + 42 + return x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") f([]) """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"str.*int"), - (2, "unsupported-operands", r"List.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"List.*int"}) def testKwargOrder(self): with file_utils.Tempdir() as d: @@ -910,30 +854,28 @@ def g(x): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(x=1, y=2, z="3") - foo.g(42, v4="the", v3="quick", v2="brown", v1="fox") + foo.f(x=1, y=2, z="3") # wrong-arg-types[e1] + foo.g(42, v4="the", v3="quick", v2="brown", v1="fox") # wrong-keyword-args[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"x, y, z.*x, y, z"), - (3, "wrong-keyword-args", r"v1, v2, v3, v4")]) + self.assertErrorRegexes( + errors, {"e1": r"x, y, z.*x, y, z", "e2": r"v1, v2, v3, v4"}) def testBadBaseClass(self): _, errors = self.InferWithErrors("""\ - class Foo(None): pass - class Bar(None if __random__ else 42): pass + class Foo(None): pass # base-class-error[e1] + class Bar(None if __random__ else 42): pass # base-class-error[e2] """) - self.assertErrorLogIs(errors, [ - (1, "base-class-error", r"Invalid base class: None"), - (2, "base-class-error", r"Optional\[\]")]) + self.assertErrorRegexes(errors, {"e1": r"Invalid base class: None", + "e2": r"Optional\[\]"}) def testCallableInUnsupportedOperands(self): _, errors = self.InferWithErrors("""\ def f(x, y=None): pass - f in f + f in f # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Callable\[\[Any, Any\], Any\].*" - r"Callable\[\[Any, Any\], Any\]")]) + self.assertErrorRegexes( + errors, {"e": (r"Callable\[\[Any, Any\], Any\].*" + r"Callable\[\[Any, Any\], Any\]")}) def testCleanPyiNamedtupleNames(self): with file_utils.Tempdir() as d: @@ -944,199 +886,216 @@ def f(x: int): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(foo.X()) + foo.f(foo.X()) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"`X`")]) + self.assertErrorRegexes(errors, {"e": r"`X`"}) def testBadAnnotation(self): _, errors = self.InferWithErrors("""\ - tuple[0] - dict[1, 2] + tuple[0] # not-indexable[e1] + dict[1, 2] # invalid-annotation[e2] # invalid-annotation[e3] class A(object): pass - A[3] + A[3] # not-indexable[e4] """) - self.assertErrorLogIs(errors, [ - (1, "not-indexable", r"class tuple"), - (2, "invalid-annotation", r"1.*Not a type"), - (2, "invalid-annotation", r"2.*Not a type"), - (4, "not-indexable", r"class A"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"class tuple", "e2": r"1.*Not a type", "e3": r"2.*Not a type", + "e4": r"class A"}) def testRevealType(self): _, errors = self.InferWithErrors("""\ - reveal_type(42 or "foo") + reveal_type(42 or "foo") # reveal-type[e1] class Foo(object): pass - reveal_type(Foo) - reveal_type(Foo()) - reveal_type([1,2,3]) + reveal_type(Foo) # reveal-type[e2] + reveal_type(Foo()) # reveal-type[e3] + reveal_type([1,2,3]) # reveal-type[e4] """) - self.assertErrorLogIs(errors, [ - (1, "reveal-type", r"^Union\[int, str\]$"), - (4, "reveal-type", r"^Type\[Foo\]$"), - (5, "reveal-type", r"^Foo$"), - (6, "reveal-type", r"^List\[int\]$"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"^Union\[int, str\]$", "e2": r"^Type\[Foo\]$", "e3": r"^Foo$", + "e4": r"^List\[int\]$"}) def testNotProtocol(self): _, errors = self.InferWithErrors("""\ a = [] a.append(1) - a = "".join(a) + a = "".join(a) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 3, "wrong-arg-types", r"\(.*List\[int\]\)$")]) # no protocol details + self.assertErrorRegexes( + errors, {"e": r"\(.*List\[int\]\)$"}) # no protocol details def testHiddenError(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ use_option = False def f(): if use_option: - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) def testUnknownInError(self): errors = self.CheckWithErrors("""\ def f(x): y = x if __random__ else None - return y.groups() + return y.groups() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"Optional\[Any\]")]) + self.assertErrorRegexes(errors, {"e": r"Optional\[Any\]"}) class OperationsTest(test_base.TargetIndependentTest): """Test operations.""" def testXor(self): - errors = self.CheckWithErrors("def f(): return 'foo' ^ 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\^.*str.*int.*'__xor__' on str.*'__rxor__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' ^ 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\^.*str.*int.*'__xor__' on str.*'__rxor__' on int"}) def testAdd(self): - errors = self.CheckWithErrors("def f(): return 'foo' + 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\+.*str.*int.*__add__ on str.*str")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' + 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\+.*str.*int.*__add__ on str.*str"}) def testInvert(self): - errors = self.CheckWithErrors("def f(): return ~None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\~.*None.*'__invert__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return ~None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\~.*None.*'__invert__' on None"}) def testSub(self): - errors = self.CheckWithErrors("def f(): return 'foo' - 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\-.*str.*int.*'__sub__' on str.*'__rsub__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' - 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\-.*str.*int.*'__sub__' on str.*'__rsub__' on int"}) def testMul(self): - errors = self.CheckWithErrors("def f(): return 'foo' * None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\*.*str.*None.*__mul__ on str.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' * None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\*.*str.*None.*__mul__ on str.*int"}) def testDiv(self): - errors = self.CheckWithErrors("def f(): return 'foo' / 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\/.*str.*int.*'__(true)?div__' on str.*'__r(true)?div__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' / 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\/.*str.*int.*'__(true)?div__' on str.*'__r(true)?div__' on int" + }) def testMod(self): - errors = self.CheckWithErrors("def f(): return None % 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\%.*None.*int.*'__mod__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return None % 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\%.*None.*int.*'__mod__' on None"}) def testLShift(self): - errors = self.CheckWithErrors("def f(): return 3 << None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\<\<.*int.*None.*__lshift__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 << None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\<\<.*int.*None.*__lshift__ on int.*int"}) def testRShift(self): - errors = self.CheckWithErrors("def f(): return 3 >> None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\>\>.*int.*None.*__rshift__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 >> None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\>\>.*int.*None.*__rshift__ on int.*int"}) def testAnd(self): - errors = self.CheckWithErrors("def f(): return 'foo' & 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\&.*str.*int.*'__and__' on str.*'__rand__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' & 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\&.*str.*int.*'__and__' on str.*'__rand__' on int"}) def testOr(self): - errors = self.CheckWithErrors("def f(): return 'foo' | 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\|.*str.*int.*'__or__' on str.*'__ror__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' | 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\|.*str.*int.*'__or__' on str.*'__ror__' on int"}) def testFloorDiv(self): - errors = self.CheckWithErrors("def f(): return 3 // 'foo'") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\/\/.*int.*str.*__floordiv__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 // 'foo' # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\/\/.*int.*str.*__floordiv__ on int.*int"}) def testPow(self): - errors = self.CheckWithErrors("def f(): return 3 ** 'foo'") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\*\*.*int.*str.*__pow__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 ** 'foo' # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\*\*.*int.*str.*__pow__ on int.*int"}) def testNeg(self): - errors = self.CheckWithErrors("def f(): return -None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\-.*None.*'__neg__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return -None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\-.*None.*'__neg__' on None"}) def testPos(self): - errors = self.CheckWithErrors("def f(): return +None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\+.*None.*'__pos__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return +None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\+.*None.*'__pos__' on None"}) class InPlaceOperationsTest(test_base.TargetIndependentTest): """Test in-place operations.""" def testIAdd(self): - errors = self.CheckWithErrors("def f(): v = []; v += 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\+\=.*List.*int.*__iadd__ on List.*Iterable")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; v += 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\+\=.*List.*int.*__iadd__ on List.*Iterable"}) class NoSymbolOperationsTest(test_base.TargetIndependentTest): """Test operations with no native symbol.""" def testGetItem(self): - errors = self.CheckWithErrors("def f(): v = []; return v['foo']") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item retrieval.*List.*str.*__getitem__ on List.*int")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; return v['foo'] # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"item retrieval.*List.*str.*__getitem__ on List.*int"}) def testDelItem(self): - errors = self.CheckWithErrors("def f(): v = {'foo': 3}; del v[3]") + errors = self.CheckWithErrors("""\ + def f(): v = {'foo': 3}; del v[3] # unsupported-operands[e] + """) d = r"Dict\[str, int\]" - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item deletion.*{d}.*int.*__delitem__ on {d}.*str".format(d=d))]) + self.assertErrorRegexes(errors, { + "e": r"item deletion.*{d}.*int.*__delitem__ on {d}.*str".format(d=d)}) def testSetItem(self): - errors = self.CheckWithErrors("def f(): v = []; v['foo'] = 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item assignment.*List.*str.*__setitem__ on List.*int")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; v['foo'] = 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"item assignment.*List.*str.*__setitem__ on List.*int"}) def testContains(self): - errors = self.CheckWithErrors("def f(): return 'foo' in 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"'in'.*int.*str.*'__contains__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' in 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"'in'.*int.*str.*'__contains__' on int"}) def testRecursion(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): if __random__: f() - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_exceptions.py b/pytype/tests/test_exceptions.py index ed8575d9a..44fb3c6fb 100644 --- a/pytype/tests/test_exceptions.py +++ b/pytype/tests/test_exceptions.py @@ -77,8 +77,7 @@ def fn(): """) def test_global_name_error(self): - errors = self.CheckWithErrors("fooey") - self.assertErrorLogIs(errors, [(1, "name-error", r"fooey")]) + self.CheckWithErrors("fooey # name-error") # TODO(kramm): Don't warn about NameErrors that are being caught. self.assertNoCrash(self.Check, """\ try: @@ -89,12 +88,11 @@ def test_global_name_error(self): """) def test_local_name_error(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def fn(): - fooey + fooey # name-error fn() """) - self.assertErrorLogIs(errors, [(2, "name-error", r"fooey")]) def test_catch_local_name_error(self): self.assertNoCrash(self.Check, """\ @@ -108,17 +106,16 @@ def fn(): """) def test_reraise(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def fn(): try: - fooey + fooey # name-error print("Yes fooey?") except NameError: print("No fooey") raise fn() """) - self.assertErrorLogIs(errors, [(3, "name-error", r"fooey")]) def test_reraise_explicit_exception(self): self.Check("""\ @@ -312,7 +309,7 @@ def f() -> int """) def test_return_or_raise_set_attribute(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): raise ValueError() def g(): @@ -320,17 +317,16 @@ def g(): def h(): func = f if __random__ else g v = func() - v.attr = None + v.attr = None # not-writable """) - self.assertErrorLogIs(errors, [(8, "not-writable")]) def test_bad_type_self(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self): - type(42, self) + type(42, self) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", r"2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def test_value(self): ty = self.Infer(""" @@ -375,16 +371,15 @@ def test_bad_type(self): errors = self.CheckWithErrors("""\ try: pass - except None: + except None: # mro-error[e1] pass try: pass - except type(None): + except type(None): # mro-error[e2] pass """) - self.assertErrorLogIs( - errors, [(3, "mro-error", r"Not a class"), - (7, "mro-error", r"None.*BaseException")]) + self.assertErrorRegexes( + errors, {"e1": r"Not a class", "e2": r"None.*BaseException"}) def test_unknown_type(self): self.Check(""" diff --git a/pytype/tests/test_flow.py b/pytype/tests/test_flow.py index 56d3ea19e..abda994de 100644 --- a/pytype/tests/test_flow.py +++ b/pytype/tests/test_flow.py @@ -339,9 +339,9 @@ def f(): try: func = None except: - func() + func() # name-error[e] """, deep=True) - self.assertErrorLogIs(errors, [(5, "name-error", r"func")]) + self.assertErrorRegexes(errors, {"e": r"func"}) def test_nested_break(self): self.assertNoCrash(self.Infer, """ diff --git a/pytype/tests/test_functions.py b/pytype/tests/test_functions.py index 7fca59b60..76e7aa1b3 100644 --- a/pytype/tests/test_functions.py +++ b/pytype/tests/test_functions.py @@ -108,14 +108,13 @@ def g(y): """) def test_unbound_closure_variable(self): - err = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def foo(): def bar(): return tuple(xs) # name-error xs = bar() foo() """) - self.assertErrorsMatch(err, []) class TestGenerators(test_base.TargetIndependentTest): @@ -209,9 +208,11 @@ def setUp(self): self.options.tweak(precise_return=True) def test_pytd_return(self): - ty, errors = self.InferWithErrors("x = 'hello'.startswith(0)") + ty, errors = self.InferWithErrors("""\ + x = 'hello'.startswith(0) # wrong-arg-types[e] + """) self.assertTypesMatchPytd(ty, "x: bool") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_param_return(self): with file_utils.Tempdir() as d: @@ -220,32 +221,29 @@ def test_param_return(self): T = TypeVar("T") def f(x: T) -> T: ... """) - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import foo - x = foo.f() + x = foo.f() # missing-parameter """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any foo: module x: Any """) - self.assertErrorLogIs(errors, [(2, "missing-parameter")]) def test_binop(self): - ty, errors = self.InferWithErrors("x = 'oops' + 0") + ty, _ = self.InferWithErrors("x = 'oops' + 0 # unsupported-operands") self.assertTypesMatchPytd(ty, "x: str") - self.assertErrorLogIs(errors, [(1, "unsupported-operands")]) def test_inplace_op(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ x = [] - x += 0 + x += 0 # unsupported-operands """) self.assertTypesMatchPytd(ty, """ from typing import List x: List[nothing] """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands")]) class TestFunctions(test_base.TargetIndependentTest): @@ -438,9 +436,9 @@ def test_named_arg_unsolvable_max_depth(self): # maximum depth. _, errors = self.InferWithErrors("""\ def f(x): - return max(foo=repr(__any_object__)) + return max(foo=repr(__any_object__)) # wrong-keyword-args[e] """, deep=True, maximum_depth=1) - self.assertErrorLogIs(errors, [(2, "wrong-keyword-args", r"foo.*max")]) + self.assertErrorRegexes(errors, {"e": r"foo.*max"}) def test_multiple_signatures_with_type_parameter(self): with file_utils.Tempdir() as d: @@ -657,9 +655,9 @@ def test_wrong_keyword(self): _, errors = self.InferWithErrors("""\ def f(x): pass - f("", y=42) + f("", y=42) # wrong-keyword-args[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", r"y")]) + self.assertErrorRegexes(errors, {"e": r"y"}) def test_staticmethod_class(self): ty = self.Infer("""\ @@ -730,9 +728,9 @@ def test_interpreter_function_in_class(self): class A(object): bar = lambda x: x def f(self): - self.bar(42) + self.bar(42) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def test_nested_lambda(self): # Inspired by b/37869955 @@ -780,12 +778,11 @@ def c(x: int, y: int, z: int = ...): ... """) def test_bad_defaults(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections X = collections.namedtuple("X", "a b c") - X.__new__.__defaults__ = (1) + X.__new__.__defaults__ = (1) # bad-function-defaults """) - self.assertErrorLogIs(errors, [(3, "bad-function-defaults")]) def test_multiple_valid_defaults(self): self.Check(""" @@ -807,12 +804,11 @@ def test_set_defaults_to_expression(self): def test_set_defaults_non_tuple_instance(self): # Test that get_atomic_python_constant fails and get_atomic_value pulls out # a non-tuple Instance. - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections X = collections.namedtuple("X", "a b c") - X.__new__.__defaults__ = (lambda x: x)(0) - """) - self.assertErrorLogIs(errors, [(3, "bad-function-defaults")]) + X.__new__.__defaults__ = (lambda x: x)(0) # bad-function-defaults + """) def test_set_builtin_defaults(self): self.assertNoCrash(self.Check, """ @@ -835,33 +831,27 @@ def test(a, b, c = 4): z = test(1, 2) z = test(1, 2, 3) """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def test(a, b, c): return a + b + c - x = test(1, 2) # should fail + x = test(1, 2) # missing-parameter test.__defaults__ = (3,) x = test(1, 2) - x = test(1) # should fail + x = test(1) # missing-parameter """) - self.assertErrorLogIs(errors, - [(3, "missing-parameter"), - (6, "missing-parameter")]) def test_interpreter_function_defaults_on_class(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class Foo(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c - a = Foo() # should fail + a = Foo() # missing-parameter Foo.__init__.__defaults__ = (1, 2) b = Foo(0) - c = Foo() # should fail + c = Foo() # missing-parameter """) - self.assertErrorLogIs(errors, - [(6, "missing-parameter"), - (9, "missing-parameter")]) def test_split_on_kwargs(self): ty = self.Infer(""" @@ -883,11 +873,10 @@ def test_pyi_starargs(self): d.create_file("foo.pyi", """ def f(x: str, ...) -> None: ... """) - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import foo - foo.f(True, False) + foo.f(True, False) # wrong-arg-types """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types")]) def test_infer_bound_pytd_func(self): ty = self.Infer(""" @@ -971,24 +960,20 @@ def __init__(self, a, b=None): def test_functools_partial_bad_call(self): errors = self.CheckWithErrors("""\ import functools - functools.partial() - functools.partial(42) + functools.partial() # missing-parameter + functools.partial(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "missing-parameter"), - (3, "wrong-arg-types", r"Callable.*int")]) + self.assertErrorRegexes(errors, {"e": r"Callable.*int"}) def test_bad_comprehensions(self): # Test that we report errors in comprehensions and generators only once # while still reporting errors in lambdas. - errors = self.CheckWithErrors("""\ - [name_error1 for x in ()] - {name_error2 for x in ()} - (name_error3 for x in ()) - lambda x: name_error4 + self.CheckWithErrors("""\ + [name_error1 for x in ()] # name-error + {name_error2 for x in ()} # name-error + (name_error3 for x in ()) # name-error + lambda x: name_error4 # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (2, "name-error"), - (3, "name-error"), (4, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_future_overlay.py b/pytype/tests/test_future_overlay.py index 2c38aefb3..fa705b7c1 100644 --- a/pytype/tests/test_future_overlay.py +++ b/pytype/tests/test_future_overlay.py @@ -33,11 +33,10 @@ def get_foo(self): """, pythonpath=[d.path]) def test_missing_import(self): - errors = self.CheckWithErrors("""\ - from future.utils import iteritems - from future.utils import with_metaclass + self.CheckWithErrors("""\ + from future.utils import iteritems # import-error + from future.utils import with_metaclass # import-error """) - self.assertErrorLogIs(errors, [(1, "import-error"), (2, "import-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_import.py b/pytype/tests/test_import.py index 7988c3f86..887338922 100644 --- a/pytype/tests/test_import.py +++ b/pytype/tests/test_import.py @@ -108,9 +108,9 @@ class Y(X): ... """) def testBadStarImport(self): - ty, errors = self.InferWithErrors(""" - from nonsense import * - from other_nonsense import * + ty, _ = self.InferWithErrors("""\ + from nonsense import * # import-error + from other_nonsense import * # import-error x = foo.bar() """) self.assertTypesMatchPytd(ty, """ @@ -118,8 +118,6 @@ def testBadStarImport(self): def __getattr__(name) -> Any x = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "import-error", r"nonsense"), - (3, "import-error", r"other_nonsense")]) def testPathImport(self): with file_utils.Tempdir() as d: @@ -426,7 +424,7 @@ def testDotDotPackageInPyi(self): from ..bar import X """) d.create_file("up2/bar.pyi", "class X: ...") - d.create_file("top.py", """\ + d.create_file("top.py", """ from up2.baz.foo import X x = X() """) @@ -442,7 +440,7 @@ def testDotDotInPyi(self): # Similar to testDotDot except in a pyi file. with file_utils.Tempdir() as d: d.create_file("foo/baz.pyi", "x: int") - d.create_file("foo/deep/bar.py", """\ + d.create_file("foo/deep/bar.py", """ from .. import baz a = baz.x """) @@ -459,18 +457,18 @@ def testTooManyDotsInPackageInPyi(self): d.create_file("up/foo.pyi", "from ..bar import X") d.create_file("up/bar.pyi", "class X: ...") _, err = self.InferWithErrors( - "from up.foo import X", pythonpath=[d.path]) - self.assertErrorLogIs( - err, [(1, "pyi-error", "Cannot resolve relative import ..bar")]) + "from up.foo import X # pyi-error[e]", pythonpath=[d.path]) + self.assertErrorRegexes( + err, {"e": r"Cannot resolve relative import \.\.bar"}) def testFromDotInPyi(self): # from . import module with file_utils.Tempdir() as d: d.create_file("foo/a.pyi", "class X: ...") - d.create_file("foo/b.pyi", """\ + d.create_file("foo/b.pyi", """ from . import a Y = a.X""") - d.create_file("top.py", """\ + d.create_file("top.py", """ import foo.b x = foo.b.Y() """) ty = self.InferFromFile(filename=d["top.py"], pythonpath=[d.path]) @@ -749,10 +747,10 @@ class B(a.A): pass """) _, errors = self.InferWithErrors("""\ - import b + import b # pyi-error[e] x = b.B() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a\.pyi")]) + self.assertErrorRegexes(errors, {"e": r"a\.pyi"}) def testSubdirAndModuleWithSameNameAsPackage(self): with file_utils.Tempdir() as d: @@ -798,20 +796,17 @@ class object: def foo(self) -> None: ... def f(x: object) -> object """) - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import foo x = foo.f(foo.object()) y = foo.f(foo.object()) - foo.f(object()) # error + foo.f(object()) # wrong-arg-types """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ foo = ... # type: module x = ... # type: foo.object y = ... # type: foo.object """) - self.assertErrorLogIs(errors, [ - (4, "wrong-arg-types"), - ]) def testNoFailOnBadSymbolLookup(self): with file_utils.Tempdir() as d: @@ -873,14 +868,11 @@ def testAttributeOnModule(self): foo = ... # type: int """) _, errors = self.InferWithErrors("""\ - from a import foo, bar + from a import foo, bar # import-error[e1] import a - a.baz + a.baz # module-attr[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (1, "import-error", r"bar"), - (3, "module-attr", r"baz"), - ]) + self.assertErrorRegexes(errors, {"e1": r"bar", "e2": r"baz"}) def testFromImport(self): with file_utils.Tempdir() as d: @@ -906,7 +898,7 @@ def testImportMapFilter(self): Qux = bar.Quack """.format(imp_path) init_fn = d.create_file("foo/__init__.py", init_body) - initpyi_fn = d.create_file("foo/__init__.pyi~", """\ + initpyi_fn = d.create_file("foo/__init__.pyi~", """ from typing import Any bar = ... # type: Any baz = ... # type: Any @@ -914,7 +906,7 @@ def testImportMapFilter(self): """) bar_fn = d.create_file("foo/bar.py", "class Quack(object): pass") barpyi_fn = d.create_file("foo/bar.pyi", "class Quack(object): pass") - imports_fn = d.create_file("imports_info", """\ + imports_fn = d.create_file("imports_info", """ {0} {1} {2} {3} """.format(init_fn[1:-3], initpyi_fn, bar_fn[1:-3], barpyi_fn)) @@ -1133,19 +1125,18 @@ def testUnimportedSubmoduleFailure(self): _, errors = self.InferWithErrors("""\ import sub.bar.baz x = sub.bar.baz.A() - y = sub.bar.quux.B() + y = sub.bar.quux.B() # module-attr[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "module-attr", r"quux.*sub\.bar")]) + self.assertErrorRegexes(errors, {"e": r"quux.*sub\.bar"}) def testSubmoduleAttributeError(self): with file_utils.Tempdir() as d: d.create_file("package/__init__.pyi", "submodule: module") d.create_file("package/submodule.pyi", "") - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from package import submodule - submodule.asd + submodule.asd # module-attr """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "module-attr")]) def testInitOnlySubmodule(self): """Test a submodule without its own stub file.""" diff --git a/pytype/tests/test_list.py b/pytype/tests/test_list.py index 6839db1a1..98ece81f1 100644 --- a/pytype/tests/test_list.py +++ b/pytype/tests/test_list.py @@ -75,7 +75,7 @@ def test_getitem_slot(self): b = a[1] c = 1 if __random__ else 2 d = a[c] - e = a["s"] + e = a["s"] # unsupported-operands[e] f = a[-1] g = a[slice(1,2)] # should be List[str] """) @@ -89,8 +89,7 @@ def test_getitem_slot(self): f = ... # type: int g = ... # type: List[Union[int, str]] """) - self.assertErrorLogIs(errors, [(5, "unsupported-operands", - r"__getitem__ on List")]) + self.assertErrorRegexes(errors, {"e": r"__getitem__ on List"}) def test_index_out_of_range(self): ty = self.Infer(""" diff --git a/pytype/tests/test_namedtuple.py b/pytype/tests/test_namedtuple.py index 6c22dadbf..72dd9e0f9 100644 --- a/pytype/tests/test_namedtuple.py +++ b/pytype/tests/test_namedtuple.py @@ -79,22 +79,15 @@ def test_str_args2(self): """) def test_bad_fieldnames(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple("_", ["abc", "def", "ghi"]) - collections.namedtuple("_", "_") - collections.namedtuple("_", "a, 1") - collections.namedtuple("_", "a, !") - collections.namedtuple("_", "a, b, c, a") - collections.namedtuple("1", "") + collections.namedtuple("_", ["abc", "def", "ghi"]) # invalid-namedtuple-arg + collections.namedtuple("_", "_") # invalid-namedtuple-arg + collections.namedtuple("_", "a, 1") # invalid-namedtuple-arg + collections.namedtuple("_", "a, !") # invalid-namedtuple-arg + collections.namedtuple("_", "a, b, c, a") # invalid-namedtuple-arg + collections.namedtuple("1", "") # invalid-namedtuple-arg """) - self.assertErrorLogIs(errorlog, - [(2, "invalid-namedtuple-arg"), - (3, "invalid-namedtuple-arg"), - (4, "invalid-namedtuple-arg"), - (5, "invalid-namedtuple-arg"), - (6, "invalid-namedtuple-arg"), - (7, "invalid-namedtuple-arg")]) def test_rename(self): ty = self.Infer(""" @@ -106,19 +99,15 @@ def test_rename(self): ty, self._namedtuple_def(S=("S", ["abc", "_1", "ghi", "_3"]))) def test_bad_initialize(self): - _, errlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ from collections import namedtuple X = namedtuple("X", "y z") - a = X(1) - b = X(y = 2) - c = X(w = 3) + a = X(1) # missing-parameter + b = X(y = 2) # missing-parameter + c = X(w = 3) # wrong-keyword-args d = X(y = "hello", z = 4j) # works """) - self.assertErrorLogIs(errlog, [ - (4, "missing-parameter"), - (5, "missing-parameter"), - (6, "wrong-keyword-args")]) def test_class_name(self): ty = self.Infer( @@ -155,15 +144,14 @@ class X(NamedTuple('X', [('y', str), ('z', int)])): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.X() # wrong arg count - foo.X(0, "") # wrong types - foo.X(z="", y=0) # wrong types + foo.X() # missing-parameter[e1] + foo.X(0, "") # wrong-arg-types[e2] + foo.X(z="", y=0) # wrong-arg-types[e3] foo.X("", 0) foo.X(y="", z=0) """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"y"), - (3, "wrong-arg-types", r"str.*int"), - (4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes( + errors, {"e1": r"y", "e2": r"str.*int", "e3": r"str.*int"}) def test_use_pyi_namedtuple(self): with file_utils.Tempdir() as d: @@ -173,9 +161,9 @@ class X(NamedTuple("X", [])): ... _, errors = self.InferWithErrors("""\ import foo foo.X()._replace() - foo.X().nonsense + foo.X().nonsense # attribute-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"nonsense.*X")]) + self.assertErrorRegexes(errors, {"e": r"nonsense.*X"}) def test_subclass_pyi_namedtuple(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_operators.py b/pytype/tests/test_operators.py index 217570b40..28eb75490 100644 --- a/pytype/tests/test_operators.py +++ b/pytype/tests/test_operators.py @@ -328,9 +328,9 @@ def test_unknown_right(self): class Foo(object): def __sub__(self, other): return "" - (Foo() - __any_object__).real + (Foo() - __any_object__).real # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"real.*str")]) + self.assertErrorRegexes(errors, {"e": r"real.*str"}) class InplaceTest(test_base.TargetIndependentTest, @@ -371,9 +371,9 @@ def test_list_add(self): _, errors = self.InferWithErrors("""\ class A(object): pass v = [] - v += A() + v += A() # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands", r"A.*Iterable")]) + self.assertErrorRegexes(errors, {"e": r"A.*Iterable"}) class BindingsTest(test_base.TargetIndependentTest): diff --git a/pytype/tests/test_pyi.py b/pytype/tests/test_pyi.py index 60c32c0e8..a48637f15 100644 --- a/pytype/tests/test_pyi.py +++ b/pytype/tests/test_pyi.py @@ -336,15 +336,15 @@ def testMultipleGetAttr(self): from typing import Any def __getattr__(name) -> Any """) - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ from foo import * - from bar import * # Nonsense import generates a top-level __getattr__ + from bar import * # Nonsense import generates a top-level __getattr__ # import-error[e] """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any def __getattr__(name) -> Any """) - self.assertErrorLogIs(errors, [(3, "import-error", r"bar")]) + self.assertErrorRegexes(errors, {"e": r"bar"}) def testPyiListItem(self): with file_utils.Tempdir() as d: @@ -436,8 +436,8 @@ def foo(a: K, *b, c: V, **d) -> Dict[K, V]: ... import foo a = foo.foo(*tuple(), **dict()) b = foo.foo(*(1,), **{"c": 3j}) - c = foo.foo(*(1,)) - d = foo.foo(*(), **{"d": 3j}) + c = foo.foo(*(1,)) # missing-parameter[e1] + d = foo.foo(*(), **{"d": 3j}) # missing-parameter[e2] """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict @@ -447,10 +447,7 @@ def foo(a: K, *b, c: V, **d) -> Dict[K, V]: ... c = ... # type: Any d = ... # type: Any """) - self.assertErrorLogIs(errors, [ - (4, "missing-parameter", r"\bc\b"), - (5, "missing-parameter", r"\ba\b"), - ]) + self.assertErrorRegexes(errors, {"e1": r"\bc\b", "e2": r"\ba\b"}) def testUnionWithSuperclass(self): with file_utils.Tempdir() as d: @@ -521,8 +518,8 @@ def testTypeVarConflict(self): from typing import List, Sequence class A(List[int], Sequence[str]): ... """) - ty, errors = self.InferWithErrors("""\ - import foo + ty, _ = self.InferWithErrors("""\ + import foo # pyi-error x = [] + foo.A() """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -530,7 +527,6 @@ class A(List[int], Sequence[str]): ... foo = ... # type: Any x = ... # type: list """) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testSameTypeVarName(self): with file_utils.Tempdir() as d: @@ -585,11 +581,11 @@ def bar(self): """) # We should get an error at import time rather than at use time here. _, errors = self.InferWithErrors("""\ - import foo + import foo # pyi-error[e] x = foo.Bar() x.bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", "T2")]) + self.assertErrorRegexes(errors, {"e": r"T2"}) def testStarImport(self): with file_utils.Tempdir() as d: @@ -725,7 +721,7 @@ def f(x: foo.Foo) -> None: ... def testAliasStaticMethod(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ class A: @staticmethod def t(a: str) -> None: ... diff --git a/pytype/tests/test_quick.py b/pytype/tests/test_quick.py index 78390ae32..92672c421 100644 --- a/pytype/tests/test_quick.py +++ b/pytype/tests/test_quick.py @@ -77,11 +77,11 @@ def testAnalyzeAnnotatedMaxDepth(self): # --output with --analyze-annotated has the same max depth as --check. _, errors = self.InferWithErrors("""\ def make_greeting(user_id): - return 'hello, user' + user_id + return 'hello, user' + user_id # unsupported-operands[e] def print_greeting(): print(make_greeting(0)) """, quick=True) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_recovery.py b/pytype/tests/test_recovery.py index 1a42b674b..c0232a56e 100644 --- a/pytype/tests/test_recovery.py +++ b/pytype/tests/test_recovery.py @@ -99,17 +99,13 @@ class A(object): """) def testMethodWithUnknownDecorator(self): - _, errors = self.InferWithErrors("""\ - from nowhere import decorator + self.InferWithErrors("""\ + from nowhere import decorator # import-error class Foo(object): @decorator def f(): - name_error + name_error # name-error """, deep=True) - self.assertErrorLogIs(errors, [ - (1, "import-error"), - (5, "name-error"), - ]) def testAssertInConstructor(self): self.Check("""\ @@ -133,27 +129,21 @@ def __str__(self): """) def testAttributeAccessInImpossiblePath(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ x = 3.14 if __random__ else 42 if isinstance(x, int): if isinstance(x, float): x.upper # not reported - 3 in x + 3 in x # unsupported-operands """) - self.assertErrorLogIs(errors, [ - (5, "unsupported-operands"), - ]) def testBinaryOperatorOnImpossiblePath(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ x = "" if __random__ else [] if isinstance(x, list): if isinstance(x, str): - x / x + x / x # unsupported-operands """) - self.assertErrorLogIs(errors, [ - (4, "unsupported-operands"), - ]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_reingest.py b/pytype/tests/test_reingest.py index cedd50b3b..f5b114448 100644 --- a/pytype/tests/test_reingest.py +++ b/pytype/tests/test_reingest.py @@ -123,9 +123,9 @@ def __new__(cls, a, b): _, errors = self.InferWithErrors("""\ import foo foo.X("hello", "world") - foo.X(42) # missing parameters + foo.X(42) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "missing-parameter", "b.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"b.*__new__"}) def testAlias(self): foo = self.Infer(""" @@ -151,7 +151,7 @@ def testDynamicAttributes(self): with file_utils.Tempdir() as d: d.create_file("foo1.pyi", pytd_utils.Print(foo1)) d.create_file("foo2.pyi", pytd_utils.Print(foo2)) - d.create_file("bar.pyi", """\ + d.create_file("bar.pyi", """ from foo1 import xyz from foo2 import zyx """) diff --git a/pytype/tests/test_slots.py b/pytype/tests/test_slots.py index 1f6f5a16d..b922d1d59 100644 --- a/pytype/tests/test_slots.py +++ b/pytype/tests/test_slots.py @@ -64,14 +64,11 @@ class Foo(object): """) def testSlotWithNonStrings(self): - _, errors = self.InferWithErrors(""" - class Foo(object): + _, errors = self.InferWithErrors("""\ + class Foo(object): # bad-slots[e] __slots__ = (1, 2, 3) """) - self.assertErrorLogIs( - errors, - [(2, "bad-slots", r"Invalid __slot__ entry: '1'")] - ) + self.assertErrorRegexes(errors, {"e": r"Invalid __slot__ entry: '1'"}) def testSetSlot(self): self.Check(""" @@ -111,20 +108,15 @@ class Foo(object): foo = Foo() foo.x = 1 # ok foo.y = 2 # ok - foo.z = 3 # error + foo.z = 3 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(7, "not-writable", r"z")] - ) + self.assertErrorRegexes(errors, {"e": r"z"}) def testObject(self): _, errors = self.InferWithErrors("""\ - object().foo = 42 + object().foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (1, "not-writable", r"object") - ]) + self.assertErrorRegexes(errors, {"e": r"object"}) def testAnyBaseClass(self): self.Check(""" @@ -138,22 +130,17 @@ def testParameterizedBaseClass(self): from typing import List class Foo(List[int]): __slots__ = () - Foo().foo = 42 + Foo().foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (4, "not-writable", r"foo") - ]) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testEmptySlots(self): _, errors = self.InferWithErrors("""\ class Foo(object): __slots__ = () - Foo().foo = 42 + Foo().foo = 42 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(3, "not-writable", r"foo")] - ) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testNamedTuple(self): _, errors = self.InferWithErrors("""\ @@ -163,47 +150,38 @@ def testNamedTuple(self): foo.a = 1 foo.b = 2 foo.c = 3 - foo.d = 4 # error + foo.d = 4 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (7, "not-writable", r"d") - ]) + self.assertErrorRegexes(errors, {"e": r"d"}) def testBuiltinAttr(self): - _, errors = self.InferWithErrors("""\ - "foo".bar = 1 - u"foo".bar = 2 - ().bar = 3 - [].bar = 4 - {}.bar = 5 - set().bar = 6 - frozenset().bar = 7 - frozenset().bar = 8 - Ellipsis.bar = 9 - bytearray().bar = 10 - enumerate([]).bar = 11 - True.bar = 12 - (42).bar = 13 - (3.14).bar = 14 - (3j).bar = 15 - slice(1,10).bar = 17 - memoryview(b"foo").bar = 18 - range(10).bar = 19 - """) - self.assertErrorLogIs( - errors, - [(line, "not-writable") for line in range(1, 19)] - ) + self.InferWithErrors("""\ + "foo".bar = 1 # not-writable + u"foo".bar = 2 # not-writable + ().bar = 3 # not-writable + [].bar = 4 # not-writable + {}.bar = 5 # not-writable + set().bar = 6 # not-writable + frozenset().bar = 7 # not-writable + frozenset().bar = 8 # not-writable + Ellipsis.bar = 9 # not-writable + bytearray().bar = 10 # not-writable + enumerate([]).bar = 11 # not-writable + True.bar = 12 # not-writable + (42).bar = 13 # not-writable + (3.14).bar = 14 # not-writable + (3j).bar = 15 # not-writable + slice(1,10).bar = 16 # not-writable + memoryview(b"foo").bar = 17 # not-writable + range(10).bar = 18 # not-writable + """) def testGeneratorAttr(self): _, errors = self.InferWithErrors("""\ def f(): yield 42 - f().foo = 42 + f().foo = 42 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(2, "not-writable", r"foo")] - ) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testSetAttr(self): self.Check("""\ @@ -241,12 +219,9 @@ class Foo(Bar): __slots__ = ["__foo"] def __init__(self): self.__foo = 42 - self.__baz = 42 # __baz is class-private + self.__baz = 42 # __baz is class-private # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(9, "not-writable", "__baz")] - ) + self.assertErrorRegexes(errors, {"e": r"__baz"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_special_builtins.py b/pytype/tests/test_special_builtins.py index 3a01be077..c0d714e79 100644 --- a/pytype/tests/test_special_builtins.py +++ b/pytype/tests/test_special_builtins.py @@ -201,9 +201,9 @@ def foo(self): foo1 = Foo() foo2 = Foo() if isinstance(foo1.foo, str): - x = foo2.foo.upper() # line 10 + x = foo2.foo.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(10, "attribute-error", r"upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_splits.py b/pytype/tests/test_splits.py index 4e74f19a8..f267fb0c1 100644 --- a/pytype/tests/test_splits.py +++ b/pytype/tests/test_splits.py @@ -655,14 +655,13 @@ def testPrimitiveNotEq(self): def testBuiltinFullNameCheck(self): # Don't get confused by a class named int - _, errorlog = self.InferWithErrors(""" + self.InferWithErrors("""\ class int(): pass x = "foo" if __random__ else int() if x == "foo": - x.upper() + x.upper() # attribute-error """) - self.assertNotEqual(len(errorlog), 0) def testTypeParameterInBranch(self): ty = self.Infer(""" @@ -761,12 +760,11 @@ class Value(int): value1 = ... # type: int value2 = ... # type: Value """) - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import foo if foo.value1 == foo.value2: - name_error + name_error # name-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "name-error")]) def testListElement(self): ty = self.Infer(""" diff --git a/pytype/tests/test_super.py b/pytype/tests/test_super.py index 5ec5e237f..ad1e9edf0 100644 --- a/pytype/tests/test_super.py +++ b/pytype/tests/test_super.py @@ -75,9 +75,9 @@ def testSet(self): _, errors = self.InferWithErrors("""\ class Foo(object): def foo(self, name, value): - super(Foo, self).__set__(name, value) + super(Foo, self).__set__(name, value) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"__set__.*super")]) + self.assertErrorRegexes(errors, {"e": r"__set__.*super"}) def testInheritedSet(self): self.Check(""" @@ -149,9 +149,9 @@ class Y(object): class Foo(Y): def hello(self): - return super(Foo, self)() + return super(Foo, self)() # not-callable[e] """) - self.assertErrorLogIs(errorlog, [(6, "not-callable", r"super")]) + self.assertErrorRegexes(errorlog, {"e": r"super"}) def testSuperType(self): ty = self.Infer(""" @@ -196,25 +196,23 @@ def testSuperWithAny(self): def testSingleArgumentSuper(self): _, errors = self.InferWithErrors("""\ super(object) - super(object()) + super(object()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(2, "wrong-arg-types", r"cls: type.*cls: object")]) + self.assertErrorRegexes(errors, {"e": r"cls: type.*cls: object"}) def testMethodOnSingleArgumentSuper(self): ty, errors = self.InferWithErrors("""\ sup = super(object) - sup.foo - sup.__new__(object) + sup.foo # attribute-error[e1] + sup.__new__(object) # wrong-arg-types[e2] v = sup.__new__(super) """) self.assertTypesMatchPytd(ty, """ sup = ... # type: super v = ... # type: super """) - self.assertErrorLogIs(errors, [ - (2, "attribute-error", r"'foo' on super"), - (3, "wrong-arg-types", r"Type\[super\].*Type\[object\]")]) + self.assertErrorRegexes(errors, {"e1": r"'foo' on super", + "e2": r"Type\[super\].*Type\[object\]"}) def testSuperUnderDecorator(self): self.Check("""\ @@ -233,18 +231,18 @@ def testSuperSetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __init__(self): - super(Foo, self).foo = 42 + super(Foo, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(3, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperSubclassSetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass class Bar(Foo): def __init__(self): - super(Bar, self).foo = 42 + super(Bar, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(4, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperNothingSetAttr(self): with file_utils.Tempdir() as d: @@ -255,17 +253,17 @@ class Foo(nothing): ... import foo class Bar(foo.Foo): def __init__(self): - super(foo.Foo, self).foo = 42 + super(foo.Foo, self).foo = 42 # not-writable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperAnySetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(__any_object__): def __init__(self): - super(Foo, self).foo = 42 + super(Foo, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(3, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_tracebacks.py b/pytype/tests/test_tracebacks.py index 8ea8407f8..832da8638 100644 --- a/pytype/tests/test_tracebacks.py +++ b/pytype/tests/test_tracebacks.py @@ -9,78 +9,70 @@ class TracebackTest(test_base.TargetIndependentTest): def test_no_traceback(self): _, errors = self.InferWithErrors("""\ def f(x): - "hello" + 42 + "hello" + 42 # unsupported-operands[e] f("world") """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"expects str$")]) + self.assertErrorRegexes(errors, {"e": r"expects str$"}) def test_same_traceback(self): _, errors = self.InferWithErrors("""\ def f(x, _): - x + 42 + x + 42 # unsupported-operands[e] def g(x): f("hello", x) g("world") """, deep=True) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Called from.*:\n" - r" line 4, in g")]) + self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g"}) def test_different_tracebacks(self): _, errors = self.InferWithErrors("""\ def f(x): - x + 42 + x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") f("world") """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Called from.*:\n" - r" line 3, in current file"), - (2, "unsupported-operands", - r"Called from.*:\n" - r" line 4, in current file")]) + self.assertErrorRegexes(errors, { + "e1": r"Called from.*:\n line 3, in current file", + "e2": r"Called from.*:\n line 4, in current file"}) def test_comprehension(self): _, errors = self.InferWithErrors("""\ def f(): - return {x.upper() for x in range(10)} + return {x.upper() for x in range(10)} # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*int$")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int$"}) error, = errors self.assertEqual(error.methodname, "f") def test_comprehension_in_traceback(self): _, errors = self.InferWithErrors("""\ def f(x): - return x.upper() + return x.upper() # attribute-error[e] def g(): return {f(x) for x in range(10)} """) - self.assertErrorLogIs(errors, [(2, "attribute-error", - r"Called from.*:\n line 4, in g$")]) + self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g$"}) def test_no_argument_function(self): errors = self.CheckWithErrors("""\ def f(): - return None.attr + return None.attr # attribute-error[e] f() """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"attr.*None$")]) + self.assertErrorRegexes(errors, {"e": r"attr.*None$"}) def test_max_callsites(self): errors = self.CheckWithErrors("""\ def f(s): - return "hello, " + s + return "hello, " + s # unsupported-operands[e1] # unsupported-operands[e2] # unsupported-operands[e3] f(0) f(1) f(2) f(3) """) # We limit the number of tracebacks shown for the same error. - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"line 3"), - (2, "unsupported-operands", r"line 4"), - (2, "unsupported-operands", r"line 5")]) + self.assertErrorRegexes( + errors, {"e1": r"line 3", "e2": r"line 4", "e3": r"line 5"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_tuple.py b/pytype/tests/test_tuple.py index 5fea56993..091f3f9f0 100644 --- a/pytype/tests/test_tuple.py +++ b/pytype/tests/test_tuple.py @@ -64,8 +64,8 @@ def testUnpackTuple(self): def testBadUnpacking(self): ty, errors = self.InferWithErrors("""\ tup = (1, "") - a, = tup - b, c, d = tup + a, = tup # bad-unpacking[e1] + b, c, d = tup # bad-unpacking[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Tuple @@ -75,9 +75,8 @@ def testBadUnpacking(self): c = ... # type: int or str d = ... # type: int or str """) - self.assertErrorLogIs(errors, [ - (2, "bad-unpacking", "2 values.*1 variable"), - (3, "bad-unpacking", "2 values.*3 variables")]) + self.assertErrorRegexes( + errors, {"e1": r"2 values.*1 variable", "e2": r"2 values.*3 variables"}) def testMutableItem(self): ty = self.Infer(""" @@ -95,9 +94,9 @@ def testMutableItem(self): def testBadTupleClassGetItem(self): _, errors = self.InferWithErrors("""\ v = type((3, "")) - w = v[0] + w = v[0] # not-indexable[e] """) - self.assertErrorLogIs(errors, [(2, "not-indexable", r"tuple")]) + self.assertErrorRegexes(errors, {"e": r"tuple"}) def testTupleIsInstance(self): ty = self.Infer(""" diff --git a/pytype/tests/test_type_comments.py b/pytype/tests/test_type_comments.py index a0885ec8f..b5f3dda78 100644 --- a/pytype/tests/test_type_comments.py +++ b/pytype/tests/test_type_comments.py @@ -73,22 +73,20 @@ def foo(x: int, y: str, z: float) -> None """) def testFunctionCommentOnColon(self): - _, errors = self.InferWithErrors(""" + self.InferWithErrors("""\ def f(x) \\ : # type: (None) -> None - return True + return True # bad-return-type """) - self.assertErrorLogIs(errors, [(4, "bad-return-type")]) def testMultipleFunctionComments(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ def f(x): # type: (None) -> bool - # type: (str) -> str + # type: (str) -> str # ignored-type-comment[e] return True """) - self.assertErrorLogIs(errors, [(4, "ignored-type-comment", - r"Stray type comment:.*str")]) + self.assertErrorRegexes(errors, {"e": r"Stray type comment:.*str"}) def testFunctionNoneInArgs(self): ty = self.Infer(""" @@ -183,85 +181,75 @@ class A: def testTypeCommentAfterDocstring(self): """Type comments after the docstring should not be picked up.""" - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x, y): '''Ceci n'est pas une type.''' - # type: (int, str) -> None + # type: (int, str) -> None # ignored-type-comment """) - self.assertErrorLogIs(errors, [(3, "ignored-type-comment")]) def testFunctionNoReturn(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(): - # type: () -> + # type: () -> # invalid-function-type-comment pass """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment")]) def testFunctionTooManyArgs(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 1 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 1 args, 2 given"}) def testFunctionTooFewArgs(self): _, errors = self.InferWithErrors("""\ def foo(x, y, z): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 3 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionTooFewArgsDoNotCountSelf(self): _, errors = self.InferWithErrors("""\ def foo(self, x, y, z): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 3 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionMissingArgs(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x): - # type: () -> int + # type: () -> int # invalid-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment")]) def testInvalidFunctionTypeComment(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x): - # type: blah blah blah + # type: blah blah blah # invalid-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"blah blah blah")]) def testInvalidFunctionArgs(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (abc def) -> int + # type: (abc def) -> int # invalid-function-type-comment[e] return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"abc def.*unexpected EOF")]) + self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) def testAmbiguousAnnotation(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (int if __random__ else str) -> None + # type: (int if __random__ else str) -> None # invalid-function-type-comment[e] pass """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"int.*str.*constant")]) + self.assertErrorRegexes(errors, {"e": r"int.*str.*constant"}) class AssignmentCommentTest(test_base.TargetIndependentTest): @@ -334,10 +322,9 @@ def f() -> Tuple[Mapping, dict]: ... def testBadComment(self): ty, errors = self.InferWithErrors("""\ - X = None # type: abc def + X = None # type: abc def # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", - r"abc def.*unexpected EOF")]) + self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) self.assertTypesMatchPytd(ty, """ from typing import Any X = ... # type: Any @@ -345,10 +332,9 @@ def testBadComment(self): def testConversionError(self): ty, errors = self.InferWithErrors("""\ - X = None # type: 1 if __random__ else 2 + X = None # type: 1 if __random__ else 2 # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", - r"1 if __random__ else 2.*constant")]) + self.assertErrorRegexes(errors, {"e": r"1 if __random__ else 2.*constant"}) self.assertTypesMatchPytd(ty, """ from typing import Any X = ... # type: Any @@ -356,18 +342,17 @@ def testConversionError(self): def testNameErrorInsideComment(self): _, errors = self.InferWithErrors("""\ - X = None # type: Foo + X = None # type: Foo # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", r"Foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo"}) def testWarnOnIgnoredTypeComment(self): _, errors = self.InferWithErrors("""\ X = [] - X[0] = None # type: str - # type: int + X[0] = None # type: str # ignored-type-comment[e1] + # type: int # ignored-type-comment[e2] """, deep=True) - self.assertErrorLogIs(errors, [(2, "ignored-type-comment", r"str"), - (3, "ignored-type-comment", r"int")]) + self.assertErrorRegexes(errors, {"e1": r"str", "e2": r"int"}) def testAttributeInitialization(self): ty = self.Infer(""" @@ -395,15 +380,14 @@ def testNoneToNoneType(self): def testModuleInstanceAsBadTypeComment(self): _, errors = self.InferWithErrors("""\ import sys - x = None # type: sys + x = None # type: sys # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [(2, "invalid-annotation", - r"instance of module.*x")]) + self.assertErrorRegexes(errors, {"e": r"instance of module.*x"}) def testForwardReference(self): ty, errors = self.InferWithErrors("""\ a = None # type: "A" - b = None # type: "Nonexistent" + b = None # type: "Nonexistent" # name-error[e] class A(object): def __init__(self): self.x = 42 @@ -418,7 +402,7 @@ def f(self) -> int a = ... # type: A b = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "name-error", r"Nonexistent")]) + self.assertErrorRegexes(errors, {"e": r"Nonexistent"}) def testClassVariableForwardReference(self): ty = self.Infer("""\ @@ -473,29 +457,27 @@ def g() -> A: ... """) def testClassVariableForwardReferenceError(self): - _, err = self.InferWithErrors("""\ + self.InferWithErrors("""\ class A(object): a = None # type: 'A' - g = A().a.foo() + g = A().a.foo() # attribute-error """) - self.assertErrorLogIs(err, [(3, "attribute-error")]) def testMultilineValue(self): ty, errors = self.InferWithErrors("""\ v = [ { - "a": 1 # type: complex + "a": 1 # type: complex # ignored-type-comment[e1] - } # type: dict[str, int] + } # type: dict[str, int] # ignored-type-comment[e2] ] # type: list[dict[str, float]] """) self.assertTypesMatchPytd(ty, """ v = ... # type: list[dict[str, float]] """) - self.assertErrorLogIs(errors, [(3, "ignored-type-comment", - r"Stray type comment: complex"), - (5, "ignored-type-comment", - r"Stray type comment: dict\[str, int\]")]) + self.assertErrorRegexes(errors, { + "e1": r"Stray type comment: complex", + "e2": r"Stray type comment: dict\[str, int\]"}) def testMultilineValueWithBlankLines(self): ty = self.Infer("""\ @@ -512,18 +494,16 @@ def testMultilineValueWithBlankLines(self): def testTypeCommentNameError(self): _, errors = self.InferWithErrors("""\ def f(): - x = None # type: Any + x = None # type: Any # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "invalid-type-comment", r"not defined$")]) + self.assertErrorRegexes(errors, {"e": r"not defined$"}) def testTypeCommentInvalidSyntax(self): _, errors = self.InferWithErrors("""\ def f(): - x = None # type: y = 1 + x = None # type: y = 1 # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "invalid-type-comment", r"invalid syntax$")]) + self.assertErrorRegexes(errors, {"e": r"invalid syntax$"}) def testDiscardedTypeComment(self): """Discard the first whole-line comment, keep the second.""" @@ -540,10 +520,9 @@ def hello_world() -> str: ... def testMultipleTypeComments(self): """We should not allow multiple type comments on one line.""" _, errors = self.InferWithErrors("""\ - a = 42 # type: int # type: float + a = 42 # type: int # type: float # invalid-directive[e] """) - self.assertErrorLogIs( - errors, [(1, "invalid-directive", r"Multiple")]) + self.assertErrorRegexes(errors, {"e": r"Multiple"}) def testMultipleDirectives(self): """We should support multiple directives on one line.""" @@ -613,10 +592,9 @@ def testRecursiveTypeAlias(self): errors = self.CheckWithErrors("""\ from typing import List, Union Foo = Union[str, List['Foo']] - x = 'hello' # type: Foo + x = 'hello' # type: Foo # not-supported-yet[e] """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet", - r"Recursive.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Recursive.*Foo"}) def testInstantiateFullyQuotedType(self): ty, errors = self.InferWithErrors("""\ @@ -624,7 +602,7 @@ def testInstantiateFullyQuotedType(self): x = None # type: "Optional[A]" class A(object): a = 0 - y = x.a + y = x.a # attribute-error[e] """) self.assertTypesMatchPytd(ty, """ from typing import Optional @@ -633,7 +611,7 @@ class A(object): a: int y: int """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"a.*None")]) + self.assertErrorRegexes(errors, {"e": r"a.*None"}) def testDoNotResolveLateTypeToFunction(self): ty = self.Infer(""" @@ -649,19 +627,17 @@ def A(self) -> None: ... """) def testIllegalFunctionLateType(self): - errors = self.CheckWithErrors("""\ - v = None # type: "F" + self.CheckWithErrors("""\ + v = None # type: "F" # invalid-annotation def F(): pass """) - self.assertErrorLogIs(errors, [(1, "invalid-annotation")]) def testBadTypeCommentInConstructor(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): def __init__(self): - self.x = None # type: "Bar" + self.x = None # type: "Bar" # name-error """) - self.assertErrorLogIs(errors, [(3, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_typevar.py b/pytype/tests/test_typevar.py index ace53ac3f..a9dedb306 100644 --- a/pytype/tests/test_typevar.py +++ b/pytype/tests/test_typevar.py @@ -32,13 +32,13 @@ def testInvalidTypeVar(self): ty, errors = self.InferWithErrors("""\ from typing import TypeVar typevar = TypeVar - T = typevar() + T = typevar() # invalid-typevar[e1] T = typevar("T") # ok - T = typevar(42) - T = typevar(str()) - T = typevar("T", str, int if __random__ else float) - T = typevar("T", 0, float) - T = typevar("T", str) + T = typevar(42) # invalid-typevar[e2] + T = typevar(str()) # invalid-typevar[e3] + T = typevar("T", str, int if __random__ else float) # invalid-typevar[e4] + T = typevar("T", 0, float) # invalid-typevar[e5] + T = typevar("T", str) # invalid-typevar[e6] # pytype: disable=not-supported-yet S = typevar("S", covariant=False) # ok T = typevar("T", covariant=False) # duplicate ok @@ -50,14 +50,11 @@ def testInvalidTypeVar(self): S = TypeVar("S") T = TypeVar("T") """) - self.assertErrorLogIs(errors, [ - (3, "invalid-typevar", r"wrong arguments"), - (5, "invalid-typevar", r"Expected.*str.*Actual.*int"), - (6, "invalid-typevar", r"constant str"), - (7, "invalid-typevar", r"must be constant"), - (8, "invalid-typevar", r"Expected.*_1:.*type.*Actual.*_1: int"), - (9, "invalid-typevar", r"0 or more than 1"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"wrong arguments", "e2": r"Expected.*str.*Actual.*int", + "e3": r"constant str", "e4": r"must be constant", + "e5": r"Expected.*_1:.*type.*Actual.*_1: int", "e6": r"0 or more than 1" + }) def testPrintConstraints(self): ty = self.Infer(""" @@ -114,14 +111,12 @@ def return_arg_or_42(x: _T0) -> Union[_T0, int] """) def testTypeVarInTypeComment(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import List, TypeVar T = TypeVar("T") - x = None # type: T - y = None # type: List[T] + x = None # type: T # not-supported-yet + y = None # type: List[T] # not-supported-yet """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet"), - (4, "not-supported-yet")]) def testBaseClassWithTypeVar(self): ty = self.Infer("""\ @@ -145,41 +140,33 @@ class X(l): pass """) def testBound(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", int, float, bound=str) - S = TypeVar("S", bound="") + T = TypeVar("T", int, float, bound=str) # invalid-typevar + S = TypeVar("S", bound="") # invalid-typevar U = TypeVar("U", bound=str) # ok - V = TypeVar("V", bound=int if __random__ else float) + V = TypeVar("V", bound=int if __random__ else float) # invalid-typevar """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"mutually exclusive"), - (3, "invalid-typevar", r"empty string"), - (5, "invalid-typevar", r"must be constant")]) def testCovariant(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", covariant=True) - S = TypeVar("S", covariant=42) - U = TypeVar("U", covariant=True if __random__ else False) + T = TypeVar("T", covariant=True) # not-supported-yet + S = TypeVar("S", covariant=42) # invalid-typevar[e1] + U = TypeVar("U", covariant=True if __random__ else False) # invalid-typevar[e2] """) - self.assertErrorLogIs(errors, [ - (2, "not-supported-yet"), - (3, "invalid-typevar", r"Expected.*bool.*Actual.*int"), - (4, "invalid-typevar", r"constant")]) + self.assertErrorRegexes( + errors, {"e1": r"Expected.*bool.*Actual.*int", "e2": r"constant"}) def testContravariant(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", contravariant=True) - S = TypeVar("S", contravariant=42) - U = TypeVar("U", contravariant=True if __random__ else False) + T = TypeVar("T", contravariant=True) # not-supported-yet + S = TypeVar("S", contravariant=42) # invalid-typevar[e1] + U = TypeVar("U", contravariant=True if __random__ else False) # invalid-typevar[e2] """) - self.assertErrorLogIs(errors, [ - (2, "not-supported-yet"), - (3, "invalid-typevar", r"Expected.*bool.*Actual.*int"), - (4, "invalid-typevar", r"constant")]) + self.assertErrorRegexes( + errors, {"e1": r"Expected.*bool.*Actual.*int", "e2": r"constant"}) def testDontPropagatePyval(self): # in functions like f(x: T) -> T, if T has constraints we should not copy @@ -381,20 +368,18 @@ def testStoreTypeVarInDict(self): def testLateBound(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar, Union - T = TypeVar("T", int, float, bound="str") - S = TypeVar("S", bound="") + T = TypeVar("T", int, float, bound="str") # invalid-typevar[e1] + S = TypeVar("S", bound="") # invalid-typevar[e2] U = TypeVar("U", bound="str") # ok - V = TypeVar("V", bound="int if __random__ else float") + V = TypeVar("V", bound="int if __random__ else float") # invalid-typevar[e3] W = TypeVar("W", bound="Foo") # ok, forward reference - X = TypeVar("X", bound="Bar") + X = TypeVar("X", bound="Bar") # name-error[e4] class Foo: pass """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"mutually exclusive"), - (3, "invalid-typevar", r"empty string"), - (5, "invalid-typevar", r"Must be constant"), - (7, "name-error", r"Name.*Bar")]) + self.assertErrorRegexes(errors, { + "e1": r"mutually exclusive", "e2": r"empty string", + "e3": r"Must be constant", "e4": r"Name.*Bar"}) def testLateConstraints(self): ty = self.Infer(""" diff --git a/pytype/tests/test_typing.py b/pytype/tests/test_typing.py index e937a94f8..efa64c16c 100644 --- a/pytype/tests/test_typing.py +++ b/pytype/tests/test_typing.py @@ -38,10 +38,10 @@ def test_cast2(self): """) def test_process_annotation_for_cast(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import typing v1 = typing.cast(None, __any_object__) - v2 = typing.cast(typing.Union, __any_object__) + v2 = typing.cast(typing.Union, __any_object__) # invalid-annotation v3 = typing.cast("A", __any_object__) class A(object): pass @@ -53,21 +53,17 @@ class A(object): v3: A class A(object): ... """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation")]) def test_no_typevars_for_cast(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import cast, AnyStr, Type, TypeVar, _T def f(x): - return cast(AnyStr, x) + return cast(AnyStr, x) # invalid-typevar f("hello") def g(x): - return cast(AnyStr if __random__ else int, x) + return cast(AnyStr if __random__ else int, x) # invalid-typevar g("quack") """) - self.assertErrorLogIs(errors, - [(3, "invalid-typevar"), - (6, "invalid-typevar")]) def test_cast_args(self): self.assertNoCrash(self.Check, """\ @@ -139,23 +135,18 @@ def test_not_type_checking(self): """) def test_new_type_arg_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ from typing import NewType - MyInt = NewType(int, 'MyInt') - MyStr = NewType(tp='str', name='MyStr') - MyFunnyNameType = NewType(name=123 if __random__ else 'Abc', tp=int) - MyFunnyType = NewType(name='Abc', tp=int if __random__ else 'int') + MyInt = NewType(int, 'MyInt') # wrong-arg-types[e1] + MyStr = NewType(tp='str', name='MyStr') # wrong-arg-types[e2] + MyFunnyNameType = NewType(name=123 if __random__ else 'Abc', tp=int) # wrong-arg-types[e3] + MyFunnyType = NewType(name='Abc', tp=int if __random__ else 'int') # wrong-arg-types[e4] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", - r".*Expected:.*str.*\nActually passed:.*Type\[int\].*"), - (4, "wrong-arg-types", - r".*Expected:.*type.*\nActually passed:.*str.*"), - (5, "wrong-arg-types", - r".*Expected:.*str.*\nActually passed:.*Union.*"), - (6, "wrong-arg-types", - r".*Expected:.*type.*\nActually passed:.*Union.*"),]) + self.assertErrorRegexes(errors, { + "e1": r".*Expected:.*str.*\nActually passed:.*Type\[int\].*", + "e2": r".*Expected:.*type.*\nActually passed:.*str.*", + "e3": r".*Expected:.*str.*\nActually passed:.*Union.*", + "e4": r".*Expected:.*type.*\nActually passed:.*Union.*"}) def test_classvar(self): ty = self.Infer("""\ @@ -188,17 +179,18 @@ class X: v: ClassVar[int, int] """) errors = self.CheckWithErrors("""\ - import foo + import foo # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"ClassVar.*1.*2")]) + self.assertErrorRegexes(errors, {"e": r"ClassVar.*1.*2"}) class LiteralTest(test_base.TargetIndependentTest): """Tests for typing.Literal.""" def test_py(self): - errors = self.CheckWithErrors("from typing import Literal") - self.assertErrorLogIs(errors, [(1, "not-supported-yet")]) + self.CheckWithErrors("""\ + from typing import Literal # not-supported-yet + """) def test_pyi_parameter(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_typing_namedtuple.py b/pytype/tests/test_typing_namedtuple.py index 983006382..047aaaa0e 100644 --- a/pytype/tests/test_typing_namedtuple.py +++ b/pytype/tests/test_typing_namedtuple.py @@ -7,48 +7,37 @@ class NamedTupleTest(test_base.TargetIndependentTest): """Tests for the typing.NamedTuple overlay.""" def test_basic_calls(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing Basic = typing.NamedTuple("Basic", [('a', str)]) ex = Basic("hello world") ea = ex.a - ey = Basic() # Should fail - ez = Basic("a", "b") # Should fail + ey = Basic() # missing-parameter + ez = Basic("a", "b") # wrong-arg-count """) - self.assertErrorLogIs(errors, [ - (5, "missing-parameter"), - (6, "wrong-arg-count")]) def test_optional_field_type(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing X = typing.NamedTuple("X", [('a', str), ('b', typing.Optional[int])]) xa = X('hello', None) xb = X('world', 2) - xc = X('nope', '2') # Should fail - xd = X() # Should fail - xe = X(1, "nope") # Should fail + xc = X('nope', '2') # wrong-arg-types + xd = X() # missing-parameter + xe = X(1, "nope") # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (6, "missing-parameter"), - (7, "wrong-arg-types")]) def test_class_field_type(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing class Foo(object): pass Y = typing.NamedTuple("Y", [('a', str), ('b', Foo)]) ya = Y('a', Foo()) - yb = Y('a', 1) # Should fail - yc = Y(Foo()) # Should fail - yd = Y(1) # Should fail + yb = Y('a', 1) # wrong-arg-types + yc = Y(Foo()) # missing-parameter + yd = Y(1) # missing-parameter """) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "missing-parameter"), - (8, "missing-parameter")]) def test_late_annotation(self): errors = self.CheckWithErrors("""\ @@ -56,55 +45,44 @@ def test_late_annotation(self): class Foo(object): pass X = typing.NamedTuple("X", [('a', 'Foo')]) # should be fine - Y = typing.NamedTuple("Y", [('a', 'Bar')]) # should fail + Y = typing.NamedTuple("Y", [('a', 'Bar')]) # should fail # name-error[e] """) - self.assertErrorLogIs(errors, [(5, "name-error", "Bar")]) + self.assertErrorRegexes(errors, {"e": r"Bar"}) def test_nested_containers(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing Z = typing.NamedTuple("Z", [('a', typing.List[typing.Optional[int]])]) za = Z([1]) zb = Z([None, 2]) - zc = Z(1) # Should fail + zc = Z(1) # wrong-arg-types import typing A = typing.NamedTuple("A", [('a', typing.Dict[int, str]), ('b', typing.Tuple[int, int])]) aa = A({1: '1'}, (1, 2)) ab = A({}, (1, 2)) - ac = A(1, 2) # Should fail + ac = A(1, 2) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (11, "wrong-arg-types")]) def test_pytd_field(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing import datetime B = typing.NamedTuple("B", [('a', datetime.date)]) ba = B(datetime.date(1,2,3)) - bb = B() # Should fail - bc = B(1) # Should fail + bb = B() # missing-parameter + bc = B(1) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "missing-parameter"), - (6, "wrong-arg-types")]) def test_bad_calls(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import typing - typing.NamedTuple("_", ["abc", "def", "ghi"]) + typing.NamedTuple("_", ["abc", "def", "ghi"]) # wrong-arg-types # "def" is a keyword, so the call on the next line fails. - typing.NamedTuple("_", [("abc", int), ("def", int), ("ghi", int)]) - typing.NamedTuple("1", [("a", int)]) - typing.NamedTuple("_", [[int, "a"]]) + typing.NamedTuple("_", [("abc", int), ("def", int), ("ghi", int)]) # invalid-namedtuple-arg + typing.NamedTuple("1", [("a", int)]) # invalid-namedtuple-arg + typing.NamedTuple("_", [[int, "a"]]) # wrong-arg-types """) - self.assertErrorLogIs(errorlog, - [(2, "wrong-arg-types"), - (4, "invalid-namedtuple-arg"), - (5, "invalid-namedtuple-arg"), - (6, "wrong-arg-types")]) def test_empty_args(self): self.Check( @@ -118,27 +96,26 @@ def test_tuple_fields(self): from typing import NamedTuple X = NamedTuple("X", (("a", str),)) X(a="") - X(a=42) + X(a=42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_list_field(self): errors = self.CheckWithErrors("""\ from typing import NamedTuple X = NamedTuple("X", [["a", str]]) X(a="") - X(a=42) + X(a=42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_str_fields_error(self): errors = self.CheckWithErrors("""\ from typing import NamedTuple - X = NamedTuple("X", "a b") - Y = NamedTuple("Y", ["ab"]) + X = NamedTuple("X", "a b") # wrong-arg-types[e1] + Y = NamedTuple("Y", ["ab"]) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"List.*str"), - (3, "wrong-arg-types", r"Tuple.*str")]) + self.assertErrorRegexes(errors, {"e1": r"List.*str", "e2": r"Tuple.*str"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_unions.py b/pytype/tests/test_unions.py index 006aaf7ba..47be85bc5 100644 --- a/pytype/tests/test_unions.py +++ b/pytype/tests/test_unions.py @@ -29,17 +29,14 @@ def f(): x = 42 if __random__: # Should not appear in output - x.__class__ = float - x.__class__ = str + x.__class__ = float # not-writable[e1] + x.__class__ = str # not-writable[e2] return type(x)() """, deep=True) self.assertTypesMatchPytd(ty, """ def f() -> int """) - self.assertErrorLogIs(errors, [ - (5, "not-writable", "int"), - (6, "not-writable", "int"), - ]) + self.assertErrorRegexes(errors, {"e1": r"int", "e2": r"int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_utils.py b/pytype/tests/test_utils.py index ee20cd10b..e552745d0 100644 --- a/pytype/tests/test_utils.py +++ b/pytype/tests/test_utils.py @@ -163,9 +163,9 @@ def _testCollectionsObject(self, obj, good_arg, bad_arg, error): # pylint: disa import collections def f(x: collections.{obj}): ... f({good_arg}) - f({bad_arg}) # line 5 + f({bad_arg}) # wrong-arg-types[e] """.format(obj=obj, good_arg=good_arg, bad_arg=bad_arg)) - self.assertErrorLogIs(result, [(4, "wrong-arg-types", error)]) + self.assertErrorRegexes(result, {"e": error}) class MakeCodeMixin(object): From 485a68c999084171a047131c7f11bb979b226188 Mon Sep 17 00:00:00 2001 From: Brad Solomon Date: Tue, 31 Mar 2020 12:22:31 -0700 Subject: [PATCH 05/11] Note that install is broken on Alpine Linux (#541) Related: Resolves #541 PiperOrigin-RevId: 304020432 --- README.md | 9 ++++++++- docs/index.md | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f5287840a..34ebae220 100755 --- a/README.md +++ b/README.md @@ -93,11 +93,18 @@ interpreter in `$PATH` for the Python version of the code you're analyzing. Platform support: -* Pytype is currently developed and tested on Linux, which is the main supported +* Pytype is currently developed and tested on Linux\*, which is the main supported platform. * Installation on MacOSX requires OSX 10.7 or higher and Xcode v8 or higher. * Windows is currently not supported unless you use [WSL][wsl]. +\* +Note: On Alpine Linux, installing may fail due to issues with upstream +dependencies. See the details of + +this issue for a possible fix. + + ## Installing Pytype can be installed via pip. Note that the installation requires `wheel` diff --git a/docs/index.md b/docs/index.md index 1d8e58fb3..54c911deb 100755 --- a/docs/index.md +++ b/docs/index.md @@ -91,11 +91,18 @@ interpreter in `$PATH` for the Python version of the code you're analyzing. Platform support: -* Pytype is currently developed and tested on Linux, which is the main supported +* Pytype is currently developed and tested on Linux\*, which is the main supported platform. * Installation on MacOSX requires OSX 10.7 or higher and Xcode v8 or higher. * Windows is currently not supported unless you use [WSL][wsl]. +\* +Note: On Alpine Linux, installing may fail due to issues with upstream +dependencies. See the details of + +this issue for a possible fix. + + ## Installing Pytype can be installed via pip. Note that the installation requires `wheel` From 0e19be9e3937e320103c0ebd32ee3ffe688de0c1 Mon Sep 17 00:00:00 2001 From: rechen Date: Tue, 31 Mar 2020 12:29:00 -0700 Subject: [PATCH 06/11] Cleanup: remove backslashes in pytype tests. Also removes now-unnecessary g-backslash-continuation suppressions and fixes g-generic-assert errors in pytype/errors_test. PiperOrigin-RevId: 304021801 --- pytype/debug_test.py | 16 +- pytype/directors_test.py | 10 +- pytype/errors_test.py | 36 +- pytype/load_pytd_test.py | 6 +- pytype/matcher_test.py | 10 +- pytype/pyi/lexer_test.py | 39 +- pytype/pyi/parser_memleak_test.py | 6 +- pytype/pyi/parser_test.py | 546 +++++++++--------- pytype/pytd/optimize_test.py | 4 +- pytype/pytd/pytd_utils_test.py | 8 +- pytype/pytd/visitors_test.py | 48 +- pytype/single_test.py | 20 +- pytype/tests/py2/test_abc.py | 6 +- pytype/tests/py2/test_attributes.py | 4 +- pytype/tests/py2/test_basic.py | 6 +- pytype/tests/py2/test_builtins.py | 4 +- pytype/tests/py2/test_classes.py | 4 +- pytype/tests/py2/test_decorators.py | 2 +- pytype/tests/py2/test_errors.py | 6 +- pytype/tests/py2/test_exceptions.py | 2 +- pytype/tests/py2/test_import.py | 2 +- pytype/tests/py2/test_list.py | 4 +- pytype/tests/py2/test_namedtuple.py | 2 +- pytype/tests/py2/test_pyi.py | 4 +- pytype/tests/py2/test_reingest.py | 2 +- pytype/tests/py2/test_slots.py | 6 +- pytype/tests/py2/test_stdlib.py | 2 +- pytype/tests/py2/test_super.py | 2 +- pytype/tests/py2/test_tuple.py | 2 +- pytype/tests/py2/test_typevar.py | 4 +- pytype/tests/py2/test_typing_methods.py | 2 +- pytype/tests/py2/test_typing_namedtuple.py | 8 +- pytype/tests/py3/test_abc.py | 2 +- pytype/tests/py3/test_annotations.py | 116 ++-- pytype/tests/py3/test_anystr.py | 4 +- pytype/tests/py3/test_async_generators.py | 4 +- pytype/tests/py3/test_attr.py | 4 +- pytype/tests/py3/test_attributes.py | 10 +- pytype/tests/py3/test_basic.py | 2 +- pytype/tests/py3/test_builtins.py | 18 +- pytype/tests/py3/test_checker.py | 28 +- pytype/tests/py3/test_classes.py | 22 +- pytype/tests/py3/test_coroutine.py | 10 +- pytype/tests/py3/test_dataclasses.py | 8 +- pytype/tests/py3/test_decorators.py | 4 +- pytype/tests/py3/test_dict.py | 4 +- pytype/tests/py3/test_errors.py | 52 +- pytype/tests/py3/test_flow.py | 2 +- pytype/tests/py3/test_functions.py | 40 +- pytype/tests/py3/test_generators.py | 4 +- pytype/tests/py3/test_generic.py | 42 +- pytype/tests/py3/test_import.py | 4 +- pytype/tests/py3/test_list.py | 10 +- pytype/tests/py3/test_match.py | 24 +- pytype/tests/py3/test_methods.py | 8 +- pytype/tests/py3/test_namedtuple.py | 4 +- pytype/tests/py3/test_overload.py | 14 +- pytype/tests/py3/test_protocols.py | 28 +- pytype/tests/py3/test_pyi.py | 4 +- pytype/tests/py3/test_recovery.py | 4 +- pytype/tests/py3/test_reingest.py | 4 +- pytype/tests/py3/test_slots.py | 2 +- pytype/tests/py3/test_stdlib.py | 8 +- pytype/tests/py3/test_super.py | 2 +- pytype/tests/py3/test_tracebacks.py | 2 +- pytype/tests/py3/test_tuple.py | 12 +- pytype/tests/py3/test_type_comments.py | 6 +- pytype/tests/py3/test_typevar.py | 38 +- pytype/tests/py3/test_typing.py | 44 +- pytype/tests/py3/test_typing_methods.py | 2 +- pytype/tests/py3/test_typing_namedtuple.py | 28 +- pytype/tests/py3/test_variable_annotations.py | 18 +- pytype/tests/test_abc.py | 8 +- pytype/tests/test_attr.py | 16 +- pytype/tests/test_attributes.py | 49 +- pytype/tests/test_base.py | 22 +- pytype/tests/test_base_test.py | 8 +- pytype/tests/test_basic.py | 118 ++-- pytype/tests/test_builtins2.py | 18 +- pytype/tests/test_builtins3.py | 17 +- pytype/tests/test_calls.py | 14 +- pytype/tests/test_classes.py | 48 +- pytype/tests/test_cmp.py | 8 +- pytype/tests/test_compile_to_pyc.py | 4 +- pytype/tests/test_containers.py | 4 +- pytype/tests/test_decorators.py | 8 +- pytype/tests/test_dict.py | 2 +- pytype/tests/test_disables.py | 10 +- pytype/tests/test_errors.py | 214 +++---- pytype/tests/test_exceptions.py | 32 +- pytype/tests/test_flow.py | 2 +- pytype/tests/test_functions.py | 103 ++-- pytype/tests/test_future_overlay.py | 2 +- pytype/tests/test_import.py | 86 +-- pytype/tests/test_list.py | 4 +- pytype/tests/test_namedtuple.py | 10 +- pytype/tests/test_operators.py | 4 +- pytype/tests/test_pyi.py | 46 +- pytype/tests/test_quick.py | 2 +- pytype/tests/test_recovery.py | 10 +- pytype/tests/test_reingest.py | 2 +- pytype/tests/test_slots.py | 20 +- pytype/tests/test_solver.py | 14 +- pytype/tests/test_special_builtins.py | 2 +- pytype/tests/test_splits.py | 14 +- pytype/tests/test_stdlib.py | 16 +- pytype/tests/test_super.py | 18 +- pytype/tests/test_tracebacks.py | 14 +- pytype/tests/test_tuple.py | 10 +- pytype/tests/test_type_comments.py | 86 +-- pytype/tests/test_typevar.py | 16 +- pytype/tests/test_typing.py | 24 +- pytype/tests/test_typing_methods.py | 20 +- pytype/tests/test_typing_namedtuple.py | 20 +- pytype/tests/test_unions.py | 2 +- pytype/tests/test_utils.py | 2 +- pytype/tests/test_with.py | 20 +- pytype/tools/traces/source_test.py | 8 +- pytype/tools/traces/traces_test.py | 40 +- pytype/tools/xref/callgraph_test.py | 8 +- pytype/tools/xref/indexer_test.py | 14 +- pytype/vm_test.py | 4 +- 122 files changed, 1359 insertions(+), 1349 deletions(-) diff --git a/pytype/debug_test.py b/pytype/debug_test.py index f6fd61f53..852ac6690 100644 --- a/pytype/debug_test.py +++ b/pytype/debug_test.py @@ -43,7 +43,7 @@ def testAsciiTree(self): n7 = Node("n7", n5) del n4, n6 # make pylint happy s = debug.ascii_tree(n1, lambda n: n.outgoing) - self.assertMultiLineEqual(textwrap.dedent("""\ + self.assertMultiLineEqual(textwrap.dedent(""" Node(n1) | +-Node(n2) @@ -57,15 +57,15 @@ def testAsciiTree(self): +-Node(n6) | +-Node(n7) - """), s) + """).lstrip(), s) s = debug.ascii_tree(n7, lambda n: n.incoming) - self.assertMultiLineEqual(textwrap.dedent("""\ + self.assertMultiLineEqual(textwrap.dedent(""" Node(n7) | +-Node(n5) | +-Node(n1) - """), s) + """).lstrip(), s) def testAsciiGraph(self): n1 = Node("n1") @@ -73,7 +73,7 @@ def testAsciiGraph(self): n3 = Node("n3", n2) n3.connect_to(n1) s = debug.ascii_tree(n1, lambda n: n.outgoing) - self.assertMultiLineEqual(textwrap.dedent("""\ + self.assertMultiLineEqual(textwrap.dedent(""" Node(n1) | +-Node(n2) @@ -81,7 +81,7 @@ def testAsciiGraph(self): +-Node(n3) | +-[Node(n1)] - """), s) + """).lstrip(), s) def testAsciiGraphWithCustomText(self): n1 = Node("n1") @@ -89,7 +89,7 @@ def testAsciiGraphWithCustomText(self): n3 = Node("n3", n2) n3.connect_to(n1) s = debug.ascii_tree(n1, lambda n: n.outgoing, lambda n: n.name.upper()) - self.assertMultiLineEqual(textwrap.dedent("""\ + self.assertMultiLineEqual(textwrap.dedent(""" N1 | +-N2 @@ -97,7 +97,7 @@ def testAsciiGraphWithCustomText(self): +-N3 | +-[N1] - """), s) + """).lstrip(), s) def testRootCause(self): n1 = self.prog.NewCFGNode() diff --git a/pytype/directors_test.py b/pytype/directors_test.py index e8eb00d56..583f90521 100644 --- a/pytype/directors_test.py +++ b/pytype/directors_test.py @@ -351,7 +351,7 @@ def test_strings_that_look_like_directives(self): }, self._director.type_comments) def test_type_comment_on_multiline_value(self): - self._create("""\ + self._create(""" v = [ ("hello", "world", # type: should_be_ignored @@ -360,11 +360,11 @@ def test_type_comment_on_multiline_value(self): ] # type: dict """) self.assertEqual({ - 3: ("]", "dict"), + 4: ("]", "dict"), }, self._director.type_comments) def test_type_comment_with_trailing_comma(self): - self._create("""\ + self._create(""" v = [ ("hello", "world" @@ -377,8 +377,8 @@ def test_type_comment_with_trailing_comma(self): ] # type: dict """) self.assertEqual({ - 3: ("]", "dict"), - 9: ("]", "dict"), + 4: ("]", "dict"), + 10: ("]", "dict"), }, self._director.type_comments) diff --git a/pytype/errors_test.py b/pytype/errors_test.py index 64859779a..a54ffec27 100644 --- a/pytype/errors_test.py +++ b/pytype/errors_test.py @@ -73,21 +73,21 @@ def test_no_traceback_no_opcode(self): def test_traceback(self): stack = test_utils.fake_stack(errors.MAX_TRACEBACK_LENGTH + 1) error = errors.Error.with_stack(stack, errors.SEVERITY_ERROR, "") - self.assertMultiLineEqual(error._traceback, textwrap.dedent("""\ + self.assertMultiLineEqual(error._traceback, textwrap.dedent(""" Called from (traceback): line 0, in function0 line 1, in function1 - line 2, in function2""")) + line 2, in function2""").lstrip()) @errors._error_name(_TEST_ERROR) def test_truncated_traceback(self): stack = test_utils.fake_stack(errors.MAX_TRACEBACK_LENGTH + 2) error = errors.Error.with_stack(stack, errors.SEVERITY_ERROR, "") - self.assertMultiLineEqual(error._traceback, textwrap.dedent("""\ + self.assertMultiLineEqual(error._traceback, textwrap.dedent(""" Called from (traceback): line 0, in function0 ... - line 3, in function3""")) + line 3, in function3""").lstrip()) def test__error_name(self): # This should be true as long as at least one method is annotated with @@ -119,7 +119,7 @@ def test_write_to_csv(self): errorlog.print_to_csv_file(filename) with open(filename, "r") as fi: rows = list(csv.reader(fi, delimiter=",")) - self.assertEqual(2, len(rows)) + self.assertEqual(len(rows), 2) for i, row in enumerate(rows): filename, lineno, name, actual_message, actual_details = row self.assertEqual(filename, "foo.py") @@ -138,12 +138,12 @@ def test_write_to_csv_with_traceback(self): errorlog.print_to_csv_file(filename) with open(filename, "r") as fi: (_, _, _, _, actual_details), = list(csv.reader(fi, delimiter=",")) - self.assertMultiLineEqual(actual_details, textwrap.dedent("""\ + self.assertMultiLineEqual(actual_details, textwrap.dedent(""" some details Called from (traceback): - line 0, in function0""")) + line 0, in function0""").lstrip()) class ErrorLogBaseTest(unittest.TestCase): @@ -153,7 +153,7 @@ def test_error(self): errorlog = errors.ErrorLog() op = test_utils.FakeOpcode("foo.py", 123, "foo") errorlog.error(op.to_stack(), "unknown attribute %s" % "xyz") - self.assertEqual(1, len(errorlog)) + self.assertEqual(len(errorlog), 1) e = list(errorlog)[0] # iterate the log and save the first error. self.assertEqual(errors.SEVERITY_ERROR, e._severity) self.assertEqual("unknown attribute xyz", e._message) @@ -164,18 +164,18 @@ def test_error(self): def test_error_with_details(self): errorlog = errors.ErrorLog() errorlog.error(None, "My message", "one\ntwo") - self.assertEqual(textwrap.dedent("""\ + self.assertEqual(textwrap.dedent(""" My message [test-error] one two - """), str(errorlog)) + """).lstrip(), str(errorlog)) @errors._error_name(_TEST_ERROR) def test_warn(self): errorlog = errors.ErrorLog() op = test_utils.FakeOpcode("foo.py", 123, "foo") errorlog.warn(op.to_stack(), "unknown attribute %s", "xyz") - self.assertEqual(1, len(errorlog)) + self.assertEqual(len(errorlog), 1) e = list(errorlog)[0] # iterate the log and save the first error. self.assertEqual(errors.SEVERITY_WARNING, e._severity) self.assertEqual("unknown attribute xyz", e._message) @@ -188,11 +188,11 @@ def test_has_error(self): self.assertFalse(errorlog.has_error()) # A warning is part of the error log, but isn't severe. errorlog.warn(None, "A warning") - self.assertEqual(1, len(errorlog)) + self.assertEqual(len(errorlog), 1) self.assertFalse(errorlog.has_error()) # An error is severe. errorlog.error(None, "An error") - self.assertEqual(2, len(errorlog)) + self.assertEqual(len(errorlog), 2) self.assertTrue(errorlog.has_error()) @errors._error_name(_TEST_ERROR) @@ -203,7 +203,7 @@ def test_duplicate_error_no_traceback(self): errorlog.error(stack[-1:], "error") # no traceback # Keep the error with no traceback. unique_errors = errorlog.unique_sorted_errors() - self.assertEqual(1, len(unique_errors)) + self.assertEqual(len(unique_errors), 1) self.assertIsNone(unique_errors[0]._traceback) @errors._error_name(_TEST_ERROR) @@ -230,10 +230,10 @@ def test_duplicate_error_shorter_traceback(self): errorlog.error(stack[-2:], "error") # shorter traceback # Keep the error with a shorter traceback. unique_errors = errorlog.unique_sorted_errors() - self.assertEqual(1, len(unique_errors)) - self.assertMultiLineEqual(unique_errors[0]._traceback, textwrap.dedent("""\ + self.assertEqual(len(unique_errors), 1) + self.assertMultiLineEqual(unique_errors[0]._traceback, textwrap.dedent(""" Called from (traceback): - line 1, in function1""")) + line 1, in function1""").lstrip()) @errors._error_name(_TEST_ERROR) def test_unique_errors(self): @@ -248,7 +248,7 @@ def test_unique_errors(self): errorlog.error([backframe2, current_frame], "error") # Keep both errors, since the tracebacks are different. unique_errors = errorlog.unique_sorted_errors() - self.assertEqual(2, len(unique_errors)) + self.assertEqual(len(unique_errors), 2) self.assertSetEqual(set(errorlog), set(unique_errors)) diff --git a/pytype/load_pytd_test.py b/pytype/load_pytd_test.py index 01e63393b..36d20a6e4 100644 --- a/pytype/load_pytd_test.py +++ b/pytype/load_pytd_test.py @@ -415,10 +415,10 @@ def testStarImport(self): loaded_ast = self._LoadPickledModule(d, bar) loaded_ast.Visit(visitors.VerifyLookup()) self.assertMultiLineEqual(pytd_utils.Print(loaded_ast), - textwrap.dedent("""\ + textwrap.dedent(""" import foo - bar.A = foo.A""")) + bar.A = foo.A""").lstrip()) def testFunctionAlias(self): with file_utils.Tempdir() as d: @@ -482,7 +482,7 @@ def testPython3Builtins(self): # Test that we read python3 builtins from builtin.pytd if we pass a (3, 6) # version to the loader. with file_utils.Tempdir() as d: - d.create_file("a.pyi", """\ + d.create_file("a.pyi", """ from typing import AsyncGenerator class A(AsyncGenerator[str]): ...""") loader = load_pytd.Loader("base", diff --git a/pytype/matcher_test.py b/pytype/matcher_test.py index e2e508298..f3f6708a2 100644 --- a/pytype/matcher_test.py +++ b/pytype/matcher_test.py @@ -302,7 +302,7 @@ def testPyTDFunctionAgainstCallableBadArgType(self): self.assertNoMatch(f, callable_bad_arg2) def testBoundPyTDFunctionAgainstCallable(self): - instance = self._convert("""\ + instance = self._convert(""" class A(object): def f(self, x: int) -> bool: ... """, "A", as_instance=True) @@ -389,7 +389,7 @@ def testAnyStrInstanceAgainstAnyStr(self): def testProtocol(self): left1 = self._convert_type("str", as_instance=True) - left2 = self._convert("""\ + left2 = self._convert(""" class A(object): def lower(self) : ... """, "A", as_instance=True) @@ -401,7 +401,7 @@ def lower(self) : ... def testProtocolIterator(self): left1 = self._convert_type("Iterator", as_instance=True) - left2 = self._convert("""\ + left2 = self._convert(""" class A(object): def next(self): ... def __iter__(self): ... @@ -414,7 +414,7 @@ def __iter__(self): ... def testProtocolSequence(self): left1 = self._convert_type("list", as_instance=True) - left2 = self._convert("""\ + left2 = self._convert(""" class A(object): def __getitem__(self, i) : ... def __len__(self): ... @@ -427,7 +427,7 @@ def __len__(self): ... @unittest.skip("Needs to be fixed, tries to match protocol against A") def testParameterizedProtocol(self): - left1 = self._convert("""\ + left1 = self._convert(""" from typing import Iterator class A(object): def __iter__(self) -> Iterator[int] : ... diff --git a/pytype/pyi/lexer_test.py b/pytype/pyi/lexer_test.py index 701064c23..3d8390800 100644 --- a/pytype/pyi/lexer_test.py +++ b/pytype/pyi/lexer_test.py @@ -6,9 +6,6 @@ import unittest -# We use '\' to make test code more readable: -# pylint: disable=g-backslash-continuation - # Map from token code to name. TOKEN_NAMES = {code: name for name, code in parser_ext.TOKENS.items()} @@ -160,44 +157,44 @@ def test_triplequoted(self): ("TRIPLEQUOTED", None, 1, 3, 3, 5), ("NUMBER", 2, 4), ("TRIPLEQUOTED", None, 4, 3, 4, 58), - ("NUMBER", 3, 5)], """\ + ("NUMBER", 3, 5)], """ 1 ''' one quote is allowed ' newlines and two quotes are allowed '', end on next line ''' 2 '''this shoulnd't be swallowed by the previous string''' - 3""") + 3""".lstrip("\n")) # Double quotes. - # pylint: disable=g-inconsistent-quotes,g-backslash-continuation + # pylint: disable=g-inconsistent-quotes self.check([ ("NUMBER", 1, 1), ("TRIPLEQUOTED", None, 1, 3, 3, 5), ("NUMBER", 2, 4), ("TRIPLEQUOTED", None, 4, 3, 4, 58), - ("NUMBER", 3, 5)], '''\ + ("NUMBER", 3, 5)], ''' 1 """ one quote is allowed " newlines and two quotes are allowed "", end on next line """ 2 """this shoulnd't be swallowed by the previous string""" - 3''') + 3'''.lstrip("\n")) def test_typecomment(self): - self.check([1, "TYPECOMMENT", 2, "TYPECOMMENT", 3, "TYPECOMMENT", 4], """\ + self.check([1, "TYPECOMMENT", 2, "TYPECOMMENT", 3, "TYPECOMMENT", 4], """ 1 # type: 2 #type: 3 # type: 4""") def test_comments_are_ignored(self): - self.check([("NUMBER", 1, 1), ("NUMBER", 2, 5)], """\ + self.check([("NUMBER", 1, 1), ("NUMBER", 2, 5)], """ 1 # comment until end of line # type not quite a type comment, no colon! # # The preceding line had a # followed immediately by newline. - 2""") + 2""".lstrip("\n")) def test_indent(self): self.check( [1, "INDENT", 2, "INDENT", 3, "INDENT", 4, "DEDENT", "DEDENT", 5, - "DEDENT", 6], """\ + "DEDENT", 6], """ 1 2 3 @@ -207,7 +204,7 @@ def test_indent(self): def test_indent_ignore_blank_line2(self): self.check( - [1, "INDENT", 2, 3, "DEDENT"], """\ + [1, "INDENT", 2, 3, "DEDENT"], """ 1 2 @@ -216,14 +213,14 @@ def test_indent_ignore_blank_line2(self): def test_indent_dedents_at_eof(self): self.check( - [1, "INDENT", 2, "INDENT", 3, "DEDENT", "DEDENT"], """\ + [1, "INDENT", 2, "INDENT", 3, "DEDENT", "DEDENT"], """ 1 2 3""") def test_indent_not_inside_brackets(self): self.check( - [1, "[", 2, "[", "]", 3, "]", 4, "INDENT", 5, "DEDENT"], """\ + [1, "[", 2, "[", "]", 3, "]", 4, "INDENT", 5, "DEDENT"], """ 1 [2 [ ] 3] 4 @@ -231,7 +228,7 @@ def test_indent_not_inside_brackets(self): def test_indent_not_inside_parens(self): self.check( - [1, "(", 2, "(", ")", 3, ")", 4, "INDENT", 5, "DEDENT"], """\ + [1, "(", 2, "(", ")", 3, ")", 4, "INDENT", 5, "DEDENT"], """ 1 (2 ( ) 3) 4 @@ -240,7 +237,7 @@ def test_indent_not_inside_parens(self): def test_indent_legacy_bug(self): # The legacy lexer was not properly handling 3 dedents in a row. self.check([1, "INDENT", 2, "INDENT", 3, "INDENT", 4, "DEDENT", "DEDENT", - "DEDENT", 99], """\ + "DEDENT", 99], """ 1 2 3 @@ -250,7 +247,7 @@ def test_indent_legacy_bug(self): def test_indent_mismatch(self): self.check([1, "INDENT", 2, ("LEXERROR", "Invalid indentation"), 3, - "DEDENT"], """\ + "DEDENT"], """ 1 2 3""") @@ -268,15 +265,15 @@ def test_column(self): "INDENT", ("NAME", "hello", 2, 3, 2, 7), ("NAME", "goodbye", 4, 3, 4, 9), - "DEDENT"], """\ + "DEDENT"], """ foo bar hello goodbye - """) + """.lstrip("\n")) def test_ignore_comment_indentation(self): - self.check([1, "TYPECOMMENT", 2, 3], """\ + self.check([1, "TYPECOMMENT", 2, 3], """ 1 # comment 0 # type: 2 diff --git a/pytype/pyi/parser_memleak_test.py b/pytype/pyi/parser_memleak_test.py index 98091df62..e9c658ba0 100644 --- a/pytype/pyi/parser_memleak_test.py +++ b/pytype/pyi/parser_memleak_test.py @@ -65,19 +65,19 @@ def test_builtins(self): self.check(get_builtins_source(self.PYTHON_VERSION)) def test_error_in_class(self): - self.check("""\ + self.check(""" class Foo: def m(): pass an error""") def test_error_in_function(self): - self.check("""\ + self.check(""" def m(): pass def n(x: int, y: str) -> -> """) def test_error_within_if(self): - self.check("""\ + self.check(""" if sys.version_info == (1, 2, 3): x = ... # type: int this is an error diff --git a/pytype/pyi/parser_test.py b/pytype/pyi/parser_test.py index 1af3b7e03..4a045888d 100644 --- a/pytype/pyi/parser_test.py +++ b/pytype/pyi/parser_test.py @@ -11,9 +11,6 @@ import unittest -# We use backslashes to avoid unwanted newlines in test code. -# pylint: disable=g-backslash-continuation - IGNORE = object() @@ -51,12 +48,15 @@ def check(self, src, expected=None, prologue=None, name=None, The parsed pytd.TypeDeclUnit. """ version = version or self.PYTHON_VERSION - src = textwrap.dedent(src) + src = textwrap.dedent(src).lstrip() ast = parser.parse_string(src, name=name, python_version=version, platform=platform) actual = pytd_utils.Print(ast) if expected != IGNORE: - expected = src if expected is None else textwrap.dedent(expected) + if expected is None: + expected = src + else: + expected = textwrap.dedent(expected).lstrip() if prologue: expected = "%s\n\n%s" % (textwrap.dedent(prologue), expected) # Allow blank lines at the end of `expected` for prettier tests. @@ -66,7 +66,7 @@ def check(self, src, expected=None, prologue=None, name=None, def check_error(self, src, expected_line, message): """Check that parsing the src raises the expected error.""" with self.assertRaises(parser.ParseError) as e: - parser.parse_string(textwrap.dedent(src), + parser.parse_string(textwrap.dedent(src).lstrip(), python_version=self.PYTHON_VERSION) six.assertRegex(self, utils.message(e.exception), re.escape(message)) self.assertEqual(expected_line, e.exception.line) @@ -76,14 +76,14 @@ class ParseErrorTest(unittest.TestCase): def check(self, expected, *args, **kwargs): e = parser.ParseError(*args, **kwargs) - self.assertMultiLineEqual(textwrap.dedent(expected), str(e)) + self.assertMultiLineEqual(textwrap.dedent(expected).lstrip("\n"), str(e)) def test_plain_error(self): - self.check("""\ + self.check(""" ParseError: my message""", "my message") def test_full_error(self): - self.check("""\ + self.check(""" File: "foo.py", line 123 this is a test ^ @@ -91,7 +91,7 @@ def test_full_error(self): text="this is a test", column=6) def test_indented_text(self): - self.check("""\ + self.check(""" File: "foo.py", line 123 this is a test ^ @@ -99,22 +99,21 @@ def test_indented_text(self): text=" this is a test", column=16) def test_line_without_filename(self): - self.check("""\ + self.check(""" File: "None", line 1 ParseError: my message""", "my message", line=1) def test_filename_without_line(self): - self.check("""\ + self.check(""" File: "foo.py", line None ParseError: my message""", "my message", filename="foo.py") def test_text_without_column(self): - self.check("""\ + self.check(""" ParseError: my message""", "my message", text="this is a test") def test_column_without_text(self): - self.check("""\ - ParseError: my message""", "my message", column=5) + self.check(" ParseError: my message", "my message", column=5) class ParserTest(_ParserTestBase): @@ -126,7 +125,7 @@ def test_illegal_character(self): self.check_error("^", 1, "Illegal character '^'") def test_invalid_indentation(self): - self.check_error("""\ + self.check_error(""" class Foo: x = ... # type: int y""", 3, "Invalid indentation") @@ -134,10 +133,10 @@ class Foo: def test_type_on_next_line(self): # TODO(dbaum): This probably should be an error. Current behavior matches # legacy parser. Consider changing to an error. - self.check("""\ + self.check(""" a = ... # type: int""", - """\ + """ a: int""") def test_constant(self): @@ -145,10 +144,10 @@ def test_constant(self): self.check("x: str") self.check("x = 0", "x: int") self.check("x = 0.0", "x: float") - self.check_error("\nx = 123", 2, + self.check_error("x = 123", 1, "Only '0' allowed as int literal") self.check("x = 0.0", "x: float") - self.check_error("\nx = 12.3", 2, + self.check_error("x = 12.3", 1, "Only '0.0' allowed as float literal") def test_string_constant(self): @@ -173,17 +172,17 @@ def test_alias_or_constant(self): self.check("x = True", "x: bool") self.check("x = False", "x: bool") self.check("x = Foo") - self.check("""\ + self.check(""" class A: - x = True""", """\ + x = True""", """ class A: x: bool """) - self.check("""\ + self.check(""" class A: x = ... # type: int y = x - z = y""", """\ + z = y""", """ class A: x: int y: int @@ -191,7 +190,7 @@ class A: """) def test_method_aliases(self): - self.check("""\ + self.check(""" class A: def x(self) -> int y = x @@ -199,7 +198,7 @@ def x(self) -> int @classmethod def a(cls) -> str b = a - c = b""", """\ + c = b""", """ class A: def x(self) -> int: ... @classmethod @@ -213,49 +212,49 @@ def c(cls) -> str: ... """) def test_slots(self): - self.check("""\ + self.check(""" class A: __slots__ = ... # type: tuple - """, """\ + """, """ class A: ... """) - self.check("""\ + self.check(""" class A: __slots__ = ["foo", "bar", "baz"] """) - self.check("""\ + self.check(""" class A: __slots__ = [] """) - self.check_error("""\ + self.check_error(""" __slots__ = ["foo", "bar"] """, 1, "__slots__ only allowed on the class level") - self.check_error("""\ + self.check_error(""" class A: __slots__ = ["foo", "bar"] __slots__ = ["foo", "bar", "baz"] """, 1, "Duplicate __slots__ declaration") - self.check_error("""\ + self.check_error(""" class A: __slots__ = ["foo", ?] """, 2, "syntax error") - self.check_error("""\ + self.check_error(""" class A: __slots__ = int """, 2, "__slots__ must be a list of strings") def test_nested_class(self): - self.check("""\ + self.check(""" class A: class B: ... """) def test_nested_class_alias(self): - self.check("""\ + self.check(""" class A: class B: ... C = A.B - """, """\ + """, """ from typing import Type class A: @@ -264,11 +263,11 @@ class B: ... """) def test_nested_class_module_alias(self): - self.check("""\ + self.check(""" class A: class B: ... C = A.B - """, """\ + """, """ from typing import Type C: Type[A.B] @@ -278,7 +277,7 @@ class B: ... """) def test_conditional_nested_class(self): - self.check("""\ + self.check(""" if sys.version_info >= (3, 6): class A: class B: ... @@ -305,37 +304,37 @@ def test_from_import(self): self.assertEqual(parent, pytd.NamedType("foo.c.X")) def test_duplicate_names(self): - self.check_error("""\ + self.check_error(""" def foo() -> int: ... foo = ... # type: int""", None, "Duplicate top-level identifier(s): foo") - self.check_error("""\ + self.check_error(""" from x import foo def foo() -> int: ...""", None, "Duplicate top-level identifier(s): foo") - self.check_error("""\ + self.check_error(""" X = ... # type: int class X: ...""", None, "Duplicate top-level identifier(s): X") - self.check_error("""\ + self.check_error(""" X = ... # type: int X = TypeVar('X')""", None, "Duplicate top-level identifier(s): X") # A function is allowed to appear multiple times. - self.check("""\ + self.check(""" def foo(x: int) -> int: ... def foo(x: str) -> str: ...""", - """\ + """ @overload def foo(x: int) -> int: ... @overload def foo(x: str) -> str: ...""") # @overload decorators should be properly round-tripped. - self.check("""\ + self.check(""" @overload def foo(x: int) -> int: ... @overload @@ -348,11 +347,11 @@ def test_type(self): self.check("x = ... # type: ?", "x: Any", prologue="from typing import Any") self.check("x: nothing") - self.check("x = ... # type: int or str or float", """\ + self.check("x = ... # type: int or str or float", """ from typing import Union x: Union[int, str, float]""") - self.check("x = ... # type: int and str and float", """\ + self.check("x = ... # type: int and str and float", """ x: int and str and float""") def test_empty_union_or_intersection_or_optional(self): @@ -368,10 +367,10 @@ def test_optional_extra_parameters(self): "Too many options to typing.Optional") def test_alias_lookup(self): - self.check("""\ + self.check(""" from somewhere import Foo x = ... # type: Foo - """, """\ + """, """ import somewhere from somewhere import Foo @@ -379,7 +378,7 @@ def test_alias_lookup(self): x: somewhere.Foo""") def test_type_params(self): - ast = self.check("""\ + ast = self.check(""" from typing import TypeVar T = TypeVar('T') @@ -403,44 +402,44 @@ def func(x: T) -> T: ...""") "Unrecognized keyword") def test_type_param_arguments(self): - self.check("""\ + self.check(""" from typing import List, TypeVar T = TypeVar('T', List[int], List[str])""") - self.check("""\ + self.check(""" from typing import List, TypeVar T = TypeVar('T', bound=List[str])""") # 'covariant' and 'contravariant' are ignored for now. - self.check("""\ + self.check(""" from typing import TypeVar - T = TypeVar('T', str, unicode, covariant=True)""", """\ + T = TypeVar('T', str, unicode, covariant=True)""", """ from typing import TypeVar T = TypeVar('T', str, unicode)""") - self.check("""\ + self.check(""" import other_mod from typing import TypeVar T = TypeVar('T', other_mod.A, other_mod.B)""") def test_error_formatting(self): - src = """\ + src = """ class Foo: this is not valid""" with self.assertRaises(parser.ParseError) as e: - parser.parse_string(textwrap.dedent(src), filename="foo.py", + parser.parse_string(textwrap.dedent(src).lstrip(), filename="foo.py", python_version=self.PYTHON_VERSION) - self.assertMultiLineEqual(textwrap.dedent("""\ + self.assertMultiLineEqual(textwrap.dedent(""" File: "foo.py", line 2 this is not valid ^ - ParseError: syntax error, unexpected NAME, expecting ':' or '='""" - ), str(e.exception)) + ParseError: syntax error, unexpected NAME, expecting ':' or '=' + """).strip("\n"), str(e.exception)) def test_pep484_translations(self): - ast = self.check("""\ + ast = self.check(""" x: None""") self.assertEqual(pytd.NamedType("NoneType"), ast.constants[0].type) @@ -466,7 +465,7 @@ def test_pep84_aliasing(self): name="typing") def test_module_class_clash(self): - ast = parser.parse_string(textwrap.dedent("""\ + ast = parser.parse_string(textwrap.dedent(""" from bar import X class bar: X = ... # type: ? @@ -477,7 +476,7 @@ class bar: self.assertEqual("bar.X.Baz", ast.Lookup("foo.z").type.name) def test_trailing_list_comma(self): - self.check("""\ + self.check(""" from typing import Any, Callable x: Callable[ @@ -487,7 +486,7 @@ def test_trailing_list_comma(self): ], Any, ] - """, """\ + """, """ from typing import Any, Callable x: Callable[[int, int], Any] @@ -497,47 +496,47 @@ def test_trailing_list_comma(self): class HomogeneousTypeTest(_ParserTestBase): def test_callable_parameters(self): - self.check("""\ + self.check(""" from typing import Callable x: Callable[[int, str], bool]""") - self.check("""\ + self.check(""" from typing import Callable - x = ... # type: Callable[..., bool]""", """\ + x = ... # type: Callable[..., bool]""", """ from typing import Any, Callable x: Callable[Any, bool]""") - self.check("""\ + self.check(""" from typing import Any, Callable x: Callable[Any, bool]""") - self.check("""\ + self.check(""" from typing import Any, Callable x: Callable[[Any], bool]""") - self.check("""\ + self.check(""" from typing import Callable x: Callable[[], bool]""") - self.check("""\ + self.check(""" from typing import Callable - x = ... # type: Callable[[nothing], bool]""", """\ + x = ... # type: Callable[[nothing], bool]""", """ from typing import Callable x: Callable[[], bool]""") - self.check("""\ + self.check(""" from typing import Callable - x = ... # type: Callable[[int]]""", """\ + x = ... # type: Callable[[int]]""", """ from typing import Any, Callable x: Callable[[int], Any]""") - self.check("""\ + self.check(""" from typing import Callable - x = ... # type: Callable[[], ...]""", """\ + x = ... # type: Callable[[], ...]""", """ from typing import Any, Callable x: Callable[[], Any]""") @@ -562,29 +561,29 @@ def test_ellipsis(self): "from typing import Tuple\n\nx: Tuple[int, ...]") def test_tuple(self): - self.check("""\ + self.check(""" from typing import Tuple x = ... # type: Tuple[int, str]""", - """\ + """ from typing import Tuple x: Tuple[int, str]""") - self.check("""\ + self.check(""" from typing import Tuple x = ... # type: Tuple[int, str, ...]""", - """\ + """ from typing import Any, Tuple x: Tuple[int, str, Any]""") def test_empty_tuple(self): - self.check("""\ + self.check(""" from typing import Tuple def f() -> Tuple[()]: ... - """, """\ + """, """ from typing import Tuple def f() -> Tuple[nothing, ...]: ... @@ -607,7 +606,7 @@ def test_type_tuple(self): class NamedTupleTest(_ParserTestBase): def test_no_fields(self): - self.check("x = ... # type: NamedTuple('foo', [])", """\ + self.check("x = ... # type: NamedTuple('foo', [])", """ from typing import Any, Tuple, Type, TypeVar x: `namedtuple-foo-0` @@ -628,7 +627,7 @@ def __init__(self, *args, **kwargs) -> None: ... """) def test_multiple_fields(self): - expected = """\ + expected = """ from typing import Any, Tuple, Type, TypeVar x: `namedtuple-foo-0` @@ -658,10 +657,10 @@ def __init__(self, *args, **kwargs) -> None: ... def test_dedup_basename(self): # pylint: disable=line-too-long - self.check("""\ + self.check(""" x = ... # type: NamedTuple('foo', [('a', int,)]) y = ... # type: NamedTuple('foo', [('b', str,)])""", - """\ + """ from typing import Any, Tuple, Type, TypeVar x: `namedtuple-foo-0` @@ -698,7 +697,7 @@ def __init__(self, *args, **kwargs) -> None: ... """) def test_assign_namedtuple(self): - self.check("X = NamedTuple('X', [])", """\ + self.check("X = NamedTuple('X', [])", """ from typing import Any, Tuple, Type, TypeVar X = `namedtuple-X-0` @@ -719,7 +718,7 @@ def __init__(self, *args, **kwargs) -> None: ... """) def test_subclass_namedtuple(self): - self.check("class X(NamedTuple('X', [])): ...", """\ + self.check("class X(NamedTuple('X', [])): ...", """ from typing import Any, Tuple, Type, TypeVar _Tnamedtuple-X-0 = TypeVar('_Tnamedtuple-X-0', bound=`namedtuple-X-0`) @@ -740,7 +739,7 @@ class X(`namedtuple-X-0`): ... """) def test_trailing_comma(self): - self.check("""\ + self.check(""" from typing import NamedTuple Foo = NamedTuple( "Foo", @@ -749,7 +748,7 @@ def test_trailing_comma(self): ("b", str), ], ) - """, """\ + """, """ from typing import Any, Tuple, Type, TypeVar Foo = `namedtuple-Foo-0` @@ -772,7 +771,7 @@ def __init__(self, *args, **kwargs) -> None: ... """) def test_collections_trailing_comma(self): - self.check("""\ + self.check(""" from collections import namedtuple Foo = namedtuple( "Foo", @@ -781,7 +780,7 @@ def test_collections_trailing_comma(self): "b", ], ) - """, """\ + """, """ from typing import Any, Tuple, Type, TypeVar from collections import namedtuple @@ -805,7 +804,7 @@ def __init__(self, *args, **kwargs) -> None: ... """) def test_collections_namedtuple(self): - expected = """\ + expected = """ from typing import Any, Tuple, Type, TypeVar from collections import namedtuple @@ -841,7 +840,7 @@ def test_typing_namedtuple_class(self): class X(NamedTuple): y: int z: str - """, """\ + """, """ from typing import Any, Tuple, Type, TypeVar _Tnamedtuple-X-0 = TypeVar('_Tnamedtuple-X-0', bound=`namedtuple-X-0`) @@ -870,7 +869,7 @@ class X(NamedTuple): y: int z: str def foo(self) -> None: ... - """, """\ + """, """ from typing import Any, Tuple, Type, TypeVar _Tnamedtuple-X-0 = TypeVar('_Tnamedtuple-X-0', bound=`namedtuple-X-0`) @@ -899,7 +898,7 @@ def test_typing_namedtuple_class_multi_inheritance(self): class X(dict, NamedTuple): y: int z: str - """, """\ + """, """ from typing import Any, Tuple, Type, TypeVar _Tnamedtuple-X-0 = TypeVar('_Tnamedtuple-X-0', bound=`namedtuple-X-0`) @@ -922,7 +921,7 @@ class X(dict, `namedtuple-X-0`): ... """) def test_multi_namedtuple_parent(self): - self.check_error("""\ + self.check_error(""" from typing import NamedTuple class X(NamedTuple, NamedTuple): ... """, 2, "cannot inherit from bare NamedTuple more than once") @@ -990,28 +989,28 @@ def test_typeignore(self): "def foo() -> int: ...") self.check("def foo(x) -> int: # type: ignore\n x=List[int]", "def foo(x) -> int:\n x = List[int]") - self.check("""\ + self.check(""" def foo(x: int, # type: ignore y: str) -> bool: ...""", "def foo(x: int, y: str) -> bool: ...") - self.check("""\ + self.check(""" class Foo: bar: str # type: ignore - """, """\ + """, """ class Foo: bar: str """) - self.check("""\ + self.check(""" class Foo: bar = ... # type: str # type: ignore - """, """\ + """, """ class Foo: bar: str """) - self.check("""\ + self.check(""" class Foo: bar: str = ... # type: ignore - """, """\ + """, """ class Foo: bar: str """) @@ -1021,65 +1020,65 @@ def test_decorators(self): # make sense for methods of classes. But this at least gives us some # coverage of the decorator logic. More sensible tests can be created once # classes are implemented. - self.check("""\ + self.check(""" @overload def foo() -> int: ...""", - """\ + """ def foo() -> int: ...""") # Accept and disregard type: ignore comments on a decorator - self.check("""\ + self.check(""" @overload def foo() -> int: ... @overload # type: ignore # unsupported signature def foo(bool) -> int: ...""", - """\ + """ @overload def foo() -> int: ... @overload def foo(bool) -> int: ...""") - self.check("""\ + self.check(""" @abstractmethod def foo() -> int: ...""", - """\ + """ @abstractmethod def foo() -> int: ...""") - self.check("""\ + self.check(""" @abc.abstractmethod def foo() -> int: ...""", - """\ + """ @abstractmethod def foo() -> int: ...""") - self.check("""\ + self.check(""" @staticmethod def foo() -> int: ...""") - self.check("""\ + self.check(""" @classmethod def foo() -> int: ...""") - self.check("""\ + self.check(""" @coroutine def foo() -> int: ...""") - self.check("""\ + self.check(""" @asyncio.coroutine def foo() -> int: ...""", - """\ + """ @coroutine def foo() -> int: ...""") - self.check("""\ + self.check(""" @asyncio.coroutine def foo() -> int: ... @coroutines.coroutine def foo() -> int: ... @coroutine def foo() -> str: ...""", - """\ + """ @coroutine @overload def foo() -> int: ... @@ -1090,7 +1089,7 @@ def foo() -> int: ... @overload def foo() -> str: ...""") - self.check_error("""\ + self.check_error(""" def foo() -> str: ... @coroutine def foo() -> int: ...""", @@ -1098,19 +1097,19 @@ def foo() -> int: ...""", "Overloaded signatures for foo disagree on " "coroutine decorators") - self.check_error("""\ + self.check_error(""" @property def foo(self) -> int""", None, "Module-level functions with property decorators: foo") - self.check_error("""\ + self.check_error(""" @foo.setter def foo(self, x) -> int: ...""", None, "Module-level functions with property decorators: foo") - self.check_error("""\ + self.check_error(""" @classmethod @staticmethod def foo() -> int: ...""", @@ -1118,21 +1117,21 @@ def foo() -> int: ...""", "Too many decorators for foo") def test_type_check_only(self): - self.check("""\ + self.check(""" from typing import type_check_only @type_check_only def f() -> None: ... """, "def f() -> None: ...") def test_type_check_only_class(self): - self.check("""\ + self.check(""" from typing import type_check_only @type_check_only class Foo: ... """, "class Foo: ...") def test_bad_decorated_class(self): - self.check_error("""\ + self.check_error(""" @classmethod class Foo: ... """, 2, "Unsupported class decorators: classmethod") @@ -1143,46 +1142,46 @@ def test_empty_body(self): "def foo() -> int: ...") self.check("def foo() -> int: pass", "def foo() -> int: ...") - self.check("""\ + self.check(""" def foo() -> int: ...""", - """\ + """ def foo() -> int: ...""") - self.check("""\ + self.check(""" def foo() -> int: pass""", - """\ + """ def foo() -> int: ...""") - self.check("""\ + self.check(""" def foo() -> int: '''doc string'''""", - """\ + """ def foo() -> int: ...""") def test_mutators(self): # Mutators. - self.check("""\ + self.check(""" def foo(x) -> int: x = int""") - self.check_error("""\ + self.check_error(""" def foo(x) -> int: y = int""", 1, "No parameter named y") def test_exceptions(self): - self.check("""\ + self.check(""" def foo(x) -> int: raise Error""", - """\ + """ def foo(x) -> int: raise Error()""") - self.check("""\ + self.check(""" def foo(x) -> int: raise Error()""") - self.check("""\ + self.check(""" def foo() -> int: raise RuntimeError() raise TypeError()""") - self.check("""\ + self.check(""" def foo() -> int: raise Bar.Error()""", prologue="import Bar") @@ -1201,83 +1200,83 @@ def test_async(self): class ClassTest(_ParserTestBase): def test_no_parents(self): - canonical = """\ + canonical = """ class Foo: ... """ self.check(canonical, canonical) - self.check("""\ + self.check(""" class Foo(): pass """, canonical) def test_parents(self): - self.check("""\ + self.check(""" class Foo(Bar): ... """) - self.check("""\ + self.check(""" class Foo(Bar, Baz): ... """) def test_parent_remove_nothingtype(self): - self.check("""\ + self.check(""" class Foo(nothing): ... - """, """\ + """, """ class Foo: ... """) - self.check("""\ + self.check(""" class Foo(Bar, nothing): ... - """, """\ + """, """ class Foo(Bar): ... """) def test_class_type_ignore(self): - canonical = """\ + canonical = """ class Foo: # type: ignore pass class Bar(Foo): # type: ignore pass """ - self.check(canonical, """\ + self.check(canonical, """ class Foo: ... class Bar(Foo): ... """) def test_metaclass(self): - self.check("""\ + self.check(""" class Foo(metaclass=Meta): ... """) - self.check("""\ + self.check(""" class Foo(Bar, metaclass=Meta): ... """) - self.check_error("""\ + self.check_error(""" class Foo(badkeyword=Meta): ... """, 1, "Only 'metaclass' allowed as classdef kwarg") - self.check_error("""\ + self.check_error(""" class Foo(metaclass=Meta, Bar): ... """, 1, "metaclass must be last argument") def test_shadow_pep484(self): - self.check("""\ + self.check(""" class List: def bar(self) -> List: ... """) def test_no_body(self): - canonical = """\ + canonical = """ class Foo: ... """ # There are numerous ways to indicate an empty body. self.check(canonical, canonical) - self.check("""\ + self.check(""" class Foo(): pass """, canonical) - self.check("""\ + self.check(""" class Foo(): pass """, canonical) - self.check("""\ + self.check(""" class Foo(): ... """, canonical) @@ -1292,49 +1291,49 @@ class Foo(): """docstring""" ''', canonical) # Accept type: ignore with empty body - self.check("""\ + self.check(""" class Foo: ... # type: ignore """, canonical) - self.check("""\ + self.check(""" class Foo: # type: ignore pass """, canonical) def test_attribute(self): - self.check("""\ + self.check(""" class Foo: a: int """) def test_method(self): - self.check("""\ + self.check(""" class Foo: def a(self, x: int) -> str: ... """) def test_property(self): - self.check("""\ + self.check(""" class Foo: @property def a(self) -> int - """, """\ + """, """ class Foo: a: int """) def test_duplicate_name(self): - self.check_error("""\ + self.check_error(""" class Foo: bar = ... # type: int bar = ... # type: str """, 1, "Duplicate identifier(s): bar") - self.check_error("""\ + self.check_error(""" class Foo: def bar(self) -> int: ... bar = ... # type: str """, 1, "Duplicate identifier(s): bar") # Multiple method defs are ok (needed for variant signatures). - self.check("""\ + self.check(""" class Foo: @overload def x(self) -> int: ... @@ -1343,20 +1342,20 @@ def x(self) -> str: ... """) def test_protocol_parent(self): - self.check("""\ + self.check(""" from typing import Protocol class Foo(Protocol): ... """) def test_parameterized_protocol_parent(self): - self.check("""\ + self.check(""" from typing import Protocol, TypeVar T = TypeVar('T') class Foo(Protocol[T]): ... - """, """\ + """, """ from typing import Generic, Protocol, TypeVar T = TypeVar('T') @@ -1365,7 +1364,7 @@ class Foo(Protocol, Generic[T]): ... """) def test_bad_typevar_in_mutation(self): - self.check_error("""\ + self.check_error(""" from typing import Generic, TypeVar S = TypeVar('S') @@ -1382,71 +1381,71 @@ def __init__(self, x: S): class IfTest(_ParserTestBase): def test_if_true(self): - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): x = ... # type: int - """, """\ + """, """ x: int""") def test_if_false(self): - self.check("""\ + self.check(""" if sys.version_info == (1, 2, 3): x = ... # type: int """, "") def test_else_used(self): - self.check("""\ + self.check(""" if sys.version_info == (1, 2, 3): x = ... # type: int else: y = ... # type: str - """, """\ + """, """ y: str""") def test_else_ignored(self): - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): x = ... # type: int else: y = ... # type: str - """, """\ + """, """ x: int""") def test_elif_used(self): - self.check("""\ + self.check(""" if sys.version_info == (1, 2, 3): x = ... # type: int elif sys.version_info == (2, 7, 6): y = ... # type: float else: z = ... # type: str - """, """\ + """, """ y: float""") def test_elif_preempted(self): - self.check("""\ + self.check(""" if sys.version_info > (1, 2, 3): x = ... # type: int elif sys.version_info == (2, 7, 6): y = ... # type: float else: z = ... # type: str - """, """\ + """, """ x: int""") def test_elif_ignored(self): - self.check("""\ + self.check(""" if sys.version_info == (1, 2, 3): x = ... # type: int elif sys.version_info == (4, 5, 6): y = ... # type: float else: z = ... # type: str - """, """\ + """, """ z: str""") def test_nested_if(self): - self.check("""\ + self.check(""" if sys.version_info >= (2, 0): if sys.platform == "linux": a = ... # type: int @@ -1460,7 +1459,7 @@ def test_nested_if(self): """, "a: int") def test_if_or(self): - self.check("""\ + self.check(""" if sys.version_info >= (2, 0) or sys.version_info < (0, 0, 0): a = ... # type: int if sys.version_info < (0, 0, 0) or sys.version_info >= (2, 0): @@ -1472,26 +1471,26 @@ def test_if_or(self): if (sys.platform == "windows" or sys.version_info < (0,) or sys.version_info >= (2, 7)): e = ... # type: int - """, """\ + """, """ a: int b: int d: int e: int""") def test_if_and(self): - self.check("""\ + self.check(""" if sys.version_info >= (2, 0) and sys.version_info < (3, 0): a = ... # type: int if sys.version_info >= (2, 0) and sys.version_info >= (3, 0): b = ... # type: int - """, """\ + """, """ a: int""") # The remaining tests verify that actions with side effects only take effect # within a true block. def test_conditional_import(self): - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): from foo import Processed else: @@ -1499,7 +1498,7 @@ def test_conditional_import(self): """, "from foo import Processed") def test_conditional_alias_or_constant(self): - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): x = Processed else: @@ -1507,12 +1506,12 @@ def test_conditional_alias_or_constant(self): """, "x = Processed") def test_conditional_class(self): - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): class Processed: ... else: class Ignored: ... - """, """\ + """, """ class Processed: ... """) @@ -1525,7 +1524,7 @@ def test_conditional_class_registration(self): # Dict should be registered, List should not be registered. Thus after # the "if" statement Dict refers to the local Dict class and List refers # to the PEP 484 list class. - self.check("""\ + self.check(""" from typing import List if sys.version_info == (2, 7, 6): class Dict: ... @@ -1534,7 +1533,7 @@ class List: ... x = ... # type: Dict y = ... # type: List - """, """\ + """, """ x: Dict y: list @@ -1544,12 +1543,12 @@ class Dict: ... def test_conditional_typevar(self): # The legacy parser did not handle this correctly - typevars are added # regardless of any conditions. - self.check("""\ + self.check(""" if sys.version_info == (2, 7, 6): T = TypeVar('T') else: F = TypeVar('F') - """, """\ + """, """ from typing import TypeVar T = TypeVar('T')""") @@ -1564,7 +1563,7 @@ class ClassIfTest(_ParserTestBase): # etc). def test_conditional_constant(self): - self.check("""\ + self.check(""" class Foo: if sys.version_info == (2, 7, 0): x = ... # type: int @@ -1572,13 +1571,13 @@ class Foo: y = ... # type: str else: z = ... # type: float - """, """\ + """, """ class Foo: y: str """) def test_conditional_method(self): - self.check("""\ + self.check(""" class Foo: if sys.version_info == (2, 7, 0): def a(self, x: int) -> str: ... @@ -1586,47 +1585,47 @@ def a(self, x: int) -> str: ... def b(self, x: int) -> str: ... else: def c(self, x: int) -> str: ... - """, """\ + """, """ class Foo: def b(self, x: int) -> str: ... """) def test_nested(self): - self.check("""\ + self.check(""" class Foo: if sys.version_info > (2, 7, 0): if sys.version_info == (2, 7, 6): def b(self, x: int) -> str: ... - """, """\ + """, """ class Foo: def b(self, x: int) -> str: ... """) def test_no_import(self): - self.check_error("""\ + self.check_error(""" class Foo: if sys.version_info > (2, 7, 0): import foo """, 3, "syntax error") def test_bad_alias(self): - self.check_error("""\ + self.check_error(""" class Foo: if sys.version_info > (2, 7, 0): a = b """, 1, "Illegal value for alias 'a'") def test_no_class(self): - self.check("""\ + self.check(""" class Foo: if sys.version_info <= (2, 7, 0): class Bar: ... - """, """\ + """, """ class Foo: ... """) def test_no_typevar(self): - self.check_error("""\ + self.check_error(""" class Foo: if sys.version_info > (2, 7, 0): T = TypeVar('T') @@ -1637,13 +1636,13 @@ class ConditionTest(_ParserTestBase): def check_cond(self, condition, expected, **kwargs): out = "x: int" if expected else "" - self.check("""\ + self.check(""" if %s: x = ... # type: int """ % condition, out, **kwargs) def check_cond_error(self, condition, message): - self.check_error("""\ + self.check_error(""" if %s: x = ... # type: int """ % condition, 1, message) @@ -1772,7 +1771,7 @@ class PropertyDecoratorTest(_ParserTestBase): """Tests that cover _parse_signature_as_property().""" def test_property_with_type(self): - expected = """\ + expected = """ class A(object): name: str """ @@ -1788,7 +1787,7 @@ def name(self) -> str:... class A(object): @name.setter def name(self, value: str) -> None: ... - """, """\ + """, """ from typing import Any class A(object): @@ -1823,7 +1822,7 @@ def name(self, value: int) -> None: ... """, expected) def test_property_decorator_any_type(self): - expected = """\ + expected = """ from typing import Any class A(object): @@ -1862,32 +1861,32 @@ def test_property_decorator_bad_syntax(self): class A(object): @property def name(self, bad_arg): ... - """, 2, "Unhandled decorator: property") + """, 1, "Unhandled decorator: property") self.check_error(""" class A(object): @name.setter def name(self): ... - """, 2, "Unhandled decorator: name.setter") + """, 1, "Unhandled decorator: name.setter") self.check_error(""" class A(object): @name.foo def name(self): ... - """, 2, "Unhandled decorator: name.foo") + """, 1, "Unhandled decorator: name.foo") self.check_error(""" class A(object): @notname.deleter def name(self): ... - """, 2, "Unhandled decorator: notname.deleter") + """, 1, "Unhandled decorator: notname.deleter") self.check_error(""" class A(object): @property @staticmethod def name(self): ... - """, 5, "Too many decorators for name") + """, 4, "Too many decorators for name") self.check_error(""" @property @@ -1902,7 +1901,7 @@ def name(self) -> str: ... @name.getter def name(self) -> int: ... - """, """\ + """, """ from typing import Union class A(object): @@ -1917,7 +1916,7 @@ def test_property(self): class A(object): @property def name(self) -> str: ... - """, """\ + """, """ class A(object): name: str """) @@ -1930,7 +1929,7 @@ def name(self) -> str: ... @property def name(self) -> int: ... - """, """\ + """, """ from typing import Union class A(object): @@ -1944,7 +1943,7 @@ def name(self) -> str: ... @property def name(self): ... - """, """\ + """, """ from typing import Any class A(object): @@ -1952,16 +1951,16 @@ class A(object): """) def test_method(self): - self.check("""\ + self.check(""" class A(object): def name(self) -> str: ... """) def test_merged_method(self): - ast = self.check("""\ + ast = self.check(""" def foo(x: int) -> str: ... def foo(x: str) -> str: ...""", - """\ + """ @overload def foo(x: int) -> str: ... @overload @@ -1977,7 +1976,7 @@ class A(object): def name(self): ... def name(self): ... - """, 2, "Overloaded signatures for name disagree on decorators") + """, 1, "Overloaded signatures for name disagree on decorators") def test_overloaded_signatures_disagree(self): self.check_error(""" @@ -1986,10 +1985,10 @@ class A(object): def foo(x: int): ... @classmethod def foo(x: str): ... - """, 2, "Overloaded signatures for foo disagree on decorators") + """, 1, "Overloaded signatures for foo disagree on decorators") def test_classmethod(self): - ast = self.check("""\ + ast = self.check(""" class A(object): @classmethod def foo(x: int) -> str: ... @@ -1997,7 +1996,7 @@ def foo(x: int) -> str: ... self.assertEqual("classmethod", ast.classes[0].methods[0].kind) def test_staticmethod(self): - ast = self.check("""\ + ast = self.check(""" class A(object): @staticmethod def foo(x: int) -> str: ... @@ -2005,14 +2004,14 @@ def foo(x: int) -> str: ... self.assertEqual("staticmethod", ast.classes[0].methods[0].kind) def test_new(self): - ast = self.check("""\ + ast = self.check(""" class A(object): def __new__(self) -> A: ... """) self.assertEqual("staticmethod", ast.classes[0].methods[0].kind) def test_abstractmethod(self): - ast = self.check("""\ + ast = self.check(""" class A(object): @abstractmethod def foo(x: int) -> str: ... @@ -2021,7 +2020,7 @@ def foo(x: int) -> str: ... self.assertEqual(True, ast.Lookup("A").Lookup("foo").is_abstract) def test_abstractmethod_manysignatures(self): - ast = self.check("""\ + ast = self.check(""" class A(object): @abstractmethod def foo(x: int) -> str: ... @@ -2029,7 +2028,7 @@ def foo(x: int) -> str: ... def foo(x: int, y: int) -> str: ... @abstractmethod def foo(x: int, y: int, z: int) -> str: ... - """, """\ + """, """ class A(object): @abstractmethod @overload @@ -2045,7 +2044,7 @@ def foo(x: int, y: int, z: int) -> str: ... self.assertEqual(True, ast.Lookup("A").Lookup("foo").is_abstract) def test_abstractmethod_conflict(self): - self.check_error("""\ + self.check_error(""" class A(object): @abstractmethod def foo(x: int) -> str: ... @@ -2063,21 +2062,21 @@ def test_builtins(self): class AnyTest(_ParserTestBase): def test_generic_any(self): - self.check("""\ + self.check(""" from typing import Any x = ... # type: Any[int]""", - """\ + """ from typing import Any x: Any""") def test_generic_any_alias(self): - self.check("""\ + self.check(""" from typing import Any Foo = Any Bar = Foo[int] x = ... # type: Bar[int, str]""", - """\ + """ from typing import Any Foo = Any @@ -2094,13 +2093,14 @@ def testCanonicalVersion(self): def foo(x: int = 0) -> Any: ... def foo(x: str) -> Any: ... """) - expected = textwrap.dedent("""\ + expected = textwrap.dedent(""" from typing import Any @overload def foo(x: int = ...) -> Any: ... @overload - def foo(x: str) -> Any: ...""") + def foo(x: str) -> Any: ... + """).strip() self.assertMultiLineEqual( parser.canonical_pyi(src, self.PYTHON_VERSION), expected) @@ -2108,13 +2108,13 @@ def foo(x: str) -> Any: ...""") class TypeMacroTest(_ParserTestBase): def test_simple(self): - self.check("""\ + self.check(""" from typing import List, TypeVar Alias = List[List[T]] T = TypeVar('T') S = TypeVar('S') def f(x: Alias[S]) -> S: ... - def g(x: Alias[str]) -> str: ...""", """\ + def g(x: Alias[str]) -> str: ...""", """ from typing import List, TypeVar Alias = List[List[T]] @@ -2126,11 +2126,11 @@ def f(x: List[List[S]]) -> S: ... def g(x: List[List[str]]) -> str: ...""") def test_partial_replacement(self): - self.check("""\ + self.check(""" from typing import Dict, TypeVar DictAlias = Dict[int, V] V = TypeVar('V') - def f(x: DictAlias[str]) -> None: ...""", """\ + def f(x: DictAlias[str]) -> None: ...""", """ from typing import Dict, TypeVar DictAlias = Dict[int, V] @@ -2140,12 +2140,12 @@ def f(x: DictAlias[str]) -> None: ...""", """\ def f(x: Dict[int, str]) -> None: ...""") def test_multiple_parameters(self): - self.check("""\ + self.check(""" from typing import Dict, List, TypeVar Alias = List[Dict[K, V]] K = TypeVar('K') V = TypeVar('V') - def f(x: Alias[K, V]) -> Dict[K, V]: ...""", """\ + def f(x: Alias[K, V]) -> Dict[K, V]: ...""", """ from typing import Dict, List, TypeVar Alias = List[Dict[K, V]] @@ -2156,11 +2156,11 @@ def f(x: Alias[K, V]) -> Dict[K, V]: ...""", """\ def f(x: List[Dict[K, V]]) -> Dict[K, V]: ...""") def test_no_parameters(self): - self.check("""\ + self.check(""" from typing import List, TypeVar Alias = List[List[T]] T = TypeVar('T') - def f(x: Alias) -> None: ...""", """\ + def f(x: Alias) -> None: ...""", """ from typing import Any, List, TypeVar Alias = List[List[T]] @@ -2170,12 +2170,12 @@ def f(x: Alias) -> None: ...""", """\ def f(x: List[List[Any]]) -> None: ...""") def test_union(self): - self.check("""\ + self.check(""" from typing import List, TypeVar, Union Alias = Union[List[T], List[S]] T = TypeVar('T') S = TypeVar('S') - def f(x: Alias[S, T]) -> Union[S, T]: ...""", """\ + def f(x: Alias[S, T]) -> Union[S, T]: ...""", """ from typing import List, TypeVar, Union Alias = Union[List[T], List[S]] @@ -2186,11 +2186,11 @@ def f(x: Alias[S, T]) -> Union[S, T]: ...""", """\ def f(x: Union[List[S], List[T]]) -> Union[S, T]: ...""") def test_repeated_type_parameter(self): - self.check("""\ + self.check(""" from typing import Dict, TypeVar Alias = Dict[T, T] T = TypeVar('T') - def f(x: Alias[str]) -> None: ...""", """\ + def f(x: Alias[str]) -> None: ...""", """ from typing import Dict, TypeVar Alias = Dict[T, T] @@ -2200,7 +2200,7 @@ def f(x: Alias[str]) -> None: ...""", """\ def f(x: Dict[str, str]) -> None: ...""") def test_wrong_parameter_count(self): - self.check_error("""\ + self.check_error(""" from typing import List, TypeVar Alias = List[List[T]] T = TypeVar('T') @@ -2208,11 +2208,11 @@ def f(x: Alias[T, T]) -> T: ... """, 4, "List[List[T]] expected 1 parameters, got 2") def test_anystr(self): - self.check("""\ + self.check(""" from typing import AnyStr, List Alias = List[AnyStr] def f(x: Alias[str]) -> None: ... - """, """\ + """, """ from typing import AnyStr, List Alias = List[AnyStr] @@ -2227,7 +2227,7 @@ def test_import(self): self.check(""" import mod # type: ignore def f(x: mod.attr) -> None: ... - """, """\ + """, """ import mod def f(x: mod.attr) -> None: ...""") @@ -2263,7 +2263,7 @@ def f(x: attr) -> None: ... class LiteralTest(_ParserTestBase): def test_bool(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[False] @@ -2271,14 +2271,14 @@ def test_bool(self): """) def test_int(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[42] """) def test_string(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal["x"] @@ -2286,7 +2286,7 @@ def test_string(self): """) def test_bytestring(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[b""] @@ -2295,7 +2295,7 @@ def test_bytestring(self): """) def test_unicodestring(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[u""] @@ -2304,7 +2304,7 @@ def test_unicodestring(self): """) def test_none(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[None] @@ -2312,7 +2312,7 @@ def test_none(self): def test_enum(self): # TODO(b/123775699): support enums. - self.check("""\ + self.check(""" import enum from typing import Literal @@ -2320,7 +2320,7 @@ def test_enum(self): class Color(enum.Enum): RED: str - """, """\ + """, """ import enum from typing import Any @@ -2331,46 +2331,46 @@ class Color(enum.Enum): """) def test_multiple_parameters(self): - self.check("""\ + self.check(""" from typing import Literal x: Literal[True, 0, b"", u"", None] - """, """\ + """, """ from typing import Literal, Optional, Union x: Optional[Union[Literal[True], Literal[0], Literal[b""], Literal[u""]]] """) def test_stray_number(self): - self.check_error("""\ + self.check_error(""" from typing import Tuple x: Tuple[int, int, 0, int] """, 3, "Tuple[_, _, 0, _] not supported") def test_stray_string(self): - self.check_error("""\ + self.check_error(""" from typing import Tuple x: Tuple[str, str, '', str] """, 3, "Tuple[_, _, '', _] not supported") def test_stray_bytestring(self): - self.check_error("""\ + self.check_error(""" from typing import Tuple x: Tuple[str, b'', str, str] """, 3, "Tuple[_, b'', _, _] not supported") def test_stray_unicodestring(self): - self.check_error("""\ + self.check_error(""" from typing import Tuple x: Tuple[str, u'', str, str] """, 3, "Tuple[_, u'', _, _] not supported") def test_typing_extensions(self): - self.check("""\ + self.check(""" from typing_extensions import Literal x: Literal[42] diff --git a/pytype/pytd/optimize_test.py b/pytype/pytd/optimize_test.py index cb4438011..d3db843a4 100644 --- a/pytype/pytd/optimize_test.py +++ b/pytype/pytd/optimize_test.py @@ -769,10 +769,10 @@ class B(A): ast = visitors.LookupClasses(ast, self.builtins) ast = ast.Visit(optimize.AddInheritedMethods()) self.assertMultiLineEqual(pytd_utils.Print(ast.Lookup("B")), - textwrap.dedent("""\ + textwrap.dedent(""" class B(A): def f(self) -> float: ... - """)) + """).lstrip()) def testRemoveInheritedMethodsWithLateType(self): src = textwrap.dedent(""" diff --git a/pytype/pytd/pytd_utils_test.py b/pytype/pytd/pytd_utils_test.py index b6f336769..de2ca9bd6 100644 --- a/pytype/pytd/pytd_utils_test.py +++ b/pytype/pytd/pytd_utils_test.py @@ -445,12 +445,12 @@ def foo(a: str or int) -> C self.assertTrue(pytd_utils.ASTeq(tree2, tree2)) def testASTdiff(self): - src1 = textwrap.dedent("""\ + src1 = textwrap.dedent(""" a: int - b: str""") - src2 = textwrap.dedent("""\ + b: str""").lstrip() + src2 = textwrap.dedent(""" a: int - b: float""") + b: float""").lstrip() tree1 = parser.parse_string(src1, python_version=self.PYTHON_VERSION) tree2 = parser.parse_string(src2, python_version=self.PYTHON_VERSION) normalize = lambda diff: textwrap.dedent("\n".join(diff)) diff --git a/pytype/pytd/visitors_test.py b/pytype/pytd/visitors_test.py index 1401baa00..966ddf805 100644 --- a/pytype/pytd/visitors_test.py +++ b/pytype/pytd/visitors_test.py @@ -299,10 +299,11 @@ class A(object): ... ast2 = ast2.Visit(visitors.LookupExternalTypes( {"foo": ast1}, self_name=None)) self.assertEqual(name, ast2.name) - self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent("""\ + self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent(""" import foo - A = foo.A""")) + A = foo.A + """).strip()) def testLookupTwoStarAliases(self): src1 = "class A(object): ..." @@ -359,10 +360,11 @@ def testLookupTwoStarAliasesWithDefaultPyi(self): ast3 = self.Parse(src3).Replace(name="baz").Visit(visitors.AddNamePrefix()) ast3 = ast3.Visit(visitors.LookupExternalTypes( {"foo": ast1, "bar": ast2, "baz": ast3}, self_name="baz")) - self.assertMultiLineEqual(pytd_utils.Print(ast3), textwrap.dedent("""\ + self.assertMultiLineEqual(pytd_utils.Print(ast3), textwrap.dedent(""" from typing import Any - def baz.__getattr__(name) -> Any: ...""")) + def baz.__getattr__(name) -> Any: ... + """).strip()) def testLookupStarAliasWithDuplicateGetAttr(self): src1 = "def __getattr__(name) -> ?" @@ -374,10 +376,11 @@ def __getattr__(name) -> ? ast2 = self.Parse(src2).Replace(name="bar").Visit(visitors.AddNamePrefix()) ast2 = ast2.Visit(visitors.LookupExternalTypes( {"foo": ast1, "bar": ast2}, self_name="bar")) - self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent("""\ + self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent(""" from typing import Any - def bar.__getattr__(name) -> Any: ...""")) + def bar.__getattr__(name) -> Any: ... + """).strip()) def testLookupTwoStarAliasesWithDifferentGetAttrs(self): src1 = "def __getattr__(name) -> int" @@ -402,8 +405,9 @@ def __getattr__(name) -> str ast2 = self.Parse(src2).Replace(name="bar").Visit(visitors.AddNamePrefix()) ast2 = ast2.Visit(visitors.LookupExternalTypes( {"foo": ast1, "bar": ast2}, self_name="bar")) - self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent("""\ - def bar.__getattr__(name) -> str: ...""")) + self.assertMultiLineEqual(pytd_utils.Print(ast2), textwrap.dedent(""" + def bar.__getattr__(name) -> str: ... + """).strip()) def testCollectDependencies(self): src = textwrap.dedent(""" @@ -446,12 +450,13 @@ def testPrintImports(self): def f(x: Union[int, slice]) -> List[?]: ... def g(x: foo.C.C2) -> None: ... """) - expected = textwrap.dedent("""\ + expected = textwrap.dedent(""" import foo.C from typing import Any, List, Union def f(x: Union[int, slice]) -> List[Any]: ... - def g(x: foo.C.C2) -> None: ...""") + def g(x: foo.C.C2) -> None: ... + """).strip() tree = self.Parse(src) res = pytd_utils.Print(tree) self.AssertSourceEquals(res, src) @@ -712,7 +717,7 @@ class D: b: A.B def f(self, x: A.B) -> A.B: ... """) - expected = textwrap.dedent("""\ + expected = textwrap.dedent(""" from typing import Type foo.b: foo.A.B @@ -725,7 +730,8 @@ class foo.D: b: foo.A.B def f(self, x: foo.A.B) -> foo.A.B: ... - def foo.f(x: foo.A.B) -> foo.A.B: ...""") + def foo.f(x: foo.A.B) -> foo.A.B: ... + """).strip() self.assertMultiLineEqual(expected, pytd_utils.Print( self.Parse(src).Replace(name="foo").Visit(visitors.AddNamePrefix()))) @@ -735,10 +741,11 @@ class A: class B: def copy(self) -> A.B: ... """) - expected = textwrap.dedent("""\ + expected = textwrap.dedent(""" class foo.A: class foo.A.B: - def copy(self) -> foo.A.B: ...""") + def copy(self) -> foo.A.B: ... + """).strip() self.assertMultiLineEqual(expected, pytd_utils.Print( self.Parse(src).Replace(name="foo").Visit(visitors.AddNamePrefix()))) @@ -988,10 +995,10 @@ def testPrintTypeParameterBound(self): T = TypeVar("T", bound=str) """) self.assertMultiLineEqual(pytd_utils.Print(self.Parse(src)), - textwrap.dedent("""\ + textwrap.dedent(""" from typing import TypeVar - T = TypeVar('T', bound=str)""")) + T = TypeVar('T', bound=str)""").lstrip()) def testPrintCls(self): src = textwrap.dedent(""" @@ -1009,10 +1016,10 @@ def testPrintNoReturn(self): def f() -> nothing """) self.assertMultiLineEqual(pytd_utils.Print(self.Parse(src)), - textwrap.dedent("""\ + textwrap.dedent(""" from typing import NoReturn - def f() -> NoReturn: ...""")) + def f() -> NoReturn: ...""").lstrip()) def testPrintMultilineSignature(self): src = textwrap.dedent(""" @@ -1021,14 +1028,15 @@ def f(x: int, y: str, z: bool) -> list[str]: """) self.assertMultiLineEqual( pytd_utils.Print(self.Parse(src), multiline_args=True), - textwrap.dedent("""\ + textwrap.dedent(""" from typing import List def f( x: int, y: str, z: bool - ) -> List[str]: ...""")) + ) -> List[str]: ... + """).strip()) def testRenameBuiltinsPrefix(self): """builtins.foo should get rewritten to __builtin__.foo and then to foo.""" diff --git a/pytype/single_test.py b/pytype/single_test.py index ef06b31bd..a530ab92a 100644 --- a/pytype/single_test.py +++ b/pytype/single_test.py @@ -351,13 +351,13 @@ def testCheck(self): self._CheckTypesAndErrors("simple.py", []) def testReturnType(self): - self._CheckTypesAndErrors(self._MakePyFile("""\ + self._CheckTypesAndErrors(self._MakePyFile(""" def f() -> int: return "foo" """), ["bad-return-type"]) def testUsageError(self): - self._SetUpChecking(self._MakePyFile("""\ + self._SetUpChecking(self._MakePyFile(""" def f(): pass """)) @@ -368,7 +368,7 @@ def f(): self.assertOutputStateMatches(stdout=False, stderr=True, returncode=True) def testSkipFile(self): - filename = self._MakePyFile("""\ + filename = self._MakePyFile(""" # pytype: skip-file """) self.pytype_args[self._DataPath(filename)] = self.INCLUDE @@ -395,7 +395,7 @@ def testInferComplex(self): self.assertInferredPyiEquals(filename="complex.pyi") def testCheckMain(self): - self._SetUpChecking(self._MakePyFile("""\ + self._SetUpChecking(self._MakePyFile(""" def f(): name_error def g(): @@ -441,14 +441,14 @@ def testPytree(self): [c.name for c in ast.classes]) def testNoAnalyzeAnnotated(self): - filename = self._MakePyFile("""\ + filename = self._MakePyFile(""" def f() -> str: return 42 """) self._InferTypesAndCheckErrors(self._DataPath(filename), []) def testAnalyzeAnnotated(self): - filename = self._MakePyFile("""\ + filename = self._MakePyFile(""" def f() -> str: return 42 """) @@ -476,7 +476,7 @@ def testGenerateAndUseBuiltins(self): self._RunPytype(self.pytype_args) self.assertOutputStateMatches(stdout=False, stderr=False, returncode=False) self.assertTrue(os.path.isfile(filename)) - src = self._MakePyFile("""\ + src = self._MakePyFile(""" import __future__ import sys import collections @@ -499,7 +499,7 @@ def testUseBuiltinsAndImportMap(self): self.assertTrue(os.path.isfile(filename)) # input files canary = "import pytypecanary" if typeshed.Typeshed.MISSING_FILE else "" - src = self._MakePyFile("""\ + src = self._MakePyFile(""" import __future__ import sys import collections @@ -514,7 +514,7 @@ def testUseBuiltinsAndImportMap(self): y = csv.writer z = md5.new """ % canary) - pyi = self._MakeFile("""\ + pyi = self._MakeFile(""" import datetime x = ... # type: datetime.tzinfo """, extension=".pyi") @@ -522,7 +522,7 @@ def testUseBuiltinsAndImportMap(self): self._ResetPytypeArgs() self._SetUpChecking(src) self.pytype_args["--precompiled-builtins"] = filename - self.pytype_args["--imports_info"] = self._MakeFile("""\ + self.pytype_args["--imports_info"] = self._MakeFile(""" typing /dev/null foo %s """ % pyi, extension="") diff --git a/pytype/tests/py2/test_abc.py b/pytype/tests/py2/test_abc.py index 0b4dc280c..f58045301 100644 --- a/pytype/tests/py2/test_abc.py +++ b/pytype/tests/py2/test_abc.py @@ -7,7 +7,7 @@ class AbstractMethodTests(test_base.TargetPython27FeatureTest): """Tests for @abc.abstractmethod.""" def test_name_error(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import abc class Example(object): __metaclass__ = abc.ABCMeta @@ -17,7 +17,7 @@ def foo(self): """) def test_instantiate_abstract_class(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import abc class Example(object): __metaclass__ = abc.ABCMeta @@ -47,7 +47,7 @@ class Foo(X, Implementation): """) def test_multiple_inheritance_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import abc class X(object): pass diff --git a/pytype/tests/py2/test_attributes.py b/pytype/tests/py2/test_attributes.py index dcbc0be3d..6d5198342 100644 --- a/pytype/tests/py2/test_attributes.py +++ b/pytype/tests/py2/test_attributes.py @@ -14,7 +14,7 @@ def testEmptyTypeParameterInstance(self): """) def testTypeParameterInstanceMultipleBindings(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): values = 42 args = {A() if __random__ else True: ""} @@ -60,7 +60,7 @@ class A(object): # TODO(sivachandra): Add an Python 3 equivalent after b/78645527 is fixed. def testIter(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): x = None return [y for y in x] # attribute-error[e] diff --git a/pytype/tests/py2/test_basic.py b/pytype/tests/py2/test_basic.py index 9241ad606..247946fc7 100644 --- a/pytype/tests/py2/test_basic.py +++ b/pytype/tests/py2/test_basic.py @@ -7,7 +7,7 @@ class TestExec(test_base.TargetPython27FeatureTest): """The exec statement tests.""" def test_exec_statement(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ g = {} exec "a = 11" in g, g assert g['a'] == 11 @@ -26,7 +26,7 @@ def test_printing(self): """) def test_printing_in_a_function(self): - self.Check("""\ + self.Check(""" def fn(): print "hello" fn() @@ -34,7 +34,7 @@ def fn(): """) def test_printing_to_a_file(self): - self.Check("""\ + self.Check(""" import sys print >>sys.stdout, 'hello', 'there' """) diff --git a/pytype/tests/py2/test_builtins.py b/pytype/tests/py2/test_builtins.py index 4c1164cb9..5a572e0c0 100644 --- a/pytype/tests/py2/test_builtins.py +++ b/pytype/tests/py2/test_builtins.py @@ -69,7 +69,7 @@ def testDictIterators(self): from typing import Any, Iterator def need_iterator(x: Iterator[Any]) -> None: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo d = {"a": 1} foo.need_iterator(d.iterkeys()) @@ -348,7 +348,7 @@ def testIterItems(self): """) def testIntInit(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" int(0, 1) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Union\[str, unicode\].*int"}) diff --git a/pytype/tests/py2/test_classes.py b/pytype/tests/py2/test_classes.py index 19659f1c1..688e59720 100644 --- a/pytype/tests/py2/test_classes.py +++ b/pytype/tests/py2/test_classes.py @@ -25,7 +25,7 @@ class A(object): """) def testInitTestClassInSetup(self): - ty = self.Infer("""\ + ty = self.Infer(""" import unittest class A(unittest.TestCase): def setUp(self): @@ -42,7 +42,7 @@ def fooTest(self) -> int: ... """) def testInitInheritedTestClassInSetup(self): - ty = self.Infer("""\ + ty = self.Infer(""" import unittest class A(unittest.TestCase): def setUp(self): diff --git a/pytype/tests/py2/test_decorators.py b/pytype/tests/py2/test_decorators.py index bb9347587..ce57763d7 100644 --- a/pytype/tests/py2/test_decorators.py +++ b/pytype/tests/py2/test_decorators.py @@ -8,7 +8,7 @@ class DecoratorsTest(test_base.TargetPython27FeatureTest): def testAttributeErrorUnderClassDecorator(self): # This does not detect the error under target python3 (b/78591647) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def decorate(cls): return __any_object__ @decorate diff --git a/pytype/tests/py2/test_errors.py b/pytype/tests/py2/test_errors.py index 6e771c585..79a33f468 100644 --- a/pytype/tests/py2/test_errors.py +++ b/pytype/tests/py2/test_errors.py @@ -7,14 +7,14 @@ class ErrorTest(test_base.TargetPython27FeatureTest): """Tests for errors.""" def testProtocolMismatch(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): pass next(Foo()) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"__iter__, next"}) def testProtocolMismatchPartial(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __iter__(self): return self @@ -24,7 +24,7 @@ def __iter__(self): errors, {"e": r"\n\s*next\s*$"}) # `next` on its own line def testGetSlice(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): v = []; return v[:'foo'] # unsupported-operands[e] """) self.assertErrorRegexes( diff --git a/pytype/tests/py2/test_exceptions.py b/pytype/tests/py2/test_exceptions.py index 5774fb37a..f972c765b 100644 --- a/pytype/tests/py2/test_exceptions.py +++ b/pytype/tests/py2/test_exceptions.py @@ -12,7 +12,7 @@ def test_raise_exception_2args(self): self.Check("raise ValueError, 'bad'") def test_raise_exception_3args(self): - self.Check("""\ + self.Check(""" from sys import exc_info try: raise Exception diff --git a/pytype/tests/py2/test_import.py b/pytype/tests/py2/test_import.py index 0aeda953a..c0ff864a9 100644 --- a/pytype/tests/py2/test_import.py +++ b/pytype/tests/py2/test_import.py @@ -8,7 +8,7 @@ class ImportTest(test_base.TargetPython27FeatureTest): """Tests for import.""" def testModuleAttributes(self): - ty = self.Infer("""\ + ty = self.Infer(""" import os f = os.__file__ n = os.__name__ diff --git a/pytype/tests/py2/test_list.py b/pytype/tests/py2/test_list.py index b62512840..b9b9d7497 100644 --- a/pytype/tests/py2/test_list.py +++ b/pytype/tests/py2/test_list.py @@ -8,7 +8,7 @@ class ListTest(test_base.TargetPython27FeatureTest): # __getslice__ is py2 only def test_getslice_slot(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" a = [1, '2', 3, 4] b = a[:] c = 1 if __random__ else 2 @@ -24,7 +24,7 @@ def test_getslice_slot(self): m = a[0:0] n = a[1:1] """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, List, Union a = ... # type: List[Union[int, str]] b = ... # type: List[Union[int, str]] diff --git a/pytype/tests/py2/test_namedtuple.py b/pytype/tests/py2/test_namedtuple.py index d7c07d8c2..272051b5a 100644 --- a/pytype/tests/py2/test_namedtuple.py +++ b/pytype/tests/py2/test_namedtuple.py @@ -23,7 +23,7 @@ def test_calls(self): """) def test_bad_call(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import collections collections.namedtuple() # missing-parameter collections.namedtuple("_") # missing-parameter diff --git a/pytype/tests/py2/test_pyi.py b/pytype/tests/py2/test_pyi.py index 1dcb1448c..d9869f232 100644 --- a/pytype/tests/py2/test_pyi.py +++ b/pytype/tests/py2/test_pyi.py @@ -27,7 +27,7 @@ def testVarargs(self): T = TypeVar("T") def get_varargs(x: int, *args: T, z: int, **kws: int) -> T: ... """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Union import a l1 = None # type: list[str] @@ -65,7 +65,7 @@ def testKwargs(self): T = TypeVar("T") def get_kwargs(x: int, *args: int, z: int, **kws: T) -> T: ... """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Mapping, Union import a d1 = None # type: dict[int, int] diff --git a/pytype/tests/py2/test_reingest.py b/pytype/tests/py2/test_reingest.py index b541ffece..389f6ca02 100644 --- a/pytype/tests/py2/test_reingest.py +++ b/pytype/tests/py2/test_reingest.py @@ -22,7 +22,7 @@ def foo(self): """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(foo)) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.Foo() # not-instantiable[e] foo.Bar() diff --git a/pytype/tests/py2/test_slots.py b/pytype/tests/py2/test_slots.py index a12232e05..be995a94d 100644 --- a/pytype/tests/py2/test_slots.py +++ b/pytype/tests/py2/test_slots.py @@ -7,18 +7,18 @@ class SlotsTest(test_base.TargetPython27FeatureTest): """Tests for __slots__.""" def testBuiltinAttr(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" buffer("foo").bar = 16 # not-writable """) def testSlotWithBytes(self): - self.Check("""\ + self.Check(""" class Foo(object): __slots__ = (b"x",) """) def testSlotWithUnicode(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): # bad-slots[e] __slots__ = (u"fo\\xf6", u"b\\xe4r", "baz") Foo().baz = 3 diff --git a/pytype/tests/py2/test_stdlib.py b/pytype/tests/py2/test_stdlib.py index 4f5390829..6a00d6b8c 100644 --- a/pytype/tests/py2/test_stdlib.py +++ b/pytype/tests/py2/test_stdlib.py @@ -39,7 +39,7 @@ def testStringTypes(self): """) def testDefaultDict(self): - self.Check("""\ + self.Check(""" import collections import itertools ids = collections.defaultdict(itertools.count(17).next) diff --git a/pytype/tests/py2/test_super.py b/pytype/tests/py2/test_super.py index c5c5f0d30..41b40415a 100644 --- a/pytype/tests/py2/test_super.py +++ b/pytype/tests/py2/test_super.py @@ -9,7 +9,7 @@ class SuperTest(test_base.TargetPython27FeatureTest): def testSuperMissingArg(self): # Python 2 super call does not implicitly infer the class and self # arguments. At least the class argument should be specified. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __new__(cls): return super(cls).__new__(cls) # wrong-arg-types[e1] diff --git a/pytype/tests/py2/test_tuple.py b/pytype/tests/py2/test_tuple.py index 02bccbdf8..91b424dad 100644 --- a/pytype/tests/py2/test_tuple.py +++ b/pytype/tests/py2/test_tuple.py @@ -7,7 +7,7 @@ class TupleTest(test_base.TargetPython27FeatureTest): """Tests for __builtin__.tuple.""" def testIteration(self): - ty = self.Infer("""\ + ty = self.Infer(""" class Foo(object): mytuple = (1, "foo", 3j) def __getitem__(self, pos): diff --git a/pytype/tests/py2/test_typevar.py b/pytype/tests/py2/test_typevar.py index e1d5b661e..257b85e44 100644 --- a/pytype/tests/py2/test_typevar.py +++ b/pytype/tests/py2/test_typevar.py @@ -15,7 +15,7 @@ def testUseConstraintsFromPyi(self): def f(x: T) -> T: ... def g(x: AnyStr) -> AnyStr: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f("") # wrong-arg-types[e1] foo.g(0) # wrong-arg-types[e2] @@ -26,7 +26,7 @@ def g(x: AnyStr) -> AnyStr: ... def testExtraArguments(self): # TODO(b/78905523): Make this a target-independent test. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", extra_arg=42) # invalid-typevar[e1] S = TypeVar("S", *__any_object__) # invalid-typevar[e2] diff --git a/pytype/tests/py2/test_typing_methods.py b/pytype/tests/py2/test_typing_methods.py index 6658361d0..f1d933196 100644 --- a/pytype/tests/py2/test_typing_methods.py +++ b/pytype/tests/py2/test_typing_methods.py @@ -16,7 +16,7 @@ def test_mapping(self): class MyDict(Mapping[K, V]): ... def f() -> MyDict[str, int] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo m = foo.f() a = m.copy() diff --git a/pytype/tests/py2/test_typing_namedtuple.py b/pytype/tests/py2/test_typing_namedtuple.py index 6ea0f9385..f26f1acdd 100644 --- a/pytype/tests/py2/test_typing_namedtuple.py +++ b/pytype/tests/py2/test_typing_namedtuple.py @@ -7,7 +7,7 @@ class NamedTupleTest(test_base.TargetPython27FeatureTest): """Tests for the typing.NamedTuple overlay.""" def test_basic_namedtuple(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing X = typing.NamedTuple("X", [("a", int), ("b", str)]) x = X(1, "hello") @@ -15,7 +15,7 @@ def test_basic_namedtuple(self): b = x.b """) self.assertTypesMatchPytd( - ty, """\ + ty, """ import collections from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar, Union typing: module @@ -47,14 +47,14 @@ def _replace(self: _TX, **kwds: Union[int, str]) -> _TX: ... """) def test_namedtuple_unicode(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing X = typing.NamedTuple(u"X", [(u"a", int)]) x = X(1) a = x.a """) self.assertTypesMatchPytd( - ty, """\ + ty, """ import collections from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar, Union typing: module diff --git a/pytype/tests/py3/test_abc.py b/pytype/tests/py3/test_abc.py index 692362565..7d274bf3c 100644 --- a/pytype/tests/py3/test_abc.py +++ b/pytype/tests/py3/test_abc.py @@ -53,7 +53,7 @@ class BarA(Foo, range): """) def test_abstractproperty(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" import abc class Foo(metaclass=abc.ABCMeta): @abc.abstractproperty diff --git a/pytype/tests/py3/test_annotations.py b/pytype/tests/py3/test_annotations.py index 14cf2a0c3..19bf94382 100644 --- a/pytype/tests/py3/test_annotations.py +++ b/pytype/tests/py3/test_annotations.py @@ -59,7 +59,7 @@ def foo(x: Union[int, float], y:int) -> Union[int, float]: ... """) def testCallError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" s = {1} def foo(x: int): s.intersection(x) @@ -68,7 +68,7 @@ def foo(x: int): self.assertErrorRegexes(errors, {"e": r"x: int.*x: float"}) def testAmbiguousArg(self): - self.Check("""\ + self.Check(""" def f(x: int): return x def g(y, z): @@ -82,7 +82,7 @@ def g(y, z): """) def testInnerError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x: int): return x.upper() # attribute-error[e] """) @@ -107,7 +107,7 @@ def foo(l1: List[int], l2: List[str], b) -> None: ... """) def testAnalyzeInit(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List class Foo: def f(self, x: List[int]): @@ -120,7 +120,7 @@ def f(self, x: List[int]) -> None: ... """) def testStringAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(c: "int") -> "None": c += 1 return @@ -130,7 +130,7 @@ def f(c: int) -> None: ... """) def testUnicodeAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(c: u"int") -> u"None": c += 1 return @@ -140,7 +140,7 @@ def f(c: int) -> None: ... """) def testFutureUnicodeLiteralAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" from __future__ import unicode_literals def f(c: "int") -> "None": c += 1 @@ -155,7 +155,7 @@ def f(c: int) -> None: ... """) def testTypingOnlyImport(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing if typing.TYPE_CHECKING: import calendar @@ -169,7 +169,7 @@ def f(c: calendar.Calendar) -> int: ... """) def testAmbiguousAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x: int if __random__ else float): # invalid-annotation[e1] return x def foo(x: "int if __random__ else float"): # invalid-annotation[e2] @@ -182,20 +182,20 @@ def foo(x: "int if __random__ else float"): # invalid-annotation[e2] "e2": r"int.*float.*x.*constant"}) def testBadStringAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x: str()): # invalid-annotation[e] return x """) self.assertErrorRegexes(errors, {"e": r"x.*constant"}) def testBadReturn(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(x: str, y: str) -> int: return "foo" # bad-return-type """) def testMultipleReturns(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x: str, y: str) -> int: if x: return "foo" # bad-return-type[e1] @@ -206,7 +206,7 @@ def foo(x: str, y: str) -> int: "e2": r"Expected.*int.*Actual.*complex"}) def testAmbiguousReturn(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x: str) -> int: if x: y = "foo" @@ -218,7 +218,7 @@ def foo(x: str) -> int: errors, {"e": r"Expected.*int.*Actual.*Union(?=.*complex).*str"}) def testDefaultReturn(self): - ty = self.Infer("""\ + ty = self.Infer(""" class Foo(object): def bar(self, x: float, default="") -> str: default.upper @@ -230,14 +230,14 @@ def bar(self, x: float, default=...) -> str: ... """) def testCompatBool(self): - self.Check("""\ + self.Check(""" def bar(x: bool) -> bool: return None bar(None) """) def testCompatFloat(self): - self.Check("""\ + self.Check(""" def bar(x: float) -> float: return 1 bar(42) @@ -245,7 +245,7 @@ def bar(x: float) -> float: def testCompatUnicodeStr(self): # Use str to be identical in py2 and py3 - self.Check("""\ + self.Check(""" from typing import Text def bar(x: Text) -> Text: return str("foo") @@ -253,14 +253,14 @@ def bar(x: Text) -> Text: """) def testUnsolvable(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ import unknown_module def f(x: unknown_module.Iterable): pass """) def testAny(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Any def f(x: Any): pass @@ -272,7 +272,7 @@ def f(x) -> None: ... """) def testDict(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Dict, List def keys(d: Dict[str, int]): return @@ -282,7 +282,7 @@ def keys(d: Dict[str, int]): """, deep=True) def testSequence(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Sequence def f(s: Sequence): return s @@ -293,7 +293,7 @@ def f(s: Sequence): """, deep=True) def testOptional(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Optional def f(s: Optional[int]): return s @@ -303,7 +303,7 @@ def f(s: Optional[int]): """, deep=True) def testSet(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Set def f(d: Set[str]): return @@ -314,7 +314,7 @@ def f(d: Set[str]): """, deep=True) def testFrozenSet(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import FrozenSet def f(d: FrozenSet[str]): return @@ -324,7 +324,7 @@ def f(d: FrozenSet[str]): """, deep=True) def testGenericAndTypeVar(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ import typing _T = typing.TypeVar("_T") class A(typing.Generic[_T]): @@ -332,7 +332,7 @@ class A(typing.Generic[_T]): """) def testJumpIntoClassThroughAnnotation(self): - self.Check("""\ + self.Check(""" class Foo(object): def __init__(self) -> None: self.myset = set() @@ -360,7 +360,7 @@ class B(object): """) def testWithoutForwardDecl(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" def f(a) -> Bar: # name-error[e] return Bar() @@ -377,7 +377,7 @@ def f(a) -> "Foo": class Foo(object): pass """) - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" def f(a: "Foo"): # name-error[e] return B() @@ -387,7 +387,7 @@ class B(object): self.assertErrorRegexes(errorlog, {"e": r"Foo"}) def testForwardDeclBadReturn(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" def f() -> "Foo": return 1 # bad-return-type[e] @@ -398,7 +398,7 @@ class Foo(object): self.assertErrorRegexes(errorlog, {"e": r"return type.*int"}) def testConfusingForwardDecl(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" class Foo(object): def foo(self): return 4 @@ -417,7 +417,7 @@ def g(): self.assertErrorRegexes(errorlog, {"e": r"\'bar\'.*Foo"}) def testReturnTypeError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class FooBar(object): pass def f() -> FooBar: return 3 # bad-return-type[e] @@ -429,7 +429,7 @@ def testUnknownArgument(self): d.create_file("a.pyi", """ def factory() -> type """) - ty = self.Infer("""\ + ty = self.Infer(""" import a A = a.factory() def f(x: A): @@ -443,7 +443,7 @@ def f(x) -> Any """) def testBadCallNoKwarg(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def foo(): labels = { 'baz': None @@ -464,7 +464,7 @@ def bar(path: str, **kwargs) -> str self.assertErrorRegexes(errors, {"e": error}) def testBadCallWithKwarg(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def foo(): labels = { 'baz': None @@ -485,7 +485,7 @@ def bar(path: str, **kwargs) -> str self.assertErrorRegexes(errors, {"e": error}) def testSkipFunctionsWithAnnotations(self): - ty = self.Infer("""\ + ty = self.Infer(""" _analyzed_baz = None class Foo(object): def __init__(self): @@ -540,7 +540,7 @@ def func(x: Union[Container1, Container2]): """) def testImpreciseAnnotation(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Union class A: pass class B: @@ -589,7 +589,7 @@ def f(x: List[Any]): """) def testInnerString(self): - self.Check("""\ + self.Check(""" from typing import List, Union def f(x: List["int"]): pass @@ -598,7 +598,7 @@ def g(x: Union["int"]): """) def testAmbiguousInnerAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List, Union def f(x: List[int if __random__ else str]): # invalid-annotation[e1] pass @@ -612,7 +612,7 @@ def h(x: List[Union[int, str]]): # okay "e2": r"int or str.*constant"}) def testKwargs(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Dict def f(x, **kwargs: int): return kwargs @@ -640,7 +640,7 @@ def h() -> Dict[float, int] @test_base.skip("Types not checked due to function.Args.simplify") def testSimplifiedVarargsAndKwargs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x, *args: int): pass def g(x, **kwargs: int): @@ -684,7 +684,7 @@ def Bar(): """) def testNestedNoneType(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import List, Union class A: x = 42 @@ -707,7 +707,7 @@ def g() -> List[None]: ... self.assertErrorRegexes(errors, {"e": r"x.*None"}) def testMatchLateAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): def f(self, x: "A"): pass @@ -717,7 +717,7 @@ def f(): self.assertErrorRegexes(errors, {"e": r"A.*int"}) def testRecursiveForwardReference(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): def __init__(self, x: "A"): self.foo = x.foo @@ -732,7 +732,7 @@ def f(x: int): self.assertErrorRegexes(errors, {"e1": r"int.*A", "e2": r"bar"}) def testModuleLevelForwardReferenceError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): def f(self, x: "A"): pass @@ -778,7 +778,7 @@ def f() -> int: ... """) def testDeeplyNestedAnnotation(self): - self.Check("""\ + self.Check(""" from typing import Any, Dict, List, Optional def G(x: Optional[List[Dict[str, Any]]]): if x: @@ -788,7 +788,7 @@ def F(x: Optional[List[Dict[str, Any]]]): """) def testNestedLateAnnotation(self): - self.Check("""\ + self.Check(""" from typing import List Type = "int" def f(x: "List[Type]"): @@ -796,7 +796,7 @@ def f(x: "List[Type]"): """) def testLateAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" def new_x() -> 'X': return X() class X(object): @@ -814,7 +814,7 @@ class X(object): """) def testChangeAnnotatedArg(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Dict def f(x: Dict[str, str]): x[True] = 42 @@ -828,7 +828,7 @@ def f(x: Dict[str, str]) -> Dict[str or bool, str or int]: ... """) def testInnerStringAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List def f(x: List["A"]) -> int: pass @@ -845,7 +845,7 @@ class A(object): ... """) def testTypeAliasAnnotation(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List TypeA = "A" ListA = "List[A]" @@ -865,7 +865,7 @@ class A(object): """) def testDoubleString(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List def f(x: "List[\\"int\\"]") -> int: pass @@ -876,7 +876,7 @@ def f(x: List[int]) -> int: ... """) def testDuplicateIdentifier(self): - ty = self.Infer("""\ + ty = self.Infer(""" t = int def f(x: t) -> int: pass def g(x: "t") -> int: pass @@ -890,7 +890,7 @@ def g(x: int) -> int: ... """) def testEllipsis(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Dict, Tuple def f(x: ...): pass # invalid-annotation[e1] def g(x: Tuple[str, ...]): pass @@ -915,7 +915,7 @@ class Foo(Generic[T]): def __init__(self, x: T2): self = Foo[T2] """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo def f(x: foo.Foo[int]): pass @@ -925,7 +925,7 @@ def f(x: foo.Foo[int]): self.assertErrorRegexes(errors, {"e": r"Foo\[int\].*Foo\[str\]"}) def testNoImplicitOptional(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" from typing import Optional, Union def f1(x: str = None): pass @@ -969,7 +969,7 @@ def h(): """) def testRecursiveTypeAlias(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import List, Union Foo = Union[str, List['Foo']] def f(x: Foo): # not-supported-yet[e] @@ -998,7 +998,7 @@ def f(x: List[Callable[[int], str]]) -> None: ... """) def testLateAnnotationNonNameError(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" class Foo(object): pass def f(x: "Foo.Bar"): # attribute-error @@ -1006,7 +1006,7 @@ def f(x: "Foo.Bar"): # attribute-error """) def testKeepContainerWithError(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" from typing import Dict def f(x: "Dict[str, int.error]"): # attribute-error pass diff --git a/pytype/tests/py3/test_anystr.py b/pytype/tests/py3/test_anystr.py index a07a63dc4..e600d48a1 100644 --- a/pytype/tests/py3/test_anystr.py +++ b/pytype/tests/py3/test_anystr.py @@ -75,7 +75,7 @@ def f(x: AnyStr) -> AnyStr """) def testUseAnyStrConstraints(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import AnyStr, TypeVar def f(x: AnyStr, y: AnyStr) -> AnyStr: return __any_object__ @@ -92,7 +92,7 @@ def f(x: AnyStr, y: AnyStr) -> AnyStr: ... self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testConstraintMismatch(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import AnyStr def f(x: AnyStr, y: AnyStr): ... f("", "") # ok diff --git a/pytype/tests/py3/test_async_generators.py b/pytype/tests/py3/test_async_generators.py index 3d4faca96..91814bc35 100644 --- a/pytype/tests/py3/test_async_generators.py +++ b/pytype/tests/py3/test_async_generators.py @@ -74,7 +74,7 @@ def gen() -> AsyncGenerator[Union[int, str], Any]: ... """) def testAnnotationError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import AsyncGenerator, AsyncIterator, AsyncIterable, Any, Union async def gen1() -> AsyncGenerator[bool, int]: @@ -99,7 +99,7 @@ async def fun(): "e5": r"int.*str"}) def testMatchBaseClassError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import AsyncGenerator, AsyncIterator, AsyncIterable, Union, Any async def func(): diff --git a/pytype/tests/py3/test_attr.py b/pytype/tests/py3/test_attr.py index beb5d300b..0ababc98f 100644 --- a/pytype/tests/py3/test_attr.py +++ b/pytype/tests/py3/test_attr.py @@ -81,7 +81,7 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s class Foo(object): # invalid-annotation @@ -217,7 +217,7 @@ def foo(cls) -> None: ... """) def test_bad_default_param_order(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s(auto_attribs=True) class Foo(object): # invalid-function-definition diff --git a/pytype/tests/py3/test_attributes.py b/pytype/tests/py3/test_attributes.py index e38d3f18d..f5496f387 100644 --- a/pytype/tests/py3/test_attributes.py +++ b/pytype/tests/py3/test_attributes.py @@ -7,7 +7,7 @@ class TestStrictNone(test_base.TargetPython3BasicTest): """Tests for strict attribute checking on None.""" def testExplicitNone(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Optional def f(x: Optional[str]): return x.upper() # attribute-error[e] @@ -26,7 +26,7 @@ def testClosure(self): """) def testOverwriteGlobal(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Optional d = ... # type: Optional[dict] if d: @@ -43,7 +43,7 @@ class TestAttributes(test_base.TargetPython3BasicTest): """Tests for attributes.""" def testAttrOnOptional(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Optional def f(x: Optional[str]): return x.upper() # attribute-error[e] @@ -51,7 +51,7 @@ def f(x: Optional[str]): self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testErrorInAny(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Any def f(x: Any): if __random__: @@ -72,7 +72,7 @@ def testEmptyTypeParameterInstance(self): """) def testTypeParameterInstanceMultipleBindings(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): values = 42 args = {A() if __random__ else True: ""} diff --git a/pytype/tests/py3/test_basic.py b/pytype/tests/py3/test_basic.py index 14ba09ee0..3f948ff9b 100644 --- a/pytype/tests/py3/test_basic.py +++ b/pytype/tests/py3/test_basic.py @@ -7,7 +7,7 @@ class TestExec(test_base.TargetPython3FeatureTest): """Basic tests.""" def test_exec_function(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ g = {} exec("a = 11", g, g) assert g['a'] == 11 diff --git a/pytype/tests/py3/test_builtins.py b/pytype/tests/py3/test_builtins.py index 5b0e28040..8a3d91a8e 100644 --- a/pytype/tests/py3/test_builtins.py +++ b/pytype/tests/py3/test_builtins.py @@ -115,19 +115,19 @@ def testBuiltins(self): """) def testUnicode(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" unicode("foo") # name-error """) def testBytesIteration(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def f(): for x in bytes(): return bytes() + x # unsupported-operands """) def test_inplace_division(self): - self.Check("""\ + self.Check(""" x, y = 24, 3 x /= y assert x == 8.0 and y == 3 @@ -138,7 +138,7 @@ def test_inplace_division(self): """) def test_removed_dict_methods(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" {}.iteritems # attribute-error {}.iterkeys # attribute-error {}.itervalues # attribute-error @@ -417,19 +417,19 @@ def testItems(self): """) def testIntInit(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" int(0, 1) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testRemovedBuiltins(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" long # name-error {}.has_key # attribute-error """) def testRange(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" xrange(3) # name-error v = range(3) v[0] @@ -620,14 +620,14 @@ def testMinMax(self): """) def testStrIsNotInt(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import SupportsInt def f(x: SupportsInt): pass f("") # wrong-arg-types """) def testStrIsNotFloat(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import SupportsFloat def f(x: SupportsFloat): pass f("") # wrong-arg-types diff --git a/pytype/tests/py3/test_checker.py b/pytype/tests/py3/test_checker.py index 8eecee850..f218fe232 100644 --- a/pytype/tests/py3/test_checker.py +++ b/pytype/tests/py3/test_checker.py @@ -17,7 +17,7 @@ def g(data: Set[str]): """) def testRecursiveForwardReference(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" class X(object): def __init__(self, val: "X"): pass @@ -27,7 +27,7 @@ def f(): self.assertErrorRegexes(errorlog, {"e": r"X.*int"}) def testBadReturnTypeInline(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" from typing import List def f() -> List[int]: return [object()] # bad-return-type[e] @@ -36,7 +36,7 @@ def f() -> List[int]: self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[object\]"}) def testUseVarargsAndKwargs(self): - self.Check("""\ + self.Check(""" class A(object): pass def f(*args: A, **kwargs: A): @@ -47,7 +47,7 @@ def f(*args: A, **kwargs: A): """) def testNestedNoneType(self): - self.Check("""\ + self.Check(""" from typing import List, Union def f1() -> Union[None]: pass @@ -60,7 +60,7 @@ def g2(x: List[None]): """) def testInnerClassInit(self): - self.Check("""\ + self.Check(""" from typing import List class A: def __init__(self): @@ -74,7 +74,7 @@ def h(): """) def testRecursion(self): - self.Check("""\ + self.Check(""" class A: def __init__(self, x: "B"): pass @@ -85,7 +85,7 @@ def __init__(self): """) def testBadDictValue(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" from typing import Dict def f() -> Dict[str, int]: return {"x": 42.0} # bad-return-type[e] @@ -93,7 +93,7 @@ def f() -> Dict[str, int]: self.assertErrorRegexes(errorlog, {"e": r"int.*float"}) def testInstanceAsAnnotation(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" def f(): pass def g(x: f): # invalid-annotation[e1] @@ -105,7 +105,7 @@ def h(x: 3): # invalid-annotation[e2] errorlog, {"e1": r"instance of Callable.*x", "e2": r"3.*x"}) def testBadGenerator(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" from typing import Generator def f() -> Generator[str, None, None]: for i in range(3): @@ -114,7 +114,7 @@ def f() -> Generator[str, None, None]: self.assertErrorRegexes(errorlog, {"e": r"str.*int"}) def testMultipleParameterBindings(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" from typing import List def f(x) -> List[int]: return ["", x] # bad-return-type[e] @@ -122,7 +122,7 @@ def f(x) -> List[int]: self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[str\]"}) def testNoParamBinding(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" def f() -> None: x = [] return x # bad-return-type[e] @@ -130,7 +130,7 @@ def f() -> None: self.assertErrorRegexes(errorlog, {"e": r"None.*List\[nothing\]"}) def testAttributeInIncompleteInstance(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" from typing import List class Foo(object): def __init__(self, other: "List[Foo]"): @@ -144,14 +144,14 @@ def __init__(self, other: "List[Foo]"): "e2": r"z.*Type\[Foo\]"}) def testBadGetItem(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" def f(x: int): return x[0] # unsupported-operands[e] """) self.assertErrorRegexes(errorlog, {"e": r"int.*int"}) def testBadAnnotationContainer(self): - errorlog = self.CheckWithErrors("""\ + errorlog = self.CheckWithErrors(""" class A(object): pass def f(x: int[str]): # not-indexable[e1] diff --git a/pytype/tests/py3/test_classes.py b/pytype/tests/py3/test_classes.py index e3dda37f1..ecbab92f4 100644 --- a/pytype/tests/py3/test_classes.py +++ b/pytype/tests/py3/test_classes.py @@ -61,7 +61,7 @@ def Create(self, x: MyType): """) def testRecursiveConstructorBadAttribute(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List MyType = List['Foo'] class Foo(object): @@ -118,7 +118,7 @@ class Foo(List[str]): ... """) def testMakeGenericClass(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List, TypeVar, Union T1 = TypeVar("T1") T2 = TypeVar("T2") @@ -132,7 +132,7 @@ class Foo(List[Union[T1, T2]]): ... """) def testMakeGenericClassWithConcreteValue(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Dict, TypeVar V = TypeVar("V") class Foo(Dict[str, V]): ... @@ -150,7 +150,7 @@ def testGenericReinstantiated(self): """Makes sure the result of foo.f() isn't used by both a() and b().""" with file_utils.Tempdir() as d: d.create_file("foo.pyi", "def f() -> list: ...") - self.Check("""\ + self.Check(""" import foo from typing import List def a() -> List[str]: @@ -162,7 +162,7 @@ def b() -> List[int]: """, pythonpath=[d.path]) def testParentInit(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Sequence class X(object): def __init__(self, obj: Sequence): @@ -174,7 +174,7 @@ def __init__(self, obj: int): self.assertErrorRegexes(errors, {"e": r"Sequence.*int"}) def testParameterizedClassBinaryOperator(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Sequence def f(x: Sequence[str], y: Sequence[str]) -> None: a = x + y # unsupported-operands @@ -228,7 +228,7 @@ def foo(self) -> int: def testBuildClassQuick(self): # A() hits maximum stack depth in python3.6 - ty = self.Infer("""\ + ty = self.Infer(""" def f(): class A(object): pass return {A: A()} @@ -275,7 +275,7 @@ def f(x: Foo): """) def testInitTestClassInSetup(self): - ty = self.Infer("""\ + ty = self.Infer(""" import unittest class A(unittest.TestCase): def setUp(self): @@ -292,7 +292,7 @@ def fooTest(self) -> int: ... """) def testInitInheritedTestClassInSetup(self): - ty = self.Infer("""\ + ty = self.Infer(""" import unittest class A(unittest.TestCase): def setUp(self): @@ -312,7 +312,7 @@ def fooTest(self) -> int: ... """) def testInitTestClassInInitAndSetup(self): - ty = self.Infer("""\ + ty = self.Infer(""" import unittest class A(unittest.TestCase): def __init__(self, foo: str): @@ -412,7 +412,7 @@ def bar(cls): """) def testPy2Metaclass(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import abc class Foo(object): # ignored-metaclass[e] __metaclass__ = abc.ABCMeta diff --git a/pytype/tests/py3/test_coroutine.py b/pytype/tests/py3/test_coroutine.py index c859f0d32..eed7d2855 100644 --- a/pytype/tests/py3/test_coroutine.py +++ b/pytype/tests/py3/test_coroutine.py @@ -69,7 +69,7 @@ def caller() -> Coroutine[Any, Any, Union[int, str]]: ... """) def testNativeCoroutineError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" async def f1() -> str: return 1 # bad-return-type[e1] @@ -130,7 +130,7 @@ def f3() -> Coroutine[Any, Any, Union[int, str]]: ... """) def testGeneratorBasedCoroutineError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Generator import types @@ -212,7 +212,7 @@ def f3() -> Coroutine[Any, Any, None]: ... """) def testInvalidAwaitable(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): pass @@ -258,7 +258,7 @@ def caller() -> Coroutine[Any, Any, List[Union[int, str]]]: ... """) def testAsyncForError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Iter1(object): pass @@ -350,7 +350,7 @@ def log(s: _T0) -> Coroutine[Any, Any, _T0]: ... def testAsyncWithError(self): # pylint: disable=anomalous-backslash-in-string - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class AsyncCtx1(object): pass diff --git a/pytype/tests/py3/test_dataclasses.py b/pytype/tests/py3/test_dataclasses.py index 94dd59d2c..42e9ecef5 100644 --- a/pytype/tests/py3/test_dataclasses.py +++ b/pytype/tests/py3/test_dataclasses.py @@ -135,7 +135,7 @@ def __init__(self, x: bool = ..., y: List[int] = ...) -> None: ... """) def test_type_mismatch(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import dataclasses @dataclasses.dataclass() class Foo(object): # annotation-type-mismatch @@ -143,7 +143,7 @@ class Foo(object): # annotation-type-mismatch """) def test_field_type_mismatch(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import dataclasses @dataclasses.dataclass() class Foo(object): # annotation-type-mismatch @@ -151,7 +151,7 @@ class Foo(object): # annotation-type-mismatch """) def test_factory_type_mismatch(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import dataclasses @dataclasses.dataclass() class Foo(object): # annotation-type-mismatch @@ -191,7 +191,7 @@ def __init__(self, x: bool, y: int) -> None: ... """) def test_bad_default_param_order(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import dataclasses @dataclasses.dataclass() class Foo(object): # invalid-function-definition diff --git a/pytype/tests/py3/test_decorators.py b/pytype/tests/py3/test_decorators.py index 9166f54fc..870aa7016 100644 --- a/pytype/tests/py3/test_decorators.py +++ b/pytype/tests/py3/test_decorators.py @@ -7,7 +7,7 @@ class DecoratorsTest(test_base.TargetPython3BasicTest): """Test decorators.""" def testAnnotatedSuperCallUnderBadDecorator(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" class Foo(object): def Run(self) -> None: ... class Bar(Foo): @@ -19,7 +19,7 @@ def Run(self): def testReplaceSelfToStarArg(self): # Without decorator, `self` will be in `signature.param_names`. # But after replacing, `*args` won't be in `signature.param_names`. - self.Check("""\ + self.Check(""" from typing import TypeVar T = TypeVar('T') diff --git a/pytype/tests/py3/test_dict.py b/pytype/tests/py3/test_dict.py index 49540fb1a..6c102391d 100644 --- a/pytype/tests/py3/test_dict.py +++ b/pytype/tests/py3/test_dict.py @@ -21,7 +21,7 @@ def foo(x: Union[int, None]) -> Any """) def testObjectInDict(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import Any, Dict def objectIsStr() -> Dict[str, Any]: return {object(): ""} # bad-return-type @@ -29,7 +29,7 @@ def objectIsStr() -> Dict[str, Any]: def testBigConcreteDict(self): # Test that we don't timeout. - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import Dict, Tuple, Union # A concrete dictionary with lots of concrete keys and a complicated # value type. diff --git a/pytype/tests/py3/test_errors.py b/pytype/tests/py3/test_errors.py index 678bb45c8..04ad1e054 100644 --- a/pytype/tests/py3/test_errors.py +++ b/pytype/tests/py3/test_errors.py @@ -10,7 +10,7 @@ class ErrorTest(test_base.TargetPython3BasicTest): """Tests for errors.""" def testUnion(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x: int): pass if __random__: @@ -24,7 +24,7 @@ def f(x: int): errors, {"e": r"Actually passed:.*Union\[float, str\]"}) def testInvalidAnnotations(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Dict, List, Union def f1(x: Dict): # okay pass @@ -40,7 +40,7 @@ def f4(x: Union): # invalid-annotation[e3] "e3": r"Union.*x"}) def testPrintUnsolvable(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List def f(x: List[nonsense], y: str, z: float): # name-error pass @@ -50,7 +50,7 @@ def f(x: List[nonsense], y: str, z: float): # name-error errors, {"e": r"Expected:.*x: list.*Actual.*x: set"}) def testPrintUnionOfContainers(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x: str): pass if __random__: @@ -63,7 +63,7 @@ def f(x: str): self.assertErrorRegexes(errors, {"e": error}) def testWrongBrackets(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List def f(x: List(str)): # not-callable[e] pass @@ -71,7 +71,7 @@ def f(x: List(str)): # not-callable[e] self.assertErrorRegexes(errors, {"e": r"List"}) def testInterpreterClassPrinting(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): pass def f(x: str): pass f(Foo()) # wrong-arg-types[e] @@ -79,7 +79,7 @@ def f(x: str): pass self.assertErrorRegexes(errors, {"e": r"str.*Foo"}) def testPrintDictAndTuple(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Tuple tup = None # type: Tuple[int, ...] dct = None # type: dict[str, int] @@ -99,7 +99,7 @@ def g2(x: dct): # invalid-annotation[e4] "e4": r"instance of Dict\[str, int\].*Not a type"}) def testMoveUnionInward(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f() -> str: # invalid-annotation[e] y = "hello" if __random__ else 42 yield y @@ -107,7 +107,7 @@ def f() -> str: # invalid-annotation[e] self.assertErrorRegexes(errors, {"e": r"Generator, Iterable or Iterator"}) def testInnerClassError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x: str): pass def g(): class Foo(object): pass @@ -116,7 +116,7 @@ class Foo(object): pass self.assertErrorRegexes(errors, {"e": r"x: str.*x: Foo"}) def testInnerClassError2(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): class Foo(object): pass def g(x: Foo): pass @@ -127,7 +127,7 @@ def g(x: Foo): pass def testCleanNamedtupleNames(self): # Make sure the namedtuple renaming in _pytd_print correctly extracts type # names and doesn't erase other types accidentally. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import collections X = collections.namedtuple("X", "a b c d") Y = collections.namedtuple("Z", "") @@ -149,7 +149,7 @@ def bar(x: str): "e4": r"`dictionary-keyiterator`", "e5": r"Union\[int, `X`\]"}) def testArgumentOrder(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def g(f: str, a, b, c, d, e,): pass g(a=1, b=2, c=3, d=4, e=5, f=6) # wrong-arg-types[e] @@ -158,14 +158,14 @@ def g(f: str, a, b, c, d, e,): "e": r"Expected.*f: str, \.\.\..*Actual.*f: int, \.\.\."}) def testConversionOfGeneric(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import os def f() -> None: return os.walk("/tmp") # bad-return-type """) def testInnerClass(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f() -> int: class Foo(object): pass @@ -181,7 +181,7 @@ class _Foo_DOT_Bar: ... class Foo: Bar = ... # type: Type[_Foo_DOT_Bar] """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo_bar def f(x: foo_bar.Foo.Bar): ... f(42) # wrong-arg-types[e] @@ -195,7 +195,7 @@ class A(object): @staticmethod def t(a: str) -> None: ... """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Callable import foo def f(x: Callable[[int], None], y: int) -> None: @@ -206,7 +206,7 @@ def f(x: Callable[[int], None], y: int) -> None: errors, {"e": r"Actually passed: \(x: Callable\[\[str\], None\]"}) def testGeneratorSend(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Generator, Any def f(x) -> Generator[Any, int, Any]: if x == 1: @@ -220,7 +220,7 @@ def f(x) -> Generator[Any, int, Any]: self.assertErrorRegexes(errors, {"e": r"\(self, value: int\)"}) def testGeneratorIteratorRetType(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Iterator def f() -> Iterator[str]: yield 1 # bad-return-type[e] @@ -228,7 +228,7 @@ def f() -> Iterator[str]: self.assertErrorRegexes(errors, {"e": r"str.*int"}) def testGeneratorIterableRetType(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Iterable def f() -> Iterable[str]: yield 1 # bad-return-type[e] @@ -240,7 +240,7 @@ class InPlaceOperationsTest(test_base.TargetPython3BasicTest): """Test in-place operations.""" def _testOp(self, op, symbol): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): def __%s__(self, x: "A"): return None @@ -258,7 +258,7 @@ def testIMul(self): self._testOp("imul", "*=") def testIDiv(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): def __idiv__(self, x: "A"): return None @@ -300,14 +300,14 @@ class ErrorTestPy3(test_base.TargetPython3FeatureTest): """Tests for errors.""" def testProtocolMismatch(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): pass next(Foo()) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"__iter__, __next__"}) def testProtocolMismatchPartial(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __iter__(self): return self @@ -317,7 +317,7 @@ def __iter__(self): errors, {"e": r"\n\s*__next__\s*$"}) # `next` on its own line def testGeneratorSendRetType(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generator def f() -> Generator[int, str, int]: x = yield 1 @@ -330,7 +330,7 @@ class MatrixOperationsTest(test_base.TargetPython3FeatureTest): """Test matrix operations.""" def testMatMul(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' @ 3 # unsupported-operands[e] """) @@ -338,7 +338,7 @@ def f(): "e": r"\@.*str.*int.*'__matmul__' on str.*'__rmatmul__' on int"}) def testIMatMul(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): def __imatmul__(self, x: "A"): pass diff --git a/pytype/tests/py3/test_flow.py b/pytype/tests/py3/test_flow.py index 32de2ccaf..3df62e873 100644 --- a/pytype/tests/py3/test_flow.py +++ b/pytype/tests/py3/test_flow.py @@ -27,7 +27,7 @@ def foo() -> str: """) def test_cfg_cycle_singlestep(self): - self.Check("""\ + self.Check(""" import typing class Foo(object): x = ... # type: typing.Optional[int] diff --git a/pytype/tests/py3/test_functions.py b/pytype/tests/py3/test_functions.py index ed6e8f18a..4cdd67a39 100644 --- a/pytype/tests/py3/test_functions.py +++ b/pytype/tests/py3/test_functions.py @@ -8,7 +8,7 @@ class TestClosures(test_base.TargetPython3BasicTest): """Tests for closures.""" def test_error(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(x: int): def g(): return x.upper() # attribute-error[e] @@ -20,7 +20,7 @@ class TestClosuresPy3(test_base.TargetPython3FeatureTest): """Tests for closures in Python 3.""" def test_if_split_delete_deref(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(a: int): x = "hello" def g(): @@ -37,7 +37,7 @@ def f(a: int) -> Optional[str] """) def test_closures_delete_deref(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(): x = "hello" def g(): @@ -48,7 +48,7 @@ def g(): """) def test_nonlocal(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(): x = "hello" def g(): @@ -62,7 +62,7 @@ def f() -> int """) def test_nonlocal_delete_deref(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(): x = True def g(): @@ -73,7 +73,7 @@ def g(): """) def test_reuse_after_delete_deref(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(): x = True def g(): @@ -88,7 +88,7 @@ def f() -> int """) def test_closure_annotations(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): a = 1 def g(x: int) -> int: @@ -99,7 +99,7 @@ def g(x: int) -> int: def test_filter_before_delete(self): # TODO(b/117463644): Remove the disable on line 7. - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import Optional def f(x: Optional[str]): if x is None: @@ -121,7 +121,7 @@ def setUp(self): self.options.tweak(precise_return=True) def test_interpreter_return(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def f(x: str) -> str: return x x = f(0) # wrong-arg-types[e] @@ -133,7 +133,7 @@ def f(x: str) -> str: ... self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_unknown_return(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def f(x: str): return x x = f(0) # wrong-arg-types[e] @@ -146,7 +146,7 @@ def f(x: str) -> str: ... self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_overload(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import overload @overload def f(x: str) -> str: ... @@ -167,7 +167,7 @@ class TestFunctions(test_base.TargetPython3BasicTest): """Tests for functions.""" def test_function_to_callable(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(): def g1(x: int, y: bool) -> str: return "hello world" @@ -181,7 +181,7 @@ def f() -> Tuple[Callable[[int, bool], str], Callable[[], int]] """) def test_function_to_callable_return_only(self): - ty = self.Infer("""\ + ty = self.Infer(""" def f(): def g1(x=None) -> int: return 42 @@ -195,7 +195,7 @@ def f() -> Tuple[Callable[..., int], Callable[..., str]] """) def test_fake_arguments(self): - self.Check("""\ + self.Check(""" class Foo(object): def __init__(self, x: int): @@ -235,7 +235,7 @@ def f( """) def test_typecheck_varargs(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def f(*args: int) -> int: return args[0] f(*['value']) # wrong-arg-types @@ -243,7 +243,7 @@ def f(*args: int) -> int: """) def test_typecheck_kwargs(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def f(**kwargs: int) -> int: return len(kwargs.values()) f(**{'arg': 'value'}) # wrong-arg-types @@ -294,7 +294,7 @@ def bar(*y: int): """) def text_varargs_errors(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def foo(x: str, *y: int): pass foo(*[1, 2, 3]) # wrong-arg-types[e1] @@ -319,7 +319,7 @@ def test_varargs_in_pyi_error(self): d.create_file("foo.pyi", """ def f(x: int, *args): ... """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo def g(*args): foo.f("", *args) # wrong-arg-types[e] @@ -583,7 +583,7 @@ def foo(x: int, *args: int, z: int) -> None: """) def test_varargs_with_missing_kwonly(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def foo(x: int, *args: int, z: int) -> None: pass @@ -606,7 +606,7 @@ def bar(y: Tuple[int], *z: int): """) def text_multiple_varargs_packs_errors(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def foo(x: str, *y: int): pass foo(*[1, 2, 3], *[4, 5, 6]) # wrong-arg-types[e1] diff --git a/pytype/tests/py3/test_generators.py b/pytype/tests/py3/test_generators.py index b785ce4e1..b9bcd6512 100644 --- a/pytype/tests/py3/test_generators.py +++ b/pytype/tests/py3/test_generators.py @@ -30,7 +30,7 @@ def f() -> Iterable: """) def testNoReturn(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generator def f() -> Generator[str, None, None]: yield 42 # bad-return-type[e] @@ -90,7 +90,7 @@ def f() -> Generator[str, int, Any] """) def testParameterCount(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generator def func1() -> Generator[int, int, int]: diff --git a/pytype/tests/py3/test_generic.py b/pytype/tests/py3/test_generic.py index 3ecfe4a5d..a157b91fc 100644 --- a/pytype/tests/py3/test_generic.py +++ b/pytype/tests/py3/test_generic.py @@ -8,7 +8,7 @@ class GenericBasicTest(test_base.TargetPython3BasicTest): """Tests for User-defined Generic Type.""" def testGenericTypeParamsError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic class A(Generic[int]): # invalid-annotation[e] @@ -18,7 +18,7 @@ class A(Generic[int]): # invalid-annotation[e] errors, {"e": r"Parameters.*Generic.*must.*type variables"}) def testMroError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Generic, Iterator, Generator, TypeVar T = TypeVar('T') @@ -28,7 +28,7 @@ class A(Generic[T], Iterator[T], Generator): # mro-error """) def testTemplateOrderError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic, TypeVar T1 = TypeVar('T1') @@ -67,7 +67,7 @@ def func(self, x: K1, y: K2): self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"int.*str"}) def testTypeErasureError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Generic T = TypeVar('T', int, float) @@ -90,7 +90,7 @@ def fun(self, x: T, y: S): "e3": r"y: int.*y: str"}) def testInhericPlainGenericError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic class A(Generic): # invalid-annotation[e] @@ -106,7 +106,7 @@ def testGenericWithDupTypeError(self): T = TypeVar('T') class A(Generic[T, T]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"Duplicate.*T.*a.A"}) @@ -120,7 +120,7 @@ def testMultiGenericError(self): V = TypeVar('V') class A(Generic[T], Generic[V]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes( @@ -135,14 +135,14 @@ def testGenericWithTypeMissError(self): V = TypeVar('V') class A(Dict[K, V], Generic[K]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes( errors, {"e": r"V.*are not listed in Generic.*a.A"}) def testClassInFuncError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Generic, Union T = TypeVar('T') @@ -159,7 +159,7 @@ class InnerCls2(Generic[S]): "e2": r"func.*InnerCls1.*T"}) def testClassInClassError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Generic, Iterator T = TypeVar('T', int, float, str) @@ -184,7 +184,7 @@ class C(Generic[T]): "e2": r"A.*C.*T"}) def testSignatureTypeParam(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Generic T = TypeVar('T', int, float, str) @@ -276,7 +276,7 @@ def fun(self, x: T, y: S) -> None: ... """) def testSignatureTypeError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic, TypeVar T = TypeVar('T') @@ -329,7 +329,7 @@ def put(self, elem: T): ... """) def testFuncMatchForInterpreterClassError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Generic T1 = TypeVar('T1') @@ -380,7 +380,7 @@ def fun2(self, x: T2, y: S2): ... class C(A[T, S], B[T, S], Generic[T, S]): def fun3(self, x: T, y: S): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a o = a.C[int, int]() @@ -393,7 +393,7 @@ def fun3(self, x: T, y: S): ... errors, {"e1": r"int.*str", "e2": r"int.*str", "e3": r"int.*str"}) def testTypeRenamingError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic, TypeVar T = TypeVar('T', int, float) @@ -417,7 +417,7 @@ class G(F[W]): pass # not-supported-yet[e3] "e3": r"Renaming TypeVar `U`.*"}) def testTypeParameterConflictError(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Generic, TypeVar T = TypeVar('T') @@ -461,7 +461,7 @@ class E(Any): "e2": r"Conflicting value for TypeVar"}) def testUnboundTypeParameterError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Generic, TypeVar T = TypeVar('T') @@ -503,7 +503,7 @@ class G(Sequence[G[int]], Generic[T]): ... """, pythonpath=[d.path]) def testAnyMatchAllTypes(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import collections, typing class DictA(collections.OrderedDict, typing.MutableMapping[int, int]): @@ -534,7 +534,7 @@ def __init__(self, children: List['Foo[Any]']): """) def testIllegalSelfAnnot(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Any, Generic, List, TypeVar T = TypeVar('T') class Foo(Generic[T]): @@ -561,7 +561,7 @@ class Foo(Generic[T]): ... """) def testBadParameterizedForwardReference(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Generic, TypeVar T = TypeVar('T') @@ -573,7 +573,7 @@ class Foo(Generic[T]): self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testRecursiveClass(self): - self.Check("""\ + self.Check(""" from typing import List class Foo(List["Foo"]): pass diff --git a/pytype/tests/py3/test_import.py b/pytype/tests/py3/test_import.py index 4528a59a0..ef6a7883d 100644 --- a/pytype/tests/py3/test_import.py +++ b/pytype/tests/py3/test_import.py @@ -8,7 +8,7 @@ class ImportTest(test_base.TargetPython3FeatureTest): """Tests for import.""" def testModuleAttributes(self): - ty = self.Infer("""\ + ty = self.Infer(""" import os f = os.__file__ n = os.__name__ @@ -48,7 +48,7 @@ def testRelativePriority(self): with file_utils.Tempdir() as d: d.create_file("a.pyi", "x = ... # type: int") d.create_file("b/a.pyi", "x = ... # type: complex") - ty = self.Infer("""\ + ty = self.Infer(""" import a x = a.x """, deep=False, pythonpath=[d.path], module_name="b.main") diff --git a/pytype/tests/py3/test_list.py b/pytype/tests/py3/test_list.py index f583e35ee..924425b88 100644 --- a/pytype/tests/py3/test_list.py +++ b/pytype/tests/py3/test_list.py @@ -10,7 +10,7 @@ class ListTestBasic(test_base.TargetPython3BasicTest): def test_repeated_add(self): # At the time of this writing, this test completes in <5s. If it takes # significantly longer, there's been a performance regression. - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import List, Text, Tuple def f() -> Tuple[List[Text]]: x = ( @@ -63,7 +63,7 @@ def test_byte_unpack_ex(self): """) def test_getitem_slot(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" a = [1, '2', 3, 4] p = a[1] q = 1 if __random__ else 2 @@ -71,7 +71,7 @@ def test_getitem_slot(self): s = a["s"] # unsupported-operands t = a[-1] """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, List, Union a = ... # type: List[Union[int, str]] p = ... # type: str @@ -86,7 +86,7 @@ def test_getitem_slice(self): # Python 3 uses __getitem__ with slice objects instead of __getslice__. # Pytype doesn't support slice objects well, so a lot of results here are # imprecise. It also means wrong-arg-types won't be detected. - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" a = [1, '2', 3, 4] b = a[:] c = 1 if __random__ else 2 @@ -103,7 +103,7 @@ def test_getitem_slice(self): o = a[1:1] p = a[1:2] """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, List, Union a = ... # type: List[Union[int, str]] b = ... # type: List[Union[int, str]] diff --git a/pytype/tests/py3/test_match.py b/pytype/tests/py3/test_match.py index c998976e5..b34edd504 100644 --- a/pytype/tests/py3/test_match.py +++ b/pytype/tests/py3/test_match.py @@ -12,7 +12,7 @@ def testNoArgumentPyTDFunctionAgainstCallable(self): d.create_file("foo.pyi", """ def bar() -> bool """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable import foo @@ -32,7 +32,7 @@ def f1(x: int) -> int: ... def f2(x: int) -> bool: ... def f3(x: int) -> str: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable, TypeVar import foo @@ -58,7 +58,7 @@ def f2(x: Callable[[T_constrained], T_constrained]): ... r"Actual.*Callable\[\[int\], str\]")}) def testInterpreterFunctionAgainstCallable(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable def f(x: Callable[[bool], int]): ... def g1(x: int) -> bool: @@ -73,7 +73,7 @@ def g2(x: str) -> int: r"Actual.*Callable\[\[str\], int\]")}) def testBoundInterpreterFunctionAgainstCallable(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable class A(object): @@ -108,7 +108,7 @@ def testCallableParameters(self): def f1(x: Callable[..., T]) -> List[T]: ... def f2(x: Callable[[T], Any]) -> List[T]: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Any, Callable import foo @@ -137,7 +137,7 @@ def g4(x: int) -> Any: ... """) def testVariableLengthFunctionAgainstCallable(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Any, Callable def f(x: Callable[[int], Any]): pass def g1(x: int=0): pass @@ -150,7 +150,7 @@ def g2(x: str=""): pass r"Actual.*Callable\[\[str\], Any\]")}) def testCallableInstanceAgainstCallableWithTypeParameters(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable, TypeVar T = TypeVar("T") def f(x: Callable[[T], T]): ... @@ -162,7 +162,7 @@ def g() -> Callable[[int], str]: return __any_object__ r"Actual.*Callable\[\[int\], str\]")}) def testFunctionWithTypeParameterReturnAgainstCallable(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Callable, AnyStr, TypeVar T = TypeVar("T") def f(x: Callable[..., AnyStr]): ... @@ -201,7 +201,7 @@ def bar(self, x: Dict[Tuple[AnyStr], AnyStr]): ... """) def testFormalType(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import AnyStr, List, NamedTuple def f(x: str): pass @@ -213,7 +213,7 @@ def g(x: List[str]): """) def testTypeVarWithBound(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable, TypeVar T1 = TypeVar("T1", bound=int) T2 = TypeVar("T2") @@ -260,7 +260,7 @@ def g(f: Callable[[T], Any], x: T): def testAnyStrAgainstBoundedCallable(self): # Constraints and bounds should still be enforced when a type parameter # appears only once in a callable. - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Any, AnyStr, Callable, TypeVar IntVar = TypeVar('IntVar', bound=int) def f(x: AnyStr) -> AnyStr: @@ -274,7 +274,7 @@ def g(f: Callable[[IntVar], Any], x: IntVar): def testAnyStrAgainstMultipleParamCallable(self): # Callable[[T], T] needs to accept any argument, so AnyStr cannot match it. - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Any, AnyStr, Callable, TypeVar T = TypeVar('T') def f(x: AnyStr) -> AnyStr: diff --git a/pytype/tests/py3/test_methods.py b/pytype/tests/py3/test_methods.py index 4fd78fb20..32ec8f9af 100644 --- a/pytype/tests/py3/test_methods.py +++ b/pytype/tests/py3/test_methods.py @@ -16,7 +16,7 @@ def __init__(self: int) -> int """) def testAnnotatedSelf(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(x: int): pass # invalid-annotation[e] @@ -24,7 +24,7 @@ def __init__(x: int): self.assertErrorRegexes(errors, {"e": r"int.*x"}) def testLateAnnotatedSelf(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(x: "X"): pass # invalid-annotation[e] @@ -34,7 +34,7 @@ class X(object): self.assertErrorRegexes(errors, {"e": r"X.*x"}) def testAttributeWithAnnotatedSelf(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(self: int): self.x = 3 # invalid-annotation[e] @@ -44,7 +44,7 @@ def foo(self): self.assertErrorRegexes(errors, {"e": r"int.*self"}) def testAttributeWithAnnotatedSelfAndFunctionInit(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(self: int): self.x = 3 # invalid-annotation[e] diff --git a/pytype/tests/py3/test_namedtuple.py b/pytype/tests/py3/test_namedtuple.py index a3a4dc1e4..71cc03e8b 100644 --- a/pytype/tests/py3/test_namedtuple.py +++ b/pytype/tests/py3/test_namedtuple.py @@ -7,7 +7,7 @@ class NamedtupleTests(test_base.TargetPython3BasicTest): """Tests for collections.namedtuple.""" def test_namedtuple_match(self): - self.Check("""\ + self.Check(""" import collections from typing import Any, Dict @@ -23,7 +23,7 @@ class NamedtupleTestsPy3(test_base.TargetPython3FeatureTest): def test_bad_call(self): """The last two arguments are kwonly in 3.6.""" - self.InferWithErrors("""\ + self.InferWithErrors(""" import collections collections.namedtuple() # missing-parameter collections.namedtuple("_") # missing-parameter diff --git a/pytype/tests/py3/test_overload.py b/pytype/tests/py3/test_overload.py index fea30006e..d2047ec2b 100644 --- a/pytype/tests/py3/test_overload.py +++ b/pytype/tests/py3/test_overload.py @@ -19,7 +19,7 @@ def f(x): """) def test_bad_implementation(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload @overload def f(x: int) -> str: @@ -30,7 +30,7 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_bad_call(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload @overload def f(x: int) -> int: @@ -72,7 +72,7 @@ def f(x=None): """) def test_multiple_overload_bad_implementation(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload @overload def f(x: int) -> int: @@ -86,7 +86,7 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_multiple_overload_bad_call(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload @overload def f(x: int) -> int: @@ -128,7 +128,7 @@ def g() -> Callable: ... """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(ty)) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo foo.f(0) # ok foo.f("") # ok @@ -137,7 +137,7 @@ def g() -> Callable: ... self.assertErrorRegexes(errors, {"e": r"int.*float"}) def test_method_bad_implementation(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload class Foo(object): @overload @@ -176,7 +176,7 @@ def f(self, x: str) -> str: ... """) def test_call_overload(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import overload @overload def f(x: int) -> int: diff --git a/pytype/tests/py3/test_protocols.py b/pytype/tests/py3/test_protocols.py index ce4cedf3a..7709a4085 100644 --- a/pytype/tests/py3/test_protocols.py +++ b/pytype/tests/py3/test_protocols.py @@ -30,7 +30,7 @@ def __len__(self): """) def test_check_protocol_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import protocols def f(x: protocols.SupportsAbs): @@ -41,7 +41,7 @@ def f(x: protocols.SupportsAbs): errors, {"e": r"\(x: SupportsAbs\).*\(x: List\[str\]\)"}) def test_check_iterator_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Iterator def f(x: Iterator[int]): return None @@ -55,7 +55,7 @@ def __iter__(self): self.assertErrorRegexes(errors, {"e": r"Iterator\[int\].*Foo"}) def test_check_protocol_match_unknown(self): - self.Check("""\ + self.Check(""" from typing import Sized def f(x: Sized): pass @@ -68,7 +68,7 @@ def g(x): """) def test_check_parameterized_protocol(self): - self.Check("""\ + self.Check(""" from typing import Iterator, Iterable class Foo(object): @@ -84,7 +84,7 @@ def f(x: Iterable[int]): """) def test_check_parameterized_protocol_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Iterator, Iterable class Foo(object): @@ -101,7 +101,7 @@ def f(x: Iterable[int]): errors, {"e": r"\(x: Iterable\[int\]\).*\(x: Foo\)"}) def test_check_parameterized_protocol_multi_signature(self): - self.Check("""\ + self.Check(""" from typing import Sequence, Union class Foo(object): @@ -118,7 +118,7 @@ def f(x: Sequence[int]): """) def test_check_parameterized_protocol_error_multi_signature(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Sequence, Union class Foo(object): @@ -256,7 +256,7 @@ def f(s: Iterable[T]) -> T: ... """, pythonpath=[d.path]) def test_inherited_abstract_method_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Iterator class Foo(object): def __iter__(self) -> Iterator[str]: @@ -314,7 +314,7 @@ def f(x: Hashable): """) def test_list_hash(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Hashable def f(x: Hashable): pass @@ -323,7 +323,7 @@ def f(x: Hashable): self.assertErrorRegexes(errors, {"e": r"Hashable.*List.*__hash__"}) def test_hash_constant(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Hashable class Foo(object): __hash__ = None @@ -388,7 +388,7 @@ def f(x: Appendable): """) def test_custom_protocol_error(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing_extensions import Protocol class Appendable(Protocol): def append(self): @@ -433,7 +433,7 @@ def append(self) -> None: """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(ty)) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo class NotAppendable(object): pass @@ -458,7 +458,7 @@ def remove(self): """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(ty)) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from foo import Mutable class NotMutable(object): def remove(self): @@ -504,7 +504,7 @@ def count(self) -> int: """) def test_check_method_body(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing_extensions import Protocol class Countable(Protocol): def count(self) -> int: diff --git a/pytype/tests/py3/test_pyi.py b/pytype/tests/py3/test_pyi.py index af897d7f6..7d68b92a7 100644 --- a/pytype/tests/py3/test_pyi.py +++ b/pytype/tests/py3/test_pyi.py @@ -8,12 +8,12 @@ class PYITest(test_base.TargetPython3BasicTest): """Tests for PYI.""" def testUnneccessaryAnyImport(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing def foo(**kwargs: typing.Any) -> int: return 1 def bar(*args: typing.Any) -> int: return 2 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ typing = ... # type: module def foo(**kwargs) -> int: ... def bar(*args) -> int: ... diff --git a/pytype/tests/py3/test_recovery.py b/pytype/tests/py3/test_recovery.py index 1709b945c..5888ad7d8 100644 --- a/pytype/tests/py3/test_recovery.py +++ b/pytype/tests/py3/test_recovery.py @@ -7,7 +7,7 @@ class RecoveryTests(test_base.TargetPython3BasicTest): """Tests for recovering after errors.""" def testFunctionWithUnknownDecorator(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from nowhere import decorator # import-error @decorator def f(): @@ -19,7 +19,7 @@ def g(x: int) -> None: def testComplexInit(self): """Test that we recover when __init__ triggers a utils.TooComplexError.""" - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import AnyStr class X(object): def __init__(self, diff --git a/pytype/tests/py3/test_reingest.py b/pytype/tests/py3/test_reingest.py index 78eaab9f2..50823b877 100644 --- a/pytype/tests/py3/test_reingest.py +++ b/pytype/tests/py3/test_reingest.py @@ -16,7 +16,7 @@ def f(x: T) -> T: return x """, deep=False) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(foo)) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f("") # wrong-arg-types[e] """, pythonpath=[d.path]) @@ -54,7 +54,7 @@ def foo(self): """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(foo)) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.Foo() # not-instantiable[e] foo.Bar() diff --git a/pytype/tests/py3/test_slots.py b/pytype/tests/py3/test_slots.py index b585b88a5..91ab8b517 100644 --- a/pytype/tests/py3/test_slots.py +++ b/pytype/tests/py3/test_slots.py @@ -14,7 +14,7 @@ class Foo(object): """) def testSlotWithBytes(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" class Foo(object): # bad-slots __slots__ = (b"x",) """) diff --git a/pytype/tests/py3/test_stdlib.py b/pytype/tests/py3/test_stdlib.py index aa1ae3fe9..8fb1ad252 100644 --- a/pytype/tests/py3/test_stdlib.py +++ b/pytype/tests/py3/test_stdlib.py @@ -11,7 +11,7 @@ class StdLibTestsBasic(test_base.TargetPython3BasicTest, def testCollectionsDeque(self): # This method is different from the preceding ones because we model # collections.deque as a subclass, rather than an alias, of typing.Deque. - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Deque import collections def f1(x: Deque): ... @@ -22,7 +22,7 @@ def f2(x: int): ... self.assertErrorRegexes(errors, {"e": r"int.*deque"}) def testCollectionsDequeInit(self): - ty = self.Infer("""\ + ty = self.Infer(""" import collections x = collections.deque([1, 2, 3], maxlen=10) """) @@ -32,7 +32,7 @@ def testCollectionsDequeInit(self): """) def testPartial(self): - self.Check("""\ + self.Check(""" import functools from typing import TypeVar T = TypeVar('T', float, str) @@ -150,7 +150,7 @@ def f(fi: typing.IO) -> Union[bytes, str]: ... """) def testDefaultDict(self): - self.Check("""\ + self.Check(""" import collections import itertools ids = collections.defaultdict(itertools.count(17).__next__) diff --git a/pytype/tests/py3/test_super.py b/pytype/tests/py3/test_super.py index bad37fa94..fd4059bc3 100644 --- a/pytype/tests/py3/test_super.py +++ b/pytype/tests/py3/test_super.py @@ -66,7 +66,7 @@ def call_inner(a) -> int """) def test_super_without_args_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): def m(self): pass diff --git a/pytype/tests/py3/test_tracebacks.py b/pytype/tests/py3/test_tracebacks.py index d2922d793..3e872fb4c 100644 --- a/pytype/tests/py3/test_tracebacks.py +++ b/pytype/tests/py3/test_tracebacks.py @@ -7,7 +7,7 @@ class TracebackTest(test_base.TargetPython3BasicTest): """Tests for tracebacks in error messages.""" def test_build_class(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def f(self, x: Bar): # name-error[e] pass diff --git a/pytype/tests/py3/test_tuple.py b/pytype/tests/py3/test_tuple.py index 0e4326dad..c6c5eda09 100644 --- a/pytype/tests/py3/test_tuple.py +++ b/pytype/tests/py3/test_tuple.py @@ -8,7 +8,7 @@ class TupleTest(test_base.TargetPython3BasicTest): """Tests for __builtin__.tuple.""" def testUnpackInlineTuple(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Tuple def f(x: Tuple[str, int]): return x @@ -53,7 +53,7 @@ def f() -> tuple: """) def testTuplePrinting(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Tuple def f(x: Tuple[str, ...]): pass @@ -102,7 +102,7 @@ def testInlineTupleError(self): from typing import Tuple class A(Tuple[str, int]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Tuple, Type import foo def f(x: Type[Tuple[int, str]]): @@ -145,7 +145,7 @@ def testMismatchedPyiTuple(self): d.create_file("bar.pyi", """ class Bar(tuple): ... """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Tuple import bar def foo() -> Tuple[bar.Bar, bar.Bar]: @@ -158,7 +158,7 @@ class TupleTestPython3Feature(test_base.TargetPython3FeatureTest): """Tests for __builtin__.tuple.""" def testIteration(self): - ty = self.Infer("""\ + ty = self.Infer(""" class Foo(object): mytuple = (1, "foo", 3j) def __getitem__(self, pos): @@ -174,7 +174,7 @@ def __getitem__(self, pos: int) -> int or str or complex """) def testBadUnpackingWithSlurp(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" a, *b, c = (1,) # bad-unpacking[e] """) self.assertErrorRegexes(errors, {"e": r"1 value.*3 variables"}) diff --git a/pytype/tests/py3/test_type_comments.py b/pytype/tests/py3/test_type_comments.py index aee187d82..e3e0b24d1 100644 --- a/pytype/tests/py3/test_type_comments.py +++ b/pytype/tests/py3/test_type_comments.py @@ -7,14 +7,14 @@ class FunctionCommentWithAnnotationsTest(test_base.TargetPython3BasicTest): """Tests for type comments that require annotations.""" def testFunctionTypeCommentPlusAnnotations(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(x: int) -> float: # type: (int) -> float # redundant-function-type-comment return x """) def testListComprehensionComments(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List def f(x: str): pass @@ -22,7 +22,7 @@ def g(xs: List[str]) -> List[str]: ys = [f(x) for x in xs] # type: List[str] return ys """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import List def f(x: str) -> None: ... def g(xs: List[str]) -> List[str]: ... diff --git a/pytype/tests/py3/test_typevar.py b/pytype/tests/py3/test_typevar.py index 5f28b4f7a..a33291d60 100644 --- a/pytype/tests/py3/test_typevar.py +++ b/pytype/tests/py3/test_typevar.py @@ -68,7 +68,7 @@ def testImportTypeVarNameChange(self): T = TypeVar("T") X = TypeVar("X") """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" # This is illegal: A TypeVar("T") needs to be stored under the name "T". from a import T as T2 # invalid-typevar[e1] from a import X @@ -78,7 +78,7 @@ def f(x: T2) -> T2: ... self.assertErrorRegexes(errors, {"e1": r"T.*T2", "e2": r"X.*Y"}) def testMultipleSubstitution(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Dict, Tuple, TypeVar K = TypeVar("K") V = TypeVar("V") @@ -97,7 +97,7 @@ def f(x: Dict[K, V]) -> Tuple[V, K]: ... """) def testUnion(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import TypeVar, Union S = TypeVar("S") T = TypeVar("T") @@ -116,7 +116,7 @@ def f(x: S, y: T) -> Union[S, T]: ... """) def testBadSubstitution(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List, TypeVar S = TypeVar("S") T = TypeVar("T") @@ -139,7 +139,7 @@ def f4(x: S, y: T, z: T) -> List[S]: "e4": r"List\[bool\].*List\[Union\[float, int\]\]"}) def testUseConstraints(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", int, float) def f(x: T) -> T: @@ -159,7 +159,7 @@ def f(x: T) -> T: ... self.assertErrorRegexes(errors, {"e": r"Union\[float, int\].*str"}) def testTypeParameterType(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Type, TypeVar T = TypeVar("T") def f(x: Type[T]) -> T: @@ -174,7 +174,7 @@ def f(x: Type[T]) -> T: ... """) def testPrintNestedTypeParameter(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List, TypeVar T = TypeVar("T", int, float) def f(x: List[T]): ... @@ -184,7 +184,7 @@ def f(x: List[T]): ... "e": r"List\[Union\[float, int\]\].*List\[str\]"}) def testConstraintSubtyping(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", int, float) def f(x: T, y: T): ... @@ -194,7 +194,7 @@ def f(x: T, y: T): ... self.assertErrorRegexes(errors, {"e": r"Expected.*y: bool.*Actual.*y: int"}) def testFilterValue(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", int, float) def f(x: T, y: T): ... @@ -207,7 +207,7 @@ def f(x: T, y: T): ... errors, {"e": r"Expected.*y: float.*Actual.*y: int"}) def testFilterClass(self): - self.Check("""\ + self.Check(""" from typing import TypeVar class A(object): pass class B(object): pass @@ -221,7 +221,7 @@ def f(x: T, y: T): ... """) def testSplit(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import TypeVar T = TypeVar("T", int, type(None)) def f(x: T) -> T: @@ -242,7 +242,7 @@ def f(x: T) -> T: ... """) def testEnforceNonConstrainedTypeVar(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T") def f(x: T, y: T): ... @@ -258,7 +258,7 @@ def f(x: T, y: T): ... "e2": r"Expected.*y: float.*Actual.*y: str"}) def testUselessTypeVar(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import Tuple, TypeVar T = TypeVar("T") S = TypeVar("S", int, float) @@ -274,7 +274,7 @@ def f8(x: "U") -> "U": ... # ok """) def testUseBound(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", bound=float) def f(x: T) -> T: @@ -298,7 +298,7 @@ def f(x: T) -> T self.assertErrorRegexes(errors, {"e": r"x: float.*x: str"}) def testBadReturn(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ from typing import AnyStr, Dict class Foo(object): @@ -308,7 +308,7 @@ def g(self) -> Dict[AnyStr, Dict[AnyStr, AnyStr]]: """) def testOptionalTypeVar(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Optional, TypeVar T = TypeVar("T", bound=str) def f() -> Optional[T]: @@ -397,15 +397,13 @@ class TypeVarTestPy3(test_base.TargetPython3FeatureTest): def testUseConstraintsFromPyi(self): with file_utils.Tempdir() as d: - # pylint: disable=g-backslash-continuation - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ from typing import AnyStr, TypeVar T = TypeVar("T", int, float) def f(x: T) -> T: ... def g(x: AnyStr) -> AnyStr: ... """) - # pylint: enable=g-backslash-continuation - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f("") # wrong-arg-types[e1] foo.g(0) # wrong-arg-types[e2] diff --git a/pytype/tests/py3/test_typing.py b/pytype/tests/py3/test_typing.py index af34aceae..9381a7bd6 100644 --- a/pytype/tests/py3/test_typing.py +++ b/pytype/tests/py3/test_typing.py @@ -36,7 +36,7 @@ def test_sequence_match(self): self._test_no_match("[1.1, 2.1, 3.1]", "typing.Sequence[int]") def test_generator(self): - self.Check("""\ + self.Check(""" from typing import Generator def f() -> Generator[int, None, None]: for i in range(3): @@ -44,7 +44,7 @@ def f() -> Generator[int, None, None]: """) def test_type(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Type class Foo: x = 1 @@ -77,7 +77,7 @@ def f4(foo: Type[Foo]) -> Foo """) def test_type_union(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Type, Union class Foo: bar = ... # type: int @@ -113,7 +113,7 @@ def test_callable(self): from typing import Callable def f() -> Callable """) - self.Check("""\ + self.Check(""" from typing import Callable import foo def f() -> Callable: @@ -123,7 +123,7 @@ def g() -> Callable: """, pythonpath=[d.path]) def test_callable_parameters(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Any, Callable # The below are all valid. @@ -176,7 +176,7 @@ def g9(x: Callable[[], Any]) -> None: ... "e10": r"Callable\[_ARGS, _RET].*2.*1"}) def test_callable_bad_args(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Callable lst1 = [str] lst1[0] = int @@ -210,7 +210,7 @@ def test_generics(self): V = TypeVar("V") class CustomDict(Dict[K, V]): ... """) - self.Check("""\ + self.Check(""" import typing import foo def f(x: typing.Callable[..., int]): pass @@ -269,7 +269,7 @@ class Any(object): """) def test_callable_call(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Callable f = ... # type: Callable[[int], str] v1 = f() # wrong-arg-count[e1] @@ -289,7 +289,7 @@ def test_callable_call(self): errors, {"e1": r"1.*0", "e2": r"int.*float", "e3": r"1.*2"}) def test_callable_call_with_type_parameters(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Callable, TypeVar T = TypeVar("T") def f(g: Callable[[T, T], T], y, z): @@ -319,7 +319,7 @@ def test_callable_call_with_return_only(self): """) def test_callable_call_with_varargs_and_kwargs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable f = ... # type: Callable[[], int] f(x=3) # wrong-keyword-args[e1] @@ -331,7 +331,7 @@ def test_callable_call_with_varargs_and_kwargs(self): "e4": r"hello"}) def test_callable_attribute(self): - self.Check("""\ + self.Check(""" from typing import Any, Callable def foo(fn: Callable[[Any], Any]): fn.foo # pytype: disable=attribute-error @@ -409,7 +409,7 @@ def func7(a: MySpecialA) -> A: ... """) def test_new_type_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import NewType MyInt = NewType('MyInt', int) MyStr = NewType('MyStr', str) @@ -457,28 +457,28 @@ def g() -> str: """) def test_union_ellipsis(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Union MyUnion = Union[int, ...] # invalid-annotation[e] """) self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*Union"}) def test_list_ellipsis(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import List MyList = List[int, ...] # invalid-annotation[e] """) self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*List"}) def test_multiple_ellipses(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Union MyUnion = Union[..., int, ..., str, ...] # invalid-annotation[e] """) self.assertErrorRegexes(errors, {"e": r"Ellipsis.*indices 0, 2, 4.*Union"}) def test_bad_tuple_ellipsis(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Tuple MyTuple1 = Tuple[..., ...] # invalid-annotation[e1] MyTuple2 = Tuple[...] # invalid-annotation[e2] @@ -487,7 +487,7 @@ def test_bad_tuple_ellipsis(self): "e2": r"Ellipsis.*index 0.*Tuple"}) def test_bad_callable_ellipsis(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Callable MyCallable1 = Callable[..., ...] # invalid-annotation[e1] MyCallable2 = Callable[[int], ...] # invalid-annotation[e2] @@ -501,7 +501,7 @@ def test_bad_callable_ellipsis(self): "e4": r"Callable\[_ARGS, _RET].*2.*3"}) def test_optional_parameters(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import Optional def func1(x: Optional[int]): @@ -518,7 +518,7 @@ def func3(x: Optional[int, float, str]): # invalid-annotation[e2] "e2": r"typing\.Optional can only contain one type parameter"}) def test_noreturn_parameters(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import NoReturn, List def func0() -> NoReturn: @@ -545,7 +545,7 @@ def func4(x: List[NoReturn]): # invalid-annotation[e4] "e5": r"NoReturn is not allowed"}) def test_SupportsComplex(self): - self.Check("""\ + self.Check(""" from typing import SupportsComplex def foo(x: SupportsComplex): pass @@ -630,14 +630,14 @@ def test_import_all(self): self.assertTypesMatchPytd(ty, "") def test_callable_func_name(self): - self.Check("""\ + self.Check(""" from typing import Any, Callable def foo(fn: Callable[[Any], Any]) -> str: return fn.__qualname__ """) def test_classvar(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import ClassVar class A(object): x: ClassVar[int] = 5 diff --git a/pytype/tests/py3/test_typing_methods.py b/pytype/tests/py3/test_typing_methods.py index a75ae230b..3323e6d6d 100644 --- a/pytype/tests/py3/test_typing_methods.py +++ b/pytype/tests/py3/test_typing_methods.py @@ -16,7 +16,7 @@ def test_mapping(self): class MyDict(Mapping[K, V]): ... def f() -> MyDict[str, int] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo m = foo.f() a = m.copy() diff --git a/pytype/tests/py3/test_typing_namedtuple.py b/pytype/tests/py3/test_typing_namedtuple.py index d51f14c62..a224fc224 100644 --- a/pytype/tests/py3/test_typing_namedtuple.py +++ b/pytype/tests/py3/test_typing_namedtuple.py @@ -8,7 +8,7 @@ class NamedTupleTest(test_base.TargetPython3BasicTest): """Tests for the typing.NamedTuple overlay.""" def test_make(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing A = typing.NamedTuple("A", [("b", str), ("c", str)]) a = A._make(["hello", "world"]) @@ -20,7 +20,7 @@ def f(e: A) -> None: pass """) def test_subclass(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing A = typing.NamedTuple("A", [("b", str), ("c", int)]) class B(A): @@ -51,7 +51,7 @@ def foo(x: X): "def foo(x: X) -> Callable: ...") def test_bare_union_attribute(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import NamedTuple, Union X = NamedTuple("X", [("x", Union)]) # invalid-annotation[e] def foo(x: X): @@ -66,7 +66,7 @@ class NamedTupleTestPy3(test_base.TargetPython3FeatureTest): """Tests for the typing.NamedTuple overlay in Python 3.6.""" def test_basic_namedtuple(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing X = typing.NamedTuple("X", [("a", int), ("b", str)]) x = X(1, "hello") @@ -75,7 +75,7 @@ def test_basic_namedtuple(self): """) self.assertTypesMatchPytd( ty, - """\ + """ import collections from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar, Union typing = ... # type: module @@ -115,7 +115,7 @@ def foo(x: X): "def foo(x: X) -> Union[bytes, str]: ...") def test_bad_call(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" from typing import NamedTuple E2 = NamedTuple('Employee2', [('name', str), ('id', int)], birth=str, gender=bool) # invalid-namedtuple-arg[e1] # wrong-keyword-args[e2] @@ -125,7 +125,7 @@ def test_bad_call(self): "e2": r".*(birth, gender).*NamedTuple"}) def test_bad_attribute(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" from typing import NamedTuple class SubCls(NamedTuple): # not-writable[e] @@ -135,7 +135,7 @@ def __init__(self): self.assertErrorRegexes(errorlog, {"e": r".*'__init__'.*[SubCls]"}) def test_bad_arg_count(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" from typing import NamedTuple class SubCls(NamedTuple): @@ -147,7 +147,7 @@ class SubCls(NamedTuple): self.assertErrorRegexes(errorlog, {"e": r"Missing.*'b'.*__new__"}) def test_bad_arg_name(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import NamedTuple class SubCls(NamedTuple): # invalid-namedtuple-arg @@ -158,7 +158,7 @@ class SubCls(NamedTuple): # invalid-namedtuple-arg """) def test_namedtuple_class(self): - self.Check("""\ + self.Check(""" from typing import NamedTuple class SubNamedTuple(NamedTuple): @@ -181,7 +181,7 @@ def func(): """) def test_baseclass(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import NamedTuple class baseClass(object): @@ -193,7 +193,7 @@ class SubNamedTuple(baseClass, NamedTuple): """) self.assertTypesMatchPytd( ty, - """\ + """ import collections from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar @@ -225,7 +225,7 @@ class baseClass(object): """) def test_namedtuple_class_pyi(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import NamedTuple class SubNamedTuple(NamedTuple): @@ -247,7 +247,7 @@ def func(): """) self.assertTypesMatchPytd( ty, - """\ + """ import collections from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar, Union diff --git a/pytype/tests/py3/test_variable_annotations.py b/pytype/tests/py3/test_variable_annotations.py index a9b0706cb..8f2ddb1d9 100644 --- a/pytype/tests/py3/test_variable_annotations.py +++ b/pytype/tests/py3/test_variable_annotations.py @@ -17,7 +17,7 @@ class A(object): a: int b: str """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo def f(x: int) -> None: pass @@ -34,7 +34,7 @@ class VariableAnnotationsFeatureTest(test_base.TargetPython3FeatureTest): """Tests for PEP526 variable annotations.""" def testInferTypes(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List lst: List[int] = [] @@ -46,7 +46,7 @@ class A(object): a: int = 1 b = 2 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import List lst: List[int] @@ -59,7 +59,7 @@ class A(object): """) def testIllegalAnnotations(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List, TypeVar, NoReturn T = TypeVar('T') @@ -102,7 +102,7 @@ def testUninitializedModuleAnnotation(self): """) def testOverwriteAnnotationsDict(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" __annotations__ = None foo: int # unsupported-operands[e] """) @@ -135,12 +135,12 @@ class Foo: """) def testClassVariableForwardReference(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): a: 'A' = ... x = 42 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ class A(object): a: A x: int @@ -149,13 +149,13 @@ class A(object): def testCallableForwardReference(self): # Callable[['A']...] creates an instance of A during output generation, # which previously caused a crash when iterating over existing instances. - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Callable class A(object): def __init__(self, fn: Callable[['A'], bool]): self.fn = fn """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Callable class A(object): fn: Callable[[A], bool] diff --git a/pytype/tests/test_abc.py b/pytype/tests/test_abc.py index 1811989c2..6a1ece664 100644 --- a/pytype/tests/test_abc.py +++ b/pytype/tests/test_abc.py @@ -15,14 +15,14 @@ class Example(metaclass=abc.ABCMeta): @abc.abstractmethod def foo(self) -> None: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.Example() # not-instantiable[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"foo\.Example.*foo"}) def test_stray_abstractmethod(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import abc class Example(object): # ignored-abstractmethod[e] @abc.abstractmethod @@ -58,7 +58,7 @@ class Interface(metaclass=abc.ABCMeta): def foo(self): ... class Foo(X, Interface): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.Foo().foo() # not-instantiable[e] """, pythonpath=[d.path]) @@ -101,7 +101,7 @@ def foo(self): """, pythonpath=[d.path]) def test_misplaced_abstractproperty(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import abc @abc.abstractproperty class Example(object): diff --git a/pytype/tests/test_attr.py b/pytype/tests/test_attr.py index 1bf3ef6fb..69a2fe0e6 100644 --- a/pytype/tests/test_attr.py +++ b/pytype/tests/test_attr.py @@ -140,7 +140,7 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s class Foo(object): # invalid-annotation @@ -150,7 +150,7 @@ class Foo(object): # invalid-annotation """) def test_bad_type(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s class Foo(object): @@ -270,7 +270,7 @@ def __init__(self, x: list = ...) -> None: ... """) def test_bad_factory(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import attr @attr.s class Foo(object): @@ -281,7 +281,7 @@ class Foo(object): "e2": r"Callable.*int"}) def test_default_factory_clash(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import attr @attr.s class Foo(object): @@ -381,7 +381,7 @@ def __init__(self, y: int) -> None: ... """) def test_init_bad_constant(self): - err = self.CheckWithErrors("""\ + err = self.CheckWithErrors(""" import attr @attr.s class Foo(object): @@ -390,7 +390,7 @@ class Foo(object): self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_init_bad_kwarg(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s class Foo: @@ -599,7 +599,7 @@ class Foo(object): """) def test_init_bad_constant(self): - err = self.CheckWithErrors("""\ + err = self.CheckWithErrors(""" import attr @attr.s(init=0) # wrong-arg-types[e] class Foo: @@ -608,7 +608,7 @@ class Foo: self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_bad_kwarg(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import attr @attr.s(init=__random__) # not-supported-yet class Foo: diff --git a/pytype/tests/test_attributes.py b/pytype/tests/test_attributes.py index 5b6719e8d..91a819abe 100644 --- a/pytype/tests/test_attributes.py +++ b/pytype/tests/test_attributes.py @@ -23,7 +23,7 @@ def f(self): """) def testClassConstantError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" x = None class Foo(object): x = x.upper() # attribute-error[e] @@ -31,7 +31,7 @@ class Foo(object): self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMultiplePaths(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" x = None def f(): z = None if __random__ else x @@ -82,7 +82,7 @@ def f(): """, pythonpath=[d.path]) def testReturnValue(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): pass def g(): @@ -91,7 +91,7 @@ def g(): self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMethodReturnValue(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def f(self): pass @@ -103,7 +103,7 @@ def g(): def testPyiReturnValue(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", "def f() -> None: ...") - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo def g(): return foo.f().upper() # attribute-error[e] @@ -111,7 +111,7 @@ def g(): self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testPassThroughNone(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(x): return x def g(): @@ -144,7 +144,7 @@ def g(): """) def testReturnConstant(self): - self.Check("""\ + self.Check(""" x = None def f(): return x @@ -153,14 +153,14 @@ def g(): """) def testUnpackedNone(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" _, a = 42, None b = a.upper() # attribute-error[e] """) self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testFunctionDefault(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(self, v=None): v.upper() # attribute-error[e] @@ -248,7 +248,7 @@ def f() -> Any """) def testGetItem(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): x = None return x[0] # unsupported-operands[e] @@ -270,7 +270,7 @@ def f(): """) def testContains(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): x = None return 42 in x # unsupported-operands[e] @@ -497,7 +497,7 @@ def f(x) -> Any @test_base.skip("TODO(b/63407497): implement strict checking for __setitem__") def testUnionSetAttribute(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" class A(object): x = "Hello world" def f(i): @@ -560,7 +560,7 @@ def __getattribute__(self, name) -> int """) def testHasDynamicAttributes(self): - self.Check("""\ + self.Check(""" class Foo1(object): has_dynamic_attributes = True class Foo2(object): @@ -573,7 +573,7 @@ class Foo3(object): """) def testHasDynamicAttributesSubClass(self): - self.Check("""\ + self.Check(""" class Foo(object): _HAS_DYNAMIC_ATTRIBUTES = True class Bar(Foo): @@ -584,7 +584,7 @@ class Bar(Foo): def testHasDynamicAttributesClassAttr(self): # Only instance attributes are dynamic. - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): _HAS_DYNAMIC_ATTRIBUTES = True Foo.CONST # attribute-error[e] @@ -615,7 +615,7 @@ def testHasDynamicAttributesPYI(self): class Foo(object): has_dynamic_attributes = True """) - self.Check("""\ + self.Check(""" import mod mod.Foo().baz """, pythonpath=[d.path]) @@ -638,7 +638,7 @@ class Bar(mod.Foo): """, pythonpath=[d.path]) def testAttrOnStaticMethod(self): - self.Check("""\ + self.Check(""" import collections X = collections.namedtuple("X", "a b") @@ -653,7 +653,7 @@ def testModuleTypeAttribute(self): """) def testAttrOnNone(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(arg): x = "foo" if arg else None if not x: @@ -661,7 +661,7 @@ def f(arg): """) def testIteratorOnNone(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(): pass a, b = f() # attribute-error @@ -714,7 +714,7 @@ def __init__(self) -> None: ... @test_base.skip("Needs vm._get_iter() to iterate over individual bindings.") def testBadIter(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" v = [] if __random__ else 42 for _ in v: # attribute-error[e] pass @@ -722,7 +722,7 @@ def testBadIter(self): self.assertErrorRegexes(errors, {"e": r"__iter__.*int"}) def testBadGetItem(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __getitem__(self, x): return 0 @@ -733,7 +733,7 @@ def __getitem__(self, x): self.assertErrorRegexes(errors, {"e": r"__iter__.*int.*Union\[Foo, int\]"}) def testBadContains(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __iter__(self): return iter([]) @@ -746,12 +746,11 @@ def __iter__(self): def testSubclassShadowing(self): with file_utils.Tempdir() as d: - # pylint: disable=g-backslash-continuation - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ class X: b = ... # type: int """) - self.Check("""\ + self.Check(""" import foo a = foo.X() a.b # The attribute exists diff --git a/pytype/tests/test_base.py b/pytype/tests/test_base.py index 52b2bdbbd..283f50a64 100644 --- a/pytype/tests/test_base.py +++ b/pytype/tests/test_base.py @@ -74,6 +74,19 @@ def _MatchLoaderConfig(options, loader): return True +def _Format(code): + # Removes the leading newline introduced by writing, e.g., + # self.Check(""" + # code + # """) + if test_utils.ANNOTATIONS_IMPORT + "\n\n" in code: + code = code.replace(test_utils.ANNOTATIONS_IMPORT + "\n\n", + test_utils.ANNOTATIONS_IMPORT + "\n") + elif code.startswith("\n"): + code = code[1:] + return textwrap.dedent(code) + + class BaseTest(unittest.TestCase): """Base class for implementing tests that check PyTD output.""" @@ -179,11 +192,10 @@ def Check(self, code, pythonpath=(), skip_repeat_calls=True, self.ConfigureOptions(skip_repeat_calls=skip_repeat_calls, pythonpath=pythonpath, quick=quick) try: - src = "" if six.PY3: - src = textwrap.dedent(code) + src = _Format(code) else: - src = textwrap.dedent(code.decode("utf-8")) + src = _Format(code.decode("utf-8")) errorlog = test_utils.TestErrorLog(code) if errorlog.expected: self.fail("Cannot assert errors with Check(); use CheckWithErrors()") @@ -200,7 +212,7 @@ def assertNoCrash(self, method, code, **kwargs): method(code, report_errors=False, **kwargs) def _SetUpErrorHandling(self, code, pythonpath, analyze_annotated, quick): - code = textwrap.dedent(code) + code = _Format(code) errorlog = test_utils.TestErrorLog(code) self.ConfigureOptions( pythonpath=pythonpath, analyze_annotated=analyze_annotated, quick=quick) @@ -352,7 +364,7 @@ def Infer(self, srccode, pythonpath=(), deep=True, report_errors=True, analyze_annotated=True, pickle=False, module_name=None, **kwargs): types, builtins_pytd = self._InferAndVerify( - textwrap.dedent(srccode), pythonpath=pythonpath, deep=deep, + _Format(srccode), pythonpath=pythonpath, deep=deep, analyze_annotated=analyze_annotated, module_name=module_name, report_errors=report_errors, **kwargs) types = optimize.Optimize(types, builtins_pytd, lossy=False, use_abcs=False, diff --git a/pytype/tests/test_base_test.py b/pytype/tests/test_base_test.py index 18b6a63de..f860fa30a 100644 --- a/pytype/tests/test_base_test.py +++ b/pytype/tests/test_base_test.py @@ -14,7 +14,7 @@ def _lineno(self, line): return line def test_error_comments(self): - err = self.CheckWithErrors("""\ + err = self.CheckWithErrors(""" a = 10 # a random comment b = "hello" + 3 # unsupported-operands[.mark] c = (10).foo # attribute-error @@ -30,7 +30,7 @@ def test_error_comments(self): self._lineno(4): [("wrong-arg-types", ".another_mark")]}) def test_multiple_errors_one_line(self): - err = self.CheckWithErrors("""\ + err = self.CheckWithErrors(""" x = (10).foo, "hello".foo # attribute-error[e1] # attribute-error[e2] """) line = self._lineno(1) @@ -53,7 +53,7 @@ def test_duplicate_mark(self): self.assertEqual(str(ctx.exception), "Mark e already used") def test_error_matching(self): - err = self.CheckWithErrors("""\ + err = self.CheckWithErrors(""" a = 10 b = "hello" c = a + b # unsupported-operands @@ -68,7 +68,7 @@ def test_mismatched_error(self): def test_unexpected_error(self): with self.assertRaises(AssertionError) as ctx: - self.CheckWithErrors("""\ + self.CheckWithErrors(""" (10).foo # attribute-error "hello".foo """) diff --git a/pytype/tests/test_basic.py b/pytype/tests/test_basic.py index 493c7e63c..ebd82df70 100644 --- a/pytype/tests/test_basic.py +++ b/pytype/tests/test_basic.py @@ -10,7 +10,7 @@ def test_constant(self): self.Check("17") def test_for_loop(self): - self.Check("""\ + self.Check(""" out = "" for i in range(5): out = out + str(i) @@ -18,7 +18,7 @@ def test_for_loop(self): """) def test_inplace_operators(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ x, y = 2, 3 x **= y assert x == 8 and y == 3 @@ -47,7 +47,7 @@ def test_inplace_operators(self): """) def test_inplace_division(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ x, y = 24, 3 x /= y assert x == 8 and y == 3 @@ -84,83 +84,83 @@ def f6() -> str """) def test_slice_assignment(self): - self.Check("""\ + self.Check(""" l = list(range(10)) l[3:8] = ["x"] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) l[:8] = ["x"] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) l[3:] = ["x"] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) l[:] = ["x"] print(l) """) def test_slice_deletion(self): - self.Check("""\ + self.Check(""" l = list(range(10)) del l[3:8] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) del l[:8] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) del l[3:] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) del l[:] print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) del l[::2] print(l) """) def test_building_stuff(self): - self.Check("""\ + self.Check(""" print((1+1, 2+2, 3+3)) """) - self.Check("""\ + self.Check(""" print([1+1, 2+2, 3+3]) """) - self.Check("""\ + self.Check(""" print({1:1+1, 2:2+2, 3:3+3}) """) def test_subscripting(self): - self.Check("""\ + self.Check(""" l = list(range(10)) print("%s %s %s" % (l[0], l[3], l[9])) """) - self.Check("""\ + self.Check(""" l = list(range(10)) l[5] = 17 print(l) """) - self.Check("""\ + self.Check(""" l = list(range(10)) del l[5] print(l) """) def test_generator_expression(self): - self.Check("""\ + self.Check(""" x = "-".join(str(z) for z in range(5)) assert x == "0-1-2-3-4" """) @@ -169,7 +169,7 @@ def test_generator_expression2(self): # From test_regr.py # This failed a different way than the previous join when genexps were # broken: - self.Check("""\ + self.Check(""" from textwrap import fill x = set(['test_str']) width = 70 @@ -181,31 +181,31 @@ def test_generator_expression2(self): """) def test_list_comprehension(self): - self.Check("""\ + self.Check(""" x = [z*z for z in range(5)] assert x == [0, 1, 4, 9, 16] """) def test_dict_comprehension(self): - self.Check("""\ + self.Check(""" x = {z:z*z for z in range(5)} assert x == {0:0, 1:1, 2:4, 3:9, 4:16} """) def test_set_comprehension(self): - self.Check("""\ + self.Check(""" x = {z*z for z in range(5)} assert x == {0, 1, 4, 9, 16} """) def test_list_slice(self): - self.Check("""\ + self.Check(""" [1, 2, 3][1:2] """) def test_strange_sequence_ops(self): # from stdlib: test/test_augassign.py - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ x = [1,2] x += [3,4] x *= 2 @@ -222,13 +222,13 @@ def test_strange_sequence_ops(self): """) def test_unary_operators(self): - self.Check("""\ + self.Check(""" x = 8 print(-x, ~x, not x) """) def test_attributes(self): - self.Check("""\ + self.Check(""" l = lambda: 1 # Just to have an object... l.foo = 17 print(hasattr(l, "foo"), l.foo) @@ -237,7 +237,7 @@ def test_attributes(self): """) def test_attribute_inplace_ops(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ l = lambda: 1 # Just to have an object... l.foo = 17 l.foo -= 3 @@ -245,7 +245,7 @@ def test_attribute_inplace_ops(self): """) def test_deleting_names(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" g = 17 assert g == 17 del g @@ -253,7 +253,7 @@ def test_deleting_names(self): """) def test_deleting_local_names(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(): l = 23 assert l == 23 @@ -263,7 +263,7 @@ def f(): """) def test_import(self): - self.Check("""\ + self.Check(""" import math print(math.pi, math.e) from math import sqrt @@ -273,7 +273,7 @@ def test_import(self): """) def test_classes(self): - self.Check("""\ + self.Check(""" class Thing(object): def __init__(self, x): self.x = x @@ -286,7 +286,7 @@ def meth(self, y): """) def test_class_mros(self): - self.Check("""\ + self.Check(""" class A(object): pass class B(A): pass class C(A): pass @@ -297,7 +297,7 @@ class E(C, B): pass """) def test_class_mro_method_calls(self): - self.Check("""\ + self.Check(""" class A(object): def f(self): return 'A' class B(A): pass @@ -308,7 +308,7 @@ class D(B, C): pass """) def test_calling_methods_wrong(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Thing(object): def __init__(self, x): self.x = x @@ -320,7 +320,7 @@ def meth(self, y): self.assertErrorRegexes(errors, {"e": r"self"}) def test_calling_subclass_methods(self): - self.Check("""\ + self.Check(""" class Thing(object): def foo(self): return 17 @@ -333,7 +333,7 @@ class SubThing(Thing): """) def test_other_class_methods(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Thing(object): def foo(self): return 17 @@ -348,7 +348,7 @@ def bar(self): self.assertErrorRegexes(errors, {"e": r"foo.*SubThing"}) def test_attribute_access(self): - self.Check("""\ + self.Check(""" class Thing(object): z = 17 def __init__(self): @@ -360,7 +360,7 @@ def __init__(self): """) def test_attribute_access_error(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Thing(object): z = 17 def __init__(self): @@ -371,7 +371,7 @@ def __init__(self): self.assertErrorRegexes(errors, {"e": r"xyzzy.*Thing"}) def test_staticmethods(self): - self.Check("""\ + self.Check(""" class Thing(object): @staticmethod def smeth(x): @@ -385,7 +385,7 @@ def cmeth(cls, x): """) def test_unbound_methods(self): - self.Check("""\ + self.Check(""" class Thing(object): def meth(self, x): print(x) @@ -394,7 +394,7 @@ def meth(self, x): """) def test_callback(self): - self.Check("""\ + self.Check(""" def lcase(s): return s.lower() l = ["xyz", "ABC"] @@ -404,7 +404,7 @@ def lcase(s): """) def test_unpacking(self): - self.Check("""\ + self.Check(""" a, b, c = (1, 2, 3) assert a == 1 assert b == 2 @@ -412,7 +412,7 @@ def test_unpacking(self): """) def test_jump_if_true_or_pop(self): - self.Check("""\ + self.Check(""" def f(a, b): return a or b assert f(17, 0) == 17 @@ -421,7 +421,7 @@ def f(a, b): """) def test_jump_if_false_or_pop(self): - self.Check("""\ + self.Check(""" def f(a, b): return not(a and b) assert f(17, 0) is True @@ -431,7 +431,7 @@ def f(a, b): """) def test_pop_jump_if_true(self): - self.Check("""\ + self.Check(""" def f(a): if not a: return 'foo' @@ -442,7 +442,7 @@ def f(a): """) def test_decorator(self): - self.Check("""\ + self.Check(""" def verbose(func): def _wrapper(*args, **kwargs): return func(*args, **kwargs) @@ -460,7 +460,7 @@ def test_multiple_classes(self): # across classes. This test would fail because A.__init__ would be # over-written with B.__init__, and A(1, 2, 3) would complain about # too many arguments. - self.Check("""\ + self.Check(""" class A(object): def __init__(self, a, b, c): self.sum = a + b + c @@ -486,7 +486,7 @@ def baz(): """) def test_delete_global(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" a = 3 def f(): global a @@ -506,14 +506,14 @@ class TestLoops(test_base.TargetIndependentTest): """Loop tests.""" def test_for(self): - self.Check("""\ + self.Check(""" for i in range(10): print(i) print("done") """) def test_break(self): - self.Check("""\ + self.Check(""" for i in range(10): print(i) if i == 7: @@ -523,7 +523,7 @@ def test_break(self): def test_continue(self): # fun fact: this doesn't use CONTINUE_LOOP - self.Check("""\ + self.Check(""" for i in range(10): if i % 3 == 0: continue @@ -532,7 +532,7 @@ def test_continue(self): """) def test_continue_in_try_except(self): - self.Check("""\ + self.Check(""" for i in range(10): try: if i % 3 == 0: @@ -544,7 +544,7 @@ def test_continue_in_try_except(self): """) def test_continue_in_try_finally(self): - self.Check("""\ + self.Check(""" for i in range(10): try: if i % 3 == 0: @@ -560,7 +560,7 @@ class TestComparisons(test_base.TargetIndependentTest): """Comparison tests.""" def test_in(self): - self.Check("""\ + self.Check(""" assert "x" in "xyz" assert "x" not in "abc" assert "x" in ("x", "y", "z") @@ -568,7 +568,7 @@ def test_in(self): """) def test_less(self): - self.Check("""\ + self.Check(""" assert 1 < 3 assert 1 <= 2 and 1 <= 1 assert "a" < "b" @@ -576,7 +576,7 @@ def test_less(self): """) def test_greater(self): - self.Check("""\ + self.Check(""" assert 3 > 1 assert 3 >= 1 and 3 >= 3 assert "z" > "a" @@ -587,12 +587,12 @@ def test_greater(self): class TestSlices(test_base.TargetIndependentTest): def test_slice_with_step(self): - self.Check("""\ + self.Check(""" [0][1:-2:2] """) def test_slice_on_unknown(self): - self.Check("""\ + self.Check(""" __any_object__[1:-2:2] """) diff --git a/pytype/tests/test_builtins2.py b/pytype/tests/test_builtins2.py index 5b9e646d2..c2595c461 100644 --- a/pytype/tests/test_builtins2.py +++ b/pytype/tests/test_builtins2.py @@ -177,7 +177,7 @@ def testModule(self): d.create_file("foo.pyi", """ x = ... # type: module """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo foo.x.bar() x = foo.__name__ @@ -196,7 +196,7 @@ def testClassMethod(self): class A(object): x = ... # type: classmethod """) - ty = self.Infer("""\ + ty = self.Infer(""" from foo import A y = A.x() z = A().x() @@ -214,7 +214,7 @@ def testStaticMethod(self): class A(object): x = ... # type: staticmethod """) - ty = self.Infer("""\ + ty = self.Infer(""" from foo import A y = A.x() z = A().x() @@ -344,7 +344,7 @@ def testSum(self): """) def testReversed(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" x1 = reversed(range(42)) x2 = reversed([42]) x3 = reversed((4, 2)) @@ -394,7 +394,7 @@ def testBytearrayJoin(self): """) def testReduce(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" reduce(lambda x, y: x+y, [1,2,3]).real reduce(lambda x, y: x+y, ["foo"]).upper() reduce(lambda x, y: 4, "foo").real # attribute-error[e] @@ -508,7 +508,7 @@ def testTupleInit(self): """) def testEmptyTuple(self): - self.Check("""\ + self.Check(""" isinstance(42, ()) issubclass(int, ()) type("X", (), {"foo": 42}) @@ -516,7 +516,7 @@ def testEmptyTuple(self): """) def testListExtend(self): - ty = self.Infer("""\ + ty = self.Infer(""" x1 = [42] x1.extend([""]) x2 = [42] @@ -624,7 +624,7 @@ def testSetDefaultOneArg(self): """) def testSetDefaultVarargs(self): - ty = self.Infer("""\ + ty = self.Infer(""" x1 = {} y1 = x1.setdefault(*("foo", 42)) @@ -682,7 +682,7 @@ def testExec(self): d.create_file("foo.pyi", """ x = exec """) - self.Check("""\ + self.Check(""" import foo foo.x("a = 2") """, pythonpath=[d.path]) diff --git a/pytype/tests/test_builtins3.py b/pytype/tests/test_builtins3.py index 06d51739d..df5c1746b 100644 --- a/pytype/tests/test_builtins3.py +++ b/pytype/tests/test_builtins3.py @@ -66,7 +66,7 @@ def testNextFunction(self): """) def testImplicitTypeVarImport(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" v = %s # name-error """ % abstract_utils.T) self.assertTypesMatchPytd(ty, """ @@ -91,7 +91,7 @@ def testClassOfType(self): @test_base.skip("broken") def testClear(self): - ty = self.Infer("""\ + ty = self.Infer(""" x = {1, 2} x.clear() y = {"foo": 1} @@ -122,7 +122,7 @@ def testRepr(self): """) def testIntInit(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" int() int(0) int("0") @@ -135,13 +135,12 @@ def testIntInit(self): def testNewlines(self): with file_utils.Tempdir() as d: - # pylint: disable=g-backslash-continuation - d.create_file("newlines.txt", """\ + d.create_file("newlines.txt", """ 1 2 3 """) - self.Check("""\ + self.Check(""" l = [] with open("newlines.txt", "rU") as f: for line in f: @@ -172,7 +171,7 @@ def testHasAttrNone(self): self.assertNoCrash(self.Check, "hasattr(int, None)") def testNumberAttrs(self): - ty = self.Infer("""\ + ty = self.Infer(""" a = (42).denominator b = (42).numerator c = (42).real @@ -207,7 +206,7 @@ def testBuiltins(self): """) def testSpecialBuiltinTypes(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" isinstance(1, int) isinstance(1, "no") # wrong-arg-types issubclass(int, object) @@ -344,7 +343,7 @@ def testInput(self): """) def testSetDefaultError(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" x = {} y = x.setdefault() # wrong-arg-count[e1] z = x.setdefault(1, 2, 3, *[]) # wrong-arg-count[e2] diff --git a/pytype/tests/test_calls.py b/pytype/tests/test_calls.py index 34fc22670..fbef81793 100644 --- a/pytype/tests/test_calls.py +++ b/pytype/tests/test_calls.py @@ -12,7 +12,7 @@ def testOptional(self): d.create_file("mod.pyi", """ def foo(x: int, y: int = ..., z: int = ...) -> int """) - self.Check("""\ + self.Check(""" import mod mod.foo(1) mod.foo(1, 2) @@ -24,7 +24,7 @@ def testMissing(self): d.create_file("mod.pyi", """ def foo(x, y) -> int """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import mod mod.foo(1) # missing-parameter """, pythonpath=[d.path]) @@ -34,7 +34,7 @@ def testExtraneous(self): d.create_file("mod.pyi", """ def foo(x, y) -> int """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import mod mod.foo(1, 2, 3) # wrong-arg-count """, pythonpath=[d.path]) @@ -44,7 +44,7 @@ def testMissingKwOnly(self): d.create_file("mod.pyi", """ def foo(x, y, *, z) -> int """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import mod mod.foo(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) @@ -55,7 +55,7 @@ def testExtraKeyword(self): d.create_file("mod.pyi", """ def foo(x, y) -> int """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import mod mod.foo(1, 2, z=3) # wrong-keyword-args """, pythonpath=[d.path]) @@ -66,7 +66,7 @@ def testVarArgsWithKwOnly(self): def foo(*args: int, z: int) -> int """) self.Check( - """\ + """ import mod mod.foo(1, 2, z=3) """, pythonpath=[d.path]) @@ -76,7 +76,7 @@ def testVarArgsWithMissingKwOnly(self): d.create_file("mod.pyi", """ def foo(*args: int, z: int) -> int """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import mod mod.foo(1, 2, 3) # missing-parameter[e] """, pythonpath=[d.path]) diff --git a/pytype/tests/test_classes.py b/pytype/tests/test_classes.py index a59eca1dc..8a30e3ed9 100644 --- a/pytype/tests/test_classes.py +++ b/pytype/tests/test_classes.py @@ -209,7 +209,7 @@ def __init__(self, x) -> NoneType """) def testSuperError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Base(object): def __init__(self, x, y, z): pass @@ -779,7 +779,7 @@ class X(int, object, metaclass=A): """) def testUnionBaseClass(self): - self.Check("""\ + self.Check(""" import typing class A(tuple): pass class B(tuple): pass @@ -897,20 +897,20 @@ class B(A[T]): ... class C(A[T], B[T]): ... def f() -> C[int]: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f() # mro-error[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"C"}) def testCallParameterizedClass(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import List List[str]() # not-callable """) def testErrorfulConstructors(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" class Foo(object): attr = 42 def __new__(cls): @@ -931,7 +931,7 @@ def f(self) -> int: ... """) def testNewFalse(self): - ty = self.Infer("""\ + ty = self.Infer(""" class Foo(object): def __new__(cls): return False @@ -948,7 +948,7 @@ def f(self) -> str: ... """) def testNewAmbiguous(self): - ty = self.Infer("""\ + ty = self.Infer(""" class Foo(object): def __new__(cls): if __random__: @@ -1027,7 +1027,7 @@ def __init__(self, a, b): """, pythonpath=[d.path]) def testSuperNewWrongArgCount(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __new__(cls, x): return super(Foo, cls).__new__(cls, x) # wrong-arg-count[e] @@ -1035,7 +1035,7 @@ def __new__(cls, x): self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperInitWrongArgCount(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __init__(self, x): super(Foo, self).__init__(x) # wrong-arg-count[e] @@ -1043,7 +1043,7 @@ def __init__(self, x): self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperNewMissingParameter(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __new__(cls, x): # Even when __init__ is defined, too few args is an error. @@ -1054,7 +1054,7 @@ def __init__(self, x): self.assertErrorRegexes(errors, {"e": r"cls.*__new__"}) def testNewKwarg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __new__(cls): # ok because __init__ is defined. @@ -1068,7 +1068,7 @@ def __new__(cls): self.assertErrorRegexes(errors, {"e": r"x.*__new__"}) def testInitKwarg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __init__(self): # ok because __new__ is defined. @@ -1113,7 +1113,7 @@ def __new__(cls, x): """, pythonpath=[d.path]) def testInitWithNoParams(self): - self.Check("""\ + self.Check(""" class Foo(object): def __init__(): pass @@ -1128,7 +1128,7 @@ def testInstantiateWithAbstractDict(self): """) def testNotInstantiable(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" class Foo(object): def __new__(cls): assert cls is not Foo, "not instantiable" @@ -1150,7 +1150,7 @@ class Bar(object): """) def testSubclassContainsBase(self): - ty = self.Infer("""\ + ty = self.Infer(""" def get_c(): class C(object): def __init__(self, z): @@ -1165,7 +1165,7 @@ def __init__(self, z): def bar(self, x): pass x = DC(1) """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any class DC(object): a = ... # type: int @@ -1179,7 +1179,7 @@ def get_c() -> type: ... """) def testSubclassMultipleBaseOptions(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): pass def get_base(): class B(object): pass @@ -1187,7 +1187,7 @@ class B(object): pass Base = A if __random__ else get_base() class C(Base): pass """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, Union def get_base() -> type: ... class A(object): pass @@ -1196,7 +1196,7 @@ class C(Any): pass """) def testSubclassContainsGenericBase(self): - ty = self.Infer("""\ + ty = self.Infer(""" import typing def get_base(): class C(typing.List[str]): @@ -1204,7 +1204,7 @@ def get_len(self): return len(self) return C class DL(get_base()): pass """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import List typing = ... # type: module class DL(List[str]): @@ -1213,7 +1213,7 @@ def get_base() -> type: ... """) def testSubclassOverridesBaseAttributes(self): - ty = self.Infer("""\ + ty = self.Infer(""" def get_base(): class B(object): def __init__(self): @@ -1229,7 +1229,7 @@ def __init__(self): self.c = "world" def bar(self, x): pass """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ def get_base() -> type: ... class C(object): a = ... # type: int @@ -1248,14 +1248,14 @@ def __init__(self): return C class BX(make_base(list)): pass """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ def make_base(x) -> type: ... class BX(list): x = ... # type: int """) def testSubclassBasesOverlap(self): - ty = self.Infer("""\ + ty = self.Infer(""" def make_a(): class A(object): def __init__(self): diff --git a/pytype/tests/test_cmp.py b/pytype/tests/test_cmp.py index 297122b42..d096182a3 100644 --- a/pytype/tests/test_cmp.py +++ b/pytype/tests/test_cmp.py @@ -8,7 +8,7 @@ class InTest(test_base.TargetIndependentTest): """Test for "x in y". Also test overloading of this operator.""" def test_concrete(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def f(x, y): return x in y # unsupported-operands[e] f(1, [1]) @@ -47,7 +47,7 @@ def g() -> bool """) def test_none(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = None if "" in x: # unsupported-operands[e1] del x[""] # unsupported-operands[e2] @@ -60,7 +60,7 @@ class NotInTest(test_base.TargetIndependentTest): """Test for "x not in y". Also test overloading of this operator.""" def test_concrete(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def f(x, y): return x not in y # unsupported-operands[e] f(1, [1]) @@ -93,7 +93,7 @@ def g() -> bool """) def test_none(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = None if "" not in x: # unsupported-operands[e1] x[""] = 42 # unsupported-operands[e2] diff --git a/pytype/tests/test_compile_to_pyc.py b/pytype/tests/test_compile_to_pyc.py index e98fdbf1f..8a859e092 100644 --- a/pytype/tests/test_compile_to_pyc.py +++ b/pytype/tests/test_compile_to_pyc.py @@ -15,14 +15,14 @@ def testCompilationOfUnicodeSourceWithEncoding(self): self.Check("#! my/python\n# encoding: utf-8\nprint('←↑→↓')") def testErrorLineNumbersWithEncoding1(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" # coding: utf-8 def foo(): return "1".hello # attribute-error """) def testErrorLineNumbersWithEncoding2(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" #! /bin/python # coding: utf-8 def foo(): diff --git a/pytype/tests/test_containers.py b/pytype/tests/test_containers.py index 85bbcf443..48ac24bfb 100644 --- a/pytype/tests/test_containers.py +++ b/pytype/tests/test_containers.py @@ -544,7 +544,7 @@ def testEqOperatorOnItemFromEmptyDict(self): """, deep=False) def testDict(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" mymap = {'a': 3.14, 'b':1} a = mymap['a'] b1 = mymap['b'] @@ -573,7 +573,7 @@ def testDictOrAny(self): """) def testDictGetItem(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" v = {} v.__getitem__("a") # key-error[e] """) diff --git a/pytype/tests/test_decorators.py b/pytype/tests/test_decorators.py index 21c79c1a0..24336086f 100644 --- a/pytype/tests/test_decorators.py +++ b/pytype/tests/test_decorators.py @@ -82,7 +82,7 @@ class Foo(object): """) def testBadKeyword(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __init__(self): self._bar = 1 @@ -296,7 +296,7 @@ def bar(cls): """) def testInstanceAsDecoratorError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Decorate(object): def __call__(self, func): return func @@ -310,7 +310,7 @@ def bar(cls): self.assertErrorRegexes(errors, {"e": r"Decorate.*1.*2"}) def testUncallableInstanceAsDecorator(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Decorate(object): pass # forgot to define __call__ class Foo(object): @@ -324,7 +324,7 @@ def bar(cls): errors, {"e1": r"Decorate.*1.*2", "e2": r"Decorate"}) def testAmbiguousClassMethod(self): - self.Check("""\ + self.Check(""" class Foo(): def __init__(self): pass diff --git a/pytype/tests/test_dict.py b/pytype/tests/test_dict.py index 7da5bea13..fc80b21d4 100644 --- a/pytype/tests/test_dict.py +++ b/pytype/tests/test_dict.py @@ -22,7 +22,7 @@ def testPop(self): """) def testBadPop(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" d = {"a": 42} v = d.pop("b") # key-error[e] """) diff --git a/pytype/tests/test_disables.py b/pytype/tests/test_disables.py index a0b7e269c..a9e5fbdad 100644 --- a/pytype/tests/test_disables.py +++ b/pytype/tests/test_disables.py @@ -7,7 +7,7 @@ class DisableTest(test_base.TargetIndependentTest): """Test error disabling.""" def testInvalidDirective(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = 1 # pytype: this is not a valid pytype directive. # invalid-directive """) # Invalid directives are just a warning, so has_error() should still @@ -15,7 +15,7 @@ def testInvalidDirective(self): self.assertFalse(errors.has_error()) def testInvalidDisableErrorName(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = 1 # pytype: disable=not-an-error. # invalid-directive[e] """) self.assertErrorRegexes(errors, {"e": r"Invalid error name.*not-an-error"}) @@ -24,7 +24,7 @@ def testInvalidDisableErrorName(self): self.assertFalse(errors.has_error()) def testDisableError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" x = a # name-error x = b # pytype: disable=name-error x = c # name-error @@ -32,7 +32,7 @@ def testDisableError(self): def testOpenEndedDirective(self): """Test that disables in the middle of the file can't be left open-ended.""" - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" '''This is a docstring. def f(x): pass @@ -58,7 +58,7 @@ def g(): pass self.assertFalse(errors.has_error()) def testSkipFile(self): - self.Check("""\ + self.Check(""" # pytype: skip-file name_error """) diff --git a/pytype/tests/test_errors.py b/pytype/tests/test_errors.py index 89d1e6fde..89358322b 100644 --- a/pytype/tests/test_errors.py +++ b/pytype/tests/test_errors.py @@ -8,7 +8,7 @@ class ErrorTest(test_base.TargetIndependentTest): """Tests for errors.""" def testDeduplicate(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): y = 42 y.foobar # attribute-error[e] @@ -18,14 +18,14 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"'foobar' on int$"}) def testUnknownGlobal(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): return foobar() # name-error[e] """) self.assertErrorRegexes(errors, {"e": r"foobar"}) def testInvalidAttribute(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" class A(object): pass def f(): @@ -41,35 +41,35 @@ def f() -> str self.assertErrorRegexes(errors, {"e": r"parrot.*int"}) def testImportError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import rumplestiltskin # import-error """) def testImportFromError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from sys import foobar # import-error[e] """) self.assertErrorRegexes(errors, {"e": r"sys\.foobar"}) def testNameError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" foobar # name-error """) def testWrongArgCount(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" hex(1, 2, 3, 4) # wrong-arg-count[e] """) self.assertErrorRegexes(errors, {"e": r"expects 1.*got 4"}) def testWrongArgTypes(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" hex(3j) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"int.*complex"}) def testInterpreterFunctionNameInMsg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(list): pass A.append(3) # missing-parameter[e] """) @@ -78,14 +78,14 @@ class A(list): pass def testPyTDFunctionNameInMsg(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", "class A(list): pass") - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.A.append(3) # missing-parameter[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"function list\.append"}) def testBuiltinFunctionNameInMsg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = list x += (1,2) # missing-parameter[e] """) @@ -97,13 +97,13 @@ def testRewriteBuiltinFunctionName(self): self.assertErrorRegexes(errors, {"e": r"Built-in function len"}) def testBoundMethodNameInMsg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" "".join(1) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Function str\.join"}) def testNestedClassMethodNameIsMsg(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class A(object): class B(object): def f(self): @@ -117,7 +117,7 @@ def testPrettyPrintWrongArgs(self): d.create_file("foo.pyi", """ def f(a: int, b: int, c: int, d: int, e: int): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f(1, 2, 3, "four", 5) # wrong-arg-types[e] """, pythonpath=[d.path]) @@ -125,7 +125,7 @@ def f(a: int, b: int, c: int, d: int, e: int): ... "e": r"a, b, c, d: int, [.][.][.].*a, b, c, d: str, [.][.][.]"}) def testInvalidBaseClass(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" class Foo(3): # base-class-error pass """) @@ -136,7 +136,7 @@ def testInvalidIteratorFromImport(self): class Codec(object): def __init__(self) -> None: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import mod def f(): for row in mod.Codec(): # attribute-error[e] @@ -146,7 +146,7 @@ def f(): self.assertErrorRegexes(errors, {"e": error}) def testInvalidIteratorFromClass(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): pass def f(): @@ -156,7 +156,7 @@ def f(): self.assertErrorRegexes(errors, {"e": r"__iter__.*A"}) def testIterOnModule(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import sys for _ in sys: # module-attr[e] pass @@ -171,7 +171,7 @@ def testInheritFromGeneric(self): class Foo(Generic[T]): ... class Bar(Foo[int]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import mod chr(mod.Bar()) # wrong-arg-types[e] """, pythonpath=[d.path]) @@ -183,7 +183,7 @@ def testWrongKeywordArg(self): d.create_file("mycgi.pyi", """ def escape(x: str or int) -> str or int """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import mycgi def foo(s): return mycgi.escape(s, quote=1) # wrong-keyword-args[e] @@ -195,14 +195,14 @@ def testMissingParameter(self): d.create_file("foo.pyi", """ def bar(xray, yankee, zulu) -> str """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.bar(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"zulu.*foo\.bar"}) def testBadInheritance(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" class X: pass class Bar(X): @@ -216,20 +216,20 @@ def testBadCall(self): d.create_file("other.pyi", """ def foo(x: int, y: str) -> str: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import other other.foo(1.2, []) # wrong-arg-types[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"\(x: int"}) def testCallUncallable(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" 0() # not-callable[e] """) self.assertErrorRegexes(errors, {"e": r"int"}) def testSuperError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): def __init__(self): super(A, self, "foo").__init__() # wrong-arg-count[e] @@ -239,7 +239,7 @@ def __init__(self): def testAttributeError(self): with file_utils.Tempdir() as d: d.create_file("modfoo.pyi", "") - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __getattr__(self, name): return "attr" @@ -263,7 +263,7 @@ def h(): "e4": r"No attribute 'baz' on module 'modfoo'"}) def testAttributeErrorGetAttribute(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __getattribute__(self, name): return "attr" @@ -275,7 +275,7 @@ def g(): self.assertErrorRegexes(errors, {"e": r"x"}) def testNoneAttribute(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" None.foo # attribute-error[e] """) self.assertErrorRegexes(errors, {"e": r"foo"}) @@ -285,14 +285,14 @@ def testPyiType(self): d.create_file("foo.pyi", """ def f(x: list[int]) -> int: ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f([""]) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"List\[int\].*List\[str\]"}) def testTooManyArgs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): pass f(3) # wrong-arg-count[e] @@ -300,7 +300,7 @@ def f(): self.assertErrorRegexes(errors, {"e": r"0.*1"}) def testTooFewArgs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): pass f() # missing-parameter[e] @@ -308,7 +308,7 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"x.*f"}) def testDuplicateKeyword(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x, y): pass f(3, x=3) # duplicate-keyword-argument[e] @@ -321,7 +321,7 @@ def testBadImport(self): def f() -> int: ... class f: ... """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import a # pyi-error """, pythonpath=[d.path]) @@ -331,7 +331,7 @@ def testBadImportDependency(self): from b import X class Y(X): ... """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import a # pyi-error """, pythonpath=[d.path]) @@ -342,7 +342,7 @@ def f() -> int: ... class f: ... """) d.create_file("foo/__init__.pyi", "") - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from foo import a # pyi-error[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"foo\.a"}) @@ -354,7 +354,7 @@ def testBadImportFromDependency(self): class Y(X): ... """) d.create_file("foo/__init__.pyi", "") - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from foo import a # pyi-error[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"foo\.a"}) @@ -365,7 +365,7 @@ def testBadContainer(self): from typing import SupportsInt class A(SupportsInt[int]): pass """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"SupportsInt is not a container"}) @@ -380,7 +380,7 @@ class A(Generic[K, V]): pass class B(Generic[K, V]): pass class C(A[K, V], B[V, K]): pass """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"Illegal.*order.*a\.C"}) @@ -392,7 +392,7 @@ def testDuplicateTypeParameter(self): T = TypeVar("T") class A(Generic[T, T]): pass """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"T"}) @@ -405,7 +405,7 @@ def testDuplicateGenericBaseClass(self): V = TypeVar("V") class A(Generic[T], Generic[V]): pass """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"inherit.*Generic"}) @@ -417,7 +417,7 @@ def testTypeParameterInModuleConstant(self): T = TypeVar("T") x = ... # type: T """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.x"}) @@ -430,7 +430,7 @@ def testTypeParameterInClassAttribute(self): class A(Generic[T]): x = ... # type: T """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a def f(): return a.A.x # unbound-type-param[e] @@ -445,7 +445,7 @@ def testUnboundTypeParameterInInstanceAttribute(self): class A(object): x = ... # type: T """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.A\.x"}) @@ -455,7 +455,7 @@ def testPrintUnionArg(self): d.create_file("a.pyi", """ def f(x: int or str) -> None """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a x = a.f(4.2) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) @@ -463,20 +463,20 @@ def f(x: int or str) -> None self.assertErrorRegexes(errors, {"e": pattern}) def testPrintTypeArg(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" hex(int) # wrong-arg-types[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"Actually passed.*Type\[int\]"}) def testDeleteFromSet(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" s = {1} del s[1] # unsupported-operands[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"item deletion"}) def testBadReference(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def main(): x = foo # name-error[e] for foo in []: @@ -491,7 +491,7 @@ def main() -> Any """) def testSetIntAttribute(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = 42 x.y = 42 # not-writable[e] """, deep=True) @@ -503,7 +503,7 @@ def testInvalidParametersOnMethod(self): class A(object): def __init__(self, x: int) -> None """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a x = a.A("") # wrong-arg-types[e1] x = a.A("", 42) # wrong-arg-count[e2] @@ -520,7 +520,7 @@ def testDuplicateKeywords(self): d.create_file("foo.pyi", """ def f(x, *args, y) -> None """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import foo foo.f(1, y=2) foo.f(1, 2, y=3) @@ -529,7 +529,7 @@ def f(x, *args, y) -> None """, deep=True, pythonpath=[d.path]) def testInvalidParametersDetails(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" float(list()) # wrong-arg-types[e1] float(1, list(), foobar=str) # wrong-arg-count[e2] float(1, foobar=list()) # wrong-keyword-args[e3] @@ -543,7 +543,7 @@ def testInvalidParametersDetails(self): }) def testBadSuperClass(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): def f(self): return "foo" @@ -556,7 +556,7 @@ def f(self): @test_base.skip("Need to type-check second argument to super") def testBadSuperInstance(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): pass class B(A): @@ -572,7 +572,7 @@ def testBadNameImport(self): import typing x = ... # type: typing.Rumpelstiltskin """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) @@ -584,7 +584,7 @@ def testBadNameImportFrom(self): from typing import Rumpelstiltskin x = ... # type: Rumpelstiltskin """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) @@ -599,7 +599,7 @@ class B(A): ... class C(object): ... def f(x: Type[A]) -> bool """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" import a x = a.f(a.A) y = a.f(a.B) @@ -624,7 +624,7 @@ class A(Generic[T]): ... class B(A[str]): ... def f(x: Type[A[int]]): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a x = a.f(a.B) # wrong-arg-types[e] """, pythonpath=[d.path], deep=True) @@ -640,7 +640,7 @@ class C(A, B): ... class D(B, A): ... class E(C, D): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a x = a.E() # mro-error[e] """, pythonpath=[d.path]) @@ -651,7 +651,7 @@ def testBadMRO(self): d.create_file("a.pyi", """ class A(BaseException, ValueError): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a class B(a.A): pass # mro-error[e] raise a.A() @@ -668,7 +668,7 @@ def __getattr__(name) -> Any from a import A class B(metaclass=A): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import b class C(b.B): def __init__(self): @@ -679,7 +679,7 @@ def __init__(self): def testDontTimeoutOnComplex(self): # Tests that we can solve a complex file without timing out. # Useful for catching large performance regressions. - ty = self.Infer("""\ + ty = self.Infer(""" if __random__: x = [1] else: @@ -703,7 +703,7 @@ def testFailedFunctionCall(self): def f(x: str, y: int) -> bool def f(x: str) -> bool """) - self.InferWithErrors("""\ + self.InferWithErrors(""" import a x = a.f(0, "") # wrong-arg-types """, pythonpath=[d.path]) @@ -714,7 +714,7 @@ def testNoncomputableMethod(self): T = TypeVar("T") def copy(x: T) -> T """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a class A(object): def __getattribute__(self, name): @@ -724,26 +724,26 @@ def __getattribute__(self, name): self.assertErrorRegexes(errors, {"e": r"A"}) def testBadTypeName(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = type(3, (int, object), {"a": 1}) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Actual.*int"}) def testBadTypeBases(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = type("X", (42,), {"a": 1}) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Actual.*Tuple\[int\]"}) def testHalfBadTypeBases(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = type("X", (42, object), {"a": 1}) # wrong-arg-types[e] """) self.assertErrorRegexes( errors, {"e": r"Actual.*Tuple\[int, Type\[object\]\]"}) def testBadTypeMembers(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = type("X", (int, object), {0: 1}) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"Actual.*Dict\[int, int\]"}) @@ -754,7 +754,7 @@ def testRecursion(self): class A(B): ... class B(A): ... """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" import a v = a.A() # recursion-error[e] x = v.x # No error because there is an Unsolvable in the MRO of a.A @@ -775,7 +775,7 @@ def f(x: Union): ... d.create_file("f2.pyi", """ def f(x: Optional): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import f1 # pyi-error[e1] import f2 # pyi-error[e2] """, pythonpath=[d.path]) @@ -783,7 +783,7 @@ def f(x: Optional): ... errors, {"e1": r"f1.*Union", "e2": r"f2.*Optional"}) def testBadDictAttribute(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" x = {"a": 1} y = x.a # attribute-error[e] """) @@ -795,23 +795,23 @@ def testBadPyiDict(self): from typing import Dict x = ... # type: Dict[str, int, float] """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import a # pyi-error[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"2.*3"}) def testCallNone(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" None() # not-callable """) def testInNone(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" 3 in None # unsupported-operands """) def testNoAttrError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" if __random__: y = 42 else: @@ -820,7 +820,7 @@ def testNoAttrError(self): """) def testAttrError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" if __random__: y = 42 else: @@ -830,7 +830,7 @@ def testAttrError(self): self.assertErrorRegexes(errors, {"e": r"upper.*int"}) def testPrintCallableInstance(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import Callable v = None # type: Callable[[int], str] hex(v) # wrong-arg-types[e] @@ -838,7 +838,7 @@ def testPrintCallableInstance(self): self.assertErrorRegexes(errors, {"e": r"Actual.*Callable\[\[int\], str\]"}) def testSameNameAndLine(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): return x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") @@ -852,7 +852,7 @@ def testKwargOrder(self): def f(*args, y, x, z: int): ... def g(x): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f(x=1, y=2, z="3") # wrong-arg-types[e1] foo.g(42, v4="the", v3="quick", v2="brown", v1="fox") # wrong-keyword-args[e2] @@ -861,7 +861,7 @@ def g(x): ... errors, {"e1": r"x, y, z.*x, y, z", "e2": r"v1, v2, v3, v4"}) def testBadBaseClass(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(None): pass # base-class-error[e1] class Bar(None if __random__ else 42): pass # base-class-error[e2] """) @@ -869,7 +869,7 @@ class Bar(None if __random__ else 42): pass # base-class-error[e2] "e2": r"Optional\[\]"}) def testCallableInUnsupportedOperands(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x, y=None): pass f in f # unsupported-operands[e] """) @@ -884,14 +884,14 @@ def testCleanPyiNamedtupleNames(self): X = NamedTuple("X", []) def f(x: int): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.f(foo.X()) # wrong-arg-types[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"`X`"}) def testBadAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" tuple[0] # not-indexable[e1] dict[1, 2] # invalid-annotation[e2] # invalid-annotation[e3] class A(object): pass @@ -902,7 +902,7 @@ class A(object): pass "e4": r"class A"}) def testRevealType(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" reveal_type(42 or "foo") # reveal-type[e1] class Foo(object): pass @@ -915,7 +915,7 @@ class Foo(object): "e4": r"^List\[int\]$"}) def testNotProtocol(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" a = [] a.append(1) a = "".join(a) # wrong-arg-types[e] @@ -924,7 +924,7 @@ def testNotProtocol(self): errors, {"e": r"\(.*List\[int\]\)$"}) # no protocol details def testHiddenError(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" use_option = False def f(): if use_option: @@ -932,7 +932,7 @@ def f(): """) def testUnknownInError(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(x): y = x if __random__ else None return y.groups() # attribute-error[e] @@ -944,41 +944,41 @@ class OperationsTest(test_base.TargetIndependentTest): """Test operations.""" def testXor(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' ^ 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\^.*str.*int.*'__xor__' on str.*'__rxor__' on int"}) def testAdd(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' + 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\+.*str.*int.*__add__ on str.*str"}) def testInvert(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return ~None # unsupported-operands[e] """) self.assertErrorRegexes(errors, {"e": r"\~.*None.*'__invert__' on None"}) def testSub(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' - 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\-.*str.*int.*'__sub__' on str.*'__rsub__' on int"}) def testMul(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' * None # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\*.*str.*None.*__mul__ on str.*int"}) def testDiv(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' / 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { @@ -986,61 +986,61 @@ def f(): return 'foo' / 3 # unsupported-operands[e] }) def testMod(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return None % 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, {"e": r"\%.*None.*int.*'__mod__' on None"}) def testLShift(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 3 << None # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\<\<.*int.*None.*__lshift__ on int.*int"}) def testRShift(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 3 >> None # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\>\>.*int.*None.*__rshift__ on int.*int"}) def testAnd(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' & 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\&.*str.*int.*'__and__' on str.*'__rand__' on int"}) def testOr(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' | 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\|.*str.*int.*'__or__' on str.*'__ror__' on int"}) def testFloorDiv(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 3 // 'foo' # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\/\/.*int.*str.*__floordiv__ on int.*int"}) def testPow(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 3 ** 'foo' # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"\*\*.*int.*str.*__pow__ on int.*int"}) def testNeg(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return -None # unsupported-operands[e] """) self.assertErrorRegexes(errors, {"e": r"\-.*None.*'__neg__' on None"}) def testPos(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return +None # unsupported-operands[e] """) self.assertErrorRegexes(errors, {"e": r"\+.*None.*'__pos__' on None"}) @@ -1050,7 +1050,7 @@ class InPlaceOperationsTest(test_base.TargetIndependentTest): """Test in-place operations.""" def testIAdd(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): v = []; v += 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { @@ -1061,14 +1061,14 @@ class NoSymbolOperationsTest(test_base.TargetIndependentTest): """Test operations with no native symbol.""" def testGetItem(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): v = []; return v['foo'] # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"item retrieval.*List.*str.*__getitem__ on List.*int"}) def testDelItem(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): v = {'foo': 3}; del v[3] # unsupported-operands[e] """) d = r"Dict\[str, int\]" @@ -1076,21 +1076,21 @@ def f(): v = {'foo': 3}; del v[3] # unsupported-operands[e] "e": r"item deletion.*{d}.*int.*__delitem__ on {d}.*str".format(d=d)}) def testSetItem(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): v = []; v['foo'] = 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"item assignment.*List.*str.*__setitem__ on List.*int"}) def testContains(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return 'foo' in 3 # unsupported-operands[e] """) self.assertErrorRegexes(errors, { "e": r"'in'.*int.*str.*'__contains__' on int"}) def testRecursion(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def f(): if __random__: f() diff --git a/pytype/tests/test_exceptions.py b/pytype/tests/test_exceptions.py index 44fb3c6fb..642c0b5fe 100644 --- a/pytype/tests/test_exceptions.py +++ b/pytype/tests/test_exceptions.py @@ -25,7 +25,7 @@ def f() -> int def test_catching_exceptions(self): # TODO(kramm): Don't warn about NameErrors that are being caught. # Catch the exception precisely - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ try: x[1] print("Shouldn't be here...") @@ -33,7 +33,7 @@ def test_catching_exceptions(self): print("caught it!") """) # Catch the exception by a parent class - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ try: x[1] print("Shouldn't be here...") @@ -41,7 +41,7 @@ def test_catching_exceptions(self): print("caught it!") """) # Catch all exceptions - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ try: x[1] print("Shouldn't be here...") @@ -56,7 +56,7 @@ def test_raise_exception_class(self): self.Check("raise ValueError") def test_raise_and_catch_exception(self): - self.Check("""\ + self.Check(""" try: raise ValueError("oops") except ValueError as e: @@ -65,7 +65,7 @@ def test_raise_and_catch_exception(self): """) def test_raise_and_catch_exception_in_function(self): - self.Check("""\ + self.Check(""" def fn(): raise ValueError("oops") @@ -79,7 +79,7 @@ def fn(): def test_global_name_error(self): self.CheckWithErrors("fooey # name-error") # TODO(kramm): Don't warn about NameErrors that are being caught. - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ try: fooey print("Yes fooey?") @@ -88,14 +88,14 @@ def test_global_name_error(self): """) def test_local_name_error(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def fn(): fooey # name-error fn() """) def test_catch_local_name_error(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ def fn(): try: fooey @@ -106,7 +106,7 @@ def fn(): """) def test_reraise(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def fn(): try: fooey # name-error @@ -118,7 +118,7 @@ def fn(): """) def test_reraise_explicit_exception(self): - self.Check("""\ + self.Check(""" def fn(): try: raise ValueError("ouch") @@ -129,7 +129,7 @@ def fn(): """) def test_finally_while_throwing(self): - self.Check("""\ + self.Check(""" def fn(): try: print("About to..") @@ -141,7 +141,7 @@ def fn(): """) def test_coverage_issue_92(self): - self.Check("""\ + self.Check(""" l = [] for i in range(3): try: @@ -155,7 +155,7 @@ def test_coverage_issue_92(self): """) def test_continue_in_except(self): - self.Check("""\ + self.Check(""" for i in range(3): try: pass @@ -309,7 +309,7 @@ def f() -> int """) def test_return_or_raise_set_attribute(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def f(): raise ValueError() def g(): @@ -321,7 +321,7 @@ def h(): """) def test_bad_type_self(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(self): type(42, self) # wrong-arg-count[e] @@ -368,7 +368,7 @@ def h() -> KeyError: ... """) def test_bad_type(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" try: pass except None: # mro-error[e1] diff --git a/pytype/tests/test_flow.py b/pytype/tests/test_flow.py index abda994de..5649bc7b1 100644 --- a/pytype/tests/test_flow.py +++ b/pytype/tests/test_flow.py @@ -334,7 +334,7 @@ def test_loop_over_list_of_lists(self): """) def test_call_undefined(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): try: func = None diff --git a/pytype/tests/test_functions.py b/pytype/tests/test_functions.py index 76e7aa1b3..5e209db58 100644 --- a/pytype/tests/test_functions.py +++ b/pytype/tests/test_functions.py @@ -3,15 +3,12 @@ from pytype import file_utils from pytype.tests import test_base -# We use backslashes to correct the line numbers in test code: -# pylint: disable=g-backslash-continuation - class TestClosures(test_base.TargetIndependentTest): """Tests for closures.""" def test_closures(self): - self.Check("""\ + self.Check(""" def make_adder(x): def add(y): return x+y @@ -22,7 +19,7 @@ def add(y): """) def test_closures_store_deref(self): - self.Check("""\ + self.Check(""" def make_adder(x): z = x+1 def add(y): @@ -34,7 +31,7 @@ def add(y): """) def test_empty_vs_deleted(self): - self.Check("""\ + self.Check(""" import collections Foo = collections.namedtuple('Foo', 'x') def f(): @@ -44,7 +41,7 @@ def g(): """) def test_closures_in_loop(self): - self.Check("""\ + self.Check(""" def make_fns(x): fns = [] for i in range(x): @@ -57,7 +54,7 @@ def make_fns(x): """) def test_closures_with_defaults(self): - self.Check("""\ + self.Check(""" def make_adder(x, y=13, z=43): def add(q, r=11): return x+y+z+q+r @@ -68,7 +65,7 @@ def add(q, r=11): """) def test_deep_closures(self): - self.Check("""\ + self.Check(""" def f1(a): b = 2*a def f2(c): @@ -108,7 +105,7 @@ def g(y): """) def test_unbound_closure_variable(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" def foo(): def bar(): return tuple(xs) # name-error @@ -121,7 +118,7 @@ class TestGenerators(test_base.TargetIndependentTest): """Tests for generators.""" def test_first(self): - self.Check("""\ + self.Check(""" def two(): yield 1 yield 2 @@ -130,7 +127,7 @@ def two(): """) def test_partial_generator(self): - self.Check("""\ + self.Check(""" from functools import partial def f(a,b): @@ -145,13 +142,13 @@ def f(a,b): """) def test_unsolvable(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ assert list(three) == [3,2,1] """) def test_yield_multiple_values(self): # TODO(kramm): The generator doesn't have __iter__? - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ def triples(): yield 1, 2, 3 yield 4, 5, 6 @@ -161,14 +158,14 @@ def triples(): """) def test_generator_reuse(self): - self.Check("""\ + self.Check(""" g = (x*x for x in range(5)) print(list(g)) print(list(g)) """) def test_generator_from_generator2(self): - self.Check("""\ + self.Check(""" g = (x*x for x in range(3)) print(list(g)) @@ -179,7 +176,7 @@ def test_generator_from_generator2(self): def test_generator_from_generator(self): # TODO(kramm): The generator doesn't have __iter__? - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ class Thing(object): RESOURCES = ('abc', 'def') def get_abc(self): @@ -208,7 +205,7 @@ def setUp(self): self.options.tweak(precise_return=True) def test_pytd_return(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" x = 'hello'.startswith(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, "x: bool") @@ -221,7 +218,7 @@ def test_param_return(self): T = TypeVar("T") def f(x: T) -> T: ... """) - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" import foo x = foo.f() # missing-parameter """, pythonpath=[d.path]) @@ -236,7 +233,7 @@ def test_binop(self): self.assertTypesMatchPytd(ty, "x: str") def test_inplace_op(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" x = [] x += 0 # unsupported-operands """) @@ -250,7 +247,7 @@ class TestFunctions(test_base.TargetIndependentTest): """Tests for functions.""" def test_functions(self): - self.Check("""\ + self.Check(""" def fn(a, b=17, c="Hello", d=[]): d.append(99) print(a, b, c, d) @@ -262,7 +259,7 @@ def fn(a, b=17, c="Hello", d=[]): """) def test_function_locals(self): - self.Check("""\ + self.Check(""" def f(): x = "Spite" print(x) @@ -277,7 +274,7 @@ def g(): """) def test_recursion(self): - self.Check("""\ + self.Check(""" def fact(n): if n <= 1: return 1 @@ -289,7 +286,7 @@ def fact(n): """) def test_calling_functions_with_args_kwargs(self): - self.Check("""\ + self.Check(""" def fn(a, b=17, c="Hello", d=[]): d.append(99) print(a, b, c, d) @@ -299,7 +296,7 @@ def fn(a, b=17, c="Hello", d=[]): """) def test_calling_functions_with_generator_args(self): - self.Check("""\ + self.Check(""" class A(object): def next(self): raise StopIteration() @@ -311,23 +308,23 @@ def f(*args): """) def test_defining_functions_with_args_kwargs(self): - self.Check("""\ + self.Check(""" def fn(*args): print("args is %r" % (args,)) fn(1, 2) """) - self.Check("""\ + self.Check(""" def fn(**kwargs): print("kwargs is %r" % (kwargs,)) fn(red=True, blue=False) """) - self.Check("""\ + self.Check(""" def fn(*args, **kwargs): print("args is %r" % (args,)) print("kwargs is %r" % (kwargs,)) fn(1, 2, red=True, blue=False) """) - self.Check("""\ + self.Check(""" def fn(x, y, *args, **kwargs): print("x is %r, y is %r" % (x, y)) print("args is %r" % (args,)) @@ -336,24 +333,24 @@ def fn(x, y, *args, **kwargs): """) def test_defining_functions_with_empty_args_kwargs(self): - self.Check("""\ + self.Check(""" def fn(*args): print("args is %r" % (args,)) fn() """) - self.Check("""\ + self.Check(""" def fn(**kwargs): print("kwargs is %r" % (kwargs,)) fn() """) - self.Check("""\ + self.Check(""" def fn(*args, **kwargs): print("args is %r, kwargs is %r" % (args, kwargs)) fn() """) def test_partial(self): - self.Check("""\ + self.Check(""" from functools import partial def f(a,b): @@ -365,7 +362,7 @@ def f(a,b): """) def test_partial_with_kwargs(self): - self.Check("""\ + self.Check(""" from functools import partial def f(a,b,c=0,d=0): @@ -384,7 +381,7 @@ def test_wraps(self): _AnyCallable = Callable[..., Any] def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> Callable[[_AnyCallable], _AnyCallable]: ... """) - self.Check("""\ + self.Check(""" from myfunctools import wraps def my_decorator(f): dec = wraps(f) @@ -434,7 +431,7 @@ def f(elements) -> str def test_named_arg_unsolvable_max_depth(self): # Main test here is for this not to throw a KeyError exception upon hitting # maximum depth. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): return max(foo=repr(__any_object__)) # wrong-keyword-args[e] """, deep=True, maximum_depth=1) @@ -558,7 +555,7 @@ class MyMatch(Generic[T]): pass def compile() -> MyPattern[T]: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.compile().match("") """, pythonpath=[d.path]) @@ -652,7 +649,7 @@ def h() -> Callable[[Any, Union[Tuple[Union[Tuple[type, ...], type], ...], type] """) def test_wrong_keyword(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): pass f("", y=42) # wrong-keyword-args[e] @@ -660,7 +657,7 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"y"}) def test_staticmethod_class(self): - ty = self.Infer("""\ + ty = self.Infer(""" v1, = (object.__new__,) v2 = type(object.__new__) """, deep=False) @@ -724,7 +721,7 @@ def f(self): """, pythonpath=[d.path]) def test_interpreter_function_in_class(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): bar = lambda x: x def f(self): @@ -734,13 +731,13 @@ def f(self): def test_nested_lambda(self): # Inspired by b/37869955 - self.Check("""\ + self.Check(""" def f(c): return lambda c: f(c) """) def test_nested_lambda2(self): - self.Check("""\ + self.Check(""" def f(d): return lambda c: f(c) """) @@ -752,7 +749,7 @@ def f(t): """) def test_set_defaults(self): - self.Check("""\ + self.Check(""" import collections X = collections.namedtuple("X", "a b c d") X.__new__.__defaults__ = (3, 4) @@ -763,22 +760,22 @@ def test_set_defaults(self): def test_set_defaults_non_new(self): with file_utils.Tempdir() as d: - d.create_file("a.pyi", """\ + d.create_file("a.pyi", """ def b(x: int, y: int, z: int): ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a a.b.__defaults__ = ('3',) a.b(1, 2) c = a.b """, deep=False, pythonpath=[d.path]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ a = ... # type: module def c(x: int, y: int, z: int = ...): ... """) def test_bad_defaults(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import collections X = collections.namedtuple("X", "a b c") X.__new__.__defaults__ = (1) # bad-function-defaults @@ -804,7 +801,7 @@ def test_set_defaults_to_expression(self): def test_set_defaults_non_tuple_instance(self): # Test that get_atomic_python_constant fails and get_atomic_value pulls out # a non-tuple Instance. - self.InferWithErrors("""\ + self.InferWithErrors(""" import collections X = collections.namedtuple("X", "a b c") X.__new__.__defaults__ = (lambda x: x)(0) # bad-function-defaults @@ -831,7 +828,7 @@ def test(a, b, c = 4): z = test(1, 2) z = test(1, 2, 3) """) - self.InferWithErrors("""\ + self.InferWithErrors(""" def test(a, b, c): return a + b + c x = test(1, 2) # missing-parameter @@ -841,7 +838,7 @@ def test(a, b, c): """) def test_interpreter_function_defaults_on_class(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" class Foo(object): def __init__(self, a, b, c): self.a = a @@ -873,7 +870,7 @@ def test_pyi_starargs(self): d.create_file("foo.pyi", """ def f(x: str, ...) -> None: ... """) - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import foo foo.f(True, False) # wrong-arg-types """, pythonpath=[d.path]) @@ -958,7 +955,7 @@ def __init__(self, a, b=None): """) def test_functools_partial_bad_call(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import functools functools.partial() # missing-parameter functools.partial(42) # wrong-arg-types[e] @@ -968,7 +965,7 @@ def test_functools_partial_bad_call(self): def test_bad_comprehensions(self): # Test that we report errors in comprehensions and generators only once # while still reporting errors in lambdas. - self.CheckWithErrors("""\ + self.CheckWithErrors(""" [name_error1 for x in ()] # name-error {name_error2 for x in ()} # name-error (name_error3 for x in ()) # name-error diff --git a/pytype/tests/test_future_overlay.py b/pytype/tests/test_future_overlay.py index fa705b7c1..744d756d1 100644 --- a/pytype/tests/test_future_overlay.py +++ b/pytype/tests/test_future_overlay.py @@ -33,7 +33,7 @@ def get_foo(self): """, pythonpath=[d.path]) def test_missing_import(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from future.utils import iteritems # import-error from future.utils import with_metaclass # import-error """) diff --git a/pytype/tests/test_import.py b/pytype/tests/test_import.py index 887338922..6b8a2502c 100644 --- a/pytype/tests/test_import.py +++ b/pytype/tests/test_import.py @@ -10,7 +10,7 @@ class ImportTest(test_base.TargetIndependentTest): """Tests for import.""" def testBasicImport(self): - ty = self.Infer("""\ + ty = self.Infer(""" import sys """) self.assertTypesMatchPytd(ty, """ @@ -18,7 +18,7 @@ def testBasicImport(self): """) def testBasicImport2(self): - ty = self.Infer("""\ + ty = self.Infer(""" import bad_import # doesn't exist """, report_errors=False) self.assertTypesMatchPytd(ty, """ @@ -26,7 +26,7 @@ def testBasicImport2(self): """) def testFromImportSmoke(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ from sys import exit from path.to.module import bar, baz """) @@ -35,7 +35,7 @@ def testLongFrom(self): with file_utils.Tempdir() as d: d.create_file("path/to/my_module.pyi", "def foo() -> str") - ty = self.Infer("""\ + ty = self.Infer(""" from path.to import my_module def foo(): return my_module.foo() @@ -46,12 +46,12 @@ def foo() -> str """) def testStarImportSmoke(self): - self.Check("""\ + self.Check(""" from sys import * """) def testStarImportUnknownSmoke(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ from unknown_module import * """) @@ -63,7 +63,7 @@ class A(object): pass a = ... # type: A """) - ty = self.Infer("""\ + ty = self.Infer(""" from my_module import * """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -96,7 +96,7 @@ class X: ... from a import * class Y(X): ... """) - ty = self.Infer("""\ + ty = self.Infer(""" from b import * """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -108,7 +108,7 @@ class Y(X): ... """) def testBadStarImport(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" from nonsense import * # import-error from other_nonsense import * # import-error x = foo.bar() @@ -125,7 +125,7 @@ def testPathImport(self): "def qqsv() -> str") d.create_file("path/to/__init__.pyi", "") d.create_file("path/__init__.pyi", "") - ty = self.Infer("""\ + ty = self.Infer(""" import path.to.my_module def foo(): return path.to.my_module.qqsv() @@ -141,7 +141,7 @@ def testPathImport2(self): "def qqsv() -> str") d.create_file("path/to/__init__.pyi", "") d.create_file("path/__init__.pyi", "") - ty = self.Infer("""\ + ty = self.Infer(""" import nonexistant_path.to.my_module # doesn't exist def foo(): return path.to.my_module.qqsv() @@ -153,13 +153,13 @@ def foo() -> ? """) def testImportAll(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ from module import * from path.to.module import * """) def testAssignMember(self): - self.Check("""\ + self.Check(""" import sys sys.path = [] """) @@ -446,7 +446,7 @@ def testDotDotInPyi(self): """) ty = self.InferFromFile(filename=d["foo/deep/bar.py"], pythonpath=[d.path]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ baz = ... # type: module a: int """) @@ -494,7 +494,7 @@ def testFileImport1(self): d.create_file("path/to/some/__init__.pyi", "") d.create_file("path/to/__init__.pyi", "") d.create_file("path/__init__.pyi", "") - ty = self.Infer("""\ + ty = self.Infer(""" import path.to.some.module def my_foo(x): return path.to.some.module.foo(x) @@ -511,7 +511,7 @@ def testFileImport2(self): d.create_file("path/to/some/__init__.pyi", "") d.create_file("path/to/__init__.pyi", "") d.create_file("path/__init__.pyi", "") - ty = self.Infer("""\ + ty = self.Infer(""" from path.to.some import module def my_foo(x): return module.foo(x) @@ -523,7 +523,7 @@ def my_foo(x) -> str @test_base.skip("flaky") def testSolveForImported(self): - ty = self.Infer("""\ + ty = self.Infer(""" import StringIO def my_foo(x): return x.read() @@ -540,7 +540,7 @@ def my_foo(x:StringIO.StringIO[object] or typing.IO[object] or """) def testImportBuiltins(self): - ty = self.Infer("""\ + ty = self.Infer(""" import __builtin__ as builtins def f(): @@ -574,7 +574,7 @@ def f1(self, x: Foo) -> Baz class Baz(object): pass """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo def f(x, y): return x.f1(y) @@ -603,7 +603,7 @@ def testImportedConstants(self): class Foo(object): x = ... # type: float """) - ty = self.Infer("""\ + ty = self.Infer(""" import module def f(): return module.x @@ -637,7 +637,7 @@ class Z(object): pass x = ... # type: x.X """) - ty = self.Infer("""\ + ty = self.Infer(""" import x xx = x.X() yy = x.y @@ -655,7 +655,7 @@ def testReimport(self): d.create_file("foo.pyi", """ from collections import OrderedDict as MyOrderedDict """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo d = foo.MyOrderedDict() """, deep=False, pythonpath=[d.path]) @@ -669,7 +669,7 @@ def testImportFunction(self): d.create_file("foo.pyi", """ from math import pow as mypow """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo d = foo.mypow """, deep=False, pythonpath=[d.path]) @@ -685,7 +685,7 @@ def testImportConstant(self): d.create_file("mymath.pyi", """ from math import pi as half_tau """) - ty = self.Infer("""\ + ty = self.Infer(""" import mymath from mymath import half_tau as x y = mymath.half_tau @@ -706,7 +706,7 @@ def testImportMap(self): """ % foo_filename) imports_map = imports_map_loader.build_imports_map( imports_map_filename) - ty = self.Infer("""\ + ty = self.Infer(""" from foo import bar """, deep=False, imports_map=imports_map, pythonpath=[""]) @@ -724,7 +724,7 @@ def __getattr__(name) -> Any: ... from a import Foo def f(x: Foo) -> Foo: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import b foo = b.Foo() bar = b.f(foo) @@ -746,7 +746,7 @@ def testTwoLevel(self): class B(a.A): pass """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import b # pyi-error[e] x = b.B() """, pythonpath=[d.path]) @@ -779,7 +779,7 @@ def testRedefinedBuiltin(self): object = ... # type: Any def f(x) -> Any """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f("") """, deep=False, pythonpath=[d.path]) @@ -796,7 +796,7 @@ class object: def foo(self) -> None: ... def f(x: object) -> object """) - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" import foo x = foo.f(foo.object()) y = foo.f(foo.object()) @@ -813,7 +813,7 @@ def testNoFailOnBadSymbolLookup(self): d.create_file("foo.pyi", """ def f(x: FooBar) -> FooBar """) - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ import foo """, pythonpath=[d.path]) @@ -823,7 +823,7 @@ def testImportTypeFactory(self): d.create_file("a.pyi", """ def factory() -> type """) - ty = self.Infer("""\ + ty = self.Infer(""" import a A = a.factory() """, deep=False, pythonpath=[d.path]) @@ -842,7 +842,7 @@ def testGetBadSubmoduleAsAttribute(self): """, pythonpath=[d.path]) def testIgnoredImport(self): - ty = self.Infer("""\ + ty = self.Infer(""" import sys # type: ignore import foobar # type: ignore from os import path # type: ignore @@ -867,7 +867,7 @@ def testAttributeOnModule(self): d.create_file("a.pyi", """ foo = ... # type: int """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from a import foo, bar # import-error[e1] import a a.baz # module-attr[e2] @@ -883,7 +883,7 @@ class bar(c.X): ... d.create_file("foo/c.pyi", """ class X(object): ... """) - self.Check("""\ + self.Check(""" from foo import b class Foo(b.bar): pass @@ -892,7 +892,7 @@ class Foo(b.bar): def testImportMapFilter(self): with file_utils.Tempdir() as d: imp_path = ".".join(d.path[1:].split("/")) - init_body = """\ + init_body = """ from {0}.foo import bar from {0}.foo import baz Qux = bar.Quack @@ -911,12 +911,12 @@ def testImportMapFilter(self): {2} {3} """.format(init_fn[1:-3], initpyi_fn, bar_fn[1:-3], barpyi_fn)) imports_map = imports_map_loader.build_imports_map(imports_fn, init_fn) - ty = self.Infer("""\ + ty = self.Infer(""" from {0}.foo import bar Adz = bar.Quack """.format(imp_path), deep=False, imports_map=imports_map, pythonpath=[""]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, Type bar = ... # type: module Adz = ... # type: Type[{0}.foo.bar.Quack] @@ -939,7 +939,7 @@ class Foo(): ... class Quux(Baz[T], Generic[T]): ... """) ty = self.Infer("""from pkg.a import *""", pythonpath=[d.path]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ import pkg.a import pkg.b from typing import Type, TypeVar @@ -967,14 +967,14 @@ class Y: ... d.create_file("pkg/g.pyi", """ class Z: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import pkg.a s = pkg.a.c.X() t = pkg.a.f() u = pkg.a.x v = u.Y() """, pythonpath=[d.path]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ import pkg.b import pkg.d import pkg.g @@ -1122,7 +1122,7 @@ def testUnimportedSubmoduleFailure(self): d.create_file("sub/bar/quux.pyi", "class B: ...") d.create_file("sub/__init__.pyi", "") d.create_file("sub/bar/__init__.pyi", "") - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import sub.bar.baz x = sub.bar.baz.A() y = sub.bar.quux.B() # module-attr[e] @@ -1133,7 +1133,7 @@ def testSubmoduleAttributeError(self): with file_utils.Tempdir() as d: d.create_file("package/__init__.pyi", "submodule: module") d.create_file("package/submodule.pyi", "") - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from package import submodule submodule.asd # module-attr """, pythonpath=[d.path]) @@ -1142,7 +1142,7 @@ def testInitOnlySubmodule(self): """Test a submodule without its own stub file.""" with file_utils.Tempdir() as d: d.create_file("package/__init__.pyi", "submodule: module") - self.Check("""\ + self.Check(""" from package import submodule submodule.asd """, pythonpath=[d.path]) diff --git a/pytype/tests/test_list.py b/pytype/tests/test_list.py index 98ece81f1..ded75d4fc 100644 --- a/pytype/tests/test_list.py +++ b/pytype/tests/test_list.py @@ -70,7 +70,7 @@ def test_extend_with_empty(self): """) def test_getitem_slot(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" a = [1, '2', 3, 4] b = a[1] c = 1 if __random__ else 2 @@ -79,7 +79,7 @@ def test_getitem_slot(self): f = a[-1] g = a[slice(1,2)] # should be List[str] """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, List, Union a = ... # type: List[Union[int, str]] b = ... # type: str diff --git a/pytype/tests/test_namedtuple.py b/pytype/tests/test_namedtuple.py index 72dd9e0f9..77a5796f1 100644 --- a/pytype/tests/test_namedtuple.py +++ b/pytype/tests/test_namedtuple.py @@ -79,7 +79,7 @@ def test_str_args2(self): """) def test_bad_fieldnames(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import collections collections.namedtuple("_", ["abc", "def", "ghi"]) # invalid-namedtuple-arg collections.namedtuple("_", "_") # invalid-namedtuple-arg @@ -99,7 +99,7 @@ def test_rename(self): ty, self._namedtuple_def(S=("S", ["abc", "_1", "ghi", "_3"]))) def test_bad_initialize(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from collections import namedtuple X = namedtuple("X", "y z") @@ -111,7 +111,7 @@ def test_bad_initialize(self): def test_class_name(self): ty = self.Infer( - """\ + """ import collections F = collections.namedtuple("S", ['a', 'b', 'c']) """) @@ -142,7 +142,7 @@ def test_instantiate_pyi_namedtuple(self): d.create_file("foo.pyi", """ class X(NamedTuple('X', [('y', str), ('z', int)])): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.X() # missing-parameter[e1] foo.X(0, "") # wrong-arg-types[e2] @@ -158,7 +158,7 @@ def test_use_pyi_namedtuple(self): d.create_file("foo.pyi", """ class X(NamedTuple("X", [])): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.X()._replace() foo.X().nonsense # attribute-error[e] diff --git a/pytype/tests/test_operators.py b/pytype/tests/test_operators.py index 28eb75490..89ff45524 100644 --- a/pytype/tests/test_operators.py +++ b/pytype/tests/test_operators.py @@ -324,7 +324,7 @@ def __rsub__(self, other): def test_unknown_right(self): # Reverse operators are rare enough that it makes sense to assume that the # regular operator was called when the right side is ambiguous. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __sub__(self, other): return "" @@ -368,7 +368,7 @@ def test_sub(self): self.check_inplace("isub", "-=") def test_list_add(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class A(object): pass v = [] v += A() # unsupported-operands[e] diff --git a/pytype/tests/test_pyi.py b/pytype/tests/test_pyi.py index a48637f15..ac103d532 100644 --- a/pytype/tests/test_pyi.py +++ b/pytype/tests/test_pyi.py @@ -26,7 +26,7 @@ def testOptional(self): d.create_file("mod.pyi", """ def f(x: int = ...) -> None """) - ty = self.Infer("""\ + ty = self.Infer(""" import mod def f(): return mod.f() @@ -44,7 +44,7 @@ def testSolve(self): d.create_file("mod.pyi", """ def f(node: int, *args, **kwargs) -> str """) - ty = self.Infer("""\ + ty = self.Infer(""" import mod def g(x): return mod.f(x) @@ -60,7 +60,7 @@ def testTyping(self): from typing import Any, IO, List, Optional def split(s: Optional[int]) -> List[str, ...]: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import mod def g(x): return mod.split(x) @@ -79,7 +79,7 @@ def foo(self) -> A class B(A): pass """) - ty = self.Infer("""\ + ty = self.Infer(""" import classes x = classes.B().foo() """, deep=False, pythonpath=[d.path]) @@ -94,7 +94,7 @@ def testEmptyModule(self): from typing import Any def __getattr__(name) -> Any """) - ty = self.Infer("""\ + ty = self.Infer(""" import vague x = vague.foo + vague.bar """, deep=False, pythonpath=[d.path]) @@ -114,7 +114,7 @@ def u(a, b) -> int: ... def v(cls, a, b) -> int: ... def w(self, a, b) -> int: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import decorated u = decorated.A.u(1, 2) v = decorated.A.v(1, 2) @@ -141,7 +141,7 @@ class A(object): def v(cls) -> float: ... def w(self, x: classmethod) -> int: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a u = a.A().w(a.A.v) """, deep=False, pythonpath=[d.path]) @@ -155,7 +155,7 @@ def testOptionalParameters(self): d.create_file("a.pyi", """ def parse(source, filename = ..., mode = ..., *args, **kwargs) -> int: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a u = a.parse("True") """, deep=False, pythonpath=[d.path]) @@ -169,7 +169,7 @@ def testOptimize(self): d.create_file("a.pyi", """ class Bar(dict[?, int]): ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a def f(foo, bar): return __any_object__[1] @@ -190,7 +190,7 @@ def testIterable(self): from typing import Iterable def f(l: Iterable[int]) -> int: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a u = a.f([1, 2, 3]) """, deep=False, pythonpath=[d.path]) @@ -204,7 +204,7 @@ def testObject(self): d.create_file("a.pyi", """ def make_object() -> object """) - ty = self.Infer("""\ + ty = self.Infer(""" import a def f(x=None): x = a.make_object() @@ -224,7 +224,7 @@ def testCallable(self): from typing import Callable def process_function(func: Callable[..., Any]) -> None: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo def bar(): pass @@ -238,7 +238,7 @@ def bar() -> Any: ... # 'Any' because deep=False """) def testHex(self): - ty = self.Infer("""\ + ty = self.Infer(""" x = hex(4) """, deep=False) self.assertTypesMatchPytd(ty, """ @@ -258,7 +258,7 @@ class C(A[int]): ... class D(object): def baz(self) -> int """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo def f(x): return x.bar("foo") @@ -300,7 +300,7 @@ def testIdentity(self): T = TypeVar("T") def f(x: T) -> T """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f(3) """, pythonpath=[d.path]) @@ -336,7 +336,7 @@ def testMultipleGetAttr(self): from typing import Any def __getattr__(name) -> Any """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from foo import * from bar import * # Nonsense import generates a top-level __getattr__ # import-error[e] """, pythonpath=[d.path]) @@ -368,7 +368,7 @@ def testDubiousFunctionReference(self): def DubiousType() -> None x = ... # type: DubiousType """) - ty = self.Infer("""\ + ty = self.Infer(""" import a x = a.x """, pythonpath=[d.path]) @@ -383,7 +383,7 @@ def testKeywordOnlyArgs(self): from typing import Any def foo(x: str, *y: Any, z: complex = ...) -> int: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import a x = a.foo("foo %d %d", 3, 3) """, pythonpath=[d.path]) @@ -432,7 +432,7 @@ def testStarArgs(self): V = TypeVar("V") def foo(a: K, *b, c: V, **d) -> Dict[K, V]: ... """) - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" import foo a = foo.foo(*tuple(), **dict()) b = foo.foo(*(1,), **{"c": 3j}) @@ -518,7 +518,7 @@ def testTypeVarConflict(self): from typing import List, Sequence class A(List[int], Sequence[str]): ... """) - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" import foo # pyi-error x = [] + foo.A() """, pythonpath=[d.path]) @@ -557,7 +557,7 @@ class Bar(Generic[T]): def bar(self, x:T2): self = Bar[T2] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.Bar() x.bar(10) @@ -580,7 +580,7 @@ def bar(self): self = Bar[T2] """) # We should get an error at import time rather than at use time here. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo # pyi-error[e] x = foo.Bar() x.bar() @@ -726,7 +726,7 @@ class A: @staticmethod def t(a: str) -> None: ... """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo ta = foo.A.t """, pythonpath=[d.path]) diff --git a/pytype/tests/test_quick.py b/pytype/tests/test_quick.py index 92672c421..45e157dff 100644 --- a/pytype/tests/test_quick.py +++ b/pytype/tests/test_quick.py @@ -75,7 +75,7 @@ def f() -> Any def testAnalyzeAnnotatedMaxDepth(self): # --output with --analyze-annotated has the same max depth as --check. - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def make_greeting(user_id): return 'hello, user' + user_id # unsupported-operands[e] def print_greeting(): diff --git a/pytype/tests/test_recovery.py b/pytype/tests/test_recovery.py index c0232a56e..7d4465c2a 100644 --- a/pytype/tests/test_recovery.py +++ b/pytype/tests/test_recovery.py @@ -99,7 +99,7 @@ class A(object): """) def testMethodWithUnknownDecorator(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from nowhere import decorator # import-error class Foo(object): @decorator @@ -108,7 +108,7 @@ def f(): """, deep=True) def testAssertInConstructor(self): - self.Check("""\ + self.Check(""" class Foo(object): def __init__(self): self._bar = "foo" @@ -119,7 +119,7 @@ def __str__(self): @test_base.skip("Line 7, in __str__: No attribute '_bar' on Foo'") def testConstructorInfiniteLoop(self): - self.Check("""\ + self.Check(""" class Foo(object): def __init__(self): self._bar = "foo" @@ -129,7 +129,7 @@ def __str__(self): """) def testAttributeAccessInImpossiblePath(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" x = 3.14 if __random__ else 42 if isinstance(x, int): if isinstance(x, float): @@ -138,7 +138,7 @@ def testAttributeAccessInImpossiblePath(self): """) def testBinaryOperatorOnImpossiblePath(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" x = "" if __random__ else [] if isinstance(x, list): if isinstance(x, str): diff --git a/pytype/tests/test_reingest.py b/pytype/tests/test_reingest.py index f5b114448..5c644d1f7 100644 --- a/pytype/tests/test_reingest.py +++ b/pytype/tests/test_reingest.py @@ -120,7 +120,7 @@ def __new__(cls, a, b): """) with file_utils.Tempdir() as d: d.create_file("foo.pyi", pytd_utils.Print(foo)) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo foo.X("hello", "world") foo.X(42) # missing-parameter[e] diff --git a/pytype/tests/test_slots.py b/pytype/tests/test_slots.py index b922d1d59..ad6a99ec6 100644 --- a/pytype/tests/test_slots.py +++ b/pytype/tests/test_slots.py @@ -64,7 +64,7 @@ class Foo(object): """) def testSlotWithNonStrings(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): # bad-slots[e] __slots__ = (1, 2, 3) """) @@ -113,7 +113,7 @@ class Foo(object): self.assertErrorRegexes(errors, {"e": r"z"}) def testObject(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" object().foo = 42 # not-writable[e] """) self.assertErrorRegexes(errors, {"e": r"object"}) @@ -126,7 +126,7 @@ class Foo(__any_object__): """) def testParameterizedBaseClass(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import List class Foo(List[int]): __slots__ = () @@ -135,7 +135,7 @@ class Foo(List[int]): self.assertErrorRegexes(errors, {"e": r"foo"}) def testEmptySlots(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): __slots__ = () Foo().foo = 42 # not-writable[e] @@ -143,7 +143,7 @@ class Foo(object): self.assertErrorRegexes(errors, {"e": r"foo"}) def testNamedTuple(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import collections Foo = collections.namedtuple("_", ["a", "b", "c"]) foo = Foo(None, None, None) @@ -155,7 +155,7 @@ def testNamedTuple(self): self.assertErrorRegexes(errors, {"e": r"d"}) def testBuiltinAttr(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" "foo".bar = 1 # not-writable u"foo".bar = 2 # not-writable ().bar = 3 # not-writable @@ -177,14 +177,14 @@ def testBuiltinAttr(self): """) def testGeneratorAttr(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): yield 42 f().foo = 42 # not-writable[e] """) self.assertErrorRegexes(errors, {"e": r"foo"}) def testSetAttr(self): - self.Check("""\ + self.Check(""" class Foo(object): __slots__ = () def __setattr__(self, name, value): @@ -196,7 +196,7 @@ class Bar(Foo): """) def testDescriptors(self): - self.Check("""\ + self.Check(""" class Descriptor(object): def __set__(self, obj, cls): pass @@ -210,7 +210,7 @@ class Bar(Foo): """) def testNameMangling(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Bar(object): __slots__ = ["__baz"] def __init__(self): diff --git a/pytype/tests/test_solver.py b/pytype/tests/test_solver.py index a2693c574..e53a0894b 100644 --- a/pytype/tests/test_solver.py +++ b/pytype/tests/test_solver.py @@ -265,7 +265,7 @@ def testMatchAgainstFunctionWithoutSelf(self): class myclass: def bad_method() -> bool """) - ty = self.Infer("""\ + ty = self.Infer(""" import bad_mod def f(date): return date.bad_method() @@ -277,7 +277,7 @@ def f(date) -> Any """) def testExternalName(self): - ty = self.Infer("""\ + ty = self.Infer(""" import collections def bar(l): l.append(collections.defaultdict(int, [(0, 0)])) @@ -290,7 +290,7 @@ def bar(l) -> NoneType """) def testNameConflictWithBuiltin(self): - ty = self.Infer("""\ + ty = self.Infer(""" class LookupError(KeyError): pass def f(x): @@ -327,7 +327,7 @@ def testDuplicateKeyword(self): T = TypeVar("T") def f(x, *args, y: T) -> T """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f(1, y=2j) """, deep=False, pythonpath=[d.path]) @@ -337,7 +337,7 @@ def f(x, *args, y: T) -> T """) def test_store_name_cfg(self): - ty = self.Infer("""\ + ty = self.Infer(""" a = 1 a = a + 1 """) @@ -346,14 +346,14 @@ def test_store_name_cfg(self): def test_store_global_cfg(self): # STORE_GLOBAL didn't advance the cfg, so it required additional statements # in between in order to show the bug. - ty = self.Infer("""\ + ty = self.Infer(""" global a b = 1 a = 1 b = 1 + b a = 1 + a """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ a = ... # type: int b = ... # type: int """) diff --git a/pytype/tests/test_special_builtins.py b/pytype/tests/test_special_builtins.py index c0d714e79..74ab67eac 100644 --- a/pytype/tests/test_special_builtins.py +++ b/pytype/tests/test_special_builtins.py @@ -191,7 +191,7 @@ def f() -> Tuple[int, str] """) def testDifferentPropertyInstances(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" class Foo(object): def __init__(self): self._foo = 42 if __random__ else "hello world" diff --git a/pytype/tests/test_splits.py b/pytype/tests/test_splits.py index f267fb0c1..c05fd6377 100644 --- a/pytype/tests/test_splits.py +++ b/pytype/tests/test_splits.py @@ -309,7 +309,7 @@ def a2(x) -> Union[int, str]: ... """) def testIsSubclass(self): - ty = self.Infer("""\ + ty = self.Infer(""" # Always return a bool def sig(x): return issubclass(x, object) # Classes for testing @@ -326,7 +326,7 @@ def d6(): return "y" if issubclass(B, ((C, str), int, (float, A))) else 0 # Ambiguous results def a1(x): return "y" if issubclass(x, A) else 0 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Union def sig(x) -> bool: ... def d1() -> str: ... @@ -519,7 +519,7 @@ def testDictDoesNotContain(self): def testDictMaybeContains(self): """Test that we can handle more complex cases involving dict membership.""" - ty = self.Infer("""\ + ty = self.Infer(""" if __random__: x = {"a": 1, "b": 2} else: @@ -537,7 +537,7 @@ def testDictMaybeContains(self): """) def testContainsCoerceToBool(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): def __contains__(self, x): return 1 @@ -655,7 +655,7 @@ def testPrimitiveNotEq(self): def testBuiltinFullNameCheck(self): # Don't get confused by a class named int - self.InferWithErrors("""\ + self.InferWithErrors(""" class int(): pass x = "foo" if __random__ else int() @@ -677,7 +677,7 @@ def testTypeParameterInBranch(self): def testNoneOrTuple(self): # This tests the attribute retrieval code in vm.py:_get_iter - self.Check("""\ + self.Check(""" foo = (0, 0) if __random__: foo = None @@ -760,7 +760,7 @@ class Value(int): value1 = ... # type: int value2 = ... # type: Value """) - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import foo if foo.value1 == foo.value2: name_error # name-error diff --git a/pytype/tests/test_stdlib.py b/pytype/tests/test_stdlib.py index 05dd8f115..7abe757f5 100644 --- a/pytype/tests/test_stdlib.py +++ b/pytype/tests/test_stdlib.py @@ -95,7 +95,7 @@ def testStdlib(self): """) def testNamedtuple(self): - self.Check("""\ + self.Check(""" import collections collections.namedtuple(u"_", "") collections.namedtuple("_", u"") @@ -103,7 +103,7 @@ def testNamedtuple(self): """) def testDefaultdict(self): - ty = self.Infer("""\ + ty = self.Infer(""" import collections a = collections.defaultdict(int, one = 1, two = 2) b = collections.defaultdict(int, {'one': 1, 'two': 2}) @@ -112,7 +112,7 @@ def testDefaultdict(self): e = collections.defaultdict(int) f = collections.defaultdict(default_factory = int) """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ collections = ... # type: module a = ... # type: collections.defaultdict[str, int] b = ... # type: collections.defaultdict[str, int] @@ -123,7 +123,7 @@ def testDefaultdict(self): """) def testDefaultdictNoFactory(self): - ty = self.Infer("""\ + ty = self.Infer(""" import collections a = collections.defaultdict() b = collections.defaultdict(None) @@ -134,7 +134,7 @@ def testDefaultdictNoFactory(self): g = collections.defaultdict(one = 1, two = 2) h = collections.defaultdict(default_factory = None) """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any collections = ... # type: module a = ... # type: collections.defaultdict[nothing, nothing] @@ -148,14 +148,14 @@ def testDefaultdictNoFactory(self): """) def testDefaultdictDiffDefaults(self): - ty = self.Infer("""\ + ty = self.Infer(""" import collections a = collections.defaultdict(int, one = '1') b = collections.defaultdict(str, one = 1) c = collections.defaultdict(None, one = 1) d = collections.defaultdict(int, {1: 'one'}) """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Union collections = ... # type: module a = ... # type: collections.defaultdict[str, Union[int, str]] @@ -195,7 +195,7 @@ def testCsv(self): """) def testFuture(self): - self.Check("""\ + self.Check(""" import __future__ """) diff --git a/pytype/tests/test_super.py b/pytype/tests/test_super.py index ad1e9edf0..595bd5004 100644 --- a/pytype/tests/test_super.py +++ b/pytype/tests/test_super.py @@ -72,7 +72,7 @@ class Baz(object): """) def testSet(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def foo(self, name, value): super(Foo, self).__set__(name, value) # attribute-error[e] @@ -143,7 +143,7 @@ def hello(self): """) def testCallSuper(self): - _, errorlog = self.InferWithErrors("""\ + _, errorlog = self.InferWithErrors(""" class Y(object): pass @@ -194,14 +194,14 @@ def testSuperWithAny(self): """) def testSingleArgumentSuper(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" super(object) super(object()) # wrong-arg-types[e] """) self.assertErrorRegexes(errors, {"e": r"cls: type.*cls: object"}) def testMethodOnSingleArgumentSuper(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" sup = super(object) sup.foo # attribute-error[e1] sup.__new__(object) # wrong-arg-types[e2] @@ -215,7 +215,7 @@ def testMethodOnSingleArgumentSuper(self): "e2": r"Type\[super\].*Type\[object\]"}) def testSuperUnderDecorator(self): - self.Check("""\ + self.Check(""" def decorate(cls): return __any_object__ class Parent(object): @@ -228,7 +228,7 @@ def Hello(self): """) def testSuperSetAttr(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): def __init__(self): super(Foo, self).foo = 42 # not-writable[e] @@ -236,7 +236,7 @@ def __init__(self): self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperSubclassSetAttr(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(object): pass class Bar(Foo): def __init__(self): @@ -249,7 +249,7 @@ def testSuperNothingSetAttr(self): d.create_file("foo.pyi", """ class Foo(nothing): ... """) - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import foo class Bar(foo.Foo): def __init__(self): @@ -258,7 +258,7 @@ def __init__(self): self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperAnySetAttr(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" class Foo(__any_object__): def __init__(self): super(Foo, self).foo = 42 # not-writable[e] diff --git a/pytype/tests/test_tracebacks.py b/pytype/tests/test_tracebacks.py index 832da8638..96635445a 100644 --- a/pytype/tests/test_tracebacks.py +++ b/pytype/tests/test_tracebacks.py @@ -7,7 +7,7 @@ class TracebackTest(test_base.TargetIndependentTest): """Tests for tracebacks in error messages.""" def test_no_traceback(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): "hello" + 42 # unsupported-operands[e] f("world") @@ -15,7 +15,7 @@ def f(x): self.assertErrorRegexes(errors, {"e": r"expects str$"}) def test_same_traceback(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x, _): x + 42 # unsupported-operands[e] def g(x): @@ -25,7 +25,7 @@ def g(x): self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g"}) def test_different_tracebacks(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") @@ -36,7 +36,7 @@ def f(x): "e2": r"Called from.*:\n line 4, in current file"}) def test_comprehension(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): return {x.upper() for x in range(10)} # attribute-error[e] """) @@ -45,7 +45,7 @@ def f(): self.assertEqual(error.methodname, "f") def test_comprehension_in_traceback(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): return x.upper() # attribute-error[e] def g(): @@ -54,7 +54,7 @@ def g(): self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g$"}) def test_no_argument_function(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(): return None.attr # attribute-error[e] f() @@ -62,7 +62,7 @@ def f(): self.assertErrorRegexes(errors, {"e": r"attr.*None$"}) def test_max_callsites(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" def f(s): return "hello, " + s # unsupported-operands[e1] # unsupported-operands[e2] # unsupported-operands[e3] f(0) diff --git a/pytype/tests/test_tuple.py b/pytype/tests/test_tuple.py index 091f3f9f0..923f9940e 100644 --- a/pytype/tests/test_tuple.py +++ b/pytype/tests/test_tuple.py @@ -7,7 +7,7 @@ class TupleTest(test_base.TargetIndependentTest): """Tests for __builtin__.tuple.""" def testGetItemInt(self): - ty = self.Infer("""\ + ty = self.Infer(""" t = ("", 42) v1 = t[0] v2 = t[1] @@ -25,7 +25,7 @@ def testGetItemInt(self): @test_base.skip("Needs better slice support in abstract.Tuple, convert.py.") def testGetItemSlice(self): - ty = self.Infer("""\ + ty = self.Infer(""" t = ("", 42) v1 = t[:] v2 = t[:1] @@ -46,7 +46,7 @@ def testGetItemSlice(self): """) def testUnpackTuple(self): - ty = self.Infer("""\ + ty = self.Infer(""" v1, v2 = ("", 42) _, w = ("", 42) x, (y, z) = ("", (3.14, True)) @@ -62,7 +62,7 @@ def testUnpackTuple(self): """) def testBadUnpacking(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" tup = (1, "") a, = tup # bad-unpacking[e1] b, c, d = tup # bad-unpacking[e2] @@ -92,7 +92,7 @@ def testMutableItem(self): """) def testBadTupleClassGetItem(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" v = type((3, "")) w = v[0] # not-indexable[e] """) diff --git a/pytype/tests/test_type_comments.py b/pytype/tests/test_type_comments.py index b5f3dda78..11d3f3771 100644 --- a/pytype/tests/test_type_comments.py +++ b/pytype/tests/test_type_comments.py @@ -73,14 +73,14 @@ def foo(x: int, y: str, z: float) -> None """) def testFunctionCommentOnColon(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def f(x) \\ : # type: (None) -> None return True # bad-return-type """) def testMultipleFunctionComments(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(x): # type: (None) -> bool # type: (str) -> str # ignored-type-comment[e] @@ -181,21 +181,21 @@ class A: def testTypeCommentAfterDocstring(self): """Type comments after the docstring should not be picked up.""" - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(x, y): '''Ceci n'est pas une type.''' # type: (int, str) -> None # ignored-type-comment """) def testFunctionNoReturn(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(): # type: () -> # invalid-function-type-comment pass """) def testFunctionTooManyArgs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x): # type: (int, str) -> None # invalid-function-type-comment[e] y = x @@ -204,7 +204,7 @@ def foo(x): self.assertErrorRegexes(errors, {"e": r"Expected 1 args, 2 given"}) def testFunctionTooFewArgs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x, y, z): # type: (int, str) -> None # invalid-function-type-comment[e] y = x @@ -213,7 +213,7 @@ def foo(x, y, z): self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionTooFewArgsDoNotCountSelf(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(self, x, y, z): # type: (int, str) -> None # invalid-function-type-comment[e] y = x @@ -222,21 +222,21 @@ def foo(self, x, y, z): self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionMissingArgs(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(x): # type: () -> int # invalid-function-type-comment return x """) def testInvalidFunctionTypeComment(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" def foo(x): # type: blah blah blah # invalid-function-type-comment return x """) def testInvalidFunctionArgs(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x): # type: (abc def) -> int # invalid-function-type-comment[e] return x @@ -244,7 +244,7 @@ def foo(x): self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) def testAmbiguousAnnotation(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def foo(x): # type: (int if __random__ else str) -> None # invalid-function-type-comment[e] pass @@ -321,7 +321,7 @@ def f() -> Tuple[Mapping, dict]: ... """) def testBadComment(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" X = None # type: abc def # invalid-type-comment[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) @@ -331,7 +331,7 @@ def testBadComment(self): """) def testConversionError(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" X = None # type: 1 if __random__ else 2 # invalid-type-comment[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"1 if __random__ else 2.*constant"}) @@ -341,13 +341,13 @@ def testConversionError(self): """) def testNameErrorInsideComment(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = None # type: Foo # invalid-type-comment[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"Foo"}) def testWarnOnIgnoredTypeComment(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" X = [] X[0] = None # type: str # ignored-type-comment[e1] # type: int # ignored-type-comment[e2] @@ -378,14 +378,14 @@ def testNoneToNoneType(self): """) def testModuleInstanceAsBadTypeComment(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" import sys x = None # type: sys # invalid-annotation[e] """) self.assertErrorRegexes(errors, {"e": r"instance of module.*x"}) def testForwardReference(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" a = None # type: "A" b = None # type: "Nonexistent" # name-error[e] class A(object): @@ -405,27 +405,27 @@ def f(self) -> int self.assertErrorRegexes(errors, {"e": r"Nonexistent"}) def testClassVariableForwardReference(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): a = None # type: 'A' def __init__(self): self.x = 42 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ class A(object): a: A x: int """) def testUseForwardReference(self): - ty = self.Infer("""\ + ty = self.Infer(""" a = None # type: "A" x = a.x class A(object): def __init__(self): self.x = 42 """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any class A(object): x = ... # type: int @@ -435,7 +435,7 @@ class A(object): def testUseClassVariableForwardReference(self): # Attribute accesses for A().a all get resolved to Any (b/134706992) - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): a = None # type: 'A' def f(self): @@ -445,7 +445,7 @@ def g(): return A().a y = g() """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any, TypeVar _TA = TypeVar('_TA', bound=A) class A(object): @@ -457,14 +457,14 @@ def g() -> A: ... """) def testClassVariableForwardReferenceError(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" class A(object): a = None # type: 'A' g = A().a.foo() # attribute-error """) def testMultilineValue(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" v = [ { "a": 1 # type: complex # ignored-type-comment[e1] @@ -480,7 +480,7 @@ def testMultilineValue(self): "e2": r"Stray type comment: dict\[str, int\]"}) def testMultilineValueWithBlankLines(self): - ty = self.Infer("""\ + ty = self.Infer(""" a = [[ ] @@ -492,14 +492,14 @@ def testMultilineValueWithBlankLines(self): """) def testTypeCommentNameError(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): x = None # type: Any # invalid-type-comment[e] """, deep=True) self.assertErrorRegexes(errors, {"e": r"not defined$"}) def testTypeCommentInvalidSyntax(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" def f(): x = None # type: y = 1 # invalid-type-comment[e] """, deep=True) @@ -507,7 +507,7 @@ def f(): def testDiscardedTypeComment(self): """Discard the first whole-line comment, keep the second.""" - ty = self.Infer("""\ + ty = self.Infer(""" # We want either # type: ignore or # type: int def hello_world(): # type: () -> str @@ -519,14 +519,14 @@ def hello_world() -> str: ... def testMultipleTypeComments(self): """We should not allow multiple type comments on one line.""" - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" a = 42 # type: int # type: float # invalid-directive[e] """) self.assertErrorRegexes(errors, {"e": r"Multiple"}) def testMultipleDirectives(self): """We should support multiple directives on one line.""" - self.Check("""\ + self.Check(""" a = list() # type: list[int, str] # pytype: disable=invalid-type-comment b = list() # pytype: disable=invalid-type-comment # type: list[int, str] def foo(x): pass @@ -534,13 +534,13 @@ def foo(x): pass """) def testNestedCommentAlias(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): pass class B(object): C = A x = None # type: C """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Type class A(object): pass class B(object): @@ -549,12 +549,12 @@ class B(object): """) def testNestedClassesComments(self): - ty = self.Infer("""\ + ty = self.Infer(""" class A(object): class B(object): pass x = None # type: B """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import Any class A(object): B = ... # type: type @@ -562,7 +562,7 @@ class A(object): """) def testListComprehensionComments(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List def f(x): # type: (str) -> None @@ -572,24 +572,24 @@ def g(xs): ys = [f(x) for x in xs] # type: List[str] return ys """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ from typing import List def f(x: str) -> None: ... def g(xs: List[str]) -> List[str]: ... """) def testMultipleAssignments(self): - ty = self.Infer("""\ + ty = self.Infer(""" a = 1; b = 2; c = 4 # type: float """) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ a = ... # type: int b = ... # type: int c = ... # type: float """) def testRecursiveTypeAlias(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import List, Union Foo = Union[str, List['Foo']] x = 'hello' # type: Foo # not-supported-yet[e] @@ -597,7 +597,7 @@ def testRecursiveTypeAlias(self): self.assertErrorRegexes(errors, {"e": r"Recursive.*Foo"}) def testInstantiateFullyQuotedType(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import Optional x = None # type: "Optional[A]" class A(object): @@ -627,13 +627,13 @@ def A(self) -> None: ... """) def testIllegalFunctionLateType(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" v = None # type: "F" # invalid-annotation def F(): pass """) def testBadTypeCommentInConstructor(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" class Foo(object): def __init__(self): self.x = None # type: "Bar" # name-error diff --git a/pytype/tests/test_typevar.py b/pytype/tests/test_typevar.py index a9dedb306..b8f1b2f42 100644 --- a/pytype/tests/test_typevar.py +++ b/pytype/tests/test_typevar.py @@ -20,7 +20,7 @@ def testUnusedTypeVar(self): def testImportTypeVar(self): with file_utils.Tempdir() as d: d.create_file("a.pyi", """T = TypeVar("T")""") - ty = self.Infer("""\ + ty = self.Infer(""" from a import T """, deep=False, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -29,7 +29,7 @@ def testImportTypeVar(self): """) def testInvalidTypeVar(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" from typing import TypeVar typevar = TypeVar T = typevar() # invalid-typevar[e1] @@ -111,7 +111,7 @@ def return_arg_or_42(x: _T0) -> Union[_T0, int] """) def testTypeVarInTypeComment(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import List, TypeVar T = TypeVar("T") x = None # type: T # not-supported-yet @@ -119,7 +119,7 @@ def testTypeVarInTypeComment(self): """) def testBaseClassWithTypeVar(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import List, TypeVar T = TypeVar("T") class A(List[T]): pass @@ -140,7 +140,7 @@ class X(l): pass """) def testBound(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", int, float, bound=str) # invalid-typevar S = TypeVar("S", bound="") # invalid-typevar @@ -149,7 +149,7 @@ def testBound(self): """) def testCovariant(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", covariant=True) # not-supported-yet S = TypeVar("S", covariant=42) # invalid-typevar[e1] @@ -159,7 +159,7 @@ def testCovariant(self): errors, {"e1": r"Expected.*bool.*Actual.*int", "e2": r"constant"}) def testContravariant(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar T = TypeVar("T", contravariant=True) # not-supported-yet S = TypeVar("S", contravariant=42) # invalid-typevar[e1] @@ -366,7 +366,7 @@ def testStoreTypeVarInDict(self): """) def testLateBound(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import TypeVar, Union T = TypeVar("T", int, float, bound="str") # invalid-typevar[e1] S = TypeVar("S", bound="") # invalid-typevar[e2] diff --git a/pytype/tests/test_typing.py b/pytype/tests/test_typing.py index efa64c16c..342ec5e53 100644 --- a/pytype/tests/test_typing.py +++ b/pytype/tests/test_typing.py @@ -38,7 +38,7 @@ def test_cast2(self): """) def test_process_annotation_for_cast(self): - ty, _ = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors(""" import typing v1 = typing.cast(None, __any_object__) v2 = typing.cast(typing.Union, __any_object__) # invalid-annotation @@ -55,7 +55,7 @@ class A(object): ... """) def test_no_typevars_for_cast(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" from typing import cast, AnyStr, Type, TypeVar, _T def f(x): return cast(AnyStr, x) # invalid-typevar @@ -66,7 +66,7 @@ def g(x): """) def test_cast_args(self): - self.assertNoCrash(self.Check, """\ + self.assertNoCrash(self.Check, """ import typing typing.cast(typing.AnyStr) typing.cast("str") @@ -89,7 +89,7 @@ def test_generate_type_alias(self): """) def test_protocol(self): - self.Check("""\ + self.Check(""" from typing_extensions import Protocol class Foo(Protocol): pass """) @@ -100,13 +100,13 @@ def test_recursive_tuple(self): from typing import Tuple class Foo(Tuple[Foo]): ... """) - self.Check("""\ + self.Check(""" import foo foo.Foo() """, pythonpath=[d.path]) def test_base_class(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import Iterable class Foo(Iterable): pass @@ -117,7 +117,7 @@ class Foo(Iterable): ... """) def test_type_checking(self): - self.Check("""\ + self.Check(""" import typing if typing.TYPE_CHECKING: pass @@ -126,7 +126,7 @@ def test_type_checking(self): """) def test_not_type_checking(self): - self.Check("""\ + self.Check(""" import typing if not typing.TYPE_CHECKING: name_error @@ -135,7 +135,7 @@ def test_not_type_checking(self): """) def test_new_type_arg_error(self): - _, errors = self.InferWithErrors("""\ + _, errors = self.InferWithErrors(""" from typing import NewType MyInt = NewType(int, 'MyInt') # wrong-arg-types[e1] MyStr = NewType(tp='str', name='MyStr') # wrong-arg-types[e2] @@ -149,7 +149,7 @@ def test_new_type_arg_error(self): "e4": r".*Expected:.*type.*\nActually passed:.*Union.*"}) def test_classvar(self): - ty = self.Infer("""\ + ty = self.Infer(""" from typing import ClassVar class A(object): x = 5 # type: ClassVar[int] @@ -178,7 +178,7 @@ def test_pyi_classvar_argcount(self): class X: v: ClassVar[int, int] """) - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import foo # pyi-error[e] """, pythonpath=[d.path]) self.assertErrorRegexes(errors, {"e": r"ClassVar.*1.*2"}) @@ -188,7 +188,7 @@ class LiteralTest(test_base.TargetIndependentTest): """Tests for typing.Literal.""" def test_py(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" from typing import Literal # not-supported-yet """) diff --git a/pytype/tests/test_typing_methods.py b/pytype/tests/test_typing_methods.py index b918e0782..287b5ca66 100644 --- a/pytype/tests/test_typing_methods.py +++ b/pytype/tests/test_typing_methods.py @@ -16,7 +16,7 @@ def _check_call(self, t, expr): # pylint: disable=invalid-name def f() -> %(type)s """ % {"type": t}) indented_expr = textwrap.dedent(expr).replace("\n", "\n" + " "*8) - self.Check("""\ + self.Check(""" import foo x = foo.f() %(expr)s @@ -64,7 +64,7 @@ def test_io(self): from typing import IO def f() -> IO[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f() with x as fi: @@ -120,7 +120,7 @@ def test_sequence_and_tuple(self): def seq() -> Sequence[str] def tpl() -> Tuple[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo for seq in [foo.seq(), foo.tpl()]: a = seq[0] @@ -150,7 +150,7 @@ def test_mutablesequence_and_list(self): def seq() -> MutableSequence[str] def lst() -> List[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo for seq in [foo.seq(), foo.lst()]: seq[0] = 3 @@ -184,7 +184,7 @@ def test_deque(self): from typing import Deque def deq() -> Deque[int] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo q = foo.deq() q[0] = 3 @@ -197,7 +197,7 @@ def deq() -> Deque[int] cl = q.popleft() d = q.rotate(3) """, deep=False, pythonpath=[d.path]) - self.assertTypesMatchPytd(ty, """\ + self.assertTypesMatchPytd(ty, """ foo = ... # type: module from typing import Deque q = ... # type: Deque[int] @@ -219,7 +219,7 @@ def test_mutablemapping(self): class MyDict(MutableMapping[K, V]): ... def f() -> MyDict[str, int] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo m = foo.f() m.clear() @@ -252,7 +252,7 @@ def test_abstractset(self): from typing import AbstractSet def f() -> AbstractSet[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f() a = "bar" in x @@ -284,7 +284,7 @@ def test_mutableset(self): from typing import MutableSet def f() -> MutableSet[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo x = foo.f() x.add(1) @@ -330,7 +330,7 @@ def test_pattern_and_match(self): from typing import Pattern def f() -> Pattern[str] """) - ty = self.Infer("""\ + ty = self.Infer(""" import foo pattern = foo.f() m1 = pattern.search("foo") diff --git a/pytype/tests/test_typing_namedtuple.py b/pytype/tests/test_typing_namedtuple.py index 047aaaa0e..1bb8177f7 100644 --- a/pytype/tests/test_typing_namedtuple.py +++ b/pytype/tests/test_typing_namedtuple.py @@ -7,7 +7,7 @@ class NamedTupleTest(test_base.TargetIndependentTest): """Tests for the typing.NamedTuple overlay.""" def test_basic_calls(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing Basic = typing.NamedTuple("Basic", [('a', str)]) ex = Basic("hello world") @@ -17,7 +17,7 @@ def test_basic_calls(self): """) def test_optional_field_type(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing X = typing.NamedTuple("X", [('a', str), ('b', typing.Optional[int])]) xa = X('hello', None) @@ -28,7 +28,7 @@ def test_optional_field_type(self): """) def test_class_field_type(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing class Foo(object): pass @@ -40,7 +40,7 @@ class Foo(object): """) def test_late_annotation(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" import typing class Foo(object): pass @@ -50,7 +50,7 @@ class Foo(object): self.assertErrorRegexes(errors, {"e": r"Bar"}) def test_nested_containers(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing Z = typing.NamedTuple("Z", [('a', typing.List[typing.Optional[int]])]) za = Z([1]) @@ -65,7 +65,7 @@ def test_nested_containers(self): """) def test_pytd_field(self): - self.CheckWithErrors("""\ + self.CheckWithErrors(""" import typing import datetime B = typing.NamedTuple("B", [('a', datetime.date)]) @@ -75,7 +75,7 @@ def test_pytd_field(self): """) def test_bad_calls(self): - self.InferWithErrors("""\ + self.InferWithErrors(""" import typing typing.NamedTuple("_", ["abc", "def", "ghi"]) # wrong-arg-types # "def" is a keyword, so the call on the next line fails. @@ -92,7 +92,7 @@ def test_empty_args(self): """) def test_tuple_fields(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import NamedTuple X = NamedTuple("X", (("a", str),)) X(a="") @@ -101,7 +101,7 @@ def test_tuple_fields(self): self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_list_field(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import NamedTuple X = NamedTuple("X", [["a", str]]) X(a="") @@ -110,7 +110,7 @@ def test_list_field(self): self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_str_fields_error(self): - errors = self.CheckWithErrors("""\ + errors = self.CheckWithErrors(""" from typing import NamedTuple X = NamedTuple("X", "a b") # wrong-arg-types[e1] Y = NamedTuple("Y", ["ab"]) # wrong-arg-types[e2] diff --git a/pytype/tests/test_unions.py b/pytype/tests/test_unions.py index 47be85bc5..f5e6550b8 100644 --- a/pytype/tests/test_unions.py +++ b/pytype/tests/test_unions.py @@ -24,7 +24,7 @@ def f(b, x, y) -> int or float """) def testCall(self): - ty, errors = self.InferWithErrors("""\ + ty, errors = self.InferWithErrors(""" def f(): x = 42 if __random__: diff --git a/pytype/tests/test_utils.py b/pytype/tests/test_utils.py index e552745d0..96ca3b4b8 100644 --- a/pytype/tests/test_utils.py +++ b/pytype/tests/test_utils.py @@ -159,7 +159,7 @@ class TestCollectionsMixin(object): """Mixin providing utils for tests on the collections module.""" def _testCollectionsObject(self, obj, good_arg, bad_arg, error): # pylint: disable=invalid-name - result = self.CheckWithErrors("""\ + result = self.CheckWithErrors(""" import collections def f(x: collections.{obj}): ... f({good_arg}) diff --git a/pytype/tests/test_with.py b/pytype/tests/test_with.py index 73b2e0e3b..c85f73410 100644 --- a/pytype/tests/test_with.py +++ b/pytype/tests/test_with.py @@ -7,7 +7,7 @@ class TestWithStatement(test_base.TargetIndependentTest): """Tests for the with statement.""" def test_simple_context_manager(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -31,7 +31,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_raise_in_context_manager(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -58,7 +58,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_suppressed_raise_in_context_manager(self): - self.Check("""\ + self.Check(""" class SuppressingContext(object): def __enter__(self): l.append('i') @@ -85,7 +85,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_return_in_with(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -110,7 +110,7 @@ def use_with(val): """) def test_continue_in_with(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -136,7 +136,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_break_in_with(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -162,7 +162,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_raise_in_with(self): - self.Check("""\ + self.Check(""" class NullContext(object): def __enter__(self): l.append('i') @@ -189,7 +189,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): """) def test_at_context_manager_simplified(self): - self.Check("""\ + self.Check(""" import sys class GeneratorContextManager(object): def __init__(self, gen): @@ -239,7 +239,7 @@ def my_context_manager(val): def test_at_context_manager_complete(self): # The complete code for an @contextmanager example, lifted from # the stdlib. - self.Check("""\ + self.Check(""" from functools import partial import sys @@ -311,7 +311,7 @@ def my_context_manager(val): """) def test_tempfile(self): - self.Infer("""\ + self.Infer(""" import tempfile def f(): with tempfile.NamedTemporaryFile(dir="bla", delete=False) as fi: diff --git a/pytype/tools/traces/source_test.py b/pytype/tools/traces/source_test.py index 75d3c0c3b..bf2ad37a3 100644 --- a/pytype/tools/traces/source_test.py +++ b/pytype/tools/traces/source_test.py @@ -55,20 +55,20 @@ def test_get_offset(self): def test_get_offset_multibyte(self): # With single-byte characters - src = source.Code("""\ + src = source.Code(""" # coding=utf-8 line1 # a line2 """, [], _FakeTrace, "") - self.assertEqual(src.get_offset(source.Location(3, 3)), 40) + self.assertEqual(src.get_offset(source.Location(4, 3)), 41) # With a multibyte character the byte offset should change - src = source.Code("""\ + src = source.Code(""" # coding=utf-8 line1 # ツ line2 """, [], _FakeTrace, "") - self.assertEqual(src.get_offset(source.Location(3, 3)), 42) + self.assertEqual(src.get_offset(source.Location(4, 3)), 43) def test_line(self): src = source.Code("line1\nline2", [], _FakeTrace, "") diff --git a/pytype/tools/traces/traces_test.py b/pytype/tools/traces/traces_test.py index 219ea6c2b..6da13aa0f 100644 --- a/pytype/tools/traces/traces_test.py +++ b/pytype/tools/traces/traces_test.py @@ -76,10 +76,10 @@ def test_external_type(self): self.assertEqual(pyval.cls.name, "foo.Foo") def test_py3_class(self): - src = traces.trace(textwrap.dedent("""\ + src = traces.trace(textwrap.dedent(""" class Foo(object): pass - """), config.Options.create(python_version=(3, 6))) + """).lstrip(), config.Options.create(python_version=(3, 6))) trace, = (x for x in src.traces[1] if x.op == "LOAD_BUILD_CLASS") pyval, = trace.types self.assertEqual(pyval.name, "typing.Callable") @@ -97,7 +97,7 @@ class MatchAstTestCase(unittest.TestCase): """Base class for testing traces.MatchAstVisitor.""" def _parse(self, text, options=None): - text = textwrap.dedent(text) + text = textwrap.dedent(text).lstrip() return ast.parse(text), traces.trace(text, options) def _get_traces(self, text, node_type, options=None): @@ -147,7 +147,7 @@ class MatchAttributeTest(MatchAstTestCase): """Tests for traces.MatchAstVisit.match_Attribute.""" def test_basic(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" x = 0 print(x.real) """, ast.Attribute) @@ -155,7 +155,7 @@ def test_basic(self): ((2, 8), "LOAD_ATTR", "real", ("int", "int"))]) def test_multi(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" class Foo(object): real = True x = 0 @@ -169,7 +169,7 @@ class Foo(object): ((4, 5), "LOAD_ATTR", "real", ("int", "int"))]) def test_property(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" class Foo(object): @property def x(self): @@ -188,14 +188,14 @@ def test_basic(self): self.assertTracesEqual(matches, [((1, 0), "STORE_NAME", "x", ("int",))]) def test_multiline(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" x = (1 + 2) """, ast.Name) self.assertTracesEqual(matches, [((1, 0), "STORE_NAME", "x", ("int",))]) def test_multiline_subscr(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" x = [0] x[0] = (1, 2) @@ -209,7 +209,7 @@ class MatchCallTest(MatchAstTestCase): """Tests for traces.MatchAstVisitor.match_Call.""" def test_basic(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" def f(x): return x + 1.0 f(42) @@ -218,7 +218,7 @@ def f(x): ((3, 0), "CALL_FUNCTION", "f", ("Callable[[Any], Any]", "float"))]) def _test_chain(self, call_method_op): - matches = self._get_traces("""\ + matches = self._get_traces(""" class Foo(object): def f(self, x): return x @@ -237,7 +237,7 @@ def test_chain_37(self): self._test_chain("CALL_METHOD") def test_multiple_bindings(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" class Foo(object): @staticmethod def f(x): @@ -254,7 +254,7 @@ def f(x): ("Callable[[Any], Any]", "Union[int, float]"))]) def test_bad_call(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" def f(): pass f(42) """, ast.Call) @@ -275,7 +275,7 @@ def test_literal_37(self): self._test_literal("CALL_METHOD") def test_lookahead(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" def f(x, y, z): return x + y + z f( @@ -340,7 +340,7 @@ def test_ellipsis(self): class MatchSubscriptTest(MatchAstTestCase): def test_index(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" v = "hello" print(v[0]) """, ast.Subscript) @@ -348,7 +348,7 @@ def test_index(self): matches, [((2, 6), "BINARY_SUBSCR", "__getitem__", ("str",))]) def _test_simple_slice(self, slice_op, method): - matches = self._get_traces("""\ + matches = self._get_traces(""" v = "hello" print(v[:-1]) """, ast.Subscript) @@ -363,7 +363,7 @@ def test_simple_slice_3(self): self._test_simple_slice("BINARY_SUBSCR", "__getitem__") def test_complex_slice(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" v = "hello" print(v[0:4:2]) """, ast.Subscript) @@ -374,7 +374,7 @@ def test_complex_slice(self): class MatchBinOpTest(MatchAstTestCase): def test_modulo(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" v = "hello %s" print(v % "world") """, ast.BinOp) @@ -382,7 +382,7 @@ def test_modulo(self): matches, [((2, 6), "BINARY_MODULO", "__mod__", ("str",))]) def test_modulo_multiline_string(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" ('%s' '%s' % (__any_object__, @@ -401,7 +401,7 @@ def test_basic(self): matches, [((1, 0), "MAKE_FUNCTION", sym, ("Callable[[Any], Any]",))]) def test_function_locals(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" def f(): return lambda x: x.upper() """, ast.Lambda) @@ -412,7 +412,7 @@ def f(): # py2 doesn't have symbol names to distinguish between and . @py3 def test_multiple_functions(self): - matches = self._get_traces("""\ + matches = self._get_traces(""" def f(): return (w for w in range(3)), lambda x: x.upper(), lambda y, z: (y, z) """, ast.Lambda) diff --git a/pytype/tools/xref/callgraph_test.py b/pytype/tools/xref/callgraph_test.py index a4558606f..30df7196d 100644 --- a/pytype/tools/xref/callgraph_test.py +++ b/pytype/tools/xref/callgraph_test.py @@ -43,7 +43,7 @@ def assertHasFunctions(self, fns, expected): self.assertCountEqual(actual, expected) def test_basic(self): - ix = self.index_code("""\ + ix = self.index_code(""" def f(x: str): y = x.strip() return y @@ -77,7 +77,7 @@ def g(y): self.assertParamsEqual(g.params, [("y", "typing.Any")]) def test_remote(self): - code = """\ + code = """ import foo def f(a, b): @@ -111,7 +111,7 @@ def bar() -> int: ... def test_no_outgoing_calls(self): """Capture a function with no outgoing calls.""" - ix = self.index_code("""\ + ix = self.index_code(""" def f(x: int): return "hello" """) @@ -125,7 +125,7 @@ def f(x: int): def test_call_records(self): """Use a function's call records to infer param types.""" - ix = self.index_code("""\ + ix = self.index_code(""" class A: def foo(self, x): return x + "1" diff --git a/pytype/tools/xref/indexer_test.py b/pytype/tools/xref/indexer_test.py index 2ef38e147..389dca8ad 100644 --- a/pytype/tools/xref/indexer_test.py +++ b/pytype/tools/xref/indexer_test.py @@ -58,10 +58,10 @@ class IndexerTest(test_base.TargetIndependentTest, IndexerTestMixin): """Tests for the indexer.""" def test_param_reuse(self): - ix = self.index_code("""\ + ix = self.index_code(""" def f(x): x = 1 # reuse param variable - """) + """.lstrip("\n")) self.assertDef(ix, "module.f", "f", "FunctionDef") self.assertDef(ix, "module.f.x", "x", "Param") self.assertDefLocs(ix, "module.f", [(1, 0)]) @@ -71,7 +71,7 @@ def f(x): "a/b.py, f.py, p/q.py, x/y.py not found") def test_resolved_imports(self): # We need all imports to be valid for pytype - code = """\ + code = """ import f import x.y import a.b as c @@ -202,7 +202,7 @@ def test_literal_attr(self): def test_def_types(self): # Basic sanity test of definition data - ix = self.index_code("""\ + ix = self.index_code(""" def f(): x = 42 return x @@ -219,7 +219,7 @@ def assert_data_type(fqname, cls): assert_data_type("module.f.x", abstract.Instance) def test_make_serializable(self): - ix = self.index_code("""\ + ix = self.index_code(""" def f(): x = 42 y = x @@ -251,10 +251,10 @@ def assertDefLocs(self, index, fqname, locs): return super(IndexerTestPy3, self).assertDefLocs(index, fqname, locs) def test_type_annotations(self): - ix = self.index_code("""\ + ix = self.index_code(""" def f(x: int) -> int: return x - """) + """.lstrip("\n")) self.assertDef(ix, "module.f", "f", "FunctionDef") self.assertDef(ix, "module.f.x", "x", "Param") self.assertDefLocs(ix, "module.f", [(1, 0)]) diff --git a/pytype/vm_test.py b/pytype/vm_test.py index f76214833..efb67b45c 100644 --- a/pytype/vm_test.py +++ b/pytype/vm_test.py @@ -202,10 +202,10 @@ def test_empty_data(self): self.assertEqual(self.trace_vm.opcode_traces, [(op, "x", (None,))]) def test_const(self): - src = textwrap.dedent("""\ + src = textwrap.dedent(""" x = 1 # line 1 y = x # line 2 - """) + """).lstrip() # Compiles to: # 0 LOAD_CONST 0 (1) # 3 STORE_NAME 0 (x) From ee0e1fd24bcfea95f7ad2bf88236e8b95635a84c Mon Sep 17 00:00:00 2001 From: rechen Date: Tue, 31 Mar 2020 13:27:44 -0700 Subject: [PATCH 07/11] Use six.assertRaisesRegex instead of self.assertRaisesRegex. The latter is not available in Python 2 *sigh* I increased the shard count of a test that timed out. PiperOrigin-RevId: 304034251 --- pytype/pytd/parse/preconditions_test.py | 9 +++++---- pytype/pytd/pytd_utils_test.py | 4 ++-- pytype/pytd/serialize_ast_test.py | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pytype/pytd/parse/preconditions_test.py b/pytype/pytd/parse/preconditions_test.py index b1dc2b3c7..9bff3029a 100644 --- a/pytype/pytd/parse/preconditions_test.py +++ b/pytype/pytd/parse/preconditions_test.py @@ -14,6 +14,7 @@ from pytype.pytd.parse import preconditions +import six import unittest @@ -29,8 +30,8 @@ class SubClass(BaseClass): class PreconditionsTest(unittest.TestCase): def assertError(self, regex, condition, value): - self.assertRaisesRegex( - preconditions.PreconditionError, regex, condition.check, value) + six.assertRaisesRegex( + self, preconditions.PreconditionError, regex, condition.check, value) def testClassNamePrecondition(self): c = preconditions._ClassNamePrecondition("str") @@ -78,8 +79,8 @@ def testAllowedTypes(self): self.assertEqual({"int", "str"}, self.checker.allowed_types()) def assertError(self, regex, *args, **kwargs): - self.assertRaisesRegex( - preconditions.PreconditionError, regex, self.checker.check, *args, + six.assertRaisesRegex( + self, preconditions.PreconditionError, regex, self.checker.check, *args, **kwargs) def testPositionalArgs(self): diff --git a/pytype/pytd/pytd_utils_test.py b/pytype/pytd/pytd_utils_test.py index de2ca9bd6..75f6471d8 100644 --- a/pytype/pytd/pytd_utils_test.py +++ b/pytype/pytd/pytd_utils_test.py @@ -477,8 +477,8 @@ def testGetPredefinedFileBasic(self): def testGetPredefinedFileThrows(self): # smoke test, only checks that it does throw - with self.assertRaisesRegex( - IOError, + with six.assertRaisesRegex( + self, IOError, r"File not found|Resource not found|No such file or directory"): pytd_utils.GetPredefinedFile(self.BUILTINS, "-this-file-does-not-exist") diff --git a/pytype/pytd/serialize_ast_test.py b/pytype/pytd/serialize_ast_test.py index a5cae88a0..d2fa60f0f 100644 --- a/pytype/pytd/serialize_ast_test.py +++ b/pytype/pytd/serialize_ast_test.py @@ -89,8 +89,8 @@ def testNodeIndexVisitorUsage(self): serialized_ast.class_type_nodes)[1:]) loaded_ast = serialize_ast.ProcessAst(serialized_ast, module_map) - with self.assertRaisesRegex( - ValueError, "Unresolved class: '__builtin__.NoneType'"): + with six.assertRaisesRegex( + self, ValueError, "Unresolved class: '__builtin__.NoneType'"): loaded_ast.Visit(visitors.VerifyLookup()) def testPickle(self): From 422b2f07146ef58081a75bc373cd5aedade0991a Mon Sep 17 00:00:00 2001 From: rechen Date: Tue, 31 Mar 2020 14:10:11 -0700 Subject: [PATCH 08/11] Unskip tests in Python 3.7. The issue that caused the tests to be skipped is fixed. I had to fix one of the tests to stop returning an awaitable from __aiter__ (https://www.python.org/dev/peps/pep-0492/#why-aiter-does-not-return-an-awaitable, https://docs.python.org/3/library/dis.html#opcode-GET_AITER). PiperOrigin-RevId: 304042948 --- pytype/tests/py3/test_stdlib.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pytype/tests/py3/test_stdlib.py b/pytype/tests/py3/test_stdlib.py index 8fb1ad252..1dfa91821 100644 --- a/pytype/tests/py3/test_stdlib.py +++ b/pytype/tests/py3/test_stdlib.py @@ -247,7 +247,6 @@ def testSysVersionInfoNamedAttribute(self): v: str """) - @test_utils.skipIn37("https://github.com/google/pytype/issues/203") def test_async(self): """Test various asyncio features.""" ty = self.Infer(""" @@ -288,12 +287,11 @@ def my_coroutine(seconds_to_sleep = ...) -> Coroutine[Any, Any, None]: ... def test_with(x) -> Coroutine[Any, Any, None]: ... """) - @test_utils.skipIn37("https://github.com/google/pytype/issues/203") def test_async_iter(self): ty = self.Infer(""" import asyncio class AsyncIterable: - async def __aiter__(self): + def __aiter__(self): return self async def __anext__(self): data = await self.fetch_data() @@ -311,10 +309,11 @@ async def iterate(x): iterate(AsyncIterable()) """) self.assertTypesMatchPytd(ty, """ - from typing import Any, Coroutine + from typing import Any, Coroutine, TypeVar asyncio: module + _TAsyncIterable = TypeVar('_TAsyncIterable', bound=AsyncIterable) class AsyncIterable: - def __aiter__(self) -> Coroutine[Any, Any, AsyncIterable]: ... + def __aiter__(self: _TAsyncIterable) -> _TAsyncIterable: ... def __anext__(self) -> Coroutine[Any, Any, int]: ... def fetch_data(self) -> Coroutine[Any, Any, int]: ... def iterate(x) -> Coroutine[Any, Any, None]: ... From 6142b608e8a37d887885aa61d48942e647ee33f9 Mon Sep 17 00:00:00 2001 From: rechen Date: Wed, 1 Apr 2020 13:31:08 -0700 Subject: [PATCH 09/11] Do a PyPI release. Just a normal release, despite the date =) PiperOrigin-RevId: 304251409 --- CHANGELOG | 3 +++ pytype/__version__.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 96b871d3f..88072e77b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2020.04.01 +* Do some test restructuring and cleanup. + Version 2020.03.19 * Fix a couple of pytype crashes. * Do not allow mixing string types in IO.write() in Python 3. diff --git a/pytype/__version__.py b/pytype/__version__.py index 2b5b23692..5fbc2c6ef 100644 --- a/pytype/__version__.py +++ b/pytype/__version__.py @@ -1,2 +1,2 @@ # pylint: skip-file -__version__ = '2020.03.19' +__version__ = '2020.04.01' From 729fc21acee22ae6e467b5205c7e4a99649066cb Mon Sep 17 00:00:00 2001 From: rechen Date: Wed, 1 Apr 2020 14:20:54 -0700 Subject: [PATCH 10/11] Fix two more OSS test failures. * self.assertCountEqual does not exist in Python 2. * Dictionaries are not insertion ordered in Python 3.5. PiperOrigin-RevId: 304261311 --- pytype/annotations_util.py | 2 +- pytype/tests/test_base_test.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pytype/annotations_util.py b/pytype/annotations_util.py index ca15b9f16..4cb47962f 100644 --- a/pytype/annotations_util.py +++ b/pytype/annotations_util.py @@ -160,7 +160,7 @@ def convert_class_annotations(self, node, raw_annotations): """Convert a name -> raw_annot dict to annotations.""" annotations = {} raw_items = raw_annotations.items() - if sys.version_info.major == 2: + if sys.version_info[:2] < (3, 6): # Make sure annotation errors are reported in a deterministic order. raw_items = sorted(raw_items) for name, t in raw_items: diff --git a/pytype/tests/test_base_test.py b/pytype/tests/test_base_test.py index f860fa30a..2e4d7b325 100644 --- a/pytype/tests/test_base_test.py +++ b/pytype/tests/test_base_test.py @@ -4,6 +4,7 @@ from pytype import utils from pytype.tests import test_base from pytype.tests import test_utils +import six class ErrorLogTest(test_base.TargetIndependentTest): @@ -36,7 +37,7 @@ def test_multiple_errors_one_line(self): line = self._lineno(1) self.assertEqual(err.expected, {line: [("attribute-error", "e1"), ("attribute-error", "e2")]}) - self.assertCountEqual(err.marks, ["e1", "e2"]) + six.assertCountEqual(self, err.marks, ["e1", "e2"]) self.assertIn("on int", err.marks["e1"].message) self.assertIn("on str", err.marks["e2"].message) From 430779a8afdd6c7c4281a39b25c2864ed54b3f5b Mon Sep 17 00:00:00 2001 From: rechen Date: Wed, 1 Apr 2020 17:03:57 -0700 Subject: [PATCH 11/11] Add a `key` argument to avoid type errors when sorting annotations in 3.5. Ughhh PiperOrigin-RevId: 304291925 --- pytype/annotations_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytype/annotations_util.py b/pytype/annotations_util.py index 4cb47962f..2979c4131 100644 --- a/pytype/annotations_util.py +++ b/pytype/annotations_util.py @@ -162,7 +162,7 @@ def convert_class_annotations(self, node, raw_annotations): raw_items = raw_annotations.items() if sys.version_info[:2] < (3, 6): # Make sure annotation errors are reported in a deterministic order. - raw_items = sorted(raw_items) + raw_items = sorted(raw_items, key=str) for name, t in raw_items: # Don't use the parameter name, since it's often something unhelpful # like `0`.