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/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/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
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`
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'
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/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/annotations_util.py b/pytype/annotations_util.py
index e208ef51e..2979c4131 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[:2] < (3, 6):
+ # Make sure annotation errors are reported in a deterministic order.
+ 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`.
annot = self._process_one_annotation(
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 f022ca592..583f90521 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")
@@ -349,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
@@ -358,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"
@@ -375,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/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..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.assertRaisesRegexp(
- preconditions.PreconditionError, regex, condition.check, value)
+ six.assertRaisesRegex(
+ self, preconditions.PreconditionError, regex, condition.check, value)
def testClassNamePrecondition(self):
c = preconditions._ClassNamePrecondition("str")
@@ -69,6 +70,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,8 +79,8 @@ def testAllowedTypes(self):
self.assertEqual({"int", "str"}, self.checker.allowed_types())
def assertError(self, regex, *args, **kwargs):
- self.assertRaisesRegexp(
- 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 2cd4ad505..75f6471d8 100644
--- a/pytype/pytd/pytd_utils_test.py
+++ b/pytype/pytd/pytd_utils_test.py
@@ -445,22 +445,22 @@ 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))
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,8 +477,8 @@ def testGetPredefinedFileBasic(self):
def testGetPredefinedFileThrows(self):
# smoke test, only checks that it does throw
- with self.assertRaisesRegexp(
- 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 e43bcd46f..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.assertRaisesRegexp(
- ValueError, "Unresolved class: '__builtin__.NoneType'"):
+ with six.assertRaisesRegex(
+ self, ValueError, "Unresolved class: '__builtin__.NoneType'"):
loaded_ast.Visit(visitors.VerifyLookup())
def testPickle(self):
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/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/py2/test_abc.py b/pytype/tests/py2/test_abc.py
index e396f67f2..f58045301 100644
--- a/pytype/tests/py2/test_abc.py
+++ b/pytype/tests/py2/test_abc.py
@@ -7,27 +7,26 @@ 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("""\
+ _, errors = self.InferWithErrors("""
import abc
class Example(object):
__metaclass__ = abc.ABCMeta
@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("""
@@ -48,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
@@ -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..6d5198342 100644
--- a/pytype/tests/py2/test_attributes.py
+++ b/pytype/tests/py2/test_attributes.py
@@ -14,14 +14,14 @@ def testEmptyTypeParameterInstance(self):
""")
def testTypeParameterInstanceMultipleBindings(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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("""
@@ -60,12 +60,12 @@ 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]
+ 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_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 e9eddb389..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,11 +348,10 @@ def testIterItems(self):
""")
def testIntInit(self):
- _, errors = self.InferWithErrors("""\
- int(0, 1) # line 8: expected str or unicode, got int for first arg
+ _, errors = self.InferWithErrors("""
+ 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_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 c8f401978..ce57763d7 100644
--- a/pytype/tests/py2/test_decorators.py
+++ b/pytype/tests/py2/test_decorators.py
@@ -8,15 +8,15 @@ 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
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..79a33f468 100644
--- a/pytype/tests/py2/test_errors.py
+++ b/pytype/tests/py2/test_errors.py
@@ -7,29 +7,29 @@ class ErrorTest(test_base.TargetPython27FeatureTest):
"""Tests for errors."""
def testProtocolMismatch(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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_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 f58dfc088..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
@@ -18,13 +18,13 @@ 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]
""")
- self.assertTypesMatchPytd(ty, """\
+ self.assertTypesMatchPytd(ty, """
from typing import Any, List, Union
a = ... # type: List[Union[int, str]]
b = ... # type: List[Union[int, str]]
@@ -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..272051b5a 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..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]
@@ -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.
@@ -64,16 +65,17 @@ 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]
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..389f6ca02 100644
--- a/pytype/tests/py2/test_reingest.py
+++ b/pytype/tests/py2/test_reingest.py
@@ -22,12 +22,12 @@ 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()
+ 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..be995a94d 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):
+ errors = self.CheckWithErrors("""
+ 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_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 2b8b92cd1..41b40415a 100644
--- a/pytype/tests/py2/test_super.py
+++ b/pytype/tests/py2/test_super.py
@@ -9,17 +9,16 @@ 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)
+ 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_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 fc3b447e0..257b85e44 100644
--- a/pytype/tests/py2/test_typevar.py
+++ b/pytype/tests/py2/test_typevar.py
@@ -9,33 +9,31 @@ 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: ...
def g(x: AnyStr) -> AnyStr: ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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/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 a0ad0dd34..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
@@ -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..19bf94382 100644
--- a/pytype/tests/py3/test_annotations.py
+++ b/pytype/tests/py3/test_annotations.py
@@ -59,16 +59,16 @@ 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)
- 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("""\
+ self.Check("""
def f(x: int):
return x
def g(y, z):
@@ -82,11 +82,11 @@ def g(y, z):
""")
def testInnerError(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""
@@ -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,63 +169,56 @@ def f(c: calendar.Calendar) -> int: ...
""")
def testAmbiguousAnnotation(self):
- _, errors = self.InferWithErrors("""\
- def foo(x: int if __random__ else float):
+ _, errors = self.InferWithErrors("""
+ 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()):
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ _, errors = self.InferWithErrors("""
def foo(x: str) -> int:
if x:
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("""\
+ ty = self.Infer("""
class Foo(object):
def bar(self, x: float, default="") -> str:
default.upper
@@ -237,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)
@@ -252,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")
@@ -260,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
@@ -279,76 +272,59 @@ 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, """\
+ self.assertNoCrash(self.Check, """
import typing
_T = typing.TypeVar("_T")
class A(typing.Generic[_T]):
@@ -356,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()
@@ -384,14 +360,14 @@ class B(object):
""")
def testWithoutForwardDecl(self):
- _, errorlog = self.InferWithErrors("""\
- def f(a) -> Bar:
+ _, errorlog = self.InferWithErrors("""
+ 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("""
@@ -401,29 +377,28 @@ def f(a) -> "Foo":
class Foo(object):
pass
""")
- _, errorlog = self.InferWithErrors("""\
- def f(a: "Foo"):
+ _, errorlog = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ _, errorlog = self.InferWithErrors("""
class Foo(object):
def foo(self):
return 4
@@ -436,27 +411,25 @@ 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("""\
+ _, 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:
d.create_file("a.pyi", """
def factory() -> type
""")
- ty = self.Infer("""\
+ ty = self.Infer("""
import a
A = a.factory()
def f(x: A):
@@ -470,14 +443,14 @@ def f(x) -> Any
""")
def testBadCallNoKwarg(self):
- ty, errors = self.InferWithErrors("""\
+ ty, errors = self.InferWithErrors("""
def foo():
labels = {
'baz': None
}
labels['baz'] = bar(
- labels['baz'])
+ labels['baz']) # wrong-arg-types[e]
def bar(path: str, **kwargs):
return path
@@ -488,17 +461,17 @@ 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("""\
+ ty, errors = self.InferWithErrors("""
def foo():
labels = {
'baz': None
}
labels['baz'] = bar(
- labels['baz'], x=42)
+ labels['baz'], x=42) # wrong-arg-types[e]
def bar(path: str, **kwargs):
return path
@@ -509,10 +482,10 @@ 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("""\
+ ty = self.Infer("""
_analyzed_baz = None
class Foo(object):
def __init__(self):
@@ -573,7 +546,7 @@ 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("""
@@ -616,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
@@ -625,21 +598,21 @@ 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]):
+ 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("""\
+ ty, errors = self.InferWithErrors("""
from typing import Dict
def f(x, **kwargs: int):
return kwargs
@@ -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,24 +636,21 @@ 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):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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("""
@@ -714,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
@@ -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,42 +704,41 @@ 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("""\
+ _, errors = self.InferWithErrors("""
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("""\
+ _, 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("""\
+ 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("""
@@ -809,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:
@@ -819,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]"):
@@ -827,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):
@@ -845,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
@@ -859,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
@@ -876,7 +845,7 @@ class A(object): ...
""")
def testTypeAliasAnnotation(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
from typing import List
TypeA = "A"
ListA = "List[A]"
@@ -896,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
@@ -907,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
@@ -921,11 +890,11 @@ 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
+ 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:
@@ -947,18 +915,17 @@ 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
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("""
@@ -1004,14 +969,13 @@ 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):
+ 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..e600d48a1 100644
--- a/pytype/tests/py3/test_anystr.py
+++ b/pytype/tests/py3/test_anystr.py
@@ -75,12 +75,12 @@ 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__
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("""\
+ _, 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..91814bc35 100644
--- a/pytype/tests/py3/test_async_generators.py
+++ b/pytype/tests/py3/test_async_generators.py
@@ -74,35 +74,32 @@ 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]:
- 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("""\
+ errors = self.CheckWithErrors("""
from typing import AsyncGenerator, AsyncIterator, AsyncIterable, Union, Any
async def func():
@@ -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..0ababc98f 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..f5496f387 100644
--- a/pytype/tests/py3/test_attributes.py
+++ b/pytype/tests/py3/test_attributes.py
@@ -7,12 +7,12 @@ 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()
+ 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("""
@@ -26,41 +26,39 @@ def testClosure(self):
""")
def testOverwriteGlobal(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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):
"""Tests for attributes."""
def testAttrOnOptional(self):
- errors = self.CheckWithErrors("""\
+ 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("""\
+ errors = self.CheckWithErrors("""
from typing import Any
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):
@@ -74,14 +72,14 @@ def testEmptyTypeParameterInstance(self):
""")
def testTypeParameterInstanceMultipleBindings(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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_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 207c6e3de..8a3d91a8e 100644
--- a/pytype/tests/py3/test_builtins.py
+++ b/pytype/tests/py3/test_builtins.py
@@ -115,21 +115,19 @@ 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("""\
+ self.Check("""
x, y = 24, 3
x /= y
assert x == 8.0 and y == 3
@@ -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("""
@@ -423,22 +417,20 @@ def testItems(self):
""")
def testIntInit(self):
- _, errors = self.InferWithErrors("""\
- int(0, 1) # line 8: expected str or unicode, got int for first arg
+ _, errors = self.InferWithErrors("""
+ 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..f218fe232 100644
--- a/pytype/tests/py3/test_checker.py
+++ b/pytype/tests/py3/test_checker.py
@@ -17,27 +17,26 @@ def g(data: Set[str]):
""")
def testRecursiveForwardReference(self):
- errorlog = self.CheckWithErrors("""\
+ errorlog = self.CheckWithErrors("""
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("""\
+ 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("""\
+ self.Check("""
class A(object):
pass
def f(*args: A, **kwargs: A):
@@ -48,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
@@ -61,7 +60,7 @@ def g2(x: List[None]):
""")
def testInnerClassInit(self):
- self.Check("""\
+ self.Check("""
from typing import List
class A:
def __init__(self):
@@ -75,7 +74,7 @@ def h():
""")
def testRecursion(self):
- self.Check("""\
+ self.Check("""
class A:
def __init__(self, x: "B"):
pass
@@ -86,84 +85,81 @@ 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}
+ 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("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ errorlog = self.CheckWithErrors("""
from typing import List
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("""\
+ 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("""\
+ 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..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):
@@ -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("""
@@ -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,24 +162,23 @@ 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):
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("""
@@ -229,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()}
@@ -276,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):
@@ -293,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):
@@ -313,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):
@@ -413,15 +412,14 @@ def bar(cls):
""")
def testPy2Metaclass(self):
- errors = self.CheckWithErrors("""\
+ 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..eed7d2855 100644
--- a/pytype/tests/py3/test_coroutine.py
+++ b/pytype/tests/py3/test_coroutine.py
@@ -69,9 +69,9 @@ def caller() -> Coroutine[Any, Any, Union[int, str]]: ...
""")
def testNativeCoroutineError(self):
- errors = self.CheckWithErrors("""\
+ 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("""
@@ -132,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
@@ -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("""
@@ -215,15 +212,14 @@ def f3() -> Coroutine[Any, Any, None]: ...
""")
def testInvalidAwaitable(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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("""
@@ -262,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
@@ -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,7 +349,8 @@ def log(s: _T0) -> Coroutine[Any, Any, _T0]: ...
""")
def testAsyncWithError(self):
- errors = self.CheckWithErrors("""\
+ # 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..42e9ecef5 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..870aa7016 100644
--- a/pytype/tests/py3/test_decorators.py
+++ b/pytype/tests/py3/test_decorators.py
@@ -7,20 +7,19 @@ 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`.
# 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 2f89f742b..6c102391d 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..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__:
@@ -18,176 +18,160 @@ 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, errors = self.InferWithErrors("""
def f(x: str):
pass
if __random__:
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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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:
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ _, 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
# 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", "")
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("""\
+ _, 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("""\
+ _, 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:
@@ -197,35 +181,32 @@ 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)
+ 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: ...
""")
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
from typing import Callable
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("""\
+ errors = self.CheckWithErrors("""
from typing import Generator, Any
def f(x) -> Generator[Any, int, Any]:
if x == 1:
@@ -234,43 +215,41 @@ 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("""\
+ 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("""\
+ 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):
"""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
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", "-=")
@@ -279,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
@@ -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", "%=")
@@ -321,54 +300,53 @@ class ErrorTestPy3(test_base.TargetPython3FeatureTest):
"""Tests for errors."""
def testProtocolMismatch(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ errors = self.CheckWithErrors("""
class A(object):
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_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 1ad2c39b7..4cdd67a39 100644
--- a/pytype/tests/py3/test_functions.py
+++ b/pytype/tests/py3/test_functions.py
@@ -8,19 +8,19 @@ 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()
+ 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):
"""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,19 +37,18 @@ 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("""\
+ ty = self.Infer("""
def f():
x = "hello"
def g():
@@ -63,19 +62,18 @@ 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("""\
+ ty = self.Infer("""
def f():
x = True
def g():
@@ -90,18 +88,18 @@ def f() -> int
""")
def test_closure_annotations(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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):
@@ -124,38 +121,38 @@ 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)
+ 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("""\
+ 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("""\
+ ty, errors = self.InferWithErrors("""
from typing import overload
@overload
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,14 +160,14 @@ 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):
"""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"
@@ -184,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
@@ -198,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):
@@ -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
@@ -301,17 +294,14 @@ 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])
+ 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:
@@ -329,12 +319,12 @@ 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)
+ 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):
@@ -593,13 +583,13 @@ 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
- 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("""
@@ -616,17 +606,14 @@ 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])
+ 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..b9bcd6512 100644
--- a/pytype/tests/py3/test_generators.py
+++ b/pytype/tests/py3/test_generators.py
@@ -30,12 +30,12 @@ def f() -> Iterable:
""")
def testNoReturn(self):
- _, errors = self.InferWithErrors("""\
+ _, 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):
@@ -90,24 +90,22 @@ 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]:
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..a157b91fc 100644
--- a/pytype/tests/py3/test_generic.py
+++ b/pytype/tests/py3/test_generic.py
@@ -8,28 +8,27 @@ 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]):
+ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Generic, TypeVar
T1 = TypeVar('T1')
@@ -60,16 +59,15 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar, Generic
T = TypeVar('T', int, float)
@@ -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("""\
+ _, 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:
@@ -110,11 +106,10 @@ def testGenericWithDupTypeError(self):
T = TypeVar('T')
class A(Generic[T, T]): ...
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -125,12 +120,11 @@ def testMultiGenericError(self):
V = TypeVar('V')
class A(Generic[T], Generic[V]): ...
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -141,38 +135,37 @@ def testGenericWithTypeMissError(self):
V = TypeVar('V')
class A(Dict[K, V], Generic[K]): ...
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar, Generic, Union
T = TypeVar('T')
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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar, Generic, Iterator
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,17 +175,16 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar, Generic
T = TypeVar('T', int, float, str)
@@ -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("""
@@ -285,18 +276,18 @@ 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')
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:
@@ -338,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')
@@ -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:
@@ -391,22 +380,20 @@ 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]()
- 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Generic, TypeVar
T = TypeVar('T', int, float)
@@ -416,22 +403,21 @@ 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("""\
+ ty, errors = self.InferWithErrors("""
from typing import Generic, TypeVar
T = TypeVar('T')
@@ -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,12 +457,11 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Generic, TypeVar
T = TypeVar('T')
@@ -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
@@ -519,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]):
@@ -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("""
@@ -551,15 +534,14 @@ 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]):
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("""
@@ -579,19 +561,19 @@ class Foo(Generic[T]): ...
""")
def testBadParameterizedForwardReference(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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("""\
+ 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 b45ca56fe..924425b88 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,15 +63,15 @@ 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, """\
+ self.assertTypesMatchPytd(ty, """
from typing import Any, List, Union
a = ... # type: List[Union[int, str]]
p = ... # type: str
@@ -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,14 +96,14 @@ 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]
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]]
@@ -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..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
@@ -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:
@@ -33,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
@@ -44,25 +43,22 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Callable
def f(x: Callable[[bool], int]): ...
def g1(x: int) -> bool:
@@ -70,14 +66,14 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Callable
class A(object):
@@ -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:
@@ -114,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
@@ -143,32 +137,32 @@ 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
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("""\
+ _, errors = self.InferWithErrors("""
from typing import Callable, TypeVar
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,23 +201,19 @@ 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("""\
+ _, errors = self.InferWithErrors("""
from typing import Callable, TypeVar
T1 = TypeVar("T1", bound=int)
T2 = TypeVar("T2")
@@ -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:
@@ -272,33 +260,31 @@ 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:
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.
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
from typing import Any, AnyStr, Callable, TypeVar
T = TypeVar('T')
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..32ec8f9af 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("""
@@ -16,42 +16,42 @@ def __init__(self: int) -> int
""")
def testAnnotatedSelf(self):
- errors = self.CheckWithErrors("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ 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..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,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..d2047ec2b 100644
--- a/pytype/tests/py3/test_overload.py
+++ b/pytype/tests/py3/test_overload.py
@@ -19,27 +19,27 @@ def f(x):
""")
def test_bad_implementation(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
from typing import overload
@overload
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("""\
+ errors = self.CheckWithErrors("""
from typing import overload
@overload
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("""
@@ -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:
@@ -81,12 +81,12 @@ 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("""\
+ errors = self.CheckWithErrors("""
from typing import overload
@overload
def f(x: int) -> int:
@@ -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 = """
@@ -129,16 +128,16 @@ 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
- 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("""\
+ errors = self.CheckWithErrors("""
from typing import overload
class Foo(object):
@overload
@@ -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 = """
@@ -177,14 +176,14 @@ 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:
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..7709a4085 100644
--- a/pytype/tests/py3/test_protocols.py
+++ b/pytype/tests/py3/test_protocols.py
@@ -30,18 +30,18 @@ def __len__(self):
""")
def test_check_protocol_error(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
import protocols
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("""\
+ _, errors = self.InferWithErrors("""
from typing import Iterator
def f(x: Iterator[int]):
return None
@@ -50,13 +50,12 @@ 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("""\
+ self.Check("""
from typing import Sized
def f(x: Sized):
pass
@@ -69,7 +68,7 @@ def g(x):
""")
def test_check_parameterized_protocol(self):
- self.Check("""\
+ self.Check("""
from typing import Iterator, Iterable
class Foo(object):
@@ -85,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):
@@ -96,13 +95,13 @@ 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("""\
+ self.Check("""
from typing import Sequence, Union
class Foo(object):
@@ -119,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):
@@ -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("""
@@ -257,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]:
@@ -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("""
@@ -316,26 +314,24 @@ def f(x: Hashable):
""")
def test_list_hash(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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("""\
+ errors = self.CheckWithErrors("""
from typing import Hashable
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:
@@ -392,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):
@@ -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("""
@@ -437,18 +433,18 @@ 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
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("""
@@ -462,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):
@@ -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("""
@@ -509,17 +504,16 @@ 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:
- ...
+ ... # 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_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 d2f7a8e60..5888ad7d8 100644
--- a/pytype/tests/py3/test_recovery.py
+++ b/pytype/tests/py3/test_recovery.py
@@ -7,24 +7,19 @@ 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."""
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
from typing import AnyStr
class X(object):
def __init__(self,
@@ -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..50823b877 100644
--- a/pytype/tests/py3/test_reingest.py
+++ b/pytype/tests/py3/test_reingest.py
@@ -16,11 +16,11 @@ 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("")
+ 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("""
@@ -54,12 +54,12 @@ 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()
+ 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..91ab8b517 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..1dfa91821 100644
--- a/pytype/tests/py3/test_stdlib.py
+++ b/pytype/tests/py3/test_stdlib.py
@@ -11,18 +11,18 @@ 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): ...
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("""\
+ 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__)
@@ -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]: ...
diff --git a/pytype/tests/py3/test_super.py b/pytype/tests/py3/test_super.py
index 47bfe7115..fd4059bc3 100644
--- a/pytype/tests/py3/test_super.py
+++ b/pytype/tests/py3/test_super.py
@@ -73,17 +73,13 @@ def m(self):
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..3e872fb4c 100644
--- a/pytype/tests/py3/test_tracebacks.py
+++ b/pytype/tests/py3/test_tracebacks.py
@@ -7,12 +7,12 @@ 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):
+ 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..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,17 +53,17 @@ def f() -> tuple:
""")
def testTuplePrinting(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
from typing import Tuple
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:
@@ -106,24 +102,23 @@ 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]]):
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("""
@@ -150,20 +145,20 @@ 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]:
- 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):
"""Tests for __builtin__.tuple."""
def testIteration(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
class Foo(object):
mytuple = (1, "foo", 3j)
def __getitem__(self, pos):
@@ -179,11 +174,10 @@ def __getitem__(self, pos: int) -> int or str or complex
""")
def testBadUnpackingWithSlurp(self):
- _, errors = self.InferWithErrors("""\
- a, *b, c = (1,)
+ _, errors = self.InferWithErrors("""
+ 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..e3e0b24d1 100644
--- a/pytype/tests/py3/test_type_comments.py
+++ b/pytype/tests/py3/test_type_comments.py
@@ -7,15 +7,14 @@ 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("""\
+ ty = self.Infer("""
from typing import List
def f(x: str):
pass
@@ -23,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 44f2eecaa..a33291d60 100644
--- a/pytype/tests/py3/test_typevar.py
+++ b/pytype/tests/py3/test_typevar.py
@@ -68,20 +68,17 @@ 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
+ 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("""\
+ ty = self.Infer("""
from typing import Dict, Tuple, TypeVar
K = TypeVar("K")
V = TypeVar("V")
@@ -100,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")
@@ -119,37 +116,35 @@ 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")
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("""\
+ ty, errors = self.InferWithErrors("""
from typing import TypeVar
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,11 +156,10 @@ 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("""\
+ ty = self.Infer("""
from typing import Type, TypeVar
T = TypeVar("T")
def f(x: Type[T]) -> T:
@@ -180,41 +174,40 @@ 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]): ...
- 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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar
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("""\
+ _, errors = self.InferWithErrors("""
from typing import TypeVar
T = TypeVar("T", int, float)
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("""\
+ self.Check("""
from typing import TypeVar
class A(object): pass
class B(object): pass
@@ -228,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:
@@ -249,44 +242,39 @@ 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): ...
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("""\
+ ty, errors = self.InferWithErrors("""
from typing import TypeVar
T = TypeVar("T", bound=float)
def f(x: T) -> T:
@@ -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,11 +295,10 @@ 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, """\
+ self.assertNoCrash(self.Check, """
from typing import AnyStr, Dict
class Foo(object):
@@ -321,14 +308,13 @@ 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]:
- 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("""
@@ -411,22 +397,20 @@ 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("")
- 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..9381a7bd6 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")
@@ -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,14 +44,14 @@ 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
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:
@@ -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
@@ -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:
@@ -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.
@@ -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("""\
+ 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:
@@ -214,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
@@ -273,13 +269,13 @@ 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()
+ 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("""\
+ 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("""
@@ -324,21 +319,19 @@ 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)
- 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("""\
+ self.Check("""
from typing import Any, Callable
def foo(fn: Callable[[Any], Any]):
fn.foo # pytype: disable=attribute-error
@@ -423,20 +416,16 @@ def test_new_type_error(self):
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("""
@@ -468,102 +457,95 @@ def g() -> str:
""")
def test_union_ellipsis(self):
- errors = self.CheckWithErrors("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ 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("""\
+ errors = self.CheckWithErrors("""
from typing import Optional
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("""\
+ errors = self.CheckWithErrors("""
from typing import NoReturn, List
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("""\
+ self.Check("""
from typing import SupportsComplex
def foo(x: SupportsComplex):
pass
@@ -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):
@@ -650,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 603c5e736..a224fc224 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("""
@@ -57,22 +51,22 @@ 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)])
+ 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):
"""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")
@@ -81,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
@@ -121,54 +115,50 @@ 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)
+ 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("""\
+ _, 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("""\
+ _, errorlog = self.InferWithErrors("""
from typing import NamedTuple
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("""\
+ self.Check("""
from typing import NamedTuple
class SubNamedTuple(NamedTuple):
@@ -191,7 +181,7 @@ def func():
""")
def test_baseclass(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
from typing import NamedTuple
class baseClass(object):
@@ -203,7 +193,7 @@ class SubNamedTuple(baseClass, NamedTuple):
""")
self.assertTypesMatchPytd(
ty,
- """\
+ """
import collections
from typing import Callable, Iterable, Sized, Tuple, Type, TypeVar
@@ -235,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):
@@ -257,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 74be589cb..8f2ddb1d9 100644
--- a/pytype/tests/py3/test_variable_annotations.py
+++ b/pytype/tests/py3/test_variable_annotations.py
@@ -17,26 +17,24 @@ class A(object):
a: int
b: str
""")
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
import foo
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):
"""Tests for PEP526 variable annotations."""
def testInferTypes(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
from typing import List
lst: List[int] = []
@@ -48,7 +46,7 @@ class A(object):
a: int = 1
b = 2
""")
- self.assertTypesMatchPytd(ty, """\
+ self.assertTypesMatchPytd(ty, """
from typing import List
lst: List[int]
@@ -61,26 +59,24 @@ class A(object):
""")
def testIllegalAnnotations(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
from typing import List, TypeVar, NoReturn
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("""
@@ -106,12 +102,11 @@ def testUninitializedModuleAnnotation(self):
""")
def testOverwriteAnnotationsDict(self):
- errors = self.CheckWithErrors("""\
+ 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("""
@@ -140,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
@@ -154,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 6b1a82006..6a1ece664 100644
--- a/pytype/tests/test_abc.py
+++ b/pytype/tests/test_abc.py
@@ -15,23 +15,21 @@ class Example(metaclass=abc.ABCMeta):
@abc.abstractmethod
def foo(self) -> None: ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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:
@@ -60,11 +58,11 @@ class Interface(metaclass=abc.ABCMeta):
def foo(self): ...
class Foo(X, Interface): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
@@ -103,15 +101,14 @@ def foo(self):
""", pythonpath=[d.path])
def test_misplaced_abstractproperty(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
import abc
@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..69a2fe0e6 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.
@@ -272,25 +270,24 @@ def __init__(self, x: list = ...) -> None: ...
""")
def test_bad_factory(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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("""\
+ 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("""
@@ -384,22 +381,21 @@ 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):
- 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, """
@@ -603,22 +599,21 @@ class Foo(object):
""")
def test_init_bad_constant(self):
- err = self.CheckWithErrors("""\
+ 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..91a819abe 100644
--- a/pytype/tests/test_attributes.py
+++ b/pytype/tests/test_attributes.py
@@ -23,22 +23,22 @@ def f(self):
""")
def testClassConstantError(self):
- errors = self.CheckWithErrors("""\
+ 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("""\
+ errors = self.CheckWithErrors("""
x = None
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("""
@@ -82,42 +82,42 @@ def f():
""", pythonpath=[d.path])
def testReturnValue(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
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("""\
+ errors = self.CheckWithErrors("""
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:
d.create_file("foo.pyi", "def f() -> None: ...")
- errors = self.CheckWithErrors("""\
+ 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("""\
+ 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("""
@@ -144,7 +144,7 @@ def g():
""")
def testReturnConstant(self):
- self.Check("""\
+ self.Check("""
x = None
def f():
return x
@@ -153,22 +153,21 @@ def g():
""")
def testUnpackedNone(self):
- errors = self.CheckWithErrors("""\
+ 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("""\
+ 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("""
@@ -249,13 +248,12 @@ def f() -> Any
""")
def testGetItem(self):
- errors = self.CheckWithErrors("""\
+ 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("""
@@ -272,13 +270,12 @@ def f():
""")
def testContains(self):
- errors = self.CheckWithErrors("""\
+ 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("""
@@ -564,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):
@@ -577,7 +573,7 @@ class Foo3(object):
""")
def testHasDynamicAttributesSubClass(self):
- self.Check("""\
+ self.Check("""
class Foo(object):
_HAS_DYNAMIC_ATTRIBUTES = True
class Bar(Foo):
@@ -588,12 +584,12 @@ 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
+ 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,
@@ -619,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])
@@ -642,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")
@@ -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("""
@@ -720,46 +714,43 @@ 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:
+ 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("""\
+ errors = self.CheckWithErrors("""
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("""\
+ errors = self.CheckWithErrors("""
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:
- # 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 13ba05531..283f50a64 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
@@ -71,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."""
@@ -169,20 +185,20 @@ 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)
+ 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()")
analyze.check_types(
src, filename, loader=self.loader,
errorlog=errorlog, options=self.options, **kwargs)
@@ -196,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)
@@ -211,19 +227,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 +352,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
@@ -345,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,
@@ -383,7 +402,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 +448,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..2e4d7b325 100644
--- a/pytype/tests/test_base_test.py
+++ b/pytype/tests/test_base_test.py
@@ -1,31 +1,124 @@
"""Tests for our test framework."""
+from pytype import file_utils
+from pytype import utils
from pytype.tests import test_base
+from pytype.tests import test_utils
import six
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("""\
+ 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")]})
+ six.assertCountEqual(self, 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("""\
+ 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_basic.py b/pytype/tests/test_basic.py
index 17ee2304e..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,27 +245,25 @@ 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("""\
+ self.Check("""
import math
print(math.pi, math.e)
from math import sqrt
@@ -275,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
@@ -288,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
@@ -299,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
@@ -310,19 +308,19 @@ 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
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("""\
+ self.Check("""
class Thing(object):
def foo(self):
return 17
@@ -335,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
@@ -345,12 +343,12 @@ 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("""\
+ self.Check("""
class Thing(object):
z = 17
def __init__(self):
@@ -362,18 +360,18 @@ def __init__(self):
""")
def test_attribute_access_error(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
class Thing(object):
z = 17
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("""\
+ self.Check("""
class Thing(object):
@staticmethod
def smeth(x):
@@ -387,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)
@@ -396,7 +394,7 @@ def meth(self, x):
""")
def test_callback(self):
- self.Check("""\
+ self.Check("""
def lcase(s):
return s.lower()
l = ["xyz", "ABC"]
@@ -406,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
@@ -414,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
@@ -423,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
@@ -433,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'
@@ -444,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)
@@ -462,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
@@ -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'")
@@ -509,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:
@@ -526,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
@@ -535,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:
@@ -547,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:
@@ -563,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")
@@ -571,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"
@@ -579,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"
@@ -590,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_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..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,14 +344,14 @@ 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))
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("""
@@ -395,16 +394,14 @@ 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
+ 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("""
@@ -511,7 +508,7 @@ def testTupleInit(self):
""")
def testEmptyTuple(self):
- self.Check("""\
+ self.Check("""
isinstance(42, ())
issubclass(int, ())
type("X", (), {"foo": 42})
@@ -519,7 +516,7 @@ def testEmptyTuple(self):
""")
def testListExtend(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
x1 = [42]
x1.extend([""])
x2 = [42]
@@ -627,7 +624,7 @@ def testSetDefaultOneArg(self):
""")
def testSetDefaultVarargs(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
x1 = {}
y1 = x1.setdefault(*("foo", 42))
@@ -685,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 e3c9ec948..df5c1746b 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("""
@@ -90,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}
@@ -121,26 +122,25 @@ def testRepr(self):
""")
def testIntInit(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
int()
int(0)
int("0")
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:
- # 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:
@@ -171,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
@@ -206,21 +206,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 +272,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("""
@@ -349,10 +343,10 @@ def testInput(self):
""")
def testSetDefaultError(self):
- ty, errors = self.InferWithErrors("""\
+ 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 +354,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..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,44 +24,41 @@ 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:
d.create_file("mod.pyi", """
def foo(x, y, *, z) -> int
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
@@ -69,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])
@@ -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..8a30e3ed9 100644
--- a/pytype/tests/test_classes.py
+++ b/pytype/tests/test_classes.py
@@ -209,15 +209,15 @@ def __init__(self, x) -> NoneType
""")
def testSuperError(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
class Base(object):
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("""
@@ -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,27 +897,26 @@ class B(A[T]): ...
class C(A[T], B[T]): ...
def f() -> C[int]: ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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,10 +929,9 @@ 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("""\
+ ty = self.Infer("""
class Foo(object):
def __new__(cls):
return False
@@ -950,7 +948,7 @@ def f(self) -> str: ...
""")
def testNewAmbiguous(self):
- ty = self.Infer("""\
+ ty = self.Infer("""
class Foo(object):
def __new__(cls):
if __random__:
@@ -1029,34 +1027,34 @@ 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)
+ 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, errors = self.InferWithErrors("""
class Foo(object):
def __new__(cls):
# ok because __init__ is defined.
@@ -1065,12 +1063,12 @@ 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("""\
+ _, errors = self.InferWithErrors("""
class Foo(object):
def __init__(self):
# ok because __new__ is defined.
@@ -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("""
@@ -1115,7 +1113,7 @@ def __new__(cls, x):
""", pythonpath=[d.path])
def testInitWithNoParams(self):
- self.Check("""\
+ self.Check("""
class Foo(object):
def __init__():
pass
@@ -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("""
@@ -1153,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):
@@ -1168,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
@@ -1182,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
@@ -1190,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
@@ -1199,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]):
@@ -1207,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]):
@@ -1216,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):
@@ -1232,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
@@ -1251,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 ecbc1af20..d096182a3 100644
--- a/pytype/tests/test_cmp.py
+++ b/pytype/tests/test_cmp.py
@@ -8,9 +8,9 @@ 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
+ 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("""
@@ -48,23 +47,22 @@ def g() -> bool
""")
def test_none(self):
- _, errors = self.InferWithErrors("""\
+ _, 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):
"""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
+ 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):
@@ -96,14 +93,13 @@ def g() -> bool
""")
def test_none(self):
- _, errors = self.InferWithErrors("""\
+ _, 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..8a859e092 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..48ac24bfb 100644
--- a/pytype/tests/test_containers.py
+++ b/pytype/tests/test_containers.py
@@ -548,7 +548,7 @@ def testDict(self):
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("""
@@ -575,11 +573,11 @@ def testDictOrAny(self):
""")
def testDictGetItem(self):
- _, errors = self.InferWithErrors("""\
+ _, 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..24336086f 100644
--- a/pytype/tests/test_decorators.py
+++ b/pytype/tests/test_decorators.py
@@ -82,15 +82,15 @@ class Foo(object):
""")
def testBadKeyword(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
class Foo(object):
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("""
@@ -296,35 +296,35 @@ def bar(cls):
""")
def testInstanceAsDecoratorError(self):
- errors = self.CheckWithErrors("""\
+ errors = self.CheckWithErrors("""
class Decorate(object):
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("""\
+ errors = self.CheckWithErrors("""
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("""\
+ self.Check("""
class Foo():
def __init__(self):
pass
diff --git a/pytype/tests/test_dict.py b/pytype/tests/test_dict.py
index 2a9a543c2..fc80b21d4 100644
--- a/pytype/tests/test_dict.py
+++ b/pytype/tests/test_dict.py
@@ -22,16 +22,16 @@ def testPop(self):
""")
def testBadPop(self):
- ty, errors = self.InferWithErrors("""\
+ 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..a9e5fbdad 100644
--- a/pytype/tests/test_disables.py
+++ b/pytype/tests/test_disables.py
@@ -7,35 +7,32 @@ class DisableTest(test_base.TargetIndependentTest):
"""Test error disabling."""
def testInvalidDirective(self):
- _, errors = self.InferWithErrors("""\
- x = 1 # pytype: this is not a valid pytype directive.
+ _, errors = self.InferWithErrors("""
+ 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.
+ _, errors = self.InferWithErrors("""
+ 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."""
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
'''This is a docstring.
def f(x):
pass
@@ -47,21 +44,21 @@ 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())
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 886e101f9..89358322b 100644
--- a/pytype/tests/test_errors.py
+++ b/pytype/tests/test_errors.py
@@ -8,28 +8,28 @@ class ErrorTest(test_base.TargetIndependentTest):
"""Tests for errors."""
def testDeduplicate(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""
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("""\
+ ty, errors = self.InferWithErrors("""
class A(object):
pass
def f():
- (3).parrot
+ (3).parrot # attribute-error[e]
return "foo"
""")
self.assertTypesMatchPytd(ty, """
@@ -38,116 +38,97 @@ 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
+ _, errors = self.InferWithErrors("""
+ 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)
+ _, errors = self.InferWithErrors("""
+ 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)
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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)
+ _, errors = self.InferWithErrors("""
+ "".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("""\
+ errors = self.CheckWithErrors("""
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:
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)
+ 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:
@@ -158,30 +139,29 @@ def __init__(self) -> None: ...
_, 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("""\
+ _, 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("""\
+ 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:
@@ -191,157 +171,149 @@ def testInheritFromGeneric(self):
class Foo(Generic[T]): ...
class Bar(Foo[int]): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
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)
+ 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:
d.create_file("foo.pyi", """
def bar(xray, yankee, zulu) -> str
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
d.create_file("other.pyi", """
def foo(x: int, y: str) -> str: ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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()
+ _, errors = self.InferWithErrors("""
+ 0() # not-callable[e]
""")
- self.assertErrorLogIs(errors, [(1, "not-callable", r"int")])
+ 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__()
+ 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:
d.create_file("modfoo.pyi", "")
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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("""\
+ _, errors = self.InferWithErrors("""
class Foo(object):
def __getattribute__(self, name):
return "attr"
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
+ _, errors = self.InferWithErrors("""
+ 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:
d.create_file("foo.pyi", """
def f(x: list[int]) -> int: ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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:
@@ -372,10 +342,10 @@ def f() -> int: ...
class f: ...
""")
d.create_file("foo/__init__.pyi", "")
- _, errors = self.InferWithErrors("""\
- from foo import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -384,10 +354,10 @@ def testBadImportFromDependency(self):
class Y(X): ...
""")
d.create_file("foo/__init__.pyi", "")
- _, errors = self.InferWithErrors("""\
- from foo import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -395,11 +365,10 @@ def testBadContainer(self):
from typing import SupportsInt
class A(SupportsInt[int]): pass
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -411,10 +380,10 @@ class A(Generic[K, V]): pass
class B(Generic[K, V]): pass
class C(A[K, V], B[V, K]): pass
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -423,10 +392,10 @@ def testDuplicateTypeParameter(self):
T = TypeVar("T")
class A(Generic[T, T]): pass
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -436,10 +405,10 @@ def testDuplicateGenericBaseClass(self):
V = TypeVar("V")
class A(Generic[T], Generic[V]): pass
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -448,10 +417,10 @@ def testTypeParameterInModuleConstant(self):
T = TypeVar("T")
x = ... # type: T
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -461,12 +430,12 @@ def testTypeParameterInClassAttribute(self):
class A(Generic[T]):
x = ... # type: T
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
@@ -476,47 +445,45 @@ def testUnboundTypeParameterInInstanceAttribute(self):
class A(object):
x = ... # type: T
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
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)
+ 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)
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ 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
@@ -524,11 +491,11 @@ def main() -> Any
""")
def testSetIntAttribute(self):
- _, errors = self.InferWithErrors("""\
+ _, 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:
@@ -536,81 +503,68 @@ def testInvalidParametersOnMethod(self):
class A(object):
def __init__(self, x: int) -> None
""")
- _, errors = self.InferWithErrors("""\
+ _, 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()
+ _, 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]
+ 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("""\
+ _, errors = self.InferWithErrors("""
class A(object):
def f(self):
return "foo"
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):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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:
@@ -618,11 +572,11 @@ def testBadNameImport(self):
import typing
x = ... # type: typing.Rumpelstiltskin
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -630,11 +584,11 @@ def testBadNameImportFrom(self):
from typing import Rumpelstiltskin
x = ... # type: Rumpelstiltskin
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -645,14 +599,14 @@ 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)
- 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
@@ -670,12 +624,12 @@ 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)
+ 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:
@@ -686,23 +640,23 @@ class C(A, B): ...
class D(B, A): ...
class E(C, D): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
d.create_file("a.pyi", """
class A(BaseException, ValueError): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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:
@@ -714,18 +668,18 @@ 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):
- 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.
# Useful for catching large performance regressions.
- ty = self.Infer("""\
+ ty = self.Infer("""
if __random__:
x = [1]
else:
@@ -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:
@@ -762,41 +714,39 @@ 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):
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})
+ _, errors = self.InferWithErrors("""
+ 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})
+ _, errors = self.InferWithErrors("""
+ 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})
+ _, errors = self.InferWithErrors("""
+ 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})
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -804,9 +754,9 @@ def testRecursion(self):
class A(B): ...
class B(A): ...
""")
- ty, errors = self.InferWithErrors("""\
+ 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
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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:
@@ -846,61 +795,56 @@ def testBadPyiDict(self):
from typing import Dict
x = ... # type: Dict[str, int, float]
""")
- _, errors = self.InferWithErrors("""\
- import a
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, errors = self.InferWithErrors("""
if __random__:
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("""\
+ _, 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("""\
+ _, 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:
@@ -908,32 +852,30 @@ 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")
- 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
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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:
@@ -942,201 +884,218 @@ def testCleanPyiNamedtupleNames(self):
X = NamedTuple("X", [])
def f(x: int): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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]
+ _, errors = self.InferWithErrors("""
+ 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")
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""\
+ 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..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")
@@ -77,10 +77,9 @@ 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, """\
+ self.assertNoCrash(self.Check, """
try:
fooey
print("Yes fooey?")
@@ -89,15 +88,14 @@ 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, """\
+ self.assertNoCrash(self.Check, """
def fn():
try:
fooey
@@ -108,20 +106,19 @@ 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("""\
+ self.Check("""
def fn():
try:
raise ValueError("ouch")
@@ -132,7 +129,7 @@ def fn():
""")
def test_finally_while_throwing(self):
- self.Check("""\
+ self.Check("""
def fn():
try:
print("About to..")
@@ -144,7 +141,7 @@ def fn():
""")
def test_coverage_issue_92(self):
- self.Check("""\
+ self.Check("""
l = []
for i in range(3):
try:
@@ -158,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
@@ -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("""\
+ 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("""
@@ -372,19 +368,18 @@ def h() -> KeyError: ...
""")
def test_bad_type(self):
- errors = self.CheckWithErrors("""\
+ 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..5649bc7b1 100644
--- a/pytype/tests/test_flow.py
+++ b/pytype/tests/test_flow.py
@@ -334,14 +334,14 @@ def test_loop_over_list_of_lists(self):
""")
def test_call_undefined(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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..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,21 +105,20 @@ 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):
"""Tests for generators."""
def test_first(self):
- self.Check("""\
+ self.Check("""
def two():
yield 1
yield 2
@@ -131,7 +127,7 @@ def two():
""")
def test_partial_generator(self):
- self.Check("""\
+ self.Check("""
from functools import partial
def f(a,b):
@@ -146,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
@@ -162,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))
@@ -180,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):
@@ -209,9 +205,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,39 +218,36 @@ 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):
"""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)
@@ -264,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)
@@ -279,7 +274,7 @@ def g():
""")
def test_recursion(self):
- self.Check("""\
+ self.Check("""
def fact(n):
if n <= 1:
return 1
@@ -291,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)
@@ -301,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()
@@ -313,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,))
@@ -338,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):
@@ -367,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):
@@ -386,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)
@@ -436,11 +431,11 @@ 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__))
+ 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:
@@ -560,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])
@@ -654,15 +649,15 @@ 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)
+ 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("""\
+ ty = self.Infer("""
v1, = (object.__new__,)
v2 = type(object.__new__)
""", deep=False)
@@ -726,23 +721,23 @@ 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):
- 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
- 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)
""")
@@ -754,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)
@@ -765,27 +760,26 @@ 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):
- _, 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 +801,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 +828,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 +870,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("""
@@ -969,26 +955,22 @@ def __init__(self, a, b=None):
""")
def test_functools_partial_bad_call(self):
- errors = self.CheckWithErrors("""\
+ 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..744d756d1 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..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,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:
@@ -127,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()
@@ -143,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()
@@ -155,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 = []
""")
@@ -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,13 +440,13 @@ 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
""")
ty = self.InferFromFile(filename=d["foo/deep/bar.py"],
pythonpath=[d.path])
- self.assertTypesMatchPytd(ty, """\
+ self.assertTypesMatchPytd(ty, """
baz = ... # type: module
a: int
""")
@@ -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])
@@ -496,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)
@@ -513,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)
@@ -525,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()
@@ -542,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():
@@ -576,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)
@@ -605,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
@@ -639,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
@@ -657,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])
@@ -671,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])
@@ -687,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
@@ -708,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=[""])
@@ -726,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)
@@ -748,11 +746,11 @@ def testTwoLevel(self):
class B(a.A):
pass
""")
- _, errors = self.InferWithErrors("""\
- import b
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -781,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])
@@ -798,27 +796,24 @@ 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:
d.create_file("foo.pyi", """
def f(x: FooBar) -> FooBar
""")
- self.assertNoCrash(self.Check, """\
+ self.assertNoCrash(self.Check, """
import foo
""", pythonpath=[d.path])
@@ -828,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])
@@ -847,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
@@ -872,15 +867,12 @@ def testAttributeOnModule(self):
d.create_file("a.pyi", """
foo = ... # type: int
""")
- _, errors = self.InferWithErrors("""\
- from a import foo, bar
+ _, errors = self.InferWithErrors("""
+ 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:
@@ -891,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
@@ -900,13 +892,13 @@ 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
""".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,17 +906,17 @@ 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))
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]
@@ -947,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
@@ -975,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
@@ -1130,28 +1122,27 @@ 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()
+ 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."""
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 6839db1a1..ded75d4fc 100644
--- a/pytype/tests/test_list.py
+++ b/pytype/tests/test_list.py
@@ -70,16 +70,16 @@ 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
d = a[c]
- e = a["s"]
+ e = a["s"] # unsupported-operands[e]
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
@@ -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..77a5796f1 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,23 +99,19 @@ 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(
- """\
+ """
import collections
F = collections.namedtuple("S", ['a', 'b', 'c'])
""")
@@ -153,29 +142,28 @@ 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() # 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:
d.create_file("foo.pyi", """
class X(NamedTuple("X", [])): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, 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..89ff45524 100644
--- a/pytype/tests/test_operators.py
+++ b/pytype/tests/test_operators.py
@@ -324,13 +324,13 @@ 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 ""
- (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,
@@ -368,12 +368,12 @@ 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()
+ 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..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])
@@ -338,13 +338,13 @@ def __getattr__(name) -> Any
""")
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:
@@ -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,12 +432,12 @@ 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})
- 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:
@@ -561,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)
@@ -584,12 +580,12 @@ def bar(self):
self = Bar[T2]
""")
# We should get an error at import time rather than at use time here.
- _, errors = self.InferWithErrors("""\
- import foo
+ _, errors = self.InferWithErrors("""
+ 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,12 +721,12 @@ 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: ...
""")
- 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 78390ae32..45e157dff 100644
--- a/pytype/tests/test_quick.py
+++ b/pytype/tests/test_quick.py
@@ -75,13 +75,13 @@ 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
+ 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..7d4465c2a 100644
--- a/pytype/tests/test_recovery.py
+++ b/pytype/tests/test_recovery.py
@@ -99,20 +99,16 @@ 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("""\
+ self.Check("""
class Foo(object):
def __init__(self):
self._bar = "foo"
@@ -123,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"
@@ -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..5c644d1f7 100644
--- a/pytype/tests/test_reingest.py
+++ b/pytype/tests/test_reingest.py
@@ -120,12 +120,12 @@ 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 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..ad6a99ec6 100644
--- a/pytype/tests/test_slots.py
+++ b/pytype/tests/test_slots.py
@@ -65,13 +65,10 @@ class Foo(object):
def testSlotWithNonStrings(self):
_, errors = self.InferWithErrors("""
- class Foo(object):
+ 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
+ _, errors = self.InferWithErrors("""
+ 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("""
@@ -134,79 +126,65 @@ class Foo(__any_object__):
""")
def testParameterizedBaseClass(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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("""\
+ _, 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("""\
+ _, errors = self.InferWithErrors("""
import collections
Foo = collections.namedtuple("_", ["a", "b", "c"])
foo = Foo(None, None, None)
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("""\
+ _, 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("""\
+ self.Check("""
class Foo(object):
__slots__ = ()
def __setattr__(self, name, value):
@@ -218,7 +196,7 @@ class Bar(Foo):
""")
def testDescriptors(self):
- self.Check("""\
+ self.Check("""
class Descriptor(object):
def __set__(self, obj, cls):
pass
@@ -232,7 +210,7 @@ class Bar(Foo):
""")
def testNameMangling(self):
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
class Bar(object):
__slots__ = ["__baz"]
def __init__(self):
@@ -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_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 3a01be077..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"
@@ -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..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,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("""
@@ -678,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
@@ -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_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 5ec5e237f..595bd5004 100644
--- a/pytype/tests/test_super.py
+++ b/pytype/tests/test_super.py
@@ -72,12 +72,12 @@ 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)
+ 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("""
@@ -143,15 +143,15 @@ def hello(self):
""")
def testCallSuper(self):
- _, errorlog = self.InferWithErrors("""\
+ _, errorlog = self.InferWithErrors("""
class Y(object):
pass
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("""
@@ -194,30 +194,28 @@ def testSuperWithAny(self):
""")
def testSingleArgumentSuper(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ 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("""\
+ self.Check("""
def decorate(cls):
return __any_object__
class Parent(object):
@@ -230,42 +228,42 @@ def Hello(self):
""")
def testSuperSetAttr(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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:
d.create_file("foo.pyi", """
class Foo(nothing): ...
""")
- _, errors = self.InferWithErrors("""\
+ _, errors = self.InferWithErrors("""
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("""\
+ _, 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..96635445a 100644
--- a/pytype/tests/test_tracebacks.py
+++ b/pytype/tests/test_tracebacks.py
@@ -7,80 +7,72 @@ 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
+ "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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ 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("""\
+ 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..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,10 +62,10 @@ def testUnpackTuple(self):
""")
def testBadUnpacking(self):
- ty, errors = self.InferWithErrors("""\
+ 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("""
@@ -93,11 +92,11 @@ def testMutableItem(self):
""")
def testBadTupleClassGetItem(self):
- _, errors = self.InferWithErrors("""\
+ _, 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..11d3f3771 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("""
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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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("""\
+ _, 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):
@@ -333,41 +321,38 @@ def f() -> Tuple[Mapping, dict]: ...
""")
def testBadComment(self):
- ty, errors = self.InferWithErrors("""\
- X = None # type: abc def
+ ty, errors = self.InferWithErrors("""
+ 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
""")
def testConversionError(self):
- ty, errors = self.InferWithErrors("""\
- X = None # type: 1 if __random__ else 2
+ ty, errors = self.InferWithErrors("""
+ 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
""")
def testNameErrorInsideComment(self):
- _, errors = self.InferWithErrors("""\
- X = None # type: Foo
+ _, errors = self.InferWithErrors("""
+ 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("""\
+ _, 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("""
@@ -393,17 +378,16 @@ def testNoneToNoneType(self):
""")
def testModuleInstanceAsBadTypeComment(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ 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,30 +402,30 @@ 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("""\
+ 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
@@ -451,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):
@@ -461,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):
@@ -473,32 +457,30 @@ 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("""\
+ 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("""\
+ ty = self.Infer("""
a = [[
]
@@ -510,24 +492,22 @@ def testMultilineValueWithBlankLines(self):
""")
def testTypeCommentNameError(self):
- _, errors = self.InferWithErrors("""\
+ _, 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("""\
+ _, 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."""
- ty = self.Infer("""\
+ ty = self.Infer("""
# We want either # type: ignore or # type: int
def hello_world():
# type: () -> str
@@ -539,15 +519,14 @@ 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
+ _, errors = self.InferWithErrors("""
+ 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."""
- 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
@@ -555,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):
@@ -570,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
@@ -583,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
@@ -593,38 +572,37 @@ 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
+ 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("""\
+ ty, errors = self.InferWithErrors("""
from typing import Optional
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..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,16 +29,16 @@ def testImportTypeVar(self):
""")
def testInvalidTypeVar(self):
- ty, errors = self.InferWithErrors("""\
+ 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,17 +111,15 @@ 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("""\
+ ty = self.Infer("""
from typing import List, TypeVar
T = TypeVar("T")
class A(List[T]): pass
@@ -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("""\
+ _, 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("""\
+ _, 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
@@ -379,22 +366,20 @@ def testStoreTypeVarInDict(self):
""")
def testLateBound(self):
- _, errors = self.InferWithErrors("""\
+ _, 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..342ec5e53 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,24 +53,20 @@ 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, """\
+ self.assertNoCrash(self.Check, """
import typing
typing.cast(typing.AnyStr)
typing.cast("str")
@@ -93,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
""")
@@ -104,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
@@ -121,7 +117,7 @@ class Foo(Iterable): ...
""")
def test_type_checking(self):
- self.Check("""\
+ self.Check("""
import typing
if typing.TYPE_CHECKING:
pass
@@ -130,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
@@ -141,24 +137,19 @@ def test_not_type_checking(self):
def test_new_type_arg_error(self):
_, 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("""\
+ ty = self.Infer("""
from typing import ClassVar
class A(object):
x = 5 # type: ClassVar[int]
@@ -187,18 +178,19 @@ def test_pyi_classvar_argcount(self):
class X:
v: ClassVar[int, int]
""")
- errors = self.CheckWithErrors("""\
- import foo
+ errors = self.CheckWithErrors("""
+ 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_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 983006382..1bb8177f7 100644
--- a/pytype/tests/test_typing_namedtuple.py
+++ b/pytype/tests/test_typing_namedtuple.py
@@ -7,104 +7,82 @@ 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("""\
+ errors = self.CheckWithErrors("""
import typing
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(
@@ -114,31 +92,30 @@ 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="")
- 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("""\
+ 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("""\
+ 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..f5e6550b8 100644
--- a/pytype/tests/test_unions.py
+++ b/pytype/tests/test_unions.py
@@ -24,22 +24,19 @@ 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__:
# 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 7c5e4172b..96ca3b4b8 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
@@ -158,13 +159,13 @@ 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})
- 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):
@@ -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, regexp = 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 count == 1:
- del expected_errors[pattern]
- else:
- expected_errors[pattern] -= 1
- break
- else:
- almost_matches.add(regexp)
- 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, regexp = self._parse_expected_error(pattern)
- line = self.marks.get(line, line)
- expected.append((line, name, regexp))
-
- 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, regexp = 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)
- incremented_expected_error = (line, name)
- if regexp:
- incremented_expected_error += (regexp,)
- 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]
- regexp = pattern[2] if len(pattern) > 2 else ""
- return line, name, regexp
+ 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):
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/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):
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)