diff --git a/pytype/tests/py2/test_abc.py b/pytype/tests/py2/test_abc.py index e396f67f2..0b4dc280c 100644 --- a/pytype/tests/py2/test_abc.py +++ b/pytype/tests/py2/test_abc.py @@ -7,15 +7,14 @@ class AbstractMethodTests(test_base.TargetPython27FeatureTest): """Tests for @abc.abstractmethod.""" def test_name_error(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import abc class Example(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def foo(self): - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(6, "name-error", r"name_error")]) def test_instantiate_abstract_class(self): _, errors = self.InferWithErrors("""\ @@ -25,9 +24,9 @@ class Example(object): @abc.abstractmethod def foo(self): pass - Example() # line 7 + Example() # not-instantiable[e] """) - self.assertErrorLogIs(errors, [(7, "not-instantiable", r"Example.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Example.*foo"}) def test_multiple_inheritance_implementation(self): self.Check(""" @@ -59,9 +58,9 @@ def foo(self): pass class Foo(X, Interface): pass - Foo().foo() # line 11 + Foo().foo() # not-instantiable[e] """) - self.assertErrorLogIs(errors, [(11, "not-instantiable", r"Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo.*foo"}) def test_multiple_inheritance_builtins(self): self.Check(""" diff --git a/pytype/tests/py2/test_attributes.py b/pytype/tests/py2/test_attributes.py index b48803837..dcbc0be3d 100644 --- a/pytype/tests/py2/test_attributes.py +++ b/pytype/tests/py2/test_attributes.py @@ -19,9 +19,9 @@ class A(object): values = 42 args = {A() if __random__ else True: ""} for x, y in sorted(args.iteritems()): - x.values # line 5 + x.values # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"'values' on bool")]) + self.assertErrorRegexes(errors, {"e": r"'values' on bool"}) def testTypeParameterInstanceSetAttr(self): ty = self.Infer(""" @@ -63,9 +63,9 @@ def testIter(self): errors = self.CheckWithErrors("""\ def f(): x = None - return [y for y in x] + return [y for y in x] # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"__iter__.*None")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*None"}) @test_base.skip("Needs vm._get_iter() to iterate over individual bindings.") def testMetaclassIter(self): diff --git a/pytype/tests/py2/test_builtins.py b/pytype/tests/py2/test_builtins.py index e9eddb389..4c1164cb9 100644 --- a/pytype/tests/py2/test_builtins.py +++ b/pytype/tests/py2/test_builtins.py @@ -349,10 +349,9 @@ def testIterItems(self): def testIntInit(self): _, errors = self.InferWithErrors("""\ - int(0, 1) # line 8: expected str or unicode, got int for first arg + int(0, 1) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Union\[str, unicode\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[str, unicode\].*int"}) def testAddStrAndBytearray(self): ty = self.Infer(""" diff --git a/pytype/tests/py2/test_decorators.py b/pytype/tests/py2/test_decorators.py index c8f401978..bb9347587 100644 --- a/pytype/tests/py2/test_decorators.py +++ b/pytype/tests/py2/test_decorators.py @@ -14,9 +14,9 @@ def decorate(cls): @decorate class Foo(object): def Hello(self): - return self.Goodbye() # line 6 + return self.Goodbye() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(6, "attribute-error", r"Goodbye")]) + self.assertErrorRegexes(errors, {"e": r"Goodbye"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_errors.py b/pytype/tests/py2/test_errors.py index cda165a2d..6e771c585 100644 --- a/pytype/tests/py2/test_errors.py +++ b/pytype/tests/py2/test_errors.py @@ -9,27 +9,27 @@ class ErrorTest(test_base.TargetPython27FeatureTest): def testProtocolMismatch(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", "__iter__, next") - ]) + self.assertErrorRegexes(errors, {"e": r"__iter__, next"}) def testProtocolMismatchPartial(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __iter__(self): return self - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 4, "wrong-arg-types", r"\n\s*next\s*$")]) # `next` on its own line + self.assertErrorRegexes( + errors, {"e": r"\n\s*next\s*$"}) # `next` on its own line def testGetSlice(self): - errors = self.CheckWithErrors("def f(): v = []; return v[:'foo']") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"slicing.*List.*str.*__getslice__ on List.*Optional\[int\]")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; return v[:'foo'] # unsupported-operands[e] + """) + self.assertErrorRegexes( + errors, + {"e": r"slicing.*List.*str.*__getslice__ on List.*Optional\[int\]"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_list.py b/pytype/tests/py2/test_list.py index f58dfc088..b62512840 100644 --- a/pytype/tests/py2/test_list.py +++ b/pytype/tests/py2/test_list.py @@ -18,8 +18,8 @@ def test_getslice_slot(self): g = a[2:None] h = a[None:2] i = a[None:None] - j = a[int:str] - k = a["s":] + j = a[int:str] # unsupported-operands[e1] + k = a["s":] # unsupported-operands[e2] l = a[1:-1] m = a[0:0] n = a[1:1] @@ -41,9 +41,8 @@ def test_getslice_slot(self): m = ... # type: List[nothing] n = ... # type: List[nothing] """) - self.assertErrorLogIs(errors, [ - (10, "unsupported-operands", r"__getslice__ on List"), - (11, "unsupported-operands", r"__getslice__ on List")]) + self.assertErrorRegexes(errors, { + "e1": r"__getslice__ on List", "e2": r"__getslice__ on List"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_namedtuple.py b/pytype/tests/py2/test_namedtuple.py index e1336c4ba..d7c07d8c2 100644 --- a/pytype/tests/py2/test_namedtuple.py +++ b/pytype/tests/py2/test_namedtuple.py @@ -23,18 +23,14 @@ def test_calls(self): """) def test_bad_call(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple() - collections.namedtuple("_") - collections.namedtuple("_", "", True, True, True) - collections.namedtuple("_", "", True, verbose=True) + collections.namedtuple() # missing-parameter + collections.namedtuple("_") # missing-parameter + collections.namedtuple("_", "", True, True, True) # wrong-arg-count + collections.namedtuple( + "_", "", True, verbose=True) # duplicate-keyword-argument """) - self.assertErrorLogIs(errorlog, - [(2, "missing-parameter"), - (3, "missing-parameter"), - (4, "wrong-arg-count"), - (5, "duplicate-keyword-argument")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_pyi.py b/pytype/tests/py2/test_pyi.py index 392028cd4..1dcb1448c 100644 --- a/pytype/tests/py2/test_pyi.py +++ b/pytype/tests/py2/test_pyi.py @@ -35,8 +35,10 @@ def get_varargs(x: int, *args: T, z: int, **kws: int) -> T: ... v1 = a.get_varargs(1, *l1) v2 = a.get_varargs(1, *l2, z=5) v3 = a.get_varargs(1, True, 2.0, z=5) - v4 = a.get_varargs(1, 2j, "foo", z=5) # bad: conflicting args types - v5 = a.get_varargs(1, *None) # bad: None not iterable + # bad: conflicting args types + v4 = a.get_varargs(1, 2j, "foo", z=5) # wrong-arg-types[e1] + # bad: None not iterable + v5 = a.get_varargs(1, *None) # wrong-arg-types[e2] """, deep=True, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any @@ -53,8 +55,7 @@ def get_varargs(x: int, *args: T, z: int, **kws: int) -> T: ... r"Actually passed: \(x, _, _2: str, \.\.\.\)") msg2 = (r"Expected: \(x, \*args: Iterable, \.\.\.\).*" r"Actually passed: \(x, args: None\)") - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", msg1), - (9, "wrong-arg-types", msg2)]) + self.assertErrorRegexes(errors, {"e1": msg1, "e2": msg2}) # TODO(sivachandra): Make this a target independent test after # after b/78785264 is fixed. @@ -69,11 +70,12 @@ def get_kwargs(x: int, *args: int, z: int, **kws: T) -> T: ... import a d1 = None # type: dict[int, int] d2 = None # type: Mapping[str, Union[str, complex]] - v1 = a.get_kwargs(1, 2, 3, z=5, **d1) # bad: K must be str + # bad: K must be str + v1 = a.get_kwargs(1, 2, 3, z=5, **d1) # wrong-arg-types[e1] v2 = a.get_kwargs(1, 2, 3, z=5, **d2) v3 = a.get_kwargs(1, 2, 3, z=5, v=0, u=3j) # bad: conflicting kwargs types - v4 = a.get_kwargs(1, 2, 3, z=5, v="", u=3j) + v4 = a.get_kwargs(1, 2, 3, z=5, v="", u=3j) # wrong-arg-types[e2] """, deep=True, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any, Mapping @@ -89,8 +91,7 @@ def get_kwargs(x: int, *args: int, z: int, **kws: T) -> T: ... r"Actually passed: \(x, _, _, z, kws: Dict\[int, int\]\)") msg2 = (r"Expected: \(x, _, _, u, v: complex, \.\.\.\).*" r"Actually passed: \(x, _, _, u, v: str, \.\.\.\)") - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", msg1), - (9, "wrong-arg-types", msg2)]) + self.assertErrorRegexes(errors, {"e1": msg1, "e2": msg2}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_reingest.py b/pytype/tests/py2/test_reingest.py index 7da3d2717..b541ffece 100644 --- a/pytype/tests/py2/test_reingest.py +++ b/pytype/tests/py2/test_reingest.py @@ -24,10 +24,10 @@ def foo(self): d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.Foo() + foo.Foo() # not-instantiable[e] foo.Bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_slots.py b/pytype/tests/py2/test_slots.py index 125c83611..a12232e05 100644 --- a/pytype/tests/py2/test_slots.py +++ b/pytype/tests/py2/test_slots.py @@ -7,24 +7,23 @@ class SlotsTest(test_base.TargetPython27FeatureTest): """Tests for __slots__.""" def testBuiltinAttr(self): - _, errors = self.InferWithErrors("""\ - buffer("foo").bar = 16 + self.InferWithErrors("""\ + buffer("foo").bar = 16 # not-writable """) - self.assertErrorLogIs(errors, [(1, "not-writable")]) def testSlotWithBytes(self): - _ = self.Check("""\ + self.Check("""\ class Foo(object): __slots__ = (b"x",) """) def testSlotWithUnicode(self): errors = self.CheckWithErrors("""\ - class Foo(object): + class Foo(object): # bad-slots[e] __slots__ = (u"fo\\xf6", u"b\\xe4r", "baz") Foo().baz = 3 """) - self.assertErrorLogIs(errors, [(1, "bad-slots", r"fo\\xc3\\xb6")]) + self.assertErrorRegexes(errors, {"e": r"fo\\xc3\\xb6"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_super.py b/pytype/tests/py2/test_super.py index 2b8b92cd1..c5c5f0d30 100644 --- a/pytype/tests/py2/test_super.py +++ b/pytype/tests/py2/test_super.py @@ -12,14 +12,13 @@ def testSuperMissingArg(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls): - return super(cls).__new__(cls) + return super(cls).__new__(cls) # wrong-arg-types[e1] class Bar(object): def __new__(cls): - return super().__new__(cls) + return super().__new__(cls) # wrong-arg-count[e2] """) - self.assertErrorLogIs(errors, [ - (3, "wrong-arg-types", r"Type\[super\].*Type\[Foo\]"), - (6, "wrong-arg-count", r"2.*0")]) + self.assertErrorRegexes( + errors, {"e1": r"Type\[super\].*Type\[Foo\]", "e2": r"2.*0"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py2/test_typevar.py b/pytype/tests/py2/test_typevar.py index fc3b447e0..e1d5b661e 100644 --- a/pytype/tests/py2/test_typevar.py +++ b/pytype/tests/py2/test_typevar.py @@ -9,7 +9,7 @@ class Test(test_base.TargetPython27FeatureTest): def testUseConstraintsFromPyi(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ from typing import AnyStr, TypeVar T = TypeVar("T", int, float) def f(x: T) -> T: ... @@ -17,25 +17,23 @@ def g(x: AnyStr) -> AnyStr: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f("") - foo.g(0) + foo.f("") # wrong-arg-types[e1] + foo.g(0) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"Union\[float, int\].*str"), - (3, "wrong-arg-types", r"Union\[str, unicode\].*int")]) + self.assertErrorRegexes(errors, { + "e1": r"Union\[float, int\].*str", + "e2": r"Union\[str, unicode\].*int"}) def testExtraArguments(self): # TODO(b/78905523): Make this a target-independent test. _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", extra_arg=42) - S = TypeVar("S", *__any_object__) - U = TypeVar("U", **__any_object__) + T = TypeVar("T", extra_arg=42) # invalid-typevar[e1] + S = TypeVar("S", *__any_object__) # invalid-typevar[e2] + U = TypeVar("U", **__any_object__) # invalid-typevar[e3] """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"extra_arg"), - (3, "invalid-typevar", r"\*args"), - (4, "invalid-typevar", r"\*\*kwargs")]) + self.assertErrorRegexes(errors, { + "e1": r"extra_arg", "e2": r"\*args", "e3": r"\*\*kwargs"}) def testSimplifyArgsAndKwargs(self): # TODO(b/78905523): Make this a target-independent test. diff --git a/pytype/tests/py3/test_abc.py b/pytype/tests/py3/test_abc.py index a0ad0dd34..692362565 100644 --- a/pytype/tests/py3/test_abc.py +++ b/pytype/tests/py3/test_abc.py @@ -63,7 +63,7 @@ class Bar(Foo): @property def foo(self): return super(Bar, self).foo - v1 = Foo().foo + v1 = Foo().foo # not-instantiable[e] v2 = Bar().foo """) self.assertTypesMatchPytd(ty, """ @@ -77,7 +77,7 @@ class Bar(Foo): class Foo(metaclass=abc.ABCMeta): foo = ... # type: Any """) - self.assertErrorLogIs(errors, [(10, "not-instantiable", r"Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_annotations.py b/pytype/tests/py3/test_annotations.py index f995c2c7a..14cf2a0c3 100644 --- a/pytype/tests/py3/test_annotations.py +++ b/pytype/tests/py3/test_annotations.py @@ -63,9 +63,9 @@ def testCallError(self): s = {1} def foo(x: int): s.intersection(x) - foo(3.0) + foo(3.0) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: int.*x: float")]) + self.assertErrorRegexes(errors, {"e": r"x: int.*x: float"}) def testAmbiguousArg(self): self.Check("""\ @@ -84,9 +84,9 @@ def g(y, z): def testInnerError(self): _, errors = self.InferWithErrors("""\ def foo(x: int): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) def testList(self): ty = self.Infer(""" @@ -170,45 +170,40 @@ def f(c: calendar.Calendar) -> int: ... def testAmbiguousAnnotation(self): _, errors = self.InferWithErrors("""\ - def foo(x: int if __random__ else float): + def foo(x: int if __random__ else float): # invalid-annotation[e1] return x - def foo(x: "int if __random__ else float"): + def foo(x: "int if __random__ else float"): # invalid-annotation[e2] return x """) - self.assertErrorLogIs(errors, { - (1, "invalid-annotation", r"float or int.*x.*constant"), - # For a late annotation, we print the string literal, which is why - # the types below are not in alphabetical order. - (3, "invalid-annotation", r"int.*float.*x.*constant")}) + self.assertErrorRegexes(errors, { + "e1": r"float or int.*x.*constant", + # For a late annotation, we print the string literal, which is why the + # types below are not in alphabetical order. + "e2": r"int.*float.*x.*constant"}) def testBadStringAnnotation(self): _, errors = self.InferWithErrors("""\ - def foo(x: str()): + def foo(x: str()): # invalid-annotation[e] return x """) - self.assertErrorLogIs(errors, { - (1, "invalid-annotation", r"x.*constant")}) + self.assertErrorRegexes(errors, {"e": r"x.*constant"}) def testBadReturn(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x: str, y: str) -> int: - return "foo" + return "foo" # bad-return-type """) - self.assertErrorLogIs(errors, { - (2, "bad-return-type")}) def testMultipleReturns(self): _, errors = self.InferWithErrors("""\ def foo(x: str, y: str) -> int: if x: - return "foo" + return "foo" # bad-return-type[e1] else: - return 3j + return 3j # bad-return-type[e2] """) - self.assertErrorLogIs(errors, { - (3, "bad-return-type", r"Expected.*int.*Actual.*str"), - (5, "bad-return-type", r"Expected.*int.*Actual.*complex") - }) + self.assertErrorRegexes(errors, {"e1": r"Expected.*int.*Actual.*str", + "e2": r"Expected.*int.*Actual.*complex"}) def testAmbiguousReturn(self): _, errors = self.InferWithErrors("""\ @@ -217,12 +212,10 @@ def foo(x: str) -> int: y = "foo" else: y = 3j - return y + return y # bad-return-type[e] """) - self.assertErrorLogIs(errors, { - (6, "bad-return-type", - r"Expected.*int.*Actual.*Union(?=.*complex).*str"), - }) + self.assertErrorRegexes( + errors, {"e": r"Expected.*int.*Actual.*Union(?=.*complex).*str"}) def testDefaultReturn(self): ty = self.Infer("""\ @@ -279,73 +272,56 @@ def f(x) -> None: ... """) def testDict(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Dict, List def keys(d: Dict[str, int]): return keys({"foo": 3}) keys({}) # ok - keys({3: 3}) # not allowed + keys({3: 3}) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testSequence(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Sequence def f(s: Sequence): return s f([1,2,3]) f((1,2,3)) - f({1,2,3}) - f(1) + f({1,2,3}) # wrong-arg-types + f(1) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testOptional(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Optional def f(s: Optional[int]): return s f(1) f(None) - f("foo") + f("foo") # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testSet(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Set def f(d: Set[str]): return f({"foo"}) # ok f(set()) # ok - f({}) # not allowed, {} isn't a set - f({3}) # not allowed + f({}) # {} isn't a set # wrong-arg-types + f({3}) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testFrozenSet(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import FrozenSet def f(d: FrozenSet[str]): return f(frozenset(["foo"])) # ok f(frozenset()) # ok - f(frozenset([3])) # not allowed + f(frozenset([3])) # wrong-arg-types """, deep=True) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - ]) def testGenericAndTypeVar(self): self.assertNoCrash(self.Check, """\ @@ -385,13 +361,13 @@ class B(object): def testWithoutForwardDecl(self): _, errorlog = self.InferWithErrors("""\ - def f(a) -> Bar: + def f(a) -> Bar: # name-error[e] return Bar() class Bar(object): pass """) - self.assertErrorLogIs(errorlog, [(1, "name-error", r"Bar")]) + self.assertErrorRegexes(errorlog, {"e": r"Bar"}) def testInvalidForwardDecl(self): self.Check(""" @@ -402,25 +378,24 @@ class Foo(object): pass """) _, errorlog = self.InferWithErrors("""\ - def f(a: "Foo"): + def f(a: "Foo"): # name-error[e] return B() class B(object): pass """) - self.assertErrorLogIs(errorlog, [(1, "name-error", r"Foo")]) + self.assertErrorRegexes(errorlog, {"e": r"Foo"}) def testForwardDeclBadReturn(self): _, errorlog = self.InferWithErrors("""\ def f() -> "Foo": - return 1 + return 1 # bad-return-type[e] class Foo(object): pass """) # Error message along the lines: No attribute 'bar' on Foo - self.assertErrorLogIs( - errorlog, [(2, "bad-return-type", r"return type.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"return type.*int"}) def testConfusingForwardDecl(self): _, errorlog = self.InferWithErrors("""\ @@ -436,20 +411,18 @@ def bar(self): return 2 def g(): - return f().bar() + return f().bar() # attribute-error[e] """) # Error message along the lines: No attribute 'bar' on Foo - self.assertErrorLogIs( - errorlog, [(13, "attribute-error", r"\'bar\'.*Foo")]) + self.assertErrorRegexes(errorlog, {"e": r"\'bar\'.*Foo"}) def testReturnTypeError(self): _, errors = self.InferWithErrors("""\ class FooBar(object): pass def f() -> FooBar: - return 3 + return 3 # bad-return-type[e] """, deep=True) - self.assertErrorLogIs(errors, [( - 3, "bad-return-type", r"Expected: FooBar")]) + self.assertErrorRegexes(errors, {"e": r"Expected: FooBar"}) def testUnknownArgument(self): with file_utils.Tempdir() as d: @@ -477,7 +450,7 @@ def foo(): } labels['baz'] = bar( - labels['baz']) + labels['baz']) # wrong-arg-types[e] def bar(path: str, **kwargs): return path @@ -488,7 +461,7 @@ def foo() -> None def bar(path: str, **kwargs) -> str """) error = r"Actually passed:.*path: None" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testBadCallWithKwarg(self): ty, errors = self.InferWithErrors("""\ @@ -498,7 +471,7 @@ def foo(): } labels['baz'] = bar( - labels['baz'], x=42) + labels['baz'], x=42) # wrong-arg-types[e] def bar(path: str, **kwargs): return path @@ -509,7 +482,7 @@ def foo() -> None def bar(path: str, **kwargs) -> str """) error = r"Actually passed:.*path: None" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testSkipFunctionsWithAnnotations(self): ty = self.Infer("""\ @@ -567,13 +540,13 @@ def func(x: Union[Container1, Container2]): """) def testImpreciseAnnotation(self): - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ from typing import Union class A: pass class B: x = 42 def f(v: Union[A, B]): - return v.x + return v.x # attribute-error[e] f(A()) """) self.assertTypesMatchPytd(ty, """ @@ -583,7 +556,7 @@ class B: x = ... # type: int def f(v: Union[A, B]) -> int: ... """) - self.assertErrorLogIs(errors, [(7, "attribute-error", "x.*A")]) + self.assertErrorRegexes(errors, {"e": r"x.*A"}) def testTuple(self): ty = self.Infer(""" @@ -627,16 +600,16 @@ def g(x: Union["int"]): def testAmbiguousInnerAnnotation(self): _, errors = self.InferWithErrors("""\ from typing import List, Union - def f(x: List[int if __random__ else str]): + def f(x: List[int if __random__ else str]): # invalid-annotation[e1] pass - def g(x: Union[int if __random__ else str]): + def g(x: Union[int if __random__ else str]): # invalid-annotation[e2] pass def h(x: List[Union[int, str]]): # okay pass """) - self.assertErrorLogIs(errors, [ - (2, "invalid-annotation", r"List\[int\] or List\[str\].*constant"), - (4, "invalid-annotation", r"int or str.*constant")]) + self.assertErrorRegexes(errors, { + "e1": r"List\[int\] or List\[str\].*constant", + "e2": r"int or str.*constant"}) def testKwargs(self): ty, errors = self.InferWithErrors("""\ @@ -650,8 +623,8 @@ def h() -> Dict[float, int]: f("", y=42) f("", **{}) f("", **{"y": 42}) - f("", **g()) - f("", **h()) + f("", **g()) # wrong-arg-types[e1] + f("", **h()) # wrong-arg-types[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Dict @@ -663,8 +636,7 @@ def h() -> Dict[float, int] r"Actually passed.*Dict\[str, float\]") error2 = (r"Expected.*Mapping\[str, int\].*" r"Actually passed.*Dict\[float, int\]") - self.assertErrorLogIs(errors, [(11, "wrong-arg-types", error1), - (12, "wrong-arg-types", error2)]) + self.assertErrorRegexes(errors, {"e1": error1, "e2": error2}) @test_base.skip("Types not checked due to function.Args.simplify") def testSimplifiedVarargsAndKwargs(self): @@ -673,14 +645,12 @@ def f(x, *args: int): pass def g(x, **kwargs: int): pass - f("", 42.0) - g("", y=42.0) - g("", **{"y": 42.0}) + f("", 42.0) # wrong-arg-types[e1] + g("", y=42.0) # wrong-arg-types[e2] + g("", **{"y": 42.0}) # wrong-arg-types[e3] """) error = r"Expected.*int.*Actually passed.*float" - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", error), - (6, "wrong-arg-types", error), - (7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e1": error, "e2": error, "e3": error}) def testUseVarargsAndKwargs(self): ty = self.Infer(""" @@ -722,7 +692,7 @@ def f() -> Union[A, None]: pass def g() -> List[None]: return [None] - v1 = f().x # line 8 + v1 = f().x # attribute-error[e] v2 = g()[0] """, deep=False) self.assertTypesMatchPytd(ty, """ @@ -734,7 +704,7 @@ def g() -> List[None]: ... v1 = ... # type: int v2 = ... # type: None """) - self.assertErrorLogIs(errors, [(8, "attribute-error", r"x.*None")]) + self.assertErrorRegexes(errors, {"e": r"x.*None"}) def testMatchLateAnnotation(self): _, errors = self.InferWithErrors("""\ @@ -742,34 +712,33 @@ class A(object): def f(self, x: "A"): pass def f(): - A().f(42) + A().f(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", r"A.*int")]) + self.assertErrorRegexes(errors, {"e": r"A.*int"}) def testRecursiveForwardReference(self): _, errors = self.InferWithErrors("""\ class A(object): def __init__(self, x: "A"): self.foo = x.foo - f(x) + f(x) # wrong-arg-types[e1] def method1(self): self.foo def method2(self): - self.bar + self.bar # attribute-error[e2] def f(x: int): pass """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*A"), - (8, "attribute-error", r"bar")]) + self.assertErrorRegexes(errors, {"e1": r"int.*A", "e2": r"bar"}) def testModuleLevelForwardReferenceError(self): errors = self.CheckWithErrors("""\ class A(object): def f(self, x: "A"): pass - A().f(42) + A().f(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"A.*int")]) + self.assertErrorRegexes(errors, {"e": r"A.*int"}) def testReturnAnnotation1(self): ty = self.Infer(""" @@ -923,9 +892,9 @@ def g(x: int) -> int: ... def testEllipsis(self): ty, errors = self.InferWithErrors("""\ from typing import Dict, Tuple - def f(x: ...): pass + def f(x: ...): pass # invalid-annotation[e1] def g(x: Tuple[str, ...]): pass - def h(x: Dict[..., int]): pass + def h(x: Dict[..., int]): pass # invalid-annotation[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict, Tuple @@ -933,9 +902,8 @@ def f(x) -> None: ... def g(x: Tuple[str, ...]) -> None: ... def h(x: Dict[Any, int]) -> None: ... """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*x"), - (4, "invalid-annotation", r"Ellipsis.*Dict")]) + self.assertErrorRegexes( + errors, {"e1": r"Ellipsis.*x", "e2": r"Ellipsis.*Dict"}) def testCustomContainer(self): with file_utils.Tempdir() as d: @@ -952,13 +920,12 @@ def __init__(self, x: T2): def f(x: foo.Foo[int]): pass f(foo.Foo(42)) - f(foo.Foo("")) + f(foo.Foo("")) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Foo\[int\].*Foo\[str\]")]) + self.assertErrorRegexes(errors, {"e": r"Foo\[int\].*Foo\[str\]"}) def testNoImplicitOptional(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ from typing import Optional, Union def f1(x: str = None): pass @@ -968,10 +935,10 @@ def f3(x: Union[str, None] = None): pass def f4(x: Union[str, int] = None): pass - f1(None) + f1(None) # wrong-arg-types f2(None) f3(None) - f4(None) + f4(None) # wrong-arg-types """) self.assertTypesMatchPytd(ty, """ from typing import Optional, Union @@ -980,8 +947,6 @@ def f2(x: Optional[str] = ...) -> None: ... def f3(x: Optional[str] = ...) -> None: ... def f4(x: Union[str, int] = ...) -> None: ... """) - self.assertErrorLogIs(errors, [(10, "wrong-arg-types"), - (13, "wrong-arg-types")]) def testInferReturn(self): ty = self.Infer(""" @@ -1007,11 +972,10 @@ def testRecursiveTypeAlias(self): errors = self.CheckWithErrors("""\ from typing import List, Union Foo = Union[str, List['Foo']] - def f(x: Foo): + def f(x: Foo): # not-supported-yet[e] pass """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet", - r"Recursive.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Recursive.*Foo"}) def testFullyQuotedAnnotation(self): self.Check(""" @@ -1034,25 +998,23 @@ def f(x: List[Callable[[int], str]]) -> None: ... """) def testLateAnnotationNonNameError(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): pass - def f(x: "Foo.Bar"): + def f(x: "Foo.Bar"): # attribute-error pass """) - self.assertErrorLogIs(errors, [(3, "attribute-error")]) def testKeepContainerWithError(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ from typing import Dict - def f(x: "Dict[str, int.error]"): + def f(x: "Dict[str, int.error]"): # attribute-error pass """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict def f(x: Dict[str, Any]) -> None: ... """) - self.assertErrorLogIs(errors, [(2, "attribute-error")]) class TestAnnotationsPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_anystr.py b/pytype/tests/py3/test_anystr.py index 63177cd69..a07a63dc4 100644 --- a/pytype/tests/py3/test_anystr.py +++ b/pytype/tests/py3/test_anystr.py @@ -80,7 +80,7 @@ def testUseAnyStrConstraints(self): def f(x: AnyStr, y: AnyStr) -> AnyStr: return __any_object__ v1 = f(__any_object__, u"") # ok - v2 = f(__any_object__, 42) + v2 = f(__any_object__, 42) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, TypeVar @@ -89,19 +89,18 @@ def f(x: AnyStr, y: AnyStr) -> AnyStr: ... v1 = ... # type: str v2 = ... # type: Any """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testConstraintMismatch(self): _, errors = self.InferWithErrors("""\ from typing import AnyStr def f(x: AnyStr, y: AnyStr): ... f("", "") # ok - f("", b"") + f("", b"") # wrong-arg-types[e] f(b"", b"") # ok """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", - r"Expected.*y: str.*Actual.*y: bytes")]) + self.assertErrorRegexes( + errors, {"e": r"Expected.*y: str.*Actual.*y: bytes"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_async_generators.py b/pytype/tests/py3/test_async_generators.py index e2fd72ac8..3d4faca96 100644 --- a/pytype/tests/py3/test_async_generators.py +++ b/pytype/tests/py3/test_async_generators.py @@ -78,28 +78,25 @@ def testAnnotationError(self): from typing import AsyncGenerator, AsyncIterator, AsyncIterable, Any, Union async def gen1() -> AsyncGenerator[bool, int]: - yield 1 + yield 1 # bad-return-type[e1] async def gen2() -> AsyncIterator[bool]: - yield 1 + yield 1 # bad-return-type[e2] async def gen3() -> AsyncIterable[bool]: - yield 1 + yield 1 # bad-return-type[e3] - async def gen4() -> int: + async def gen4() -> int: # invalid-annotation[e4] yield 1 async def fun(): g = gen1() - await g.asend("str") + await g.asend("str") # wrong-arg-types[e5] """) - self.assertErrorLogIs(errors, [ - (4, "bad-return-type", r"bool.*int"), - (7, "bad-return-type", r"bool.*int"), - (10, "bad-return-type", r"bool.*int"), - (12, "invalid-annotation", - r"AsyncGenerator.*AsyncIterable.*AsyncIterator"), - (17, "wrong-arg-types", r"int.*str"),]) + self.assertErrorRegexes(errors, { + "e1": r"bool.*int", "e2": r"bool.*int", "e3": r"bool.*int", + "e4": r"AsyncGenerator.*AsyncIterable.*AsyncIterator", + "e5": r"int.*str"}) def testMatchBaseClassError(self): errors = self.CheckWithErrors("""\ @@ -134,16 +131,15 @@ def f6(x: AsyncGenerator[bool, Any]): pass f1(gen()) - f2(gen()) + f2(gen()) # wrong-arg-types[e1] f3(gen()) - f4(gen()) + f4(gen()) # wrong-arg-types[e2] f5(gen()) - f6(gen()) + f6(gen()) # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (32, "wrong-arg-types", r"bool.*Union\[int, str\]"), - (34, "wrong-arg-types", r"bool.*Union\[int, str\]"), - (36, "wrong-arg-types", r"bool.*Union\[int, str\]"),]) + self.assertErrorRegexes(errors, { + "e1": r"bool.*Union\[int, str\]", "e2": r"bool.*Union\[int, str\]", + "e3": r"bool.*Union\[int, str\]"}) def testProtocol(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_attr.py b/pytype/tests/py3/test_attr.py index 688e75bf2..beb5d300b 100644 --- a/pytype/tests/py3/test_attr.py +++ b/pytype/tests/py3/test_attr.py @@ -81,13 +81,12 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s - class Foo(object): + class Foo(object): # invalid-annotation x : int = attr.ib(type=str) """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation")]) def test_defaults_with_annotation(self): ty = self.Infer(""" @@ -218,14 +217,13 @@ def foo(cls) -> None: ... """) def test_bad_default_param_order(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s(auto_attribs=True) - class Foo(object): + class Foo(object): # invalid-function-definition x: int = 10 y: str """) - self.assertErrorLogIs(err, [(4, "invalid-function-definition")]) def test_subclass_auto_attribs(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_attributes.py b/pytype/tests/py3/test_attributes.py index c78771962..e38d3f18d 100644 --- a/pytype/tests/py3/test_attributes.py +++ b/pytype/tests/py3/test_attributes.py @@ -10,9 +10,9 @@ def testExplicitNone(self): errors = self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testClosure(self): self.Check(""" @@ -30,14 +30,13 @@ def testOverwriteGlobal(self): from typing import Optional d = ... # type: Optional[dict] if d: - formatter = lambda x: d.get(x, '') # line 4 + formatter = lambda x: d.get(x, '') # attribute-error[e] else: formatter = lambda x: '' d = None formatter('key') # line 8 """) - self.assertErrorLogIs( - errors, [(4, "attribute-error", r"get.*None.*traceback.*line 8")]) + self.assertErrorRegexes(errors, {"e": r"get.*None.*traceback.*line 8"}) class TestAttributes(test_base.TargetPython3BasicTest): @@ -47,9 +46,9 @@ def testAttrOnOptional(self): errors = self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testErrorInAny(self): errors = self.CheckWithErrors("""\ @@ -57,10 +56,9 @@ def testErrorInAny(self): def f(x: Any): if __random__: x = 42 - x.upper() # line 5 + x.upper() # attribute-error[e] """) - self.assertErrorLogIs( - errors, [(5, "attribute-error", r"upper.*int.*Union\[Any, int\]")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int.*Union\[Any, int\]"}) class TestAttributesPython3FeatureTest(test_base.TargetPython3FeatureTest): @@ -79,9 +77,9 @@ class A(object): values = 42 args = {A() if __random__ else True: ""} for x, y in sorted(args.items()): - x.values # line 5 + x.values # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"'values' on bool")]) + self.assertErrorRegexes(errors, {"e": r"'values' on bool"}) def testTypeParameterInstanceSetAttr(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_builtins.py b/pytype/tests/py3/test_builtins.py index 207c6e3de..5b0e28040 100644 --- a/pytype/tests/py3/test_builtins.py +++ b/pytype/tests/py3/test_builtins.py @@ -115,18 +115,16 @@ def testBuiltins(self): """) def testUnicode(self): - errors = self.CheckWithErrors("""\ - unicode("foo") + self.CheckWithErrors("""\ + unicode("foo") # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testBytesIteration(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): for x in bytes(): - return bytes() + x + return bytes() + x # unsupported-operands """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands")]) def test_inplace_division(self): self.Check("""\ @@ -140,18 +138,14 @@ def test_inplace_division(self): """) def test_removed_dict_methods(self): - errors = self.CheckWithErrors("""\ - {}.iteritems - {}.iterkeys - {}.itervalues - {}.viewitems - {}.viewkeys - {}.viewvalues - """) - self.assertErrorLogIs( - errors, [(1, "attribute-error"), (2, "attribute-error"), - (3, "attribute-error"), (4, "attribute-error"), - (5, "attribute-error"), (6, "attribute-error")]) + self.CheckWithErrors("""\ + {}.iteritems # attribute-error + {}.iterkeys # attribute-error + {}.itervalues # attribute-error + {}.viewitems # attribute-error + {}.viewkeys # attribute-error + {}.viewvalues # attribute-error + """) def test_dict_views(self): self.Check(""" @@ -424,21 +418,19 @@ def testItems(self): def testIntInit(self): _, errors = self.InferWithErrors("""\ - int(0, 1) # line 8: expected str or unicode, got int for first arg + int(0, 1) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Union\[bytes, str\].*int"}) def testRemovedBuiltins(self): - errors = self.CheckWithErrors("""\ - long - {}.has_key + self.CheckWithErrors("""\ + long # name-error + {}.has_key # attribute-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (2, "attribute-error")]) def testRange(self): - ty, errors = self.InferWithErrors("""\ - xrange(3) + ty, _ = self.InferWithErrors("""\ + xrange(3) # name-error v = range(3) v[0] v[:] @@ -450,7 +442,6 @@ def testRange(self): y: int z: int """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testCreateStr(self): self.Check(""" @@ -569,8 +560,7 @@ def testOSErrorSubclasses(self): def testRawInput(self): # Removed in Python 3: - errors = self.CheckWithErrors("raw_input") - self.assertErrorLogIs(errors, [(1, "name-error")]) + self.CheckWithErrors("raw_input # name-error") def testClear(self): # new in Python 3 @@ -630,20 +620,18 @@ def testMinMax(self): """) def testStrIsNotInt(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import SupportsInt def f(x: SupportsInt): pass - f("") + f("") # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types")]) def testStrIsNotFloat(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import SupportsFloat def f(x: SupportsFloat): pass - f("") + f("") # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_checker.py b/pytype/tests/py3/test_checker.py index 19cb8ba81..8eecee850 100644 --- a/pytype/tests/py3/test_checker.py +++ b/pytype/tests/py3/test_checker.py @@ -22,19 +22,18 @@ class X(object): def __init__(self, val: "X"): pass def f(): - X(42) + X(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errorlog, [(5, "wrong-arg-types", r"X.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"X.*int"}) def testBadReturnTypeInline(self): errorlog = self.CheckWithErrors("""\ from typing import List def f() -> List[int]: - return [object()] + return [object()] # bad-return-type[e] f()[0] += 1 """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"List\[int\].*List\[object\]")]) + self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[object\]"}) def testUseVarargsAndKwargs(self): self.Check("""\ @@ -89,50 +88,46 @@ def testBadDictValue(self): errorlog = self.CheckWithErrors("""\ from typing import Dict def f() -> Dict[str, int]: - return {"x": 42.0} + return {"x": 42.0} # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", r"int.*float")]) + self.assertErrorRegexes(errorlog, {"e": r"int.*float"}) def testInstanceAsAnnotation(self): errorlog = self.CheckWithErrors("""\ def f(): pass - def g(x: f): + def g(x: f): # invalid-annotation[e1] pass - def h(x: 3): + def h(x: 3): # invalid-annotation[e2] pass """) - self.assertErrorLogIs(errorlog, [(3, "invalid-annotation", - r"instance of Callable.*x"), - (5, "invalid-annotation", - r"3.*x")]) + self.assertErrorRegexes( + errorlog, {"e1": r"instance of Callable.*x", "e2": r"3.*x"}) def testBadGenerator(self): errorlog = self.CheckWithErrors("""\ from typing import Generator def f() -> Generator[str, None, None]: for i in range(3): - yield i + yield i # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(4, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"str.*int"}) def testMultipleParameterBindings(self): errorlog = self.CheckWithErrors("""\ from typing import List def f(x) -> List[int]: - return ["", x] + return ["", x] # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"List\[int\].*List\[str\]")]) + self.assertErrorRegexes(errorlog, {"e": r"List\[int\].*List\[str\]"}) def testNoParamBinding(self): errorlog = self.CheckWithErrors("""\ def f() -> None: x = [] - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errorlog, [(3, "bad-return-type", - r"None.*List\[nothing\]")]) + self.assertErrorRegexes(errorlog, {"e": r"None.*List\[nothing\]"}) def testAttributeInIncompleteInstance(self): errorlog = self.CheckWithErrors("""\ @@ -140,30 +135,31 @@ def testAttributeInIncompleteInstance(self): class Foo(object): def __init__(self, other: "List[Foo]"): self.x = other[0].x # okay - self.y = other.y # No "y" on List[Foo] - self.z = Foo.z # No "z" on Type[Foo] + # No "y" on List[Foo] + self.y = other.y # attribute-error[e1] + # No "z" on Type[Foo] + self.z = Foo.z # attribute-error[e2] """) - self.assertErrorLogIs(errorlog, [(5, "attribute-error", r"y.*List\[Foo\]"), - (6, "attribute-error", r"z.*Type\[Foo\]")]) + self.assertErrorRegexes(errorlog, {"e1": r"y.*List\[Foo\]", + "e2": r"z.*Type\[Foo\]"}) def testBadGetItem(self): errorlog = self.CheckWithErrors("""\ def f(x: int): - return x[0] + return x[0] # unsupported-operands[e] """) - self.assertErrorLogIs(errorlog, [(2, "unsupported-operands", r"int.*int")]) + self.assertErrorRegexes(errorlog, {"e": r"int.*int"}) def testBadAnnotationContainer(self): errorlog = self.CheckWithErrors("""\ class A(object): pass - def f(x: int[str]): + def f(x: int[str]): # not-indexable[e1] pass - def g(x: A[str]): + def g(x: A[str]): # not-indexable[e2] pass """) - self.assertErrorLogIs(errorlog, [(3, "not-indexable", r"Generic"), - (5, "not-indexable", r"Generic")]) + self.assertErrorRegexes(errorlog, {"e1": r"Generic", "e2": r"Generic"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_classes.py b/pytype/tests/py3/test_classes.py index 16e2a2860..e3dda37f1 100644 --- a/pytype/tests/py3/test_classes.py +++ b/pytype/tests/py3/test_classes.py @@ -70,9 +70,9 @@ def __init__(self, x): def Create(self, x: MyType): self.x = x def Convert(self): - self.y + self.y # attribute-error[e] """) - self.assertErrorLogIs(errors, [(9, "attribute-error", r"y.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"y.*Foo"}) def testRecursiveConstructorSubclass(self): self.Check(""" @@ -169,17 +169,16 @@ def __init__(self, obj: Sequence): pass class Y(X): def __init__(self, obj: int): - X.__init__(self, obj) # line 7 + X.__init__(self, obj) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", r"Sequence.*int")]) + self.assertErrorRegexes(errors, {"e": r"Sequence.*int"}) def testParameterizedClassBinaryOperator(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Sequence def f(x: Sequence[str], y: Sequence[str]) -> None: - a = x + y + a = x + y # unsupported-operands """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands")]) def testInstanceAttribute(self): ty = self.Infer(""" @@ -415,13 +414,12 @@ def bar(cls): def testPy2Metaclass(self): errors = self.CheckWithErrors("""\ import abc - class Foo(object): + class Foo(object): # ignored-metaclass[e] __metaclass__ = abc.ABCMeta @abc.abstractmethod def f(self) -> int: ... """) - self.assertErrorLogIs( - errors, [(2, "ignored-metaclass", r"abc\.ABCMeta.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"abc\.ABCMeta.*Foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_coroutine.py b/pytype/tests/py3/test_coroutine.py index c1348ea1b..c859f0d32 100644 --- a/pytype/tests/py3/test_coroutine.py +++ b/pytype/tests/py3/test_coroutine.py @@ -71,7 +71,7 @@ def caller() -> Coroutine[Any, Any, Union[int, str]]: ... def testNativeCoroutineError(self): errors = self.CheckWithErrors("""\ async def f1() -> str: - return 1 + return 1 # bad-return-type[e1] async def f2() -> int: return 1 @@ -84,13 +84,11 @@ def f4(x: str): async def caller(): f4(await f1()) - f4(await f2()) - f4(await f3()) + f4(await f2()) # wrong-arg-types[e2] + f4(await f3()) # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (2, "bad-return-type", r"str.*int"), - (15, "wrong-arg-types", r"str.*int"), - (16, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes( + errors, {"e1": r"str.*int", "e2": r"str.*int", "e3": r"str.*int"}) def testGeneratorBasedCoroutinePyi(self): ty = self.Infer(""" @@ -149,13 +147,12 @@ def f3(x, y: str): pass async def caller(): - x = await f1() + x = await f1() # bad-return-type[e1] y = await f2() - f3(x, y) + f3(x, y) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [ - (17, "bad-return-type", r"Awaitable.*int"), - (19, "wrong-arg-types", r"y: str.*y: int")]) + self.assertErrorRegexes( + errors, {"e1": r"Awaitable.*int", "e2": r"y: str.*y: int"}) def testAwaitablePyi(self): ty = self.Infer(""" @@ -220,10 +217,9 @@ class A(object): pass async def fun(): - await A() + await A() # bad-return-type[e] """) - self.assertErrorLogIs(errors, [ - (5, "bad-return-type", r"Awaitable.*A")]) + self.assertErrorRegexes(errors, {"e": r"Awaitable.*A"}) def testAsyncForPyi(self): ty = self.Infer(""" @@ -298,21 +294,19 @@ async def __anext__(self): async def caller(): res = [] - async for i in Iter1(): + async for i in Iter1(): # attribute-error[e1] res.append(i) - async for i in Iter2(): + async for i in Iter2(): # attribute-error[e2] res.append(i) - async for i in Iter3(): + async for i in Iter3(): # bad-return-type[e3] res.append(i) async for i in Iter4(): res.append(i) return res """) - self.assertErrorLogIs(errors, [ - (36, "attribute-error", r"No attribute.*__aiter__"), - (38, "attribute-error", r"No attribute.*__anext__"), - (40, "bad-return-type", r"Awaitable.*Union\[int, str]"), - ]) + self.assertErrorRegexes(errors, {"e1": r"No attribute.*__aiter__", + "e2": r"No attribute.*__anext__", + "e3": r"Awaitable.*Union\[int, str\]"}) def testAsyncWithPyi(self): ty = self.Infer(""" @@ -355,6 +349,7 @@ def log(s: _T0) -> Coroutine[Any, Any, _T0]: ... """) def testAsyncWithError(self): + # pylint: disable=anomalous-backslash-in-string errors = self.CheckWithErrors("""\ class AsyncCtx1(object): pass @@ -367,15 +362,15 @@ def __aexit__(self, exc_type, exc, tb): return "str" async def caller(): - async with AsyncCtx1() as var1, AsyncCtx2() as var2: - pass + ctx1 = AsyncCtx1() + ctx2 = AsyncCtx2() + async with ctx1 as var1: # attribute-error[e1] # attribute-error[e2] + async with ctx2 as var2: # bad-return-type[e3] + pass # bad-return-type[e4] """) - self.assertErrorLogIs(errors, [ - (12, "attribute-error", r"No attribute.*__aexit__"), - (12, "attribute-error", r"No attribute.*__aenter__"), - (12, "bad-return-type", r"Awaitable.*AsyncCtx2"), - (13, "bad-return-type", r"Awaitable.*str"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"No attribute.*__aexit__", "e2": r"No attribute.*__aenter__", + "e3": r"Awaitable.*AsyncCtx2", "e4": r"Awaitable.*str"}) def testLoadPyi(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/py3/test_dataclasses.py b/pytype/tests/py3/test_dataclasses.py index 3e812f420..94dd59d2c 100644 --- a/pytype/tests/py3/test_dataclasses.py +++ b/pytype/tests/py3/test_dataclasses.py @@ -135,31 +135,28 @@ def __init__(self, x: bool = ..., y: List[int] = ...) -> None: ... """) def test_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = 10 """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_field_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = dataclasses.field(default=10) """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_factory_type_mismatch(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # annotation-type-mismatch x: bool = dataclasses.field(default_factory=set) """) - self.assertErrorLogIs(err, [(4, "annotation-type-mismatch")]) def test_field_no_init(self): ty = self.Infer(""" @@ -194,14 +191,13 @@ def __init__(self, x: bool, y: int) -> None: ... """) def test_bad_default_param_order(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import dataclasses @dataclasses.dataclass() - class Foo(object): + class Foo(object): # invalid-function-definition x: int = 10 y: str """) - self.assertErrorLogIs(err, [(4, "invalid-function-definition")]) def test_any(self): self.Check(""" diff --git a/pytype/tests/py3/test_decorators.py b/pytype/tests/py3/test_decorators.py index f21339cec..9166f54fc 100644 --- a/pytype/tests/py3/test_decorators.py +++ b/pytype/tests/py3/test_decorators.py @@ -7,15 +7,14 @@ class DecoratorsTest(test_base.TargetPython3BasicTest): """Test decorators.""" def testAnnotatedSuperCallUnderBadDecorator(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class Foo(object): def Run(self) -> None: ... class Bar(Foo): - @bad_decorator # line 4 + @bad_decorator # name-error def Run(self): return super(Bar, self).Run() """) - self.assertErrorLogIs(errors, [(4, "name-error", r"bad_decorator")]) def testReplaceSelfToStarArg(self): # Without decorator, `self` will be in `signature.param_names`. diff --git a/pytype/tests/py3/test_dict.py b/pytype/tests/py3/test_dict.py index 2f89f742b..49540fb1a 100644 --- a/pytype/tests/py3/test_dict.py +++ b/pytype/tests/py3/test_dict.py @@ -21,16 +21,15 @@ def foo(x: Union[int, None]) -> Any """) def testObjectInDict(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Any, Dict def objectIsStr() -> Dict[str, Any]: - return {object(): ""} + return {object(): ""} # bad-return-type """) - self.assertErrorLogIs(errors, [(3, "bad-return-type")]) def testBigConcreteDict(self): # Test that we don't timeout. - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Dict, Tuple, Union # A concrete dictionary with lots of concrete keys and a complicated # value type. @@ -50,9 +49,8 @@ def testBigConcreteDict(self): def f() -> Dict[Union[str, Tuple[str, None]], ValueType]: return d def g() -> Dict[int, int]: - return d # line 20 + return d # bad-return-type """) - self.assertErrorLogIs(errorlog, [(20, "bad-return-type")]) def testDictOfTuple(self): # utils.deep_variable_product(group_dict) generates a lot of combinations. diff --git a/pytype/tests/py3/test_errors.py b/pytype/tests/py3/test_errors.py index 6293dc2aa..678bb45c8 100644 --- a/pytype/tests/py3/test_errors.py +++ b/pytype/tests/py3/test_errors.py @@ -18,39 +18,36 @@ def f(x: int): else: i = 1 x = (3.14, "") - f(x[i]) + f(x[i]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Actually passed:.*Union\[float, str\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actually passed:.*Union\[float, str\]"}) def testInvalidAnnotations(self): _, errors = self.InferWithErrors("""\ from typing import Dict, List, Union def f1(x: Dict): # okay pass - def f2(x: Dict[str]): + def f2(x: Dict[str]): # invalid-annotation[e1] pass - def f3(x: List[int, str]): + def f3(x: List[int, str]): # invalid-annotation[e2] pass - def f4(x: Union): + def f4(x: Union): # invalid-annotation[e3] pass """) - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", r"typing.Dict\[_K, _V].*2.*1"), - (6, "invalid-annotation", r"typing.List\[_T].*1.*2"), - (8, "invalid-annotation", r"Union.*x")]) + self.assertErrorRegexes(errors, {"e1": r"typing.Dict\[_K, _V].*2.*1", + "e2": r"typing.List\[_T].*1.*2", + "e3": r"Union.*x"}) def testPrintUnsolvable(self): _, errors = self.InferWithErrors("""\ from typing import List - def f(x: List[nonsense], y: str, z: float): + def f(x: List[nonsense], y: str, z: float): # name-error pass - f({nonsense}, "", "") + f({nonsense}, "", "") # name-error # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "name-error", r"nonsense"), - (4, "name-error", r"nonsense"), - (4, "wrong-arg-types", r"Expected:.*x: list.*Actual.*x: set")]) + self.assertErrorRegexes( + errors, {"e": r"Expected:.*x: list.*Actual.*x: set"}) def testPrintUnionOfContainers(self): _, errors = self.InferWithErrors("""\ @@ -60,75 +57,72 @@ def f(x: str): x = dict else: x = [float] - f(x) + f(x) # wrong-arg-types[e] """) error = r"Actual.*Union\[List\[Type\[float\]\], Type\[dict\]\]" - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testWrongBrackets(self): _, errors = self.InferWithErrors("""\ from typing import List - def f(x: List(str)): + def f(x: List(str)): # not-callable[e] pass """) - self.assertErrorLogIs(errors, [(2, "not-callable", r"List")]) + self.assertErrorRegexes(errors, {"e": r"List"}) def testInterpreterClassPrinting(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass def f(x: str): pass - f(Foo()) + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"str.*Foo"}) def testPrintDictAndTuple(self): _, errors = self.InferWithErrors("""\ from typing import Tuple tup = None # type: Tuple[int, ...] dct = None # type: dict[str, int] - def f1(x: (int, str)): # line 4 + def f1(x: (int, str)): # invalid-annotation[e1] pass - def f2(x: tup): # line 6 + def f2(x: tup): # invalid-annotation[e2] pass - def g1(x: {"a": 1}): # line 8 + def g1(x: {"a": 1}): # invalid-annotation[e3] pass - def g2(x: dct): # line 10 + def g2(x: dct): # invalid-annotation[e4] pass """) - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", r"(int, str).*Not a type"), - (6, "invalid-annotation", - r"instance of Tuple\[int, \.\.\.\].*Not a type"), - (8, "invalid-annotation", r"{'a': '1'}.*Not a type"), - (10, "invalid-annotation", r"instance of Dict\[str, int\].*Not a type") - ]) + self.assertErrorRegexes(errors, { + "e1": r"(int, str).*Not a type", + "e2": r"instance of Tuple\[int, \.\.\.\].*Not a type", + "e3": r"{'a': '1'}.*Not a type", + "e4": r"instance of Dict\[str, int\].*Not a type"}) def testMoveUnionInward(self): _, errors = self.InferWithErrors("""\ - def f() -> str: + def f() -> str: # invalid-annotation[e] y = "hello" if __random__ else 42 yield y """) - self.assertErrorLogIs(errors, [( - 1, "invalid-annotation", r"Generator, Iterable or Iterator")]) + self.assertErrorRegexes(errors, {"e": r"Generator, Iterable or Iterator"}) def testInnerClassError(self): _, errors = self.InferWithErrors("""\ def f(x: str): pass def g(): class Foo(object): pass - f(Foo()) + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: str.*x: Foo")]) + self.assertErrorRegexes(errors, {"e": r"x: str.*x: Foo"}) def testInnerClassError2(self): _, errors = self.InferWithErrors("""\ def f(): class Foo(object): pass def g(x: Foo): pass - g("") + g("") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"x: Foo.*x: str")]) + self.assertErrorRegexes(errors, {"e": r"x: Foo.*x: str"}) def testCleanNamedtupleNames(self): # Make sure the namedtuple renaming in _pytd_print correctly extracts type @@ -140,54 +134,44 @@ def testCleanNamedtupleNames(self): W = collections.namedtuple("W", "abc def ghi abc", rename=True) def bar(x: str): return x - bar(X(1,2,3,4)) # 7 - bar(Y()) # 8 - bar(W(1,2,3,4)) # 9 - bar({1: 2}.__iter__()) # 10 + bar(X(1,2,3,4)) # wrong-arg-types[e1] + bar(Y()) # wrong-arg-types[e2] + bar(W(1,2,3,4)) # wrong-arg-types[e3] + bar({1: 2}.__iter__()) # wrong-arg-types[e4] if __random__: a = X(1,2,3,4) else: a = 1 - bar(a) # 15 + bar(a) # wrong-arg-types[e5] """) - self.assertErrorLogIs(errors, - [(7, "wrong-arg-types", r"`X`"), - (8, "wrong-arg-types", r"`Z`"), - (9, "wrong-arg-types", r"`W`"), - (10, "wrong-arg-types", r"`dictionary-keyiterator`"), - (15, "wrong-arg-types", r"Union\[int, `X`\]") - ]) + self.assertErrorRegexes(errors, { + "e1": r"`X`", "e2": r"`Z`", "e3": r"`W`", + "e4": r"`dictionary-keyiterator`", "e5": r"Union\[int, `X`\]"}) def testArgumentOrder(self): _, errors = self.InferWithErrors("""\ def g(f: str, a, b, c, d, e,): pass - g(a=1, b=2, c=3, d=4, e=5, f=6) + g(a=1, b=2, c=3, d=4, e=5, f=6) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", - r"Expected.*f: str, \.\.\..*Actual.*f: int, \.\.\.")] - ) + self.assertErrorRegexes(errors, { + "e": r"Expected.*f: str, \.\.\..*Actual.*f: int, \.\.\."}) def testConversionOfGeneric(self): - _, errors = self.InferWithErrors(""" + self.InferWithErrors("""\ import os def f() -> None: - return os.walk("/tmp") + return os.walk("/tmp") # bad-return-type """) - self.assertErrorLogIs(errors, [ - (4, "bad-return-type") - ]) def testInnerClass(self): _, errors = self.InferWithErrors("""\ def f() -> int: class Foo(object): pass - return Foo() # line 4 + return Foo() # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(4, "bad-return-type", r"int.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"int.*Foo"}) def testNestedProtoClass(self): with file_utils.Tempdir() as d: @@ -200,14 +184,13 @@ class Foo: errors = self.CheckWithErrors("""\ import foo_bar def f(x: foo_bar.Foo.Bar): ... - f(42) + f(42) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(3, "wrong-arg-types", r"foo_bar\.Foo\.Bar")]) + self.assertErrorRegexes(errors, {"e": r"foo_bar\.Foo\.Bar"}) def testStaticmethodInError(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ class A(object): @staticmethod def t(a: str) -> None: ... @@ -217,12 +200,10 @@ def t(a: str) -> None: ... import foo def f(x: Callable[[int], None], y: int) -> None: return x(y) - f(foo.A.t, 1) + f(foo.A.t, 1) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, - [(5, "wrong-arg-types", - r"Actually passed: \(x: Callable\[\[str\], None\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actually passed: \(x: Callable\[\[str\], None\]"}) def testGeneratorSend(self): errors = self.CheckWithErrors("""\ @@ -234,26 +215,25 @@ def f(x) -> Generator[Any, int, Any]: yield "1" x = f(2) - x.send("123") + x.send("123") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(9, "wrong-arg-types", - r"\(self, value: int\)")]) + self.assertErrorRegexes(errors, {"e": r"\(self, value: int\)"}) def testGeneratorIteratorRetType(self): errors = self.CheckWithErrors("""\ from typing import Iterator def f() -> Iterator[str]: - yield 1 + yield 1 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def testGeneratorIterableRetType(self): errors = self.CheckWithErrors("""\ from typing import Iterable def f() -> Iterable[str]: - yield 1 + yield 1 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class InPlaceOperationsTest(test_base.TargetPython3BasicTest): @@ -266,11 +246,10 @@ def __%s__(self, x: "A"): return None def f(): v = A() - v %s 3 # line 6 + v %s 3 # unsupported-operands[e] """ % (op, symbol)) - self.assertErrorLogIs(errors, [ - (6, "unsupported-operands", - r"%s.*A.*int.*__%s__ on A.*A" % (re.escape(symbol), op))]) + self.assertErrorRegexes(errors, { + "e": r"%s.*A.*int.*__%s__ on A.*A" % (re.escape(symbol), op)}) def testISub(self): self._testOp("isub", "-=") @@ -287,10 +266,10 @@ def __itruediv__(self, x: "A"): return None def f(): v = A() - v /= 3 # line 8 + v /= 3 # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [ - (8, "unsupported-operands", r"\/\=.*A.*int.*__i(true)?div__ on A.*A")]) + self.assertErrorRegexes( + errors, {"e": r"\/\=.*A.*int.*__i(true)?div__ on A.*A"}) def testIMod(self): self._testOp("imod", "%=") @@ -323,40 +302,40 @@ class ErrorTestPy3(test_base.TargetPython3FeatureTest): def testProtocolMismatch(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", "__iter__, __next__") - ]) + self.assertErrorRegexes(errors, {"e": r"__iter__, __next__"}) def testProtocolMismatchPartial(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __iter__(self): return self - next(Foo()) + next(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 4, "wrong-arg-types", r"\n\s*__next__\s*$")]) # `next` on its own line + self.assertErrorRegexes( + errors, {"e": r"\n\s*__next__\s*$"}) # `next` on its own line def testGeneratorSendRetType(self): _, errors = self.InferWithErrors("""\ from typing import Generator def f() -> Generator[int, str, int]: x = yield 1 - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(4, "bad-return-type", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) class MatrixOperationsTest(test_base.TargetPython3FeatureTest): """Test matrix operations.""" def testMatMul(self): - errors = self.CheckWithErrors("def f(): return 'foo' @ 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\@.*str.*int.*'__matmul__' on str.*'__rmatmul__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): + return 'foo' @ 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\@.*str.*int.*'__matmul__' on str.*'__rmatmul__' on int"}) def testIMatMul(self): errors = self.CheckWithErrors("""\ @@ -365,10 +344,9 @@ def __imatmul__(self, x: "A"): pass def f(): v = A() - v @= 3 # line 6 + v @= 3 # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [ - (6, "unsupported-operands", r"\@.*A.*int.*__imatmul__ on A.*A")]) + self.assertErrorRegexes(errors, {"e": r"\@.*A.*int.*__imatmul__ on A.*A"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_exceptions.py b/pytype/tests/py3/test_exceptions.py index c9f9de5f9..97e3de9d9 100644 --- a/pytype/tests/py3/test_exceptions.py +++ b/pytype/tests/py3/test_exceptions.py @@ -18,8 +18,7 @@ def test_raise_exception_from(self): def test_exception_message(self): # This attribute was removed in Python 3. - errors = self.CheckWithErrors("ValueError().message") - self.assertErrorLogIs(errors, [(1, "attribute-error")]) + self.CheckWithErrors("ValueError().message # attribute-error") def test_suppress_context(self): self.Check("ValueError().__suppress_context__") diff --git a/pytype/tests/py3/test_functions.py b/pytype/tests/py3/test_functions.py index 1ad2c39b7..ed6e8f18a 100644 --- a/pytype/tests/py3/test_functions.py +++ b/pytype/tests/py3/test_functions.py @@ -11,9 +11,9 @@ def test_error(self): errors = self.CheckWithErrors("""\ def f(x: int): def g(): - return x.upper() + return x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", "upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) class TestClosuresPy3(test_base.TargetPython3FeatureTest): @@ -37,16 +37,15 @@ def f(a: int) -> Optional[str] """) def test_closures_delete_deref(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): x = "hello" def g(): nonlocal x # force x to be stored in a closure cell x = 10 del x - return x + return x # name-error """) - self.assertErrorLogIs(errors, [(7, "name-error")]) def test_nonlocal(self): ty = self.Infer("""\ @@ -63,16 +62,15 @@ def f() -> int """) def test_nonlocal_delete_deref(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): x = True def g(): nonlocal x del x g() - return x + return x # name-error """) - self.assertErrorLogIs(errors, [(7, "name-error")]) def test_reuse_after_delete_deref(self): ty = self.Infer("""\ @@ -95,13 +93,13 @@ def f(): a = 1 def g(x: int) -> int: a # makes sure g is a closure - return "hello" + return "hello" # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(5, "bad-return-type", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_filter_before_delete(self): # TODO(b/117463644): Remove the disable on line 7. - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import Optional def f(x: Optional[str]): if x is None: @@ -111,9 +109,8 @@ def nested(): print(x.upper()) # pytype: disable=name-error del x nested() - return x # line 10 + return x # name-error """) - self.assertErrorLogIs(errors, [(10, "name-error")]) class PreciseReturnTest(test_base.TargetPython3BasicTest): @@ -127,26 +124,26 @@ def test_interpreter_return(self): ty, errors = self.InferWithErrors("""\ def f(x: str) -> str: return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ def f(x: str) -> str: ... x: str """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_unknown_return(self): ty, errors = self.InferWithErrors("""\ def f(x: str): return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any def f(x: str) -> str: ... x: Any """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_interpreter_overload(self): ty, errors = self.InferWithErrors("""\ @@ -155,7 +152,7 @@ def test_interpreter_overload(self): def f(x: str) -> str: ... def f(x): return x - x = f(0) + x = f(0) # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import overload @@ -163,7 +160,7 @@ def f(x): def f(x: str) -> str: ... x: str """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class TestFunctions(test_base.TargetPython3BasicTest): @@ -238,24 +235,20 @@ def f( """) def test_typecheck_varargs(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(*args: int) -> int: return args[0] - f(*['value']) - f(1, 'hello', 'world') + f(*['value']) # wrong-arg-types + f(1, 'hello', 'world') # wrong-arg-types """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types"), - (4, "wrong-arg-types")]) def test_typecheck_kwargs(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(**kwargs: int) -> int: return len(kwargs.values()) - f(**{'arg': 'value'}) - f(arg='value', arg2=3) - """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types"), - (4, "wrong-arg-types")]) + f(**{'arg': 'value'}) # wrong-arg-types + f(arg='value', arg2=3) # wrong-arg-types + """) def test_pass_func_to_complex_func(self): # This test gets an unsolvable binding added to the variable containing the @@ -304,14 +297,11 @@ def text_varargs_errors(self): errors = self.CheckWithErrors("""\ def foo(x: str, *y: int): pass - foo(*[1, 2, 3]) + foo(*[1, 2, 3]) # wrong-arg-types[e1] def bar(*z: int): - foo(*z) + foo(*z) # wrong-arg-types[e2] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", "str.*int"), - (5, "wrong-arg-types", "str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) def test_varargs_in_pyi(self): with file_utils.Tempdir() as d: @@ -332,9 +322,9 @@ def f(x: int, *args): ... errors = self.CheckWithErrors("""\ import foo def g(*args): - foo.f("", *args) + foo.f("", *args) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) class TestFunctionsPython3Feature(test_base.TargetPython3FeatureTest): @@ -597,9 +587,9 @@ def test_varargs_with_missing_kwonly(self): def foo(x: int, *args: int, z: int) -> None: pass - foo(1, 2, 5) + foo(1, 2, 5) # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(4, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) def test_multiple_varargs_packs(self): self.Check(""" @@ -619,14 +609,11 @@ def text_multiple_varargs_packs_errors(self): errors = self.CheckWithErrors("""\ def foo(x: str, *y: int): pass - foo(*[1, 2, 3], *[4, 5, 6]) + foo(*[1, 2, 3], *[4, 5, 6]) # wrong-arg-types[e1] def bar(*z: int): - foo(*z, *z) + foo(*z, *z) # wrong-arg-types[e2] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", "str.*int"), - (5, "wrong-arg-types", "str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_generators.py b/pytype/tests/py3/test_generators.py index 60bc4f4a7..b785ce4e1 100644 --- a/pytype/tests/py3/test_generators.py +++ b/pytype/tests/py3/test_generators.py @@ -33,9 +33,9 @@ def testNoReturn(self): _, errors = self.InferWithErrors("""\ from typing import Generator def f() -> Generator[str, None, None]: - yield 42 + yield 42 # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(3, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) class GeneratorFeatureTest(test_base.TargetPython3FeatureTest): @@ -97,17 +97,15 @@ def func1() -> Generator[int, int, int]: x = yield 5 return x - def func2() -> Generator[int, int]: + def func2() -> Generator[int, int]: # invalid-annotation[e1] x = yield 5 - def func3() -> Generator[int]: + def func3() -> Generator[int]: # invalid-annotation[e2] yield 5 """) - self.assertErrorLogIs(errors, [ - (7, "invalid-annotation", - r"typing.Generator\[_T, _T2, _V].*3.*2"), - (10, "invalid-annotation", - r"typing.Generator\[_T, _T2, _V].*3.*1")]) + self.assertErrorRegexes(errors, { + "e1": r"typing.Generator\[_T, _T2, _V].*3.*2", + "e2": r"typing.Generator\[_T, _T2, _V].*3.*1"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_generic.py b/pytype/tests/py3/test_generic.py index 07cdcd212..3ecfe4a5d 100644 --- a/pytype/tests/py3/test_generic.py +++ b/pytype/tests/py3/test_generic.py @@ -11,22 +11,21 @@ def testGenericTypeParamsError(self): _, errors = self.InferWithErrors("""\ from typing import Generic - class A(Generic[int]): + class A(Generic[int]): # invalid-annotation[e] pass """) - self.assertErrorLogIs(errors, [ - (3, "invalid-annotation", "Parameters.*Generic.*must.*type variables")]) + self.assertErrorRegexes( + errors, {"e": r"Parameters.*Generic.*must.*type variables"}) def testMroError(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Generic, Iterator, Generator, TypeVar T = TypeVar('T') - class A(Generic[T], Iterator[T], Generator): + class A(Generic[T], Iterator[T], Generator): # mro-error pass """) - self.assertErrorLogIs(errors, [(5, "mro-error")]) def testTemplateOrderError(self): _, errors = self.InferWithErrors("""\ @@ -60,13 +59,12 @@ def func(self, x: K1, y: K2): A = ClassA[int, str, int, int]() B = ClassB[int, str, int, int]() - A.func(5, "5") # Error + A.func(5, "5") # wrong-arg-types[e1] A.func("5", 5) # OK B.func(5, "5") # OK - B.func("5", 5) # Error + B.func("5", 5) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(31, "wrong-arg-types", r"str.*int"), - (34, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"int.*str"}) def testTypeErasureError(self): _, errors = self.InferWithErrors("""\ @@ -82,25 +80,23 @@ def __init__(self, x: T = None, y: S = None): def fun(self, x: T, y: S): pass - o1 = MyClass[str, str]() + o1 = MyClass[str, str]() # bad-concrete-type[e1] o2 = MyClass[int, int]() - o2.fun("5", 5) - o2.fun(5, "5") + o2.fun("5", 5) # wrong-arg-types[e2] + o2.fun(5, "5") # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (13, "bad-concrete-type", r"Union\[float, int\].*str"), - (15, "wrong-arg-types", r"x: int.*x: str"), - (16, "wrong-arg-types", r"y: int.*y: str")]) + self.assertErrorRegexes(errors, {"e1": r"Union\[float, int\].*str", + "e2": r"x: int.*x: str", + "e3": r"y: int.*y: str"}) def testInhericPlainGenericError(self): _, errors = self.InferWithErrors("""\ from typing import Generic - class A(Generic): + class A(Generic): # invalid-annotation[e] pass """) - self.assertErrorLogIs( - errors, [(3, "invalid-annotation", r"Cannot inherit.*plain Generic")]) + self.assertErrorRegexes(errors, {"e": r"Cannot inherit.*plain Generic"}) def testGenericWithDupTypeError(self): with file_utils.Tempdir() as d: @@ -111,10 +107,9 @@ def testGenericWithDupTypeError(self): class A(Generic[T, T]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", "Duplicate.*T.*a.A")]) + self.assertErrorRegexes(errors, {"e": r"Duplicate.*T.*a.A"}) def testMultiGenericError(self): with file_utils.Tempdir() as d: @@ -126,11 +121,10 @@ def testMultiGenericError(self): class A(Generic[T], Generic[V]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", - r"Cannot inherit.*Generic.*multiple times")]) + self.assertErrorRegexes( + errors, {"e": r"Cannot inherit.*Generic.*multiple times"}) def testGenericWithTypeMissError(self): with file_utils.Tempdir() as d: @@ -142,10 +136,10 @@ def testGenericWithTypeMissError(self): class A(Dict[K, V], Generic[K]): ... """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, [(1, "pyi-error", r"V.*are not listed in Generic.*a.A")]) + self.assertErrorRegexes( + errors, {"e": r"V.*are not listed in Generic.*a.A"}) def testClassInFuncError(self): _, errors = self.InferWithErrors("""\ @@ -155,15 +149,14 @@ def testClassInFuncError(self): S = TypeVar('S') def func(x: T, y: S) -> Union[T, S]: - class InnerCls1(Generic[T]): + class InnerCls1(Generic[T]): # invalid-annotation[e1] # invalid-annotation[e2] class InnerCls2(Generic[S]): pass return x + y """) - self.assertErrorLogIs( - errors, [(7, "invalid-annotation", r"func.*InnerCls1.*T"), - (7, "invalid-annotation", r"func.*InnerCls2.*S")]) + self.assertErrorRegexes(errors, {"e1": r"func.*InnerCls2.*S", + "e2": r"func.*InnerCls1.*T"}) def testClassInClassError(self): _, errors = self.InferWithErrors("""\ @@ -172,7 +165,7 @@ def testClassInClassError(self): T = TypeVar('T', int, float, str) S = TypeVar('S') - class MyClass(Generic[T, S]): + class MyClass(Generic[T, S]): # invalid-annotation[e1] def __init__(self, x: T = None, y: S = None): pass @@ -182,14 +175,13 @@ def f(self, x: T, y: S): class InnerClass1(Iterator[T]): pass - class A(Generic[T]): + class A(Generic[T]): # invalid-annotation[e2] class B(Generic[S]): class C(Generic[T]): pass """) - self.assertErrorLogIs(errors, [ - (6, "invalid-annotation", r"MyClass.*InnerClass1.*T"), - (16, "invalid-annotation", r"A.*C.*T")]) + self.assertErrorRegexes(errors, {"e1": r"MyClass.*InnerClass1.*T", + "e2": r"A.*C.*T"}) def testSignatureTypeParam(self): _, errors = self.InferWithErrors("""\ @@ -205,18 +197,17 @@ def __init__(self, x: T = None, y: S = None): def func1(self, x: T, y: S): pass - def func2(self, x: V): pass + def func2(self, x: V): pass # invalid-annotation[e1] - def func1(x: S): pass + def func1(x: S): pass # invalid-annotation[e2] def func2(x: S) -> S: return x def func3(x: T): pass """) - self.assertErrorLogIs( - errors, [(13, "invalid-annotation", r"Invalid type annotation 'V'"), - (15, "invalid-annotation", r"Invalid type annotation 'S'")]) + self.assertErrorRegexes(errors, {"e1": r"Invalid type annotation 'V'", + "e2": r"Invalid type annotation 'S'"}) def testPyiOutput(self): ty = self.Infer(""" @@ -292,11 +283,11 @@ def testSignatureTypeError(self): V = TypeVar('V') class MyClass(Generic[T]): - def __init__(self, x: T, y: V): + def __init__(self, x: T, y: V): # invalid-annotation[e] pass """) - self.assertErrorLogIs(errors, [ - (7, "invalid-annotation", r"V.*Appears only once in the signature")]) + self.assertErrorRegexes( + errors, {"e": r"V.*Appears only once in the signature"}) def testTypeParameterWithoutSubstitution(self): with file_utils.Tempdir() as d: @@ -361,14 +352,12 @@ def fun3(self, x: T, y: S): pass o = C[int, int]() - o.fun1("5", "5") - o.fun2("5", "5") - o.fun3("5", "5") + o.fun1("5", "5") # wrong-arg-types[e1] + o.fun2("5", "5") # wrong-arg-types[e2] + o.fun3("5", "5") # wrong-arg-types[e3] """) - self.assertErrorLogIs(errors, [ - (23, "wrong-arg-types", r"int.*str"), - (24, "wrong-arg-types", r"int.*str"), - (25, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes( + errors, {"e1": r"int.*str", "e2": r"int.*str", "e3": r"int.*str"}) def testFuncMatchForPytdClassError(self): with file_utils.Tempdir() as d: @@ -396,14 +385,12 @@ def fun3(self, x: T, y: S): ... o = a.C[int, int]() - o.fun1("5", "5") - o.fun2("5", "5") - o.fun3("5", "5") + o.fun1("5", "5") # wrong-arg-types[e1] + o.fun2("5", "5") # wrong-arg-types[e2] + o.fun3("5", "5") # wrong-arg-types[e3] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types", r"int.*str"), - (6, "wrong-arg-types", r"int.*str"), - (7, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes( + errors, {"e1": r"int.*str", "e2": r"int.*str", "e3": r"int.*str"}) def testTypeRenamingError(self): _, errors = self.InferWithErrors("""\ @@ -416,19 +403,18 @@ def testTypeRenamingError(self): W = TypeVar('W') class A(Generic[T]): pass - class B(A[V]): pass + class B(A[V]): pass # not-supported-yet[e1] class C(Generic[V]): pass class D(C[T]): pass - class E(D[S]): pass + class E(D[S]): pass # not-supported-yet[e2] class F(Generic[U]): pass - class G(F[W]): pass + class G(F[W]): pass # not-supported-yet[e3] """) - self.assertErrorLogIs(errors, [ - (10, "not-supported-yet", r"Renaming TypeVar `T`.*"), - (14, "not-supported-yet", r"Renaming TypeVar `T`.*"), - (17, "not-supported-yet", r"Renaming TypeVar `U`.*")]) + self.assertErrorRegexes(errors, {"e1": r"Renaming TypeVar `T`.*", + "e2": r"Renaming TypeVar `T`.*", + "e3": r"Renaming TypeVar `U`.*"}) def testTypeParameterConflictError(self): ty, errors = self.InferWithErrors("""\ @@ -443,9 +429,9 @@ class A(Generic[T]): pass class B(A[V]): pass class D(B[S], A[U]): pass - class E(D[int, str]): pass + class E(D[int, str]): pass # invalid-annotation[e1] - d = D[int, str]() + d = D[int, str]() # invalid-annotation[e2] e = E() """) self.assertTypesMatchPytd(ty, """ @@ -471,9 +457,8 @@ class D(B[S], A[U]): class E(Any): pass """) - self.assertErrorLogIs(errors, [ - (12, "invalid-annotation", r"Conflicting value for TypeVar"), - (14, "invalid-annotation", r"Conflicting value for TypeVar")]) + self.assertErrorRegexes(errors, {"e1": r"Conflicting value for TypeVar", + "e2": r"Conflicting value for TypeVar"}) def testUnboundTypeParameterError(self): _, errors = self.InferWithErrors("""\ @@ -484,10 +469,9 @@ def testUnboundTypeParameterError(self): class A(Generic[T]): pass class B(A): pass - class D(B, A[U]): pass + class D(B, A[U]): pass # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [ - (8, "invalid-annotation", r"Conflicting value for TypeVar D.U")]) + self.assertErrorRegexes(errors, {"e": r"Conflicting value for TypeVar D.U"}) def testSelfTypeParameter(self): # The purpose is to verify there is no infinite recursion @@ -535,11 +519,10 @@ class DictC(collections.OrderedDict, DictB): d2 = DictA() d3 = DictC() x = d1["123"] - y = d2["123"] - z = d3["123"] + y = d2["123"] # unsupported-operands[e1] + z = d3["123"] # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [(16, "unsupported-operands", r"str.*int"), - (17, "unsupported-operands", r"str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"str.*int"}) def testNoSelfAnnot(self): self.Check(""" @@ -556,10 +539,9 @@ def testIllegalSelfAnnot(self): T = TypeVar('T') class Foo(Generic[T]): def __init__(self: 'Foo', children: List['Foo[Any]']): - pass + pass # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(5, "invalid-annotation", r"self.*__init__")]) + self.assertErrorRegexes(errors, {"e": r"self.*__init__"}) def testParameterizedForwardReference(self): ty = self.Infer(""" @@ -583,12 +565,12 @@ def testBadParameterizedForwardReference(self): from typing import Generic, TypeVar T = TypeVar('T') - v = None # type: "Foo[int, str]" + v = None # type: "Foo[int, str]" # invalid-annotation[e] class Foo(Generic[T]): pass """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation", r"1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testRecursiveClass(self): self.Check("""\ diff --git a/pytype/tests/py3/test_list.py b/pytype/tests/py3/test_list.py index b45ca56fe..f583e35ee 100644 --- a/pytype/tests/py3/test_list.py +++ b/pytype/tests/py3/test_list.py @@ -10,16 +10,15 @@ class ListTestBasic(test_base.TargetPython3BasicTest): def test_repeated_add(self): # At the time of this writing, this test completes in <5s. If it takes # significantly longer, there's been a performance regression. - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from typing import List, Text, Tuple def f() -> Tuple[List[Text]]: x = ( ['' % __any_object__, ''] + [''] + [''] + [''.format()] + [''] + [['' % __any_object__, '', '']] ) - return ([__any_object__] + [''] + x,) + return ([__any_object__] + [''] + x,) # bad-return-type """) - self.assertErrorLogIs(errors, [(7, "bad-return-type")]) class ListTest(test_base.TargetPython3FeatureTest): @@ -64,12 +63,12 @@ def test_byte_unpack_ex(self): """) def test_getitem_slot(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ a = [1, '2', 3, 4] p = a[1] q = 1 if __random__ else 2 r = a[q] - s = a["s"] + s = a["s"] # unsupported-operands t = a[-1] """) self.assertTypesMatchPytd(ty, """\ @@ -81,14 +80,13 @@ def test_getitem_slot(self): s = ... # type: Any t = ... # type: int """) - self.assertErrorLogIs(errors, [(5, "unsupported-operands")]) @test_base.skip("Requires more precise slice objects") def test_getitem_slice(self): # Python 3 uses __getitem__ with slice objects instead of __getslice__. # Pytype doesn't support slice objects well, so a lot of results here are # imprecise. It also means wrong-arg-types won't be detected. - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ a = [1, '2', 3, 4] b = a[:] c = 1 if __random__ else 2 @@ -98,8 +96,8 @@ def test_getitem_slice(self): g = a[2:None] h = a[None:2] i = a[None:None] - j = a[int:str] - k = a["s":] + j = a[int:str] # wrong-arg-types + k = a["s":] # wrong-arg-types m = a[1:-1] n = a[0:0] o = a[1:1] @@ -123,9 +121,6 @@ def test_getitem_slice(self): o = ... # type: List[nothing] p = ... # type: List[str] """) - self.assertErrorLogIs(errors, [ - (10, "wrong-arg-types"), - (11, "wrong-arg-types")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_match.py b/pytype/tests/py3/test_match.py index 0fcc9353b..c998976e5 100644 --- a/pytype/tests/py3/test_match.py +++ b/pytype/tests/py3/test_match.py @@ -20,11 +20,10 @@ def f(x: Callable[[], int]): ... def g(x: Callable[[], str]): ... f(foo.bar) # ok - g(foo.bar) + g(foo.bar) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"\(x: Callable\[\[\], str\]\).*" - r"\(x: Callable\[\[\], bool\]\)")]) + self.assertErrorRegexes(errors, { + "e": r"\(x: Callable\[\[\], str\]\).*\(x: Callable\[\[\], bool\]\)"}) def testPyTDFunctionAgainstCallableWithTypeParameters(self): with file_utils.Tempdir() as d: @@ -44,22 +43,19 @@ def f2(x: Callable[[T_constrained], T_constrained]): ... f1(foo.f1) # ok f1(foo.f2) # ok - f1(foo.f3) + f1(foo.f3) # wrong-arg-types[e1] f2(foo.f1) # ok - f2(foo.f2) - f2(foo.f3) + f2(foo.f2) # wrong-arg-types[e2] + f2(foo.f3) # wrong-arg-types[e3] """, pythonpath=[d.path]) expected = r"Callable\[\[Union\[bool, int\]\], Union\[bool, int\]\]" - self.assertErrorLogIs(errors, [ - (11, "wrong-arg-types", - r"Expected.*Callable\[\[str\], str\].*" - r"Actual.*Callable\[\[int\], str\]"), - (13, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], bool\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (14, "wrong-arg-types", - r"Expected.*" + expected + ".*" - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, { + "e1": (r"Expected.*Callable\[\[str\], str\].*" + r"Actual.*Callable\[\[int\], str\]"), + "e2": (r"Expected.*Callable\[\[bool\], bool\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e3": (r"Expected.*" + expected + ".*" + r"Actual.*Callable\[\[int\], str\]")}) def testInterpreterFunctionAgainstCallable(self): _, errors = self.InferWithErrors("""\ @@ -70,11 +66,11 @@ def g1(x: int) -> bool: def g2(x: str) -> int: return __any_object__ f(g1) # ok - f(g2) + f(g2) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], int\].*" - r"Actual.*Callable\[\[str\], int\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[bool\], int\].*" + r"Actual.*Callable\[\[str\], int\]")}) def testBoundInterpreterFunctionAgainstCallable(self): _, errors = self.InferWithErrors("""\ @@ -91,20 +87,18 @@ def f2(x: Callable[[A, bool], int]): ... def f3(x: Callable[[bool], str]): ... f1(bound) # ok - f2(bound) - f3(bound) - f1(unbound) + f2(bound) # wrong-arg-types[e1] + f3(bound) # wrong-arg-types[e2] + f1(unbound) # wrong-arg-types[e3] f2(unbound) # ok """) - self.assertErrorLogIs(errors, [(14, "wrong-arg-types", - r"Expected.*Callable\[\[A, bool\], int\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (15, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], str\].*" - r"Actual.*Callable\[\[int\], bool\]"), - (16, "wrong-arg-types", - r"Expected.*Callable\[\[bool\], int\].*" - r"Actual.*Callable\[\[Any, int\], bool\]")]) + self.assertErrorRegexes(errors, { + "e1": (r"Expected.*Callable\[\[A, bool\], int\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e2": (r"Expected.*Callable\[\[bool\], str\].*" + r"Actual.*Callable\[\[int\], bool\]"), + "e3": (r"Expected.*Callable\[\[bool\], int\].*" + r"Actual.*Callable\[\[Any, int\], bool\]")}) def testCallableParameters(self): with file_utils.Tempdir() as d: @@ -149,11 +143,11 @@ def f(x: Callable[[int], Any]): pass def g1(x: int=0): pass def g2(x: str=""): pass f(g1) # ok - f(g2) + f(g2) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"Expected.*Callable\[\[int\], Any\].*" - r"Actual.*Callable\[\[str\], Any\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[int\], Any\].*" + r"Actual.*Callable\[\[str\], Any\]")}) def testCallableInstanceAgainstCallableWithTypeParameters(self): _, errors = self.InferWithErrors("""\ @@ -161,14 +155,14 @@ def testCallableInstanceAgainstCallableWithTypeParameters(self): T = TypeVar("T") def f(x: Callable[[T], T]): ... def g() -> Callable[[int], str]: return __any_object__ - f(g()) + f(g()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*Callable\[\[str\], str\].*" - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, { + "e": (r"Expected.*Callable\[\[str\], str\].*" + r"Actual.*Callable\[\[int\], str\]")}) def testFunctionWithTypeParameterReturnAgainstCallable(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Callable, AnyStr, TypeVar T = TypeVar("T") def f(x: Callable[..., AnyStr]): ... @@ -176,9 +170,8 @@ def g1(x: AnyStr) -> AnyStr: return x def g2(x: T) -> T: return x f(g1) # ok - f(g2) + f(g2) # wrong-arg-types """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types")]) def testUnionInTypeParameter(self): with file_utils.Tempdir() as d: @@ -208,20 +201,16 @@ def bar(self, x: Dict[Tuple[AnyStr], AnyStr]): ... """) def testFormalType(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import AnyStr, List, NamedTuple def f(x: str): pass - f(AnyStr) + f(AnyStr) # invalid-typevar def g(x: List[str]): pass - g([AnyStr]) - H = NamedTuple("H", [('a', AnyStr)]) + g([AnyStr]) # invalid-typevar + H = NamedTuple("H", [('a', AnyStr)]) # invalid-typevar """) - self.assertErrorLogIs(errors, [ - (4, "invalid-typevar"), - (7, "invalid-typevar"), - (8, "invalid-typevar")]) def testTypeVarWithBound(self): _, errors = self.InferWithErrors("""\ @@ -232,10 +221,9 @@ def f(x: T1) -> T1: return __any_object__ def g(x: Callable[[T2], T2]) -> None: pass - g(f) # line 8 + g(f) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(8, "wrong-arg-types", - r"Expected.*T2.*Actual.*T1")]) + self.assertErrorRegexes(errors, {"e": r"Expected.*T2.*Actual.*T1"}) def testCallableBaseClass(self): with file_utils.Tempdir() as d: @@ -279,11 +267,10 @@ def f(x: AnyStr) -> AnyStr: return x def g(f: Callable[[IntVar], Any], x: IntVar): pass - g(f, 0) + g(f, 0) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Callable\[\[IntVar\], Any\].*Callable\[\[AnyStr\], AnyStr\]")]) + self.assertErrorRegexes(errors, { + "e": r"Callable\[\[IntVar\], Any\].*Callable\[\[AnyStr\], AnyStr\]"}) def testAnyStrAgainstMultipleParamCallable(self): # Callable[[T], T] needs to accept any argument, so AnyStr cannot match it. @@ -294,11 +281,10 @@ def f(x: AnyStr) -> AnyStr: return x def g(f: Callable[[T], T]): pass - g(f) + g(f) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Callable\[\[T\], T\].*Callable\[\[AnyStr\], AnyStr\]")]) + self.assertErrorRegexes(errors, { + "e": r"Callable\[\[T\], T\].*Callable\[\[AnyStr\], AnyStr\]"}) class MatchTestPy3(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_methods.py b/pytype/tests/py3/test_methods.py index e0e415a2d..4fd78fb20 100644 --- a/pytype/tests/py3/test_methods.py +++ b/pytype/tests/py3/test_methods.py @@ -4,7 +4,7 @@ class TestMethods(test_base.TargetPython3BasicTest): - """Tests for class methods""" + """Tests for class methods.""" def testFunctionInit(self): ty = self.Infer(""" @@ -19,39 +19,39 @@ def testAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(x: int): - pass + pass # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*x")]) + self.assertErrorRegexes(errors, {"e": r"int.*x"}) def testLateAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(x: "X"): - pass + pass # invalid-annotation[e] class X(object): pass """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"X.*x")]) + self.assertErrorRegexes(errors, {"e": r"X.*x"}) def testAttributeWithAnnotatedSelf(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self: int): - self.x = 3 + self.x = 3 # invalid-annotation[e] def foo(self): return self.x """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*self")]) + self.assertErrorRegexes(errors, {"e": r"int.*self"}) def testAttributeWithAnnotatedSelfAndFunctionInit(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self: int): - self.x = 3 + self.x = 3 # invalid-annotation[e] def __init__(self: int): pass """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation", r"int.*self")]) + self.assertErrorRegexes(errors, {"e": r"int.*self"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_namedtuple.py b/pytype/tests/py3/test_namedtuple.py index 145f427b4..a3a4dc1e4 100644 --- a/pytype/tests/py3/test_namedtuple.py +++ b/pytype/tests/py3/test_namedtuple.py @@ -23,20 +23,14 @@ class NamedtupleTestsPy3(test_base.TargetPython3FeatureTest): def test_bad_call(self): """The last two arguments are kwonly in 3.6.""" - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple() - collections.namedtuple("_") - collections.namedtuple("_", "", True) - collections.namedtuple("_", "", True, True) - collections.namedtuple("_", "", True, True, True) + collections.namedtuple() # missing-parameter + collections.namedtuple("_") # missing-parameter + collections.namedtuple("_", "", True) # wrong-arg-count + collections.namedtuple("_", "", True, True) # wrong-arg-count + collections.namedtuple("_", "", True, True, True) # wrong-arg-count """) - self.assertErrorLogIs(errorlog, - [(2, "missing-parameter"), - (3, "missing-parameter"), - (4, "wrong-arg-count"), - (5, "wrong-arg-count"), - (6, "wrong-arg-count")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_overload.py b/pytype/tests/py3/test_overload.py index 11f755f7e..fea30006e 100644 --- a/pytype/tests/py3/test_overload.py +++ b/pytype/tests/py3/test_overload.py @@ -25,9 +25,9 @@ def test_bad_implementation(self): def f(x: int) -> str: pass def f(x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(6, "bad-return-type", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_bad_call(self): errors = self.CheckWithErrors("""\ @@ -37,9 +37,9 @@ def f(x: int) -> int: pass def f(x): return x - f("") + f("") # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_sub_return(self): ty = self.Infer(""" @@ -81,9 +81,9 @@ def f(x: int) -> int: def f(x: str) -> int: pass def f(x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(9, "bad-return-type", "int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_multiple_overload_bad_call(self): errors = self.CheckWithErrors("""\ @@ -96,11 +96,10 @@ def f(x: int, y: str) -> str: pass def f(x, y=None): return x if y is None else y - f("") - f(0, 0) + f("") # wrong-arg-types[e1] + f(0, 0) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(10, "wrong-arg-types", r"int.*str"), - (11, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e1": r"int.*str", "e2": r"str.*int"}) def test_pyi(self): src = """ @@ -133,9 +132,9 @@ def g() -> Callable: ... import foo foo.f(0) # ok foo.f("") # ok - foo.f(0.0) # error + foo.f(0.0) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*float")]) + self.assertErrorRegexes(errors, {"e": r"int.*float"}) def test_method_bad_implementation(self): errors = self.CheckWithErrors("""\ @@ -148,9 +147,9 @@ def f(self, x: int) -> int: def f(self, x: str) -> int: pass def f(self, x): - return x + return x # bad-return-type[e] """) - self.assertErrorLogIs(errors, [(10, "bad-return-type", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_method_pyi(self): src = """ @@ -182,9 +181,9 @@ def test_call_overload(self): @overload def f(x: int) -> int: pass - f(0) + f(0) # not-callable[e] """) - self.assertErrorLogIs(errors, [(5, "not-callable", r"overload")]) + self.assertErrorRegexes(errors, {"e": r"overload"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_protocols.py b/pytype/tests/py3/test_protocols.py index 629517091..ce4cedf3a 100644 --- a/pytype/tests/py3/test_protocols.py +++ b/pytype/tests/py3/test_protocols.py @@ -35,10 +35,10 @@ def test_check_protocol_error(self): def f(x: protocols.SupportsAbs): return x.__abs__() - f(["foo"]) + f(["foo"]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"\(x: SupportsAbs\).*\(x: List\[str\]\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: SupportsAbs\).*\(x: List\[str\]\)"}) def test_check_iterator_error(self): _, errors = self.InferWithErrors("""\ @@ -50,10 +50,9 @@ def next(self) -> str: return '' def __iter__(self): return self - f(Foo()) # line 9 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"Iterator\[int\].*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Iterator\[int\].*Foo"}) def test_check_protocol_match_unknown(self): self.Check("""\ @@ -96,10 +95,10 @@ def f(x: Iterable[int]): pass foo = Foo() - f(foo) + f(foo) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(11, "wrong-arg-types", - r"\(x: Iterable\[int\]\).*\(x: Foo\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: Iterable\[int\]\).*\(x: Foo\)"}) def test_check_parameterized_protocol_multi_signature(self): self.Check("""\ @@ -132,10 +131,10 @@ def f(x: Sequence[int]): pass foo = Foo() - f(foo) + f(foo) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(13, "wrong-arg-types", - r"\(x: Sequence\[int\]\).*\(x: Foo\)")]) + self.assertErrorRegexes( + errors, {"e": r"\(x: Sequence\[int\]\).*\(x: Foo\)"}) def test_construct_dict_with_protocol(self): self.Check(""" @@ -266,10 +265,9 @@ def next(self): return __any_object__ def f(x: Iterator[int]): pass - f(Foo()) # line 9 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"Iterator\[int\].*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Iterator\[int\].*Foo"}) def test_reversible(self): self.Check(""" @@ -320,10 +318,9 @@ def test_list_hash(self): from typing import Hashable def f(x: Hashable): pass - f([]) # line 4 + f([]) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(4, "wrong-arg-types", r"Hashable.*List.*__hash__")]) + self.assertErrorRegexes(errors, {"e": r"Hashable.*List.*__hash__"}) def test_hash_constant(self): errors = self.CheckWithErrors("""\ @@ -332,10 +329,9 @@ class Foo(object): __hash__ = None def f(x: Hashable): pass - f(Foo()) # line 6 + f(Foo()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(6, "wrong-arg-types", r"Hashable.*Foo.*__hash__")]) + self.assertErrorRegexes(errors, {"e": r"Hashable.*Foo.*__hash__"}) def test_generic_callable(self): with file_utils.Tempdir() as d: @@ -401,12 +397,12 @@ class NotAppendable(object): pass def f(x: Appendable): pass - f(42) # error - f(NotAppendable()) # error + f(42) # wrong-arg-types[e1] + f(NotAppendable()) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [ - (9, "wrong-arg-types", r"Appendable.*int.*append"), - (10, "wrong-arg-types", r"Appendable.*NotAppendable.*append")]) + self.assertErrorRegexes(errors, { + "e1": r"Appendable.*int.*append", + "e2": r"Appendable.*NotAppendable.*append"}) def test_reingest_custom_protocol(self): ty = self.Infer(""" @@ -443,12 +439,12 @@ class NotAppendable(object): pass def f(x: foo.Appendable): pass - f(42) # error - f(NotAppendable()) # error + f(42) # wrong-arg-types[e1] + f(NotAppendable()) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types", r"Appendable.*int.*append"), - (7, "wrong-arg-types", r"Appendable.*NotAppendable.*append")]) + self.assertErrorRegexes(errors, { + "e1": r"Appendable.*int.*append", + "e2": r"Appendable.*NotAppendable.*append"}) def test_reingest_custom_protocol_inherit_method(self): ty = self.Infer(""" @@ -470,10 +466,9 @@ def remove(self): def f(x: Mutable): pass f([]) # ok - f(NotMutable()) # error + f(NotMutable()) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (8, "wrong-arg-types", r"Mutable.*NotMutable.*append")]) + self.assertErrorRegexes(errors, {"e": r"Mutable.*NotMutable.*append"}) def test_reingest_custom_protocol_implement_method(self): ty = self.Infer(""" @@ -513,13 +508,12 @@ def test_check_method_body(self): from typing_extensions import Protocol class Countable(Protocol): def count(self) -> int: - ... + ... # bad-return-type[e] class MyCountable(Countable): def count(self): return super(MyCountable, self).count() """) - self.assertErrorLogIs( - errors, [(4, "bad-return-type", r"int.*None.*line 7")]) + self.assertErrorRegexes(errors, {"e": r"int.*None.*line 7"}) class ProtocolsTestPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_recovery.py b/pytype/tests/py3/test_recovery.py index d2f7a8e60..1709b945c 100644 --- a/pytype/tests/py3/test_recovery.py +++ b/pytype/tests/py3/test_recovery.py @@ -7,20 +7,15 @@ class RecoveryTests(test_base.TargetPython3BasicTest): """Tests for recovering after errors.""" def testFunctionWithUnknownDecorator(self): - _, errors = self.InferWithErrors("""\ - from nowhere import decorator + self.InferWithErrors("""\ + from nowhere import decorator # import-error @decorator def f(): - name_error + name_error # name-error @decorator def g(x: int) -> None: - x.upper() + x.upper() # attribute-error """, deep=True) - self.assertErrorLogIs(errors, [ - (1, "import-error"), - (4, "name-error"), - (7, "attribute-error"), - ]) def testComplexInit(self): """Test that we recover when __init__ triggers a utils.TooComplexError.""" @@ -37,10 +32,10 @@ def __init__(self, string_ref: AnyStr = None, type_ref: AnyStr = None) -> None: pass - def foo(self, x: other_module.X) -> None: # line 13 + def foo(self, x: other_module.X) -> None: # name-error[e] pass """, deep=True) - self.assertErrorLogIs(errors, [(13, "name-error", r"other_module")]) + self.assertErrorRegexes(errors, {"e": r"other_module"}) class RecoveryTestsPython3(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_reingest.py b/pytype/tests/py3/test_reingest.py index a8a7089ab..78eaab9f2 100644 --- a/pytype/tests/py3/test_reingest.py +++ b/pytype/tests/py3/test_reingest.py @@ -18,9 +18,9 @@ def f(x: T) -> T: return x d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.f("") + foo.f("") # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"float.*str")]) + self.assertErrorRegexes(errors, {"e": r"float.*str"}) def testDefaultArgumentType(self): foo = self.Infer(""" @@ -56,10 +56,10 @@ def foo(self): d.create_file("foo.pyi", pytd_utils.Print(foo)) _, errors = self.InferWithErrors("""\ import foo - foo.Foo() + foo.Foo() # not-instantiable[e] foo.Bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_slots.py b/pytype/tests/py3/test_slots.py index f0c39d834..b585b88a5 100644 --- a/pytype/tests/py3/test_slots.py +++ b/pytype/tests/py3/test_slots.py @@ -14,11 +14,10 @@ class Foo(object): """) def testSlotWithBytes(self): - errors = self.CheckWithErrors("""\ - class Foo(object): + self.CheckWithErrors("""\ + class Foo(object): # bad-slots __slots__ = (b"x",) """) - self.assertErrorLogIs(errors, [(1, "bad-slots")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_stdlib.py b/pytype/tests/py3/test_stdlib.py index d67c8918a..aa1ae3fe9 100644 --- a/pytype/tests/py3/test_stdlib.py +++ b/pytype/tests/py3/test_stdlib.py @@ -17,9 +17,9 @@ def testCollectionsDeque(self): def f1(x: Deque): ... def f2(x: int): ... f1(collections.deque()) - f2(collections.deque()) # line 6 + f2(collections.deque()) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", r"int.*deque")]) + self.assertErrorRegexes(errors, {"e": r"int.*deque"}) def testCollectionsDequeInit(self): ty = self.Infer("""\ diff --git a/pytype/tests/py3/test_super.py b/pytype/tests/py3/test_super.py index 47bfe7115..bad37fa94 100644 --- a/pytype/tests/py3/test_super.py +++ b/pytype/tests/py3/test_super.py @@ -66,24 +66,20 @@ def call_inner(a) -> int """) def test_super_without_args_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ class A(object): def m(self): pass class B(A): def m(self): def f(): - super().m() + super().m() # invalid-super-call[e1] f() def func(x: int): - super().m() + super().m() # invalid-super-call[e2] """) - self.assertErrorLogIs( - errors, - [(8, "invalid-super-call", - r".*Missing 'self' argument.*"), - (11, "invalid-super-call", - r".*Missing __class__ closure.*")]) + self.assertErrorRegexes(errors, {"e1": r".*Missing 'self' argument.*", + "e2": r".*Missing __class__ closure.*"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_tracebacks.py b/pytype/tests/py3/test_tracebacks.py index cca593b4f..d2922d793 100644 --- a/pytype/tests/py3/test_tracebacks.py +++ b/pytype/tests/py3/test_tracebacks.py @@ -9,10 +9,10 @@ class TracebackTest(test_base.TargetPython3BasicTest): def test_build_class(self): errors = self.CheckWithErrors("""\ class Foo(object): - def f(self, x: Bar): + def f(self, x: Bar): # name-error[e] pass """) - self.assertErrorLogIs(errors, [(2, "name-error", r"Bar.*not defined$")]) + self.assertErrorRegexes(errors, {"e": r"Bar.*not defined$"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_tuple.py b/pytype/tests/py3/test_tuple.py index 1e44a54da..0e4326dad 100644 --- a/pytype/tests/py3/test_tuple.py +++ b/pytype/tests/py3/test_tuple.py @@ -59,11 +59,11 @@ def f(x: Tuple[str, ...]): pass def g(y: Tuple[str]): pass - f((42,)) - f(tuple([42])) + f((42,)) # wrong-arg-types[e1] + f(tuple([42])) # wrong-arg-types[e2] f(("", "")) # okay - g((42,)) - g(("", "")) + g((42,)) # wrong-arg-types[e3] + g(("", "")) # wrong-arg-types[e4] g(("",)) # okay g(tuple([""])) # okay """) @@ -72,15 +72,11 @@ def g(y: Tuple[str]): tuple_int = r"Tuple\[int\]" tuple_ints = r"Tuple\[int, \.\.\.\]" tuple_str_str = r"Tuple\[str, str\]" - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"%s.*%s" % (x, tuple_int)), - (7, "wrong-arg-types", - r"%s.*%s" % (x, tuple_ints)), - (9, "wrong-arg-types", - r"%s.*%s" % (y, tuple_int)), - (10, "wrong-arg-types", - r"%s.*%s" % (y, tuple_str_str)) - ]) + self.assertErrorRegexes(errors, { + "e1": r"%s.*%s" % (x, tuple_int), + "e2": r"%s.*%s" % (x, tuple_ints), + "e3": r"%s.*%s" % (y, tuple_int), + "e4": r"%s.*%s" % (y, tuple_str_str)}) def testInlineTuple(self): with file_utils.Tempdir() as d: @@ -113,17 +109,16 @@ def f(x: Type[Tuple[int, str]]): pass def g(x: Tuple[int, str]): pass - f(type(("", 1))) - g(("", 1)) - g(foo.A()) + f(type(("", 1))) # wrong-arg-types[e1] + g(("", 1)) # wrong-arg-types[e2] + g(foo.A()) # wrong-arg-types[e3] """, pythonpath=[d.path]) expected = r"Tuple\[int, str\]" actual = r"Tuple\[str, int\]" - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", - r"Type\[%s\].*Type\[%s\]" % (expected, actual)), - (8, "wrong-arg-types", r"%s.*%s" % (expected, actual)), - (9, "wrong-arg-types", r"%s.*foo\.A" % expected)]) + self.assertErrorRegexes(errors, { + "e1": r"Type\[%s\].*Type\[%s\]" % (expected, actual), + "e2": r"%s.*%s" % (expected, actual), + "e3": r"%s.*foo\.A" % expected}) def testTupleCombinationExplosion(self): self.Check(""" @@ -154,9 +149,9 @@ class Bar(tuple): ... from typing import Tuple import bar def foo() -> Tuple[bar.Bar, bar.Bar]: - return bar.Bar(None, None) # line 4 + return bar.Bar(None, None) # wrong-arg-count[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "wrong-arg-count", "1.*3")]) + self.assertErrorRegexes(errors, {"e": r"1.*3"}) class TupleTestPython3Feature(test_base.TargetPython3FeatureTest): @@ -180,10 +175,9 @@ def __getitem__(self, pos: int) -> int or str or complex def testBadUnpackingWithSlurp(self): _, errors = self.InferWithErrors("""\ - a, *b, c = (1,) + a, *b, c = (1,) # bad-unpacking[e] """) - self.assertErrorLogIs( - errors, [(1, "bad-unpacking", "1 value.*3 variables")]) + self.assertErrorRegexes(errors, {"e": r"1 value.*3 variables"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/py3/test_type_comments.py b/pytype/tests/py3/test_type_comments.py index bb6c41993..aee187d82 100644 --- a/pytype/tests/py3/test_type_comments.py +++ b/pytype/tests/py3/test_type_comments.py @@ -7,12 +7,11 @@ class FunctionCommentWithAnnotationsTest(test_base.TargetPython3BasicTest): """Tests for type comments that require annotations.""" def testFunctionTypeCommentPlusAnnotations(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x: int) -> float: - # type: (int) -> float + # type: (int) -> float # redundant-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "redundant-function-type-comment")]) def testListComprehensionComments(self): ty = self.Infer("""\ diff --git a/pytype/tests/py3/test_typevar.py b/pytype/tests/py3/test_typevar.py index 44f2eecaa..5f28b4f7a 100644 --- a/pytype/tests/py3/test_typevar.py +++ b/pytype/tests/py3/test_typevar.py @@ -70,15 +70,12 @@ def testImportTypeVarNameChange(self): """) _, errors = self.InferWithErrors("""\ # This is illegal: A TypeVar("T") needs to be stored under the name "T". - from a import T as T2 + from a import T as T2 # invalid-typevar[e1] from a import X - Y = X + Y = X # invalid-typevar[e2] def f(x: T2) -> T2: ... """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", "T.*T2"), - (4, "invalid-typevar", "X.*Y"), - ]) + self.assertErrorRegexes(errors, {"e1": r"T.*T2", "e2": r"X.*Y"}) def testMultipleSubstitution(self): ty = self.Infer("""\ @@ -124,24 +121,22 @@ def testBadSubstitution(self): S = TypeVar("S") T = TypeVar("T") def f1(x: S) -> List[S]: - return {x} + return {x} # bad-return-type[e1] def f2(x: S) -> S: return 42 # no error because never called def f3(x: S) -> S: - return 42 + return 42 # bad-return-type[e2] # bad-return-type[e3] def f4(x: S, y: T, z: T) -> List[S]: - return [y] + return [y] # bad-return-type[e4] f3("") f3(16) # ok f3(False) f4(True, 3.14, 0) f4("hello", "world", "domination") # ok """) - self.assertErrorLogIs(errors, [ - (5, "bad-return-type", r"List\[S\].*set"), - (9, "bad-return-type", r"str.*int"), - (9, "bad-return-type", r"bool.*int"), - (11, "bad-return-type", r"List\[bool\].*List\[Union\[float, int\]\]")]) + self.assertErrorRegexes(errors, { + "e1": r"List\[S\].*set", "e2": r"str.*int", "e3": r"bool.*int", + "e4": r"List\[bool\].*List\[Union\[float, int\]\]"}) def testUseConstraints(self): ty, errors = self.InferWithErrors("""\ @@ -149,7 +144,7 @@ def testUseConstraints(self): T = TypeVar("T", int, float) def f(x: T) -> T: return __any_object__ - v = f("") + v = f("") # wrong-arg-types[e] w = f(True) # ok u = f(__any_object__) # ok """) @@ -161,8 +156,7 @@ def f(x: T) -> T: ... w = ... # type: bool u = ... # type: int or float """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Union\[float, int\].*str")]) + self.assertErrorRegexes(errors, {"e": r"Union\[float, int\].*str"}) def testTypeParameterType(self): ty = self.Infer("""\ @@ -184,10 +178,10 @@ def testPrintNestedTypeParameter(self): from typing import List, TypeVar T = TypeVar("T", int, float) def f(x: List[T]): ... - f([""]) + f([""]) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (4, "wrong-arg-types", r"List\[Union\[float, int\]\].*List\[str\]")]) + self.assertErrorRegexes(errors, { + "e": r"List\[Union\[float, int\]\].*List\[str\]"}) def testConstraintSubtyping(self): _, errors = self.InferWithErrors("""\ @@ -195,10 +189,9 @@ def testConstraintSubtyping(self): T = TypeVar("T", int, float) def f(x: T, y: T): ... f(True, False) # ok - f(True, 42) + f(True, 42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*y: bool.*Actual.*y: int")]) + self.assertErrorRegexes(errors, {"e": r"Expected.*y: bool.*Actual.*y: int"}) def testFilterValue(self): _, errors = self.InferWithErrors("""\ @@ -207,11 +200,11 @@ def testFilterValue(self): def f(x: T, y: T): ... x = 3 x = 42.0 - f(x, 3) + f(x, 3) # wrong-arg-types[e] f(x, 42.0) # ok """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-types", - r"Expected.*y: float.*Actual.*y: int")]) + self.assertErrorRegexes( + errors, {"e": r"Expected.*y: float.*Actual.*y: int"}) def testFilterClass(self): self.Check("""\ @@ -254,36 +247,31 @@ def testEnforceNonConstrainedTypeVar(self): T = TypeVar("T") def f(x: T, y: T): ... f(42, True) # ok - f(42, "") + f(42, "") # wrong-arg-types[e1] f(42, 16j) # ok f(object(), 42) # ok f(42, object()) # ok - f(42.0, "") + f(42.0, "") # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", - r"Expected.*y: int.*Actual.*y: str"), - (9, "wrong-arg-types", - r"Expected.*y: float.*Actual.*y: str")]) + self.assertErrorRegexes(errors, { + "e1": r"Expected.*y: int.*Actual.*y: str", + "e2": r"Expected.*y: float.*Actual.*y: str"}) def testUselessTypeVar(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import Tuple, TypeVar T = TypeVar("T") S = TypeVar("S", int, float) - def f1(x: T): ... - def f2() -> T: ... - def f3(x: Tuple[T]): ... + def f1(x: T): ... # invalid-annotation + def f2() -> T: ... # invalid-annotation + def f3(x: Tuple[T]): ... # invalid-annotation def f4(x: Tuple[T, T]): ... # ok def f5(x: S): ... # ok - def f6(x: "U"): ... + def f6(x: "U"): ... # invalid-annotation def f7(x: T, y: "T"): ... # ok def f8(x: "U") -> "U": ... # ok U = TypeVar("U") """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation"), - (5, "invalid-annotation"), - (6, "invalid-annotation"), - (9, "invalid-annotation")]) def testUseBound(self): ty, errors = self.InferWithErrors("""\ @@ -295,7 +283,7 @@ def f(x: T) -> T: v2 = f(True) # ok v3 = f(42) # ok v4 = f(3.14) # ok - v5 = f("") + v5 = f("") # wrong-arg-types[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, TypeVar @@ -307,8 +295,7 @@ def f(x: T) -> T v4 = ... # type: float v5 = ... # type: Any """) - self.assertErrorLogIs( - errors, [(9, "wrong-arg-types", r"x: float.*x: str")]) + self.assertErrorRegexes(errors, {"e": r"x: float.*x: str"}) def testBadReturn(self): self.assertNoCrash(self.Check, """\ @@ -325,10 +312,9 @@ def testOptionalTypeVar(self): from typing import Optional, TypeVar T = TypeVar("T", bound=str) def f() -> Optional[T]: - return 42 if __random__ else None + return 42 if __random__ else None # bad-return-type[e] """, deep=True) - self.assertErrorLogIs( - errors, [(4, "bad-return-type", r"Optional\[T\].*int")]) + self.assertErrorRegexes(errors, {"e": r"Optional\[T\].*int"}) def testUnicodeLiterals(self): ty = self.Infer(""" @@ -421,12 +407,12 @@ def g(x: AnyStr) -> AnyStr: ... # pylint: enable=g-backslash-continuation _, errors = self.InferWithErrors("""\ import foo - foo.f("") - foo.g(0) + foo.f("") # wrong-arg-types[e1] + foo.g(0) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"Union\[float, int\].*str"), - (3, "wrong-arg-types", r"Union\[bytes, str\].*int")]) + self.assertErrorRegexes(errors, { + "e1": r"Union\[float, int\].*str", + "e2": r"Union\[bytes, str\].*int"}) def testSubprocess(self): ty = self.Infer(""" diff --git a/pytype/tests/py3/test_typing.py b/pytype/tests/py3/test_typing.py index 443e7e075..af34aceae 100644 --- a/pytype/tests/py3/test_typing.py +++ b/pytype/tests/py3/test_typing.py @@ -20,8 +20,8 @@ def _test_match(self, arg, annotation, disables=""): self.Check(self._TEMPLATE % locals()) def _test_no_match(self, arg, annotation, disables=""): - _, errors = self.InferWithErrors(self._TEMPLATE % locals()) - self.assertNotEqual(0, len(errors)) + code = (self._TEMPLATE % locals()).rstrip() + " # wrong-arg-types" + self.InferWithErrors(code) def test_list_match(self): self._test_match("[1, 2, 3]", "typing.List") @@ -51,7 +51,7 @@ class Foo: def f1(foo: Type[Foo]): return foo.x def f2(foo: Type[Foo]): - return foo.y # bad + return foo.y # attribute-error[e] def f3(foo: Type[Foo]): return foo.mro() def f4(foo: Type[Foo]): @@ -61,7 +61,7 @@ def f4(foo: Type[Foo]): v3 = f3(Foo) v4 = f4(Foo) """) - self.assertErrorLogIs(errors, [(7, "attribute-error", r"y.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"y.*Foo"}) self.assertTypesMatchPytd(ty, """ from typing import Any, Type class Foo: @@ -86,13 +86,13 @@ def f1(x: Type[Union[int, Foo]]): # differently. See get_attribute() in attribute.py. x.bar def f2(x: Union[Type[int], Type[Foo]]): - x.bar + x.bar # attribute-error[e] f1(x) def f3(x: Type[Union[int, Foo]]): f1(x) f2(x) """) - self.assertErrorLogIs(errors, [(9, "attribute-error", "bar.*int")]) + self.assertErrorRegexes(errors, {"e": r"bar.*int"}) def test_use_type_alias(self): with file_utils.Tempdir() as d: @@ -131,19 +131,19 @@ def f1(x: Callable[[int, str], bool]): ... def f2(x: Callable[..., bool]): ... def f3(x: Callable[[], bool]): ... - def g1(x: Callable[int, bool]): ... # bad: _ARGS not a list + def g1(x: Callable[int, bool]): ... # _ARGS not a list # invalid-annotation[e1] lst = [int] if __random__ else [str] - def g2(x: Callable[lst, bool]): ... # bad: _ARGS ambiguous + def g2(x: Callable[lst, bool]): ... # _ARGS ambiguous # invalid-annotation[e2] # invalid-annotation[e3] # bad: _RET ambiguous - def g3(x: Callable[[], bool if __random__ else str]): ... + def g3(x: Callable[[], bool if __random__ else str]): ... # invalid-annotation[e4] # bad: _ARGS[0] ambiguous - def g4(x: Callable[[int if __random__ else str], bool]): ... + def g4(x: Callable[[int if __random__ else str], bool]): ... # invalid-annotation[e5] lst = None # type: list[int] - def g5(x: Callable[lst, bool]): ... # bad: _ARGS not a constant - def g6(x: Callable[[42], bool]): ... # bad: _ARGS[0] not a type - def g7(x: Callable[[], bool, int]): ... # bad: Too many params - def g8(x: Callable[Any, bool]): ... # bad: Any is not allowed - def g9(x: Callable[[]]) -> None: ... + def g5(x: Callable[lst, bool]): ... # _ARGS not a constant # invalid-annotation[e6] + def g6(x: Callable[[42], bool]): ... # _ARGS[0] not a type # invalid-annotation[e7] + def g7(x: Callable[[], bool, int]): ... # Too many params # invalid-annotation[e8] + def g8(x: Callable[Any, bool]): ... # Any is not allowed # invalid-annotation[e9] + def g9(x: Callable[[]]) -> None: ... # invalid-annotation[e10] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Callable, List, Type @@ -163,32 +163,28 @@ def g7(x: Callable[[], bool]) -> None: ... def g8(x: Callable[Any, bool]) -> None: ... def g9(x: Callable[[], Any]) -> None: ... """) - self.assertErrorLogIs(errors, [ - (8, "invalid-annotation", - r"'int'.*must be a list of argument types or ellipsis"), - (10, "invalid-annotation", r"\[int\] or \[str\].*Must be constant"), - (10, "invalid-annotation", - r"'Any'.*must be a list of argument types or ellipsis"), - (12, "invalid-annotation", r"bool or str.*Must be constant"), - (14, "invalid-annotation", r"int or str.*Must be constant"), - (16, "invalid-annotation", - r"instance of List\[int\].*Must be constant"), - (17, "invalid-annotation", r"instance of int"), - (18, "invalid-annotation", r"Callable.*Expected 2.*got 3"), - (19, "invalid-annotation", - r"'Any'.*must be a list of argument types or ellipsis"), - (20, "invalid-annotation", r"Callable\[_ARGS, _RET].*2.*1"),]) + self.assertErrorRegexes(errors, { + "e1": r"'int'.*must be a list of argument types or ellipsis", + "e2": r"\[int\] or \[str\].*Must be constant", + "e3": r"'Any'.*must be a list of argument types or ellipsis", + "e4": r"bool or str.*Must be constant", + "e5": r"int or str.*Must be constant", + "e6": r"instance of List\[int\].*Must be constant", + "e7": r"instance of int", + "e8": r"Callable.*Expected 2.*got 3", + "e9": r"'Any'.*must be a list of argument types or ellipsis", + "e10": r"Callable\[_ARGS, _RET].*2.*1"}) def test_callable_bad_args(self): ty, errors = self.InferWithErrors("""\ from typing import Callable lst1 = [str] lst1[0] = int - def g1(x: Callable[lst1, bool]): ... # line 4 + def g1(x: Callable[lst1, bool]): ... # invalid-annotation[e1] lst2 = [str] while __random__: lst2.append(int) - def g2(x: Callable[lst2, bool]): ... # line 8 + def g2(x: Callable[lst2, bool]): ... # invalid-annotation[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Callable, List, Type, Union @@ -200,11 +196,11 @@ def g2(x: Callable[..., bool]) -> None: ... # For the first error, it would be more precise to say [str or int], since # the mutation is simple enough that we could keep track of the change to # the constant, but we don't do that yet. - self.assertErrorLogIs(errors, [ - (4, "invalid-annotation", - r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant"), - (8, "invalid-annotation", - r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant"),]) + self.assertErrorRegexes(errors, { + "e1": (r"instance of List\[Type\[Union\[int, str\]\]\].*" + r"Must be constant"), + "e2": r"instance of List\[Type\[Union\[int, str\]\]\].*Must be constant" + }) def test_generics(self): with file_utils.Tempdir() as d: @@ -276,10 +272,10 @@ def test_callable_call(self): ty, errors = self.InferWithErrors("""\ from typing import Callable f = ... # type: Callable[[int], str] - v1 = f() + v1 = f() # wrong-arg-count[e1] v2 = f(True) # ok - v3 = f(42.0) - v4 = f(1, 2) + v3 = f(42.0) # wrong-arg-types[e2] + v4 = f(1, 2) # wrong-arg-count[e3] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Callable @@ -289,16 +285,15 @@ def test_callable_call(self): v3 = ... # type: Any v4 = ... # type: Any """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*0"), - (5, "wrong-arg-types", "int.*float"), - (6, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes( + errors, {"e1": r"1.*0", "e2": r"int.*float", "e3": r"1.*2"}) def test_callable_call_with_type_parameters(self): ty, errors = self.InferWithErrors("""\ from typing import Callable, TypeVar T = TypeVar("T") def f(g: Callable[[T, T], T], y, z): - return g(y, z) + return g(y, z) # wrong-arg-types[e] v1 = f(__any_object__, 42, 3.14) # ok v2 = f(__any_object__, 42, "hello world") """, deep=True) @@ -309,7 +304,7 @@ def f(g: Callable[[T, T], T], y, z): ... v1 = ... # type: int or float v2 = ... # type: Any """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e": r"int.*str"}) def test_callable_call_with_return_only(self): ty = self.Infer(""" @@ -327,15 +322,13 @@ def test_callable_call_with_varargs_and_kwargs(self): _, errors = self.InferWithErrors("""\ from typing import Callable f = ... # type: Callable[[], int] - f(x=3) - f(*(42,)) - f(**{"x": "hello", "y": "world"}) - f(*(42,), **{"hello": "world"}) + f(x=3) # wrong-keyword-args[e1] + f(*(42,)) # wrong-arg-count[e2] + f(**{"x": "hello", "y": "world"}) # wrong-keyword-args[e3] + f(*(42,), **{"hello": "world"}) # wrong-keyword-args[e4] """) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", r"x"), - (4, "wrong-arg-count", r"0.*1"), - (5, "wrong-keyword-args", r"x, y"), - (6, "wrong-keyword-args", r"hello")]) + self.assertErrorRegexes(errors, {"e1": r"x", "e2": r"0.*1", "e3": r"x, y", + "e4": r"hello"}) def test_callable_attribute(self): self.Check("""\ @@ -416,27 +409,23 @@ def func7(a: MySpecialA) -> A: ... """) def test_new_type_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ from typing import NewType MyInt = NewType('MyInt', int) MyStr = NewType('MyStr', str) def func1(i: MyInt) -> MyInt: return i def func2(i: int) -> MyInt: - return i + return i # bad-return-type[e1] def func3(s: MyStr) -> MyStr: return s - func1(123) - func3(MyStr(123)) - """) - self.assertErrorLogIs( - errors, - [(8, "bad-return-type", - r"Expected: MyInt\nActually returned: int"), - (11, "wrong-arg-types", - r".*Expected: \(i: MyInt\)\nActually passed: \(i: int\)"), - (12, "wrong-arg-types", - r".*Expected:.*val: str\)\nActually passed:.*val: int\)"),]) + func1(123) # wrong-arg-types[e2] + func3(MyStr(123)) # wrong-arg-types[e3] + """) + self.assertErrorRegexes(errors, { + "e1": r"Expected: MyInt\nActually returned: int", + "e2": r".*Expected: \(i: MyInt\)\nActually passed: \(i: int\)", + "e3": r".*Expected:.*val: str\)\nActually passed:.*val: int\)"}) def test_maybe_return(self): self.Check(""" @@ -470,50 +459,46 @@ def g() -> str: def test_union_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Union - MyUnion = Union[int, ...] + MyUnion = Union[int, ...] # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*Union")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*Union"}) def test_list_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import List - MyList = List[int, ...] + MyList = List[int, ...] # invalid-annotation[e] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*List")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*index 1.*List"}) def test_multiple_ellipses(self): errors = self.CheckWithErrors("""\ from typing import Union - MyUnion = Union[..., int, ..., str, ...] + MyUnion = Union[..., int, ..., str, ...] # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [ - (2, "invalid-annotation", r"Ellipsis.*indices 0, 2, 4.*Union")]) + self.assertErrorRegexes(errors, {"e": r"Ellipsis.*indices 0, 2, 4.*Union"}) def test_bad_tuple_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Tuple - MyTuple1 = Tuple[..., ...] - MyTuple2 = Tuple[...] + MyTuple1 = Tuple[..., ...] # invalid-annotation[e1] + MyTuple2 = Tuple[...] # invalid-annotation[e2] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 0.*Tuple"), - (3, "invalid-annotation", r"Ellipsis.*index 0.*Tuple")]) + self.assertErrorRegexes(errors, {"e1": r"Ellipsis.*index 0.*Tuple", + "e2": r"Ellipsis.*index 0.*Tuple"}) def test_bad_callable_ellipsis(self): errors = self.CheckWithErrors("""\ from typing import Callable - MyCallable1 = Callable[..., ...] - MyCallable2 = Callable[[int], ...] - MyCallable3 = Callable[[...], int] - MyCallable4 = Callable[[int], int, int] + MyCallable1 = Callable[..., ...] # invalid-annotation[e1] + MyCallable2 = Callable[[int], ...] # invalid-annotation[e2] + MyCallable3 = Callable[[...], int] # invalid-annotation[e3] + MyCallable4 = Callable[[int], int, int] # invalid-annotation[e4] """) - self.assertErrorLogIs( - errors, [(2, "invalid-annotation", r"Ellipsis.*index 1.*Callable"), - (3, "invalid-annotation", r"Ellipsis.*index 1.*Callable"), - (4, "invalid-annotation", r"Ellipsis.*index 0.*list"), - (5, "invalid-annotation", r"Callable\[_ARGS, _RET].*2.*3")]) + self.assertErrorRegexes(errors, { + "e1": r"Ellipsis.*index 1.*Callable", + "e2": r"Ellipsis.*index 1.*Callable", + "e3": r"Ellipsis.*index 0.*list", + "e4": r"Callable\[_ARGS, _RET].*2.*3"}) def test_optional_parameters(self): errors = self.CheckWithErrors("""\ @@ -522,16 +507,15 @@ def test_optional_parameters(self): def func1(x: Optional[int]): pass - def func2(x: Optional): + def func2(x: Optional): # invalid-annotation[e1] pass - def func3(x: Optional[int, float, str]): + def func3(x: Optional[int, float, str]): # invalid-annotation[e2] pass """) - self.assertErrorLogIs( - errors, [(6, "invalid-annotation", r"Not a type"), - (9, "invalid-annotation", - r"typing.Optional can only contain one type parameter")]) + self.assertErrorRegexes( + errors, {"e1": r"Not a type", + "e2": r"typing\.Optional can only contain one type parameter"}) def test_noreturn_parameters(self): errors = self.CheckWithErrors("""\ @@ -540,27 +524,25 @@ def test_noreturn_parameters(self): def func0() -> NoReturn: raise ValueError() - def func1() -> List[NoReturn]: + def func1() -> List[NoReturn]: # invalid-annotation[e1] raise ValueError() def func2(x) -> NoReturn: if x > 1: - raise ValueError() + raise ValueError() # bad-return-type[e2] - def func3(x: NoReturn): + def func3(x: NoReturn): # invalid-annotation[e3] pass - def func4(x: List[NoReturn]): + def func4(x: List[NoReturn]): # invalid-annotation[e4] pass - bad = None # type: NoReturn + bad = None # type: NoReturn # invalid-annotation[e5] """) - self.assertErrorLogIs( - errors, [(6, "invalid-annotation", r"NoReturn is not allowed"), - (11, "bad-return-type", r"NoReturn.*None"), - (13, "invalid-annotation", r"NoReturn is not allowed"), - (16, "invalid-annotation", r"NoReturn is not allowed"), - (19, "invalid-annotation", r"NoReturn is not allowed")]) + self.assertErrorRegexes(errors, { + "e1": r"NoReturn is not allowed", "e2": r"NoReturn.*None", + "e3": r"NoReturn is not allowed", "e4": r"NoReturn is not allowed", + "e5": r"NoReturn is not allowed"}) def test_SupportsComplex(self): self.Check("""\ @@ -575,7 +557,7 @@ class CounterTest(test_base.TargetPython3BasicTest): """Tests for typing.Counter.""" def test_counter_generic(self): - ty, errors = self.InferWithErrors(""" + ty, _ = self.InferWithErrors(""" import collections import typing def freqs(s: str) -> typing.Counter[str]: @@ -587,8 +569,8 @@ def freqs(s: str) -> typing.Counter[str]: x + y x | y x & y - x - z # line 13 error: unsupported-operands - x.most_common(1, 2, 3) # line 14 error: wrong-arg-count + x - z # unsupported-operands + x.most_common(1, 2, 3) # wrong-arg-count a = x.most_common() b = x.most_common(1) c = x.elements() @@ -614,8 +596,6 @@ def freqs(s: str) -> typing.Counter[str]: def freqs(s: str) -> Counter[str]: ... """) - self.assertErrorLogIs( - errors, [(13, "unsupported-operands"), (14, "wrong-arg-count")]) class TypingTestPython3Feature(test_base.TargetPython3FeatureTest): diff --git a/pytype/tests/py3/test_typing_namedtuple.py b/pytype/tests/py3/test_typing_namedtuple.py index 603c5e736..d51f14c62 100644 --- a/pytype/tests/py3/test_typing_namedtuple.py +++ b/pytype/tests/py3/test_typing_namedtuple.py @@ -8,22 +8,19 @@ class NamedTupleTest(test_base.TargetPython3BasicTest): """Tests for the typing.NamedTuple overlay.""" def test_make(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing A = typing.NamedTuple("A", [("b", str), ("c", str)]) a = A._make(["hello", "world"]) b = A._make(["hello", "world"], len=len) - c = A._make([1, 2]) # Should fail - d = A._make(A) # Should fail + c = A._make([1, 2]) # wrong-arg-types + d = A._make(A) # wrong-arg-types def f(e: A) -> None: pass f(a) """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (6, "wrong-arg-types")]) def test_subclass(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing A = typing.NamedTuple("A", [("b", str), ("c", int)]) class B(A): @@ -36,15 +33,12 @@ def take_b(b: B) -> None: pass take_a(x) take_b(x) take_b(y) - take_b(A("", 0)) # Should fail - B() # Should fail + take_b(A("", 0)) # wrong-arg-types + B() # missing-parameter # _make and _replace should return instances of the subclass. take_b(B._make(["hello", 0])) take_b(y._replace(b="world")) """) - self.assertErrorLogIs(errors, [ - (13, "wrong-arg-types"), - (14, "missing-parameter")]) def test_callable_attribute(self): ty = self.Infer(""" @@ -59,13 +53,13 @@ def foo(x: X): def test_bare_union_attribute(self): ty, errors = self.InferWithErrors("""\ from typing import NamedTuple, Union - X = NamedTuple("X", [("x", Union)]) + X = NamedTuple("X", [("x", Union)]) # invalid-annotation[e] def foo(x: X): return x.x """) self.assertMultiLineEqual(pytd_utils.Print(ty.Lookup("foo")), "def foo(x: X) -> Any: ...") - self.assertErrorLogIs(errors, [(2, "invalid-annotation", r"Union.*x")]) + self.assertErrorRegexes(errors, {"e": r"Union.*x"}) class NamedTupleTestPy3(test_base.TargetPython3FeatureTest): @@ -124,22 +118,21 @@ def test_bad_call(self): _, errorlog = self.InferWithErrors("""\ from typing import NamedTuple E2 = NamedTuple('Employee2', [('name', str), ('id', int)], - birth=str, gender=bool) + birth=str, gender=bool) # invalid-namedtuple-arg[e1] # wrong-keyword-args[e2] """) - self.assertErrorLogIs(errorlog, [ - (3, "invalid-namedtuple-arg", "Either list of fields or keywords.*"), - (3, "wrong-keyword-args", ".*(birth, gender).*NamedTuple")]) + self.assertErrorRegexes(errorlog, { + "e1": r"Either list of fields or keywords.*", + "e2": r".*(birth, gender).*NamedTuple"}) def test_bad_attribute(self): _, errorlog = self.InferWithErrors("""\ from typing import NamedTuple - class SubCls(NamedTuple): + class SubCls(NamedTuple): # not-writable[e] def __init__(self): pass """) - self.assertErrorLogIs(errorlog, [ - (3, "not-writable", ".*'__init__'.*[SubCls]")]) + self.assertErrorRegexes(errorlog, {"e": r".*'__init__'.*[SubCls]"}) def test_bad_arg_count(self): _, errorlog = self.InferWithErrors("""\ @@ -149,23 +142,20 @@ class SubCls(NamedTuple): a: int b: int - cls1 = SubCls(5) + cls1 = SubCls(5) # missing-parameter[e] """) - self.assertErrorLogIs(errorlog, [ - (7, "missing-parameter", "Missing.*'b'.*__new__")]) + self.assertErrorRegexes(errorlog, {"e": r"Missing.*'b'.*__new__"}) def test_bad_arg_name(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import NamedTuple - class SubCls(NamedTuple): + class SubCls(NamedTuple): # invalid-namedtuple-arg _a: int b: int cls1 = SubCls(5) """) - self.assertErrorLogIs(errorlog, [ - (3, "invalid-namedtuple-arg")]) def test_namedtuple_class(self): self.Check("""\ diff --git a/pytype/tests/py3/test_variable_annotations.py b/pytype/tests/py3/test_variable_annotations.py index 74be589cb..a9b0706cb 100644 --- a/pytype/tests/py3/test_variable_annotations.py +++ b/pytype/tests/py3/test_variable_annotations.py @@ -23,13 +23,11 @@ def f(x: int) -> None: pass obj = foo.A() f(foo.x) - f(foo.y) + f(foo.y) # wrong-arg-types[e1] f(obj.a) - f(obj.b) + f(obj.b) # wrong-arg-types[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types", r"int.*List"), - (8, "wrong-arg-types", r"int.*str")]) + self.assertErrorRegexes(errors, {"e1": r"int.*List", "e2": r"int.*str"}) class VariableAnnotationsFeatureTest(test_base.TargetPython3FeatureTest): @@ -66,21 +64,19 @@ def testIllegalAnnotations(self): T = TypeVar('T') - a: "abc" = "1" - b: 123 = "2" - c: NoReturn = "3" + a: "abc" = "1" # name-error[e1] + b: 123 = "2" # invalid-annotation[e2] + c: NoReturn = "3" # invalid-annotation[e3] d: List[int] = [] - e: List[T] = [] - f: int if __random__ else str = 123 - h: NoReturn = None - """) - self.assertErrorLogIs(errors, [ - (5, "name-error", "Name \'abc\' is not defined"), - (6, "invalid-annotation", "Not a type"), - (7, "invalid-annotation", "NoReturn is not allowed"), - (9, "not-supported-yet", r"type parameter.*variable annotation"), - (10, "invalid-annotation", r"Type must be constant"), - (11, "invalid-annotation", r"NoReturn is not allowed")]) + e: List[T] = [] # not-supported-yet[e4] + f: int if __random__ else str = 123 # invalid-annotation[e5] + h: NoReturn = None # invalid-annotation[e6] + """) + self.assertErrorRegexes(errors, { + "e1": r"Name \'abc\' is not defined", "e2": r"Not a type", + "e3": r"NoReturn is not allowed", + "e4": r"type parameter.*variable annotation", + "e5": r"Type must be constant", "e6": r"NoReturn is not allowed"}) def testUninitializedClassAnnotation(self): ty = self.Infer(""" @@ -108,10 +104,9 @@ def testUninitializedModuleAnnotation(self): def testOverwriteAnnotationsDict(self): errors = self.CheckWithErrors("""\ __annotations__ = None - foo: int + foo: int # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(2, "unsupported-operands", r"None.*__setitem__")]) + self.assertErrorRegexes(errors, {"e": r"None.*__setitem__"}) def testShadowNone(self): ty = self.Infer(""" diff --git a/pytype/tests/test_abc.py b/pytype/tests/test_abc.py index 6b1a82006..1811989c2 100644 --- a/pytype/tests/test_abc.py +++ b/pytype/tests/test_abc.py @@ -17,21 +17,19 @@ def foo(self) -> None: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.Example() + foo.Example() # not-instantiable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", - r"foo\.Example.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Example.*foo"}) def test_stray_abstractmethod(self): _, errors = self.InferWithErrors("""\ import abc - class Example(object): + class Example(object): # ignored-abstractmethod[e] @abc.abstractmethod def foo(self): pass """) - self.assertErrorLogIs(errors, [(2, "ignored-abstractmethod", - r"foo.*Example")]) + self.assertErrorRegexes(errors, {"e": r"foo.*Example"}) def test_multiple_inheritance_implementation_pyi(self): with file_utils.Tempdir() as d: @@ -62,9 +60,9 @@ class Foo(X, Interface): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.Foo().foo() + foo.Foo().foo() # not-instantiable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "not-instantiable", r"foo\.Foo.*foo")]) + self.assertErrorRegexes(errors, {"e": r"foo\.Foo.*foo"}) def test_abc_metaclass_from_decorator(self): with file_utils.Tempdir() as d: @@ -108,10 +106,9 @@ def test_misplaced_abstractproperty(self): @abc.abstractproperty class Example(object): pass - Example() + Example() # not-callable[e] """) - self.assertErrorLogIs(errors, - [(5, "not-callable", r"'abstractproperty' object")]) + self.assertErrorRegexes(errors, {"e": r"'abstractproperty' object"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_attr.py b/pytype/tests/test_attr.py index 7c0435ff3..1bf3ef6fb 100644 --- a/pytype/tests/test_attr.py +++ b/pytype/tests/test_attr.py @@ -140,24 +140,22 @@ def __init__(self, x: int, y: str) -> None: ... """) def test_type_clash(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s - class Foo(object): + class Foo(object): # invalid-annotation x = attr.ib(type=str) # type: int y = attr.ib(type=str, default="") # type: int Foo(x="") # should not report an error """) - self.assertErrorLogIs(errors, [(4, "invalid-annotation")]) def test_bad_type(self): - errors = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s class Foo(object): - x = attr.ib(type=10) + x = attr.ib(type=10) # invalid-annotation """) - self.assertErrorLogIs(errors, [(5, "invalid-annotation")]) def test_name_mangling(self): # NOTE: Python itself mangles names starting with two underscores. @@ -276,21 +274,20 @@ def test_bad_factory(self): import attr @attr.s class Foo(object): - x = attr.ib(default=attr.Factory(42)) - y = attr.ib(factory=42) + x = attr.ib(default=attr.Factory(42)) # wrong-arg-types[e1] + y = attr.ib(factory=42) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"Callable.*int"), - (5, "wrong-arg-types", r"Callable.*int")]) + self.assertErrorRegexes(errors, {"e1": r"Callable.*int", + "e2": r"Callable.*int"}) def test_default_factory_clash(self): errors = self.CheckWithErrors("""\ import attr @attr.s class Foo(object): - x = attr.ib(default=None, factory=list) + x = attr.ib(default=None, factory=list) # duplicate-keyword-argument[e] """) - self.assertErrorLogIs( - errors, [(4, "duplicate-keyword-argument", r"default")]) + self.assertErrorRegexes(errors, {"e": r"default"}) def test_takes_self(self): ty = self.Infer(""" @@ -388,18 +385,17 @@ def test_init_bad_constant(self): import attr @attr.s class Foo(object): - x = attr.ib(init=0) + x = attr.ib(init=0) # wrong-arg-types[e] """) - self.assertErrorLogIs(err, [(4, "wrong-arg-types", r"bool.*int")]) + self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_init_bad_kwarg(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr @attr.s class Foo: - x = attr.ib(init=__random__) # type: str + x = attr.ib(init=__random__) # type: str # not-supported-yet """) - self.assertErrorLogIs(err, [(5, "not-supported-yet")]) def test_class(self): self.assertNoCrash(self.Check, """ @@ -605,20 +601,19 @@ class Foo(object): def test_init_bad_constant(self): err = self.CheckWithErrors("""\ import attr - @attr.s(init=0) + @attr.s(init=0) # wrong-arg-types[e] class Foo: pass """) - self.assertErrorLogIs(err, [(2, "wrong-arg-types", r"bool.*int")]) + self.assertErrorRegexes(err, {"e": r"bool.*int"}) def test_bad_kwarg(self): - err = self.CheckWithErrors(""" + self.CheckWithErrors("""\ import attr - @attr.s(init=__random__) + @attr.s(init=__random__) # not-supported-yet class Foo: pass """) - self.assertErrorLogIs(err, [(3, "not-supported-yet")]) def test_depth(self): self.Check(""" diff --git a/pytype/tests/test_attributes.py b/pytype/tests/test_attributes.py index 5cd63d923..5b6719e8d 100644 --- a/pytype/tests/test_attributes.py +++ b/pytype/tests/test_attributes.py @@ -26,9 +26,9 @@ def testClassConstantError(self): errors = self.CheckWithErrors("""\ x = None class Foo(object): - x = x.upper() + x = x.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMultiplePaths(self): errors = self.CheckWithErrors("""\ @@ -36,9 +36,9 @@ def testMultiplePaths(self): def f(): z = None if __random__ else x y = z - return y.upper() + return y.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testLateInitialization(self): ty = self.Infer(""" @@ -86,9 +86,9 @@ def testReturnValue(self): def f(): pass def g(): - return f().upper() + return f().upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testMethodReturnValue(self): errors = self.CheckWithErrors("""\ @@ -96,9 +96,9 @@ class Foo(object): def f(self): pass def g(): - return Foo().f().upper() + return Foo().f().upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testPyiReturnValue(self): with file_utils.Tempdir() as d: @@ -106,18 +106,18 @@ def testPyiReturnValue(self): errors = self.CheckWithErrors("""\ import foo def g(): - return foo.f().upper() + return foo.f().upper() # attribute-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testPassThroughNone(self): errors = self.CheckWithErrors("""\ def f(x): return x def g(): - return f(None).upper() + return f(None).upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testShadowedLocalOrigin(self): self.Check(""" @@ -155,20 +155,19 @@ def g(): def testUnpackedNone(self): errors = self.CheckWithErrors("""\ _, a = 42, None - b = a.upper() + b = a.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*None")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None"}) def testFunctionDefault(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self, v=None): - v.upper() + v.upper() # attribute-error[e] def f(): Foo() """) - self.assertErrorLogIs( - errors, [(3, "attribute-error", r"upper.*None.*traceback.*line 5")]) + self.assertErrorRegexes(errors, {"e": r"upper.*None.*traceback.*line 5"}) def testKeepNoneReturn(self): ty = self.Infer(""" @@ -252,10 +251,9 @@ def testGetItem(self): errors = self.CheckWithErrors("""\ def f(): x = None - return x[0] + return x[0] # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(3, "unsupported-operands", r"item retrieval.*None.*int")]) + self.assertErrorRegexes(errors, {"e": r"item retrieval.*None.*int"}) def testIgnoreGetItem(self): self.Check(""" @@ -275,10 +273,9 @@ def testContains(self): errors = self.CheckWithErrors("""\ def f(): x = None - return 42 in x + return 42 in x # unsupported-operands[e] """) - self.assertErrorLogIs( - errors, [(3, "unsupported-operands", r"'in'.*None.*int")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*None.*int"}) def testIgnoreContains(self): self.Check(""" @@ -500,13 +497,13 @@ def f(x) -> Any @test_base.skip("TODO(b/63407497): implement strict checking for __setitem__") def testUnionSetAttribute(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ class A(object): x = "Hello world" def f(i): t = A() l = [t] - l[i].x = 1 # line 6 + l[i].x = 1 # not-writable return l[i].x """) self.assertTypesMatchPytd(ty, """ @@ -515,7 +512,6 @@ class A(object): x = ... # type: str def f(i) -> Any """) - self.assertErrorLogIs(errors, [(6, "not-writable")]) def testSetClass(self): ty = self.Infer(""" @@ -591,9 +587,9 @@ def testHasDynamicAttributesClassAttr(self): errors = self.CheckWithErrors("""\ class Foo(object): _HAS_DYNAMIC_ATTRIBUTES = True - Foo.CONST + Foo.CONST # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", "CONST.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"CONST.*Foo"}) def testHasDynamicAttributesMetaclass(self): # Since class attributes of Foo are instance attributes for the metaclass, @@ -657,21 +653,19 @@ def testModuleTypeAttribute(self): """) def testAttrOnNone(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(arg): x = "foo" if arg else None if not x: - x.upper() + x.upper() # attribute-error """) - self.assertErrorLogIs(errors, [(4, "attribute-error")]) def testIteratorOnNone(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): pass - a, b = f() + a, b = f() # attribute-error """) - self.assertErrorLogIs(errors, [(3, "attribute-error")]) def testOverloadedBuiltin(self): self.Check(""" @@ -722,10 +716,10 @@ def __init__(self) -> None: ... def testBadIter(self): errors = self.CheckWithErrors("""\ v = [] if __random__ else 42 - for _ in v: + for _ in v: # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"__iter__.*int")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*int"}) def testBadGetItem(self): errors = self.CheckWithErrors("""\ @@ -733,11 +727,10 @@ class Foo(object): def __getitem__(self, x): return 0 v = Foo() if __random__ else 42 - for _ in v: # line 5 + for _ in v: # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(5, "attribute-error", - r"__iter__.*int.*Union\[Foo, int\]")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*int.*Union\[Foo, int\]"}) def testBadContains(self): errors = self.CheckWithErrors("""\ @@ -745,12 +738,11 @@ class Foo(object): def __iter__(self): return iter([]) v = Foo() if __random__ else 42 - if 42 in v: # line 5 + if 42 in v: # unsupported-operands[e] pass """) - self.assertErrorLogIs( - errors, [(5, "unsupported-operands", - r"'in'.*'Union\[Foo, int\]' and 'int'")]) + self.assertErrorRegexes( + errors, {"e": r"'in'.*'Union\[Foo, int\]' and 'int'"}) def testSubclassShadowing(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_basic.py b/pytype/tests/test_basic.py index 17ee2304e..493c7e63c 100644 --- a/pytype/tests/test_basic.py +++ b/pytype/tests/test_basic.py @@ -245,24 +245,22 @@ def test_attribute_inplace_ops(self): """) def test_deleting_names(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ g = 17 assert g == 17 del g - g + g # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) def test_deleting_local_names(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def f(): l = 23 assert l == 23 del l - l + l # name-error f() """) - self.assertErrorLogIs(errors, [(5, "name-error")]) def test_import(self): self.Check("""\ @@ -317,9 +315,9 @@ def __init__(self, x): def meth(self, y): return self.x * y thing1 = Thing(2) - print(Thing.meth(14)) + print(Thing.meth(14)) # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(7, "missing-parameter", r"self")]) + self.assertErrorRegexes(errors, {"e": r"self"}) def test_calling_subclass_methods(self): self.Check("""\ @@ -345,9 +343,9 @@ def bar(self): return 9 st = SubThing() - print(st.foo()) + print(st.foo()) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(10, "attribute-error", r"foo.*SubThing")]) + self.assertErrorRegexes(errors, {"e": r"foo.*SubThing"}) def test_attribute_access(self): self.Check("""\ @@ -368,9 +366,9 @@ class Thing(object): def __init__(self): self.x = 23 t = Thing() - print(t.xyzzy) + print(t.xyzzy) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(6, "attribute-error", r"xyzzy.*Thing")]) + self.assertErrorRegexes(errors, {"e": r"xyzzy.*Thing"}) def test_staticmethods(self): self.Check("""\ @@ -488,15 +486,14 @@ def baz(): """) def test_delete_global(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ a = 3 def f(): global a del a f() - x = a + x = a # name-error """) - self.assertErrorLogIs(errors, [(6, "name-error")]) def test_string(self): self.Check("v = '\\xff'") diff --git a/pytype/tests/test_builtins1.py b/pytype/tests/test_builtins1.py index 05fc2c3ad..381d5760c 100644 --- a/pytype/tests/test_builtins1.py +++ b/pytype/tests/test_builtins1.py @@ -114,8 +114,8 @@ def t_testMax2(x, y) -> ? """) def testZipError(self): - errors = self.CheckWithErrors("zip([], [], [], 42)") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", "Iterable.*int")]) + errors = self.CheckWithErrors("zip([], [], [], 42) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Iterable.*int"}) def testDictDefaults(self): ty = self.Infer(""" @@ -316,9 +316,8 @@ def f(x) -> str """) def testOpenError(self): - src = "open(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)" - errors = self.CheckWithErrors(src) - self.assertErrorLogIs(errors, [(1, "wrong-arg-count")]) + src = "open(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) # wrong-arg-count" + self.CheckWithErrors(src) def testSignal(self): ty = self.Infer(""" diff --git a/pytype/tests/test_builtins2.py b/pytype/tests/test_builtins2.py index 6569594d2..5b9e646d2 100644 --- a/pytype/tests/test_builtins2.py +++ b/pytype/tests/test_builtins2.py @@ -349,9 +349,9 @@ def testReversed(self): x2 = reversed([42]) x3 = reversed((4, 2)) x4 = reversed("hello") - x5 = reversed({42}) - x6 = reversed(frozenset([42])) - x7 = reversed({True: 42}) + x5 = reversed({42}) # wrong-arg-types[e1] + x6 = reversed(frozenset([42])) # wrong-arg-types[e2] + x7 = reversed({True: 42}) # wrong-arg-types[e3] x8 = next(reversed([42])) x9 = list(reversed([42])) """) @@ -367,10 +367,9 @@ def testReversed(self): x8 = ... # type: int x9 = ... # type: List[int] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-types", r"Set\[int\]"), - (6, "wrong-arg-types", r"FrozenSet\[int\]"), - (7, "wrong-arg-types", - r"Dict\[bool, int\]")]) + self.assertErrorRegexes(errors, {"e1": r"Set\[int\]", + "e2": r"FrozenSet\[int\]", + "e3": r"Dict\[bool, int\]"}) def testStrJoin(self): ty = self.Infer(""" @@ -398,13 +397,11 @@ def testReduce(self): _, errors = self.InferWithErrors("""\ reduce(lambda x, y: x+y, [1,2,3]).real reduce(lambda x, y: x+y, ["foo"]).upper() - reduce(lambda x, y: 4, "foo").real + reduce(lambda x, y: 4, "foo").real # attribute-error[e] reduce(lambda x, y: 4, [], "foo").upper() reduce(lambda x, y: "s", [1,2,3], 0).upper() """) - self.assertErrorLogIs(errors, [ - (3, "attribute-error", "real.*str") - ]) + self.assertErrorRegexes(errors, {"e": r"real.*str"}) def testDictPopItem(self): ty = self.Infer(""" diff --git a/pytype/tests/test_builtins3.py b/pytype/tests/test_builtins3.py index e3c9ec948..06d51739d 100644 --- a/pytype/tests/test_builtins3.py +++ b/pytype/tests/test_builtins3.py @@ -66,12 +66,13 @@ def testNextFunction(self): """) def testImplicitTypeVarImport(self): - ty, errors = self.InferWithErrors("v = " + abstract_utils.T) + ty, _ = self.InferWithErrors("""\ + v = %s # name-error + """ % abstract_utils.T) self.assertTypesMatchPytd(ty, """ from typing import Any v = ... # type: Any """) - self.assertErrorLogIs(errors, [(1, "name-error")]) def testExplicitTypeVarImport(self): self.Check(""" @@ -128,9 +129,9 @@ def testIntInit(self): int("0", 10) int(u"0") int(u"0", 10) - int(0, 1, 2) # line 7: wrong argcount + int(0, 1, 2) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(7, "wrong-arg-count", r"1.*4")]) + self.assertErrorRegexes(errors, {"e": r"1.*4"}) def testNewlines(self): with file_utils.Tempdir() as d: @@ -206,21 +207,15 @@ def testBuiltins(self): """) def testSpecialBuiltinTypes(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ isinstance(1, int) - isinstance(1, "no") + isinstance(1, "no") # wrong-arg-types issubclass(int, object) - issubclass(0, 0) - issubclass(int, 0) + issubclass(0, 0) # wrong-arg-types + issubclass(int, 0) # wrong-arg-types hasattr(str, "upper") - hasattr(int, int) + hasattr(int, int) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types"), - (4, "wrong-arg-types"), - (5, "wrong-arg-types"), - (7, "wrong-arg-types"), - ]) def testUnpackList(self): ty = self.Infer(""" @@ -278,8 +273,8 @@ def testFromHex(self): """) def testNoneLength(self): - errors = self.CheckWithErrors("len(None)") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"Sized.*None")]) + errors = self.CheckWithErrors("len(None) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Sized.*None"}) def testSequenceLength(self): self.Check(""" @@ -351,8 +346,8 @@ def testInput(self): def testSetDefaultError(self): ty, errors = self.InferWithErrors("""\ x = {} - y = x.setdefault() - z = x.setdefault(1, 2, 3, *[]) + y = x.setdefault() # wrong-arg-count[e1] + z = x.setdefault(1, 2, 3, *[]) # wrong-arg-count[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict @@ -360,8 +355,7 @@ def testSetDefaultError(self): y = ... # type: Any z = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "wrong-arg-count", "2.*0"), - (3, "wrong-arg-count", "2.*3")]) + self.assertErrorRegexes(errors, {"e1": r"2.*0", "e2": r"2.*3"}) def testTuple(self): ty = self.Infer(""" diff --git a/pytype/tests/test_calls.py b/pytype/tests/test_calls.py index e319b30ce..34fc22670 100644 --- a/pytype/tests/test_calls.py +++ b/pytype/tests/test_calls.py @@ -24,22 +24,20 @@ def testMissing(self): d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1) + mod.foo(1) # missing-parameter """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter")]) def testExtraneous(self): with file_utils.Tempdir() as d: d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1, 2, 3) + mod.foo(1, 2, 3) # wrong-arg-count """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-count")]) def testMissingKwOnly(self): with file_utils.Tempdir() as d: @@ -48,20 +46,19 @@ def foo(x, y, *, z) -> int """) _, errors = self.InferWithErrors("""\ import mod - mod.foo(1, 2) + mod.foo(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) def testExtraKeyword(self): with file_utils.Tempdir() as d: d.create_file("mod.pyi", """ def foo(x, y) -> int """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import mod - mod.foo(1, 2, z=3) + mod.foo(1, 2, z=3) # wrong-keyword-args """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-keyword-args")]) def testVarArgsWithKwOnly(self): with file_utils.Tempdir() as d: @@ -79,12 +76,11 @@ def testVarArgsWithMissingKwOnly(self): d.create_file("mod.pyi", """ def foo(*args: int, z: int) -> int """) - _, errors = self.InferWithErrors( - """\ + _, errors = self.InferWithErrors("""\ import mod - mod.foo(1, 2, 3) + mod.foo(1, 2, 3) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"\bz\b")]) + self.assertErrorRegexes(errors, {"e": r"\bz\b"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_classes.py b/pytype/tests/test_classes.py index b691c65e7..a59eca1dc 100644 --- a/pytype/tests/test_classes.py +++ b/pytype/tests/test_classes.py @@ -215,9 +215,9 @@ def __init__(self, x, y, z): pass class Foo(Base): def __init__(self, x): - super(Foo, self).__init__() + super(Foo, self).__init__() # missing-parameter[e] """) - self.assertErrorLogIs(errors, [(6, "missing-parameter", r"x")]) + self.assertErrorRegexes(errors, {"e": r"x"}) def testSuperInInit(self): ty = self.Infer(""" @@ -899,25 +899,24 @@ def f() -> C[int]: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f() + foo.f() # mro-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"C")]) + self.assertErrorRegexes(errors, {"e": r"C"}) def testCallParameterizedClass(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import List - List[str]() - """) - self.assertErrorLogIs(errors, [(2, "not-callable")]) + List[str]() # not-callable + """) def testErrorfulConstructors(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ class Foo(object): attr = 42 def __new__(cls): - return name_error + return name_error # name-error def __init__(self): - self.attribute_error + self.attribute_error # attribute-error self.instance_attr = self.attr def f(self): return self.instance_attr @@ -930,7 +929,6 @@ class Foo(object): def __new__(cls) -> Any: ... def f(self) -> int: ... """) - self.assertErrorLogIs(errors, [(4, "name-error"), (6, "attribute-error")]) def testNewFalse(self): ty = self.Infer("""\ @@ -1032,28 +1030,28 @@ def testSuperNewWrongArgCount(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls, x): - return super(Foo, cls).__new__(cls, x) + return super(Foo, cls).__new__(cls, x) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperInitWrongArgCount(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __init__(self, x): - super(Foo, self).__init__(x) + super(Foo, self).__init__(x) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def testSuperNewMissingParameter(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __new__(cls, x): # Even when __init__ is defined, too few args is an error. - return super(Foo, cls).__new__() + return super(Foo, cls).__new__() # missing-parameter[e] def __init__(self, x): pass """, deep=True) - self.assertErrorLogIs(errors, [(4, "missing-parameter", r"cls.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"cls.*__new__"}) def testNewKwarg(self): _, errors = self.InferWithErrors("""\ @@ -1065,9 +1063,9 @@ def __init__(self): pass class Bar(object): def __new__(cls): - return super(Bar, cls).__new__(cls, x=42) # bad! + return super(Bar, cls).__new__(cls, x=42) # wrong-keyword-args[e] """, deep=True) - self.assertErrorLogIs(errors, [(9, "wrong-keyword-args", r"x.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"x.*__new__"}) def testInitKwarg(self): _, errors = self.InferWithErrors("""\ @@ -1079,9 +1077,9 @@ def __new__(cls): return super(Foo, cls).__new__(cls) class Bar(object): def __init__(self): - super(Bar, self).__init__(x=42) # bad! + super(Bar, self).__init__(x=42) # wrong-keyword-args[e] """, deep=True) - self.assertErrorLogIs(errors, [(9, "wrong-keyword-args", r"x.*__init__")]) + self.assertErrorRegexes(errors, {"e": r"x.*__init__"}) def testAliasInnerClass(self): ty = self.Infer(""" @@ -1130,14 +1128,13 @@ def testInstantiateWithAbstractDict(self): """) def testNotInstantiable(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): def __new__(cls): assert cls is not Foo, "not instantiable" def foo(self): - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(5, "name-error")]) def testMetaclassOnUnknownClass(self): self.Check(""" diff --git a/pytype/tests/test_cmp.py b/pytype/tests/test_cmp.py index ecbc1af20..297122b42 100644 --- a/pytype/tests/test_cmp.py +++ b/pytype/tests/test_cmp.py @@ -10,7 +10,7 @@ class InTest(test_base.TargetIndependentTest): def test_concrete(self): ty, errors = self.InferWithErrors("""\ def f(x, y): - return x in y + return x in y # unsupported-operands[e] f(1, [1]) f(1, [2]) f("x", "x") @@ -19,8 +19,7 @@ def f(x, y): f("y", object()) """, deep=False, show_library_calls=True) self.assertOnlyHasReturnType(ty.Lookup("f"), self.bool) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"'in'.*object")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*object"}) def test_deep(self): ty = self.Infer(""" @@ -50,12 +49,11 @@ def g() -> bool def test_none(self): _, errors = self.InferWithErrors("""\ x = None - if "" in x: - del x[""] + if "" in x: # unsupported-operands[e1] + del x[""] # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [ - (2, "unsupported-operands", r"'in'.*None"), - (3, "unsupported-operands", r"item deletion.*None")]) + self.assertErrorRegexes( + errors, {"e1": r"'in'.*None", "e2": r"item deletion.*None"}) class NotInTest(test_base.TargetIndependentTest): @@ -64,7 +62,7 @@ class NotInTest(test_base.TargetIndependentTest): def test_concrete(self): ty, errors = self.InferWithErrors("""\ def f(x, y): - return x not in y + return x not in y # unsupported-operands[e] f(1, [1]) f(1, [2]) f("x", "x") @@ -73,8 +71,7 @@ def f(x, y): f("y", object()) """, deep=False, show_library_calls=True) self.assertOnlyHasReturnType(ty.Lookup("f"), self.bool) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"'in'.*object")]) + self.assertErrorRegexes(errors, {"e": r"'in'.*object"}) # "not in" maps to the inverse of __contains__ def test_overloaded(self): @@ -98,12 +95,11 @@ def g() -> bool def test_none(self): _, errors = self.InferWithErrors("""\ x = None - if "" not in x: - x[""] = 42 + if "" not in x: # unsupported-operands[e1] + x[""] = 42 # unsupported-operands[e2] """) - self.assertErrorLogIs(errors, [ - (2, "unsupported-operands", r"'in'.*None"), - (3, "unsupported-operands", r"item assignment.*None")]) + self.assertErrorRegexes( + errors, {"e1": r"'in'.*None", "e2": r"item assignment.*None"}) class IsTest(test_base.TargetIndependentTest): diff --git a/pytype/tests/test_compile_to_pyc.py b/pytype/tests/test_compile_to_pyc.py index 93af1f606..e98fdbf1f 100644 --- a/pytype/tests/test_compile_to_pyc.py +++ b/pytype/tests/test_compile_to_pyc.py @@ -5,6 +5,7 @@ class CompileToPycTest(test_base.TargetIndependentTest): + """Tests for compilation to bytecode.""" def testCompilationOfUnicodeSource(self): self.Check("print('←↑→↓')") @@ -14,20 +15,18 @@ def testCompilationOfUnicodeSourceWithEncoding(self): self.Check("#! my/python\n# encoding: utf-8\nprint('←↑→↓')") def testErrorLineNumbersWithEncoding1(self): - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ # coding: utf-8 def foo(): - return "1".hello + return "1".hello # attribute-error """) - self.assertErrorLogIs(errorlog, [(3, "attribute-error")]) def testErrorLineNumbersWithEncoding2(self): - errorlog = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ #! /bin/python # coding: utf-8 def foo(): - return "1".hello + return "1".hello # attribute-error """) - self.assertErrorLogIs(errorlog, [(4, "attribute-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_containers.py b/pytype/tests/test_containers.py index 0b3dc9f30..85bbcf443 100644 --- a/pytype/tests/test_containers.py +++ b/pytype/tests/test_containers.py @@ -544,11 +544,11 @@ def testEqOperatorOnItemFromEmptyDict(self): """, deep=False) def testDict(self): - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ mymap = {'a': 3.14, 'b':1} a = mymap['a'] b1 = mymap['b'] - c = mymap['foobar'] + c = mymap['foobar'] # key-error[e] mymap[str()] = 3j b2 = mymap['b'] """, deep=True) @@ -560,9 +560,7 @@ def testDict(self): c = ... # type: Any b2 = ... # type: Union[int, float, complex] """) - self.assertErrorLogIs(errors, [ - (5, "key-error", "foobar") - ]) + self.assertErrorRegexes(errors, {"e": r"foobar"}) def testDictOrAny(self): self.Check(""" @@ -577,9 +575,9 @@ def testDictOrAny(self): def testDictGetItem(self): _, errors = self.InferWithErrors("""\ v = {} - v.__getitem__("a") + v.__getitem__("a") # key-error[e] """) - self.assertErrorLogIs(errors, [(2, "key-error", r"'a'")]) + self.assertErrorRegexes(errors, {"e": r"'a'"}) def testEmptyList(self): ty = self.Infer(""" diff --git a/pytype/tests/test_decorators.py b/pytype/tests/test_decorators.py index dd914c264..21c79c1a0 100644 --- a/pytype/tests/test_decorators.py +++ b/pytype/tests/test_decorators.py @@ -88,9 +88,9 @@ def __init__(self): self._bar = 1 def _SetBar(self, value): self._bar = value - bar = property(should_fail=_SetBar) + bar = property(should_fail=_SetBar) # wrong-keyword-args[e] """) - self.assertErrorLogIs(errors, [(6, "wrong-keyword-args", r"should_fail")]) + self.assertErrorRegexes(errors, {"e": r"should_fail"}) def testFgetIsOptional(self): self.Check(""" @@ -302,12 +302,12 @@ def __call__(self, func): return func class Foo(object): @classmethod - @Decorate # forgot to instantiate Decorate + @Decorate # forgot to instantiate Decorate # wrong-arg-count[e] def bar(cls): pass Foo.bar() """) - self.assertErrorLogIs(errors, [(6, "wrong-arg-count", r"Decorate.*1.*2")]) + self.assertErrorRegexes(errors, {"e": r"Decorate.*1.*2"}) def testUncallableInstanceAsDecorator(self): errors = self.CheckWithErrors("""\ @@ -315,13 +315,13 @@ class Decorate(object): pass # forgot to define __call__ class Foo(object): @classmethod - @Decorate # forgot to instantiate Decorate + @Decorate # forgot to instantiate Decorate # wrong-arg-count[e1] def bar(cls): pass - Foo.bar() + Foo.bar() # not-callable[e2] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-count", r"Decorate.*1.*2"), - (8, "not-callable", r"Decorate")]) + self.assertErrorRegexes( + errors, {"e1": r"Decorate.*1.*2", "e2": r"Decorate"}) def testAmbiguousClassMethod(self): self.Check("""\ diff --git a/pytype/tests/test_dict.py b/pytype/tests/test_dict.py index 2a9a543c2..7da5bea13 100644 --- a/pytype/tests/test_dict.py +++ b/pytype/tests/test_dict.py @@ -24,14 +24,14 @@ def testPop(self): def testBadPop(self): ty, errors = self.InferWithErrors("""\ d = {"a": 42} - v = d.pop("b") + v = d.pop("b") # key-error[e] """) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict d = ... # type: Dict[str, int] v = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "key-error", r"b")]) + self.assertErrorRegexes(errors, {"e": r"b"}) def testAmbiguousPop(self): ty = self.Infer(""" diff --git a/pytype/tests/test_disables.py b/pytype/tests/test_disables.py index b7d80f846..a0b7e269c 100644 --- a/pytype/tests/test_disables.py +++ b/pytype/tests/test_disables.py @@ -8,30 +8,27 @@ class DisableTest(test_base.TargetIndependentTest): def testInvalidDirective(self): _, errors = self.InferWithErrors("""\ - x = 1 # pytype: this is not a valid pytype directive. + x = 1 # pytype: this is not a valid pytype directive. # invalid-directive """) - self.assertErrorLogIs(errors, [(1, "invalid-directive")]) # Invalid directives are just a warning, so has_error() should still # return False. self.assertFalse(errors.has_error()) def testInvalidDisableErrorName(self): _, errors = self.InferWithErrors("""\ - x = 1 # pytype: disable=not-an-error. + x = 1 # pytype: disable=not-an-error. # invalid-directive[e] """) - self.assertErrorLogIs(errors, [(1, "invalid-directive", - r"Invalid error name.*not-an-error")]) + self.assertErrorRegexes(errors, {"e": r"Invalid error name.*not-an-error"}) # Invalid directives are just a warning, so has_error() should still # return False. self.assertFalse(errors.has_error()) def testDisableError(self): - _, errors = self.InferWithErrors("""\ - x = a + self.InferWithErrors("""\ + x = a # name-error x = b # pytype: disable=name-error - x = c + x = c # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (3, "name-error")]) def testOpenEndedDirective(self): """Test that disables in the middle of the file can't be left open-ended.""" @@ -47,16 +44,16 @@ class A(object): CONSTANT = 42 # pytype: disable=not-callable # ok (before first class/function def) def f(x): - # type: ignore # bad + # type: ignore # late-directive[e1] pass def g(): pass x = y # pytype: disable=name-error # ok (single line) # pytype: disable=attribute-error # ok (re-enabled) - # pytype: disable=wrong-arg-types # bad + # pytype: disable=wrong-arg-types # late-directive[e2] # pytype: enable=attribute-error """) - self.assertErrorLogIs(errors, [(12, "late-directive", "Type checking"), - (17, "late-directive", "wrong-arg-types")]) + self.assertErrorRegexes( + errors, {"e1": r"Type checking", "e2": r"wrong-arg-types"}) # late-directive is a warning self.assertFalse(errors.has_error()) diff --git a/pytype/tests/test_errors.py b/pytype/tests/test_errors.py index 886e101f9..89d1e6fde 100644 --- a/pytype/tests/test_errors.py +++ b/pytype/tests/test_errors.py @@ -11,25 +11,25 @@ def testDeduplicate(self): _, errors = self.InferWithErrors("""\ def f(x): y = 42 - y.foobar + y.foobar # attribute-error[e] f(3) f(4) """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"'foobar' on int$")]) + self.assertErrorRegexes(errors, {"e": r"'foobar' on int$"}) def testUnknownGlobal(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ def f(): - return foobar() + return foobar() # name-error[e] """) - self.assertErrorLogIs(errors, [(3, "name-error", r"foobar")]) + self.assertErrorRegexes(errors, {"e": r"foobar"}) def testInvalidAttribute(self): ty, errors = self.InferWithErrors("""\ class A(object): pass def f(): - (3).parrot + (3).parrot # attribute-error[e] return "foo" """) self.assertTypesMatchPytd(ty, """ @@ -38,86 +38,69 @@ class A(object): def f() -> str """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"parrot.*int")]) + self.assertErrorRegexes(errors, {"e": r"parrot.*int"}) def testImportError(self): - _, errors = self.InferWithErrors("""\ - import rumplestiltskin + self.InferWithErrors("""\ + import rumplestiltskin # import-error """) - self.assertErrorLogIs(errors, [(1, "import-error", r"rumplestiltskin")]) def testImportFromError(self): _, errors = self.InferWithErrors("""\ - from sys import foobar + from sys import foobar # import-error[e] """) - self.assertErrorLogIs(errors, [(1, "import-error", r"sys\.foobar")]) + self.assertErrorRegexes(errors, {"e": r"sys\.foobar"}) def testNameError(self): - _, errors = self.InferWithErrors("""\ - foobar + self.InferWithErrors("""\ + foobar # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error", r"foobar")]) def testWrongArgCount(self): _, errors = self.InferWithErrors("""\ - hex(1, 2, 3, 4) + hex(1, 2, 3, 4) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-count", r"expects 1.*got 4")]) + self.assertErrorRegexes(errors, {"e": r"expects 1.*got 4"}) def testWrongArgTypes(self): _, errors = self.InferWithErrors("""\ - hex(3j) + hex(3j) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"int.*complex")]) + self.assertErrorRegexes(errors, {"e": r"int.*complex"}) def testInterpreterFunctionNameInMsg(self): _, errors = self.InferWithErrors("""\ class A(list): pass - A.append(3) + A.append(3) # missing-parameter[e] """) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.append")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.append"}) def testPyTDFunctionNameInMsg(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", "class A(list): pass") _, errors = self.InferWithErrors("""\ import foo - foo.A.append(3) + foo.A.append(3) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.append")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.append"}) def testBuiltinFunctionNameInMsg(self): _, errors = self.InferWithErrors("""\ x = list - x += (1,2) + x += (1,2) # missing-parameter[e] """) - self.assertErrorLogIs( - errors, - [(2, "missing-parameter", r"function list.__iadd__")] - ) + self.assertErrorRegexes(errors, {"e": r"function list\.__iadd__"}) def testRewriteBuiltinFunctionName(self): """Should rewrite `function __builtin__.len` to `built-in function len`.""" - _, errors = self.InferWithErrors("x = len(None)") - self.assertErrorLogIs( - errors, - [(1, "wrong-arg-types", r"Built-in function len")] - ) + _, errors = self.InferWithErrors("x = len(None) # wrong-arg-types[e]") + self.assertErrorRegexes(errors, {"e": r"Built-in function len"}) def testBoundMethodNameInMsg(self): _, errors = self.InferWithErrors("""\ - "".join(1) + "".join(1) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, - [(1, "wrong-arg-types", r"Function str.join")] - ) + self.assertErrorRegexes(errors, {"e": r"Function str\.join"}) def testNestedClassMethodNameIsMsg(self): errors = self.CheckWithErrors("""\ @@ -125,9 +108,9 @@ class A(object): class B(object): def f(self): pass - A.B().f("oops") + A.B().f("oops") # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(5, "wrong-arg-count", r"Function B.f")]) + self.assertErrorRegexes(errors, {"e": r"Function B.f"}) def testPrettyPrintWrongArgs(self): with file_utils.Tempdir() as d: @@ -136,18 +119,16 @@ def f(a: int, b: int, c: int, d: int, e: int): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(1, 2, 3, "four", 5) + foo.f(1, 2, 3, "four", 5) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", ("a, b, c, d: int, [.][.][.].*" - "a, b, c, d: str, [.][.][.]"))]) + self.assertErrorRegexes(errors, { + "e": r"a, b, c, d: int, [.][.][.].*a, b, c, d: str, [.][.][.]"}) def testInvalidBaseClass(self): - _, errors = self.InferWithErrors("""\ - class Foo(3): + self.InferWithErrors("""\ + class Foo(3): # base-class-error pass """) - self.assertErrorLogIs(errors, [(1, "base-class-error")]) def testInvalidIteratorFromImport(self): with file_utils.Tempdir() as d: @@ -155,33 +136,32 @@ def testInvalidIteratorFromImport(self): class Codec(object): def __init__(self) -> None: ... """) - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ import mod def f(): - for row in mod.Codec(): + for row in mod.Codec(): # attribute-error[e] pass """, pythonpath=[d.path]) error = r"No attribute.*__iter__.*on mod\.Codec" - self.assertErrorLogIs(errors, [(4, "attribute-error", error)]) + self.assertErrorRegexes(errors, {"e": error}) def testInvalidIteratorFromClass(self): _, errors = self.InferWithErrors("""\ class A(object): pass def f(): - for row in A(): + for row in A(): # attribute-error[e] pass """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"__iter__.*A")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*A"}) def testIterOnModule(self): errors = self.CheckWithErrors("""\ import sys - for _ in sys: + for _ in sys: # module-attr[e] pass """) - self.assertErrorLogIs( - errors, [(2, "module-attr", r"__iter__.*module 'sys'")]) + self.assertErrorRegexes(errors, {"e": r"__iter__.*module 'sys'"}) def testInheritFromGeneric(self): with file_utils.Tempdir() as d: @@ -193,10 +173,10 @@ class Bar(Foo[int]): ... """) _, errors = self.InferWithErrors("""\ import mod - chr(mod.Bar()) + chr(mod.Bar()) # wrong-arg-types[e] """, pythonpath=[d.path]) # "Line 3, in f: Can't retrieve item out of dict. Empty?" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"int.*mod\.Bar")]) + self.assertErrorRegexes(errors, {"e": r"int.*mod\.Bar"}) def testWrongKeywordArg(self): with file_utils.Tempdir() as d: @@ -206,10 +186,9 @@ def escape(x: str or int) -> str or int _, errors = self.InferWithErrors("""\ import mycgi def foo(s): - return mycgi.escape(s, quote=1) + return mycgi.escape(s, quote=1) # wrong-keyword-args[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", - r"quote.*mycgi\.escape")]) + self.assertErrorRegexes(errors, {"e": r"quote.*mycgi\.escape"}) def testMissingParameter(self): with file_utils.Tempdir() as d: @@ -218,21 +197,19 @@ def bar(xray, yankee, zulu) -> str """) _, errors = self.InferWithErrors("""\ import foo - foo.bar(1, 2) + foo.bar(1, 2) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", - r"zulu.*foo\.bar")]) + self.assertErrorRegexes(errors, {"e": r"zulu.*foo\.bar"}) def testBadInheritance(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class X: pass class Bar(X): pass - class Baz(X, Bar): + class Baz(X, Bar): # mro-error pass """) - self.assertErrorLogIs(errors, [(5, "mro-error")]) def testBadCall(self): with file_utils.Tempdir() as d: @@ -241,24 +218,23 @@ def foo(x: int, y: str) -> str: ... """) _, errors = self.InferWithErrors("""\ import other - other.foo(1.2, []) + other.foo(1.2, []) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"\(x: int")]) + self.assertErrorRegexes(errors, {"e": r"\(x: int"}) def testCallUncallable(self): _, errors = self.InferWithErrors("""\ - 0() + 0() # not-callable[e] """) - self.assertErrorLogIs(errors, [(1, "not-callable", r"int")]) + self.assertErrorRegexes(errors, {"e": r"int"}) def testSuperError(self): _, errors = self.InferWithErrors("""\ class A(object): def __init__(self): - super(A, self, "foo").__init__() + super(A, self, "foo").__init__() # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", "2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def testAttributeError(self): with file_utils.Tempdir() as d: @@ -268,26 +244,23 @@ class Foo(object): def __getattr__(self, name): return "attr" def f(): - return Foo.foo # line 5 + return Foo.foo # attribute-error[e1] def g(x): if x: y = None else: y = 1 - return y.bar # line 11 + return y.bar # attribute-error[e2] # attribute-error[e3] def h(): return Foo().foo # No error import modfoo - modfoo.baz # line 15 + modfoo.baz # module-attr[e4] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (5, "attribute-error", r"No attribute 'foo' on Type\[Foo\]"), - (11, "attribute-error", - r"No attribute 'bar' on None\nIn Optional\[int\]"), - (11, "attribute-error", - r"No attribute 'bar' on int\nIn Optional\[int\]"), - (15, "module-attr", - "No attribute 'baz' on module 'modfoo'")]) + self.assertErrorRegexes(errors, { + "e1": r"No attribute 'foo' on Type\[Foo\]", + "e2": r"No attribute 'bar' on int\nIn Optional\[int\]", + "e3": r"No attribute 'bar' on None\nIn Optional\[int\]", + "e4": r"No attribute 'baz' on module 'modfoo'"}) def testAttributeErrorGetAttribute(self): _, errors = self.InferWithErrors("""\ @@ -297,15 +270,15 @@ def __getattribute__(self, name): def f(): return Foo().x # There should be no error on this line. def g(): - return Foo.x + return Foo.x # attribute-error[e] """) - self.assertErrorLogIs(errors, [(7, "attribute-error", r"x")]) + self.assertErrorRegexes(errors, {"e": r"x"}) def testNoneAttribute(self): _, errors = self.InferWithErrors("""\ - None.foo + None.foo # attribute-error[e] """) - self.assertErrorLogIs(errors, [(1, "attribute-error", r"foo")]) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testPyiType(self): with file_utils.Tempdir() as d: @@ -314,34 +287,33 @@ def f(x: list[int]) -> int: ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f([""]) + foo.f([""]) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", - r"List\[int\].*List\[str\]")]) + self.assertErrorRegexes(errors, {"e": r"List\[int\].*List\[str\]"}) def testTooManyArgs(self): _, errors = self.InferWithErrors("""\ def f(): pass - f(3) + f(3) # wrong-arg-count[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", r"0.*1")]) + self.assertErrorRegexes(errors, {"e": r"0.*1"}) def testTooFewArgs(self): _, errors = self.InferWithErrors("""\ def f(x): pass - f() + f() # missing-parameter[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "missing-parameter", r"x.*f")]) + self.assertErrorRegexes(errors, {"e": r"x.*f"}) def testDuplicateKeyword(self): _, errors = self.InferWithErrors("""\ def f(x, y): pass - f(3, x=3) + f(3, x=3) # duplicate-keyword-argument[e] """, deep=True) - self.assertErrorLogIs(errors, [(3, "duplicate-keyword-argument", r"f.*x")]) + self.assertErrorRegexes(errors, {"e": r"f.*x"}) def testBadImport(self): with file_utils.Tempdir() as d: @@ -349,10 +321,9 @@ def testBadImport(self): def f() -> int: ... class f: ... """) - _, errors = self.InferWithErrors("""\ - import a + self.InferWithErrors("""\ + import a # pyi-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testBadImportDependency(self): with file_utils.Tempdir() as d: @@ -360,10 +331,9 @@ def testBadImportDependency(self): from b import X class Y(X): ... """) - _, errors = self.InferWithErrors("""\ - import a + self.InferWithErrors("""\ + import a # pyi-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testBadImportFrom(self): with file_utils.Tempdir() as d: @@ -373,9 +343,9 @@ class f: ... """) d.create_file("foo/__init__.pyi", "") _, errors = self.InferWithErrors("""\ - from foo import a + from foo import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"foo\.a")]) + self.assertErrorRegexes(errors, {"e": r"foo\.a"}) def testBadImportFromDependency(self): with file_utils.Tempdir() as d: @@ -385,9 +355,9 @@ class Y(X): ... """) d.create_file("foo/__init__.pyi", "") _, errors = self.InferWithErrors("""\ - from foo import a + from foo import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"foo\.a")]) + self.assertErrorRegexes(errors, {"e": r"foo\.a"}) def testBadContainer(self): with file_utils.Tempdir() as d: @@ -396,10 +366,9 @@ def testBadContainer(self): class A(SupportsInt[int]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", - r"SupportsInt is not a container")]) + self.assertErrorRegexes(errors, {"e": r"SupportsInt is not a container"}) def testBadTypeParameterOrder(self): with file_utils.Tempdir() as d: @@ -412,9 +381,9 @@ class B(Generic[K, V]): pass class C(A[K, V], B[V, K]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Illegal.*order.*a\.C")]) + self.assertErrorRegexes(errors, {"e": r"Illegal.*order.*a\.C"}) def testDuplicateTypeParameter(self): with file_utils.Tempdir() as d: @@ -424,9 +393,9 @@ def testDuplicateTypeParameter(self): class A(Generic[T, T]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"T")]) + self.assertErrorRegexes(errors, {"e": r"T"}) def testDuplicateGenericBaseClass(self): with file_utils.Tempdir() as d: @@ -437,9 +406,9 @@ def testDuplicateGenericBaseClass(self): class A(Generic[T], Generic[V]): pass """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"inherit.*Generic")]) + self.assertErrorRegexes(errors, {"e": r"inherit.*Generic"}) def testTypeParameterInModuleConstant(self): with file_utils.Tempdir() as d: @@ -449,9 +418,9 @@ def testTypeParameterInModuleConstant(self): x = ... # type: T """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a.*T.*a\.x")]) + self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.x"}) def testTypeParameterInClassAttribute(self): with file_utils.Tempdir() as d: @@ -464,9 +433,9 @@ class A(Generic[T]): _, errors = self.InferWithErrors("""\ import a def f(): - return a.A.x + return a.A.x # unbound-type-param[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "unbound-type-param", r"x.*A.*T")]) + self.assertErrorRegexes(errors, {"e": r"x.*A.*T"}) def testUnboundTypeParameterInInstanceAttribute(self): with file_utils.Tempdir() as d: @@ -477,9 +446,9 @@ class A(object): x = ... # type: T """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a.*T.*a\.A\.x")]) + self.assertErrorRegexes(errors, {"e": r"a.*T.*a\.A\.x"}) def testPrintUnionArg(self): with file_utils.Tempdir() as d: @@ -488,35 +457,33 @@ def f(x: int or str) -> None """) _, errors = self.InferWithErrors("""\ import a - x = a.f(4.2) + x = a.f(4.2) # wrong-arg-types[e] """, deep=True, pythonpath=[d.path]) pattern = r"Expected.*Union\[int, str\].*Actually passed" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", pattern)]) + self.assertErrorRegexes(errors, {"e": pattern}) def testPrintTypeArg(self): _, errors = self.InferWithErrors("""\ - hex(int) + hex(int) # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs( - errors, [(1, "wrong-arg-types", r"Actually passed.*Type\[int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actually passed.*Type\[int\]"}) def testDeleteFromSet(self): _, errors = self.InferWithErrors("""\ s = {1} - del s[1] + del s[1] # unsupported-operands[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "unsupported-operands", r"item deletion")]) + self.assertErrorRegexes(errors, {"e": r"item deletion"}) def testBadReference(self): ty, errors = self.InferWithErrors("""\ def main(): - x = foo + x = foo # name-error[e] for foo in []: pass return x """, deep=True) - self.assertErrorLogIs(errors, [(2, "name-error", r"foo")]) + self.assertErrorRegexes(errors, {"e": r"foo"}) # Make sure we recovered from the error and got the right return type self.assertTypesMatchPytd(ty, """ from typing import Any @@ -526,9 +493,9 @@ def main() -> Any def testSetIntAttribute(self): _, errors = self.InferWithErrors("""\ x = 42 - x.y = 42 + x.y = 42 # not-writable[e] """, deep=True) - self.assertErrorLogIs(errors, [(2, "not-writable", r"y.*int")]) + self.assertErrorRegexes(errors, {"e": r"y.*int"}) def testInvalidParametersOnMethod(self): with file_utils.Tempdir() as d: @@ -538,54 +505,42 @@ def __init__(self, x: int) -> None """) _, errors = self.InferWithErrors("""\ import a - x = a.A("") - x = a.A("", 42) - x = a.A(42, y="") - x = a.A(42, x=42) - x = a.A() + x = a.A("") # wrong-arg-types[e1] + x = a.A("", 42) # wrong-arg-count[e2] + x = a.A(42, y="") # wrong-keyword-args[e3] + x = a.A(42, x=42) # duplicate-keyword-argument[e4] + x = a.A() # missing-parameter[e5] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"A\.__init__"), - (3, "wrong-arg-count", r"A\.__init__"), - (4, "wrong-keyword-args", r"A\.__init__"), - (5, "duplicate-keyword-argument", - r"A\.__init__"), - (6, "missing-parameter", r"A\.__init__")]) + self.assertErrorRegexes(errors, { + "e1": r"A\.__init__", "e2": r"A\.__init__", "e3": r"A\.__init__", + "e4": r"A\.__init__", "e5": r"A\.__init__"}) def testDuplicateKeywords(self): with file_utils.Tempdir() as d: d.create_file("foo.pyi", """ def f(x, *args, y) -> None """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import foo foo.f(1, y=2) foo.f(1, 2, y=3) - foo.f(1, x=1) + foo.f(1, x=1) # duplicate-keyword-argument # foo.f(y=1, y=2) # caught by compiler """, deep=True, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (4, "duplicate-keyword-argument"), - ]) def testInvalidParametersDetails(self): _, errors = self.InferWithErrors("""\ - float(list()) - float(1, list(), foobar=str) - float(1, foobar=list()) - float(1, x="") - hex() + float(list()) # wrong-arg-types[e1] + float(1, list(), foobar=str) # wrong-arg-count[e2] + float(1, foobar=list()) # wrong-keyword-args[e3] + float(1, x="") # duplicate-keyword-argument[e4] + hex() # missing-parameter[e5] """) - self.assertErrorLogIs(errors, [ - (1, "wrong-arg-types", - r"Actually passed:.*self, x: List\[nothing\]"), - (2, "wrong-arg-count", r"Actually passed:.*self, x, " - r"_, foobar"), - (3, "wrong-keyword-args", - r"Actually passed:.*self, x, foobar"), - (4, "duplicate-keyword-argument", - r"Actually passed:.*self, x, x"), - (5, "missing-parameter", r"Actually passed: \(\)") - ]) + self.assertErrorRegexes(errors, { + "e1": r"Actually passed:.*self, x: List\[nothing\]", + "e2": r"_, foobar", "e3": r"Actually passed:.*self, x, foobar", + "e4": r"Actually passed:.*self, x, x", "e5": r"Actually passed: \(\)", + }) def testBadSuperClass(self): _, errors = self.InferWithErrors("""\ @@ -595,10 +550,9 @@ def f(self): class B(A): def f(self): - return super(self, B).f() # should be super(B, self) + return super(self, B).f() # should be super(B, self) # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs(errors, [ - (7, "wrong-arg-types", r"cls: type.*cls: B")]) + self.assertErrorRegexes(errors, {"e": r"cls: type.*cls: B"}) @test_base.skip("Need to type-check second argument to super") def testBadSuperInstance(self): @@ -607,10 +561,10 @@ class A(object): pass class B(A): def __init__(self): - super(B, A).__init__() # A cannot be the second argument to super + super(B, A).__init__() # A cannot be the second argument to super # wrong-arg-types[e] """, deep=True) - self.assertErrorLogIs( - errors, [(5, "wrong-arg-types", r"Type\[B\].*Type\[A\]")]) + self.assertErrorRegexes( + errors, {"e": r"Type\[B\].*Type\[A\]"}) def testBadNameImport(self): with file_utils.Tempdir() as d: @@ -619,10 +573,10 @@ def testBadNameImport(self): x = ... # type: typing.Rumpelstiltskin """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Rumpelstiltskin")]) + self.assertErrorRegexes(errors, {"e": r"Rumpelstiltskin"}) def testBadNameImportFrom(self): with file_utils.Tempdir() as d: @@ -631,10 +585,10 @@ def testBadNameImportFrom(self): x = ... # type: Rumpelstiltskin """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] x = a.x """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"Rumpelstiltskin")]) + self.assertErrorRegexes(errors, {"e": r"Rumpelstiltskin"}) def testMatchType(self): with file_utils.Tempdir() as d: @@ -649,10 +603,10 @@ def f(x: Type[A]) -> bool import a x = a.f(a.A) y = a.f(a.B) - z = a.f(a.C) + z = a.f(a.C) # wrong-arg-types[e] """, pythonpath=[d.path], deep=True) error = r"Expected.*Type\[a\.A\].*Actual.*Type\[a\.C\]" - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", error)]) + self.assertErrorRegexes(errors, {"e": error}) self.assertTypesMatchPytd(ty, """ from typing import Any a = ... # type: module @@ -672,10 +626,10 @@ def f(x: Type[A[int]]): ... """) _, errors = self.InferWithErrors("""\ import a - x = a.f(a.B) + x = a.f(a.B) # wrong-arg-types[e] """, pythonpath=[d.path], deep=True) expected_error = r"Expected.*Type\[a\.A\[int\]\].*Actual.*Type\[a\.B\]" - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", expected_error)]) + self.assertErrorRegexes(errors, {"e": expected_error}) def testMROError(self): with file_utils.Tempdir() as d: @@ -688,9 +642,9 @@ class E(C, D): ... """) _, errors = self.InferWithErrors("""\ import a - x = a.E() + x = a.E() # mro-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"E")]) + self.assertErrorRegexes(errors, {"e": r"E"}) def testBadMRO(self): with file_utils.Tempdir() as d: @@ -699,10 +653,10 @@ class A(BaseException, ValueError): ... """) _, errors = self.InferWithErrors("""\ import a - class B(a.A): pass + class B(a.A): pass # mro-error[e] raise a.A() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "mro-error", r"A")]) + self.assertErrorRegexes(errors, {"e": r"A"}) def testUnsolvableAsMetaclass(self): with file_utils.Tempdir() as d: @@ -718,9 +672,9 @@ class B(metaclass=A): ... import b class C(b.B): def __init__(self): - f = open(self.x, 'r') + f = open(self.x, 'r') # attribute-error[e] """, pythonpath=[d.path], deep=True) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"x.*C")]) + self.assertErrorRegexes(errors, {"e": r"x.*C"}) def testDontTimeoutOnComplex(self): # Tests that we can solve a complex file without timing out. @@ -749,12 +703,10 @@ def testFailedFunctionCall(self): def f(x: str, y: int) -> bool def f(x: str) -> bool """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import a - x = a.f(0, "") + x = a.f(0, "") # wrong-arg-types """, pythonpath=[d.path]) - # Tests that [wrong-arg-types] rather than [wrong-arg-count] is reported - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"")]) def testNoncomputableMethod(self): with file_utils.Tempdir() as d: @@ -767,36 +719,34 @@ def copy(x: T) -> T class A(object): def __getattribute__(self, name): return a.copy(self) - x = A()() + x = A()() # not-callable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(5, "not-callable", r"A")]) + self.assertErrorRegexes(errors, {"e": r"A"}) def testBadTypeName(self): _, errors = self.InferWithErrors("""\ - X = type(3, (int, object), {"a": 1}) + X = type(3, (int, object), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"Actual.*int")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*int"}) def testBadTypeBases(self): _, errors = self.InferWithErrors("""\ - X = type("X", (42,), {"a": 1}) + X = type("X", (42,), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Tuple\[int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Tuple\[int\]"}) def testHalfBadTypeBases(self): _, errors = self.InferWithErrors("""\ - X = type("X", (42, object), {"a": 1}) + X = type("X", (42, object), {"a": 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Tuple\[int, Type\[object\]\]")]) + self.assertErrorRegexes( + errors, {"e": r"Actual.*Tuple\[int, Type\[object\]\]"}) def testBadTypeMembers(self): _, errors = self.InferWithErrors("""\ - X = type("X", (int, object), {0: 1}) + X = type("X", (int, object), {0: 1}) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", - r"Actual.*Dict\[int, int\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Dict\[int, int\]"}) def testRecursion(self): with file_utils.Tempdir() as d: @@ -806,7 +756,7 @@ class B(A): ... """) ty, errors = self.InferWithErrors("""\ import a - v = a.A() + v = a.A() # recursion-error[e] x = v.x # No error because there is an Unsolvable in the MRO of a.A """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -815,30 +765,29 @@ class B(A): ... v = ... # type: a.A x = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "recursion-error", r"a\.A")]) + self.assertErrorRegexes(errors, {"e": r"a\.A"}) def testEmptyUnionOrOptional(self): with file_utils.Tempdir() as d: - d.create_file("f1.pyi", """\ + d.create_file("f1.pyi", """ def f(x: Union): ... """) - d.create_file("f2.pyi", """\ + d.create_file("f2.pyi", """ def f(x: Optional): ... """) _, errors = self.InferWithErrors("""\ - import f1 - import f2 + import f1 # pyi-error[e1] + import f2 # pyi-error[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"f1.*Union"), - (2, "pyi-error", r"f2.*Optional")]) + self.assertErrorRegexes( + errors, {"e1": r"f1.*Union", "e2": r"f2.*Optional"}) def testBadDictAttribute(self): _, errors = self.InferWithErrors("""\ x = {"a": 1} - y = x.a + y = x.a # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", - r"a.*Dict\[str, int\]")]) + self.assertErrorRegexes(errors, {"e": r"a.*Dict\[str, int\]"}) def testBadPyiDict(self): with file_utils.Tempdir() as d: @@ -847,31 +796,28 @@ def testBadPyiDict(self): x = ... # type: Dict[str, int, float] """) _, errors = self.InferWithErrors("""\ - import a + import a # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def testCallNone(self): - _, errors = self.InferWithErrors("""\ - None() + self.InferWithErrors("""\ + None() # not-callable """) - self.assertErrorLogIs(errors, [(1, "not-callable")]) def testInNone(self): - _, errors = self.InferWithErrors("""\ - 3 in None + self.InferWithErrors("""\ + 3 in None # unsupported-operands """) - self.assertErrorLogIs(errors, [(1, "unsupported-operands")]) def testNoAttrError(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ if __random__: y = 42 else: y = "foo" - y.upper + y.upper # attribute-error """) - self.assertErrorLogIs(errors, [(5, "attribute-error")]) def testAttrError(self): _, errors = self.InferWithErrors("""\ @@ -879,28 +825,26 @@ def testAttrError(self): y = 42 else: y = "foo" - y.upper + y.upper # attribute-error[e] """) - self.assertErrorLogIs(errors, [(5, "attribute-error", "upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) def testPrintCallableInstance(self): _, errors = self.InferWithErrors("""\ from typing import Callable v = None # type: Callable[[int], str] - hex(v) + hex(v) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-types", - r"Actual.*Callable\[\[int\], str\]")]) + self.assertErrorRegexes(errors, {"e": r"Actual.*Callable\[\[int\], str\]"}) def testSameNameAndLine(self): _, errors = self.InferWithErrors("""\ def f(x): - return x + 42 + return x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") f([]) """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"str.*int"), - (2, "unsupported-operands", r"List.*int")]) + self.assertErrorRegexes(errors, {"e1": r"str.*int", "e2": r"List.*int"}) def testKwargOrder(self): with file_utils.Tempdir() as d: @@ -910,30 +854,28 @@ def g(x): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(x=1, y=2, z="3") - foo.g(42, v4="the", v3="quick", v2="brown", v1="fox") + foo.f(x=1, y=2, z="3") # wrong-arg-types[e1] + foo.g(42, v4="the", v3="quick", v2="brown", v1="fox") # wrong-keyword-args[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (2, "wrong-arg-types", r"x, y, z.*x, y, z"), - (3, "wrong-keyword-args", r"v1, v2, v3, v4")]) + self.assertErrorRegexes( + errors, {"e1": r"x, y, z.*x, y, z", "e2": r"v1, v2, v3, v4"}) def testBadBaseClass(self): _, errors = self.InferWithErrors("""\ - class Foo(None): pass - class Bar(None if __random__ else 42): pass + class Foo(None): pass # base-class-error[e1] + class Bar(None if __random__ else 42): pass # base-class-error[e2] """) - self.assertErrorLogIs(errors, [ - (1, "base-class-error", r"Invalid base class: None"), - (2, "base-class-error", r"Optional\[\]")]) + self.assertErrorRegexes(errors, {"e1": r"Invalid base class: None", + "e2": r"Optional\[\]"}) def testCallableInUnsupportedOperands(self): _, errors = self.InferWithErrors("""\ def f(x, y=None): pass - f in f + f in f # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Callable\[\[Any, Any\], Any\].*" - r"Callable\[\[Any, Any\], Any\]")]) + self.assertErrorRegexes( + errors, {"e": (r"Callable\[\[Any, Any\], Any\].*" + r"Callable\[\[Any, Any\], Any\]")}) def testCleanPyiNamedtupleNames(self): with file_utils.Tempdir() as d: @@ -944,199 +886,216 @@ def f(x: int): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.f(foo.X()) + foo.f(foo.X()) # wrong-arg-types[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"`X`")]) + self.assertErrorRegexes(errors, {"e": r"`X`"}) def testBadAnnotation(self): _, errors = self.InferWithErrors("""\ - tuple[0] - dict[1, 2] + tuple[0] # not-indexable[e1] + dict[1, 2] # invalid-annotation[e2] # invalid-annotation[e3] class A(object): pass - A[3] + A[3] # not-indexable[e4] """) - self.assertErrorLogIs(errors, [ - (1, "not-indexable", r"class tuple"), - (2, "invalid-annotation", r"1.*Not a type"), - (2, "invalid-annotation", r"2.*Not a type"), - (4, "not-indexable", r"class A"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"class tuple", "e2": r"1.*Not a type", "e3": r"2.*Not a type", + "e4": r"class A"}) def testRevealType(self): _, errors = self.InferWithErrors("""\ - reveal_type(42 or "foo") + reveal_type(42 or "foo") # reveal-type[e1] class Foo(object): pass - reveal_type(Foo) - reveal_type(Foo()) - reveal_type([1,2,3]) + reveal_type(Foo) # reveal-type[e2] + reveal_type(Foo()) # reveal-type[e3] + reveal_type([1,2,3]) # reveal-type[e4] """) - self.assertErrorLogIs(errors, [ - (1, "reveal-type", r"^Union\[int, str\]$"), - (4, "reveal-type", r"^Type\[Foo\]$"), - (5, "reveal-type", r"^Foo$"), - (6, "reveal-type", r"^List\[int\]$"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"^Union\[int, str\]$", "e2": r"^Type\[Foo\]$", "e3": r"^Foo$", + "e4": r"^List\[int\]$"}) def testNotProtocol(self): _, errors = self.InferWithErrors("""\ a = [] a.append(1) - a = "".join(a) + a = "".join(a) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [( - 3, "wrong-arg-types", r"\(.*List\[int\]\)$")]) # no protocol details + self.assertErrorRegexes( + errors, {"e": r"\(.*List\[int\]\)$"}) # no protocol details def testHiddenError(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ use_option = False def f(): if use_option: - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) def testUnknownInError(self): errors = self.CheckWithErrors("""\ def f(x): y = x if __random__ else None - return y.groups() + return y.groups() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"Optional\[Any\]")]) + self.assertErrorRegexes(errors, {"e": r"Optional\[Any\]"}) class OperationsTest(test_base.TargetIndependentTest): """Test operations.""" def testXor(self): - errors = self.CheckWithErrors("def f(): return 'foo' ^ 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\^.*str.*int.*'__xor__' on str.*'__rxor__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' ^ 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\^.*str.*int.*'__xor__' on str.*'__rxor__' on int"}) def testAdd(self): - errors = self.CheckWithErrors("def f(): return 'foo' + 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\+.*str.*int.*__add__ on str.*str")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' + 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\+.*str.*int.*__add__ on str.*str"}) def testInvert(self): - errors = self.CheckWithErrors("def f(): return ~None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\~.*None.*'__invert__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return ~None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\~.*None.*'__invert__' on None"}) def testSub(self): - errors = self.CheckWithErrors("def f(): return 'foo' - 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\-.*str.*int.*'__sub__' on str.*'__rsub__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' - 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\-.*str.*int.*'__sub__' on str.*'__rsub__' on int"}) def testMul(self): - errors = self.CheckWithErrors("def f(): return 'foo' * None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\*.*str.*None.*__mul__ on str.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' * None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\*.*str.*None.*__mul__ on str.*int"}) def testDiv(self): - errors = self.CheckWithErrors("def f(): return 'foo' / 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\/.*str.*int.*'__(true)?div__' on str.*'__r(true)?div__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' / 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\/.*str.*int.*'__(true)?div__' on str.*'__r(true)?div__' on int" + }) def testMod(self): - errors = self.CheckWithErrors("def f(): return None % 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\%.*None.*int.*'__mod__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return None % 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\%.*None.*int.*'__mod__' on None"}) def testLShift(self): - errors = self.CheckWithErrors("def f(): return 3 << None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\<\<.*int.*None.*__lshift__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 << None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\<\<.*int.*None.*__lshift__ on int.*int"}) def testRShift(self): - errors = self.CheckWithErrors("def f(): return 3 >> None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\>\>.*int.*None.*__rshift__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 >> None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\>\>.*int.*None.*__rshift__ on int.*int"}) def testAnd(self): - errors = self.CheckWithErrors("def f(): return 'foo' & 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\&.*str.*int.*'__and__' on str.*'__rand__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' & 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\&.*str.*int.*'__and__' on str.*'__rand__' on int"}) def testOr(self): - errors = self.CheckWithErrors("def f(): return 'foo' | 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\|.*str.*int.*'__or__' on str.*'__ror__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' | 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\|.*str.*int.*'__or__' on str.*'__ror__' on int"}) def testFloorDiv(self): - errors = self.CheckWithErrors("def f(): return 3 // 'foo'") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\/\/.*int.*str.*__floordiv__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 // 'foo' # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\/\/.*int.*str.*__floordiv__ on int.*int"}) def testPow(self): - errors = self.CheckWithErrors("def f(): return 3 ** 'foo'") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\*\*.*int.*str.*__pow__ on int.*int")]) + errors = self.CheckWithErrors("""\ + def f(): return 3 ** 'foo' # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\*\*.*int.*str.*__pow__ on int.*int"}) def testNeg(self): - errors = self.CheckWithErrors("def f(): return -None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\-.*None.*'__neg__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return -None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\-.*None.*'__neg__' on None"}) def testPos(self): - errors = self.CheckWithErrors("def f(): return +None") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"\+.*None.*'__pos__' on None")]) + errors = self.CheckWithErrors("""\ + def f(): return +None # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, {"e": r"\+.*None.*'__pos__' on None"}) class InPlaceOperationsTest(test_base.TargetIndependentTest): """Test in-place operations.""" def testIAdd(self): - errors = self.CheckWithErrors("def f(): v = []; v += 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"\+\=.*List.*int.*__iadd__ on List.*Iterable")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; v += 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"\+\=.*List.*int.*__iadd__ on List.*Iterable"}) class NoSymbolOperationsTest(test_base.TargetIndependentTest): """Test operations with no native symbol.""" def testGetItem(self): - errors = self.CheckWithErrors("def f(): v = []; return v['foo']") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item retrieval.*List.*str.*__getitem__ on List.*int")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; return v['foo'] # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"item retrieval.*List.*str.*__getitem__ on List.*int"}) def testDelItem(self): - errors = self.CheckWithErrors("def f(): v = {'foo': 3}; del v[3]") + errors = self.CheckWithErrors("""\ + def f(): v = {'foo': 3}; del v[3] # unsupported-operands[e] + """) d = r"Dict\[str, int\]" - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item deletion.*{d}.*int.*__delitem__ on {d}.*str".format(d=d))]) + self.assertErrorRegexes(errors, { + "e": r"item deletion.*{d}.*int.*__delitem__ on {d}.*str".format(d=d)}) def testSetItem(self): - errors = self.CheckWithErrors("def f(): v = []; v['foo'] = 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", - r"item assignment.*List.*str.*__setitem__ on List.*int")]) + errors = self.CheckWithErrors("""\ + def f(): v = []; v['foo'] = 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"item assignment.*List.*str.*__setitem__ on List.*int"}) def testContains(self): - errors = self.CheckWithErrors("def f(): return 'foo' in 3") - self.assertErrorLogIs(errors, [ - (1, "unsupported-operands", r"'in'.*int.*str.*'__contains__' on int")]) + errors = self.CheckWithErrors("""\ + def f(): return 'foo' in 3 # unsupported-operands[e] + """) + self.assertErrorRegexes(errors, { + "e": r"'in'.*int.*str.*'__contains__' on int"}) def testRecursion(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): if __random__: f() - name_error + name_error # name-error """) - self.assertErrorLogIs(errors, [(4, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_exceptions.py b/pytype/tests/test_exceptions.py index ed8575d9a..44fb3c6fb 100644 --- a/pytype/tests/test_exceptions.py +++ b/pytype/tests/test_exceptions.py @@ -77,8 +77,7 @@ def fn(): """) def test_global_name_error(self): - errors = self.CheckWithErrors("fooey") - self.assertErrorLogIs(errors, [(1, "name-error", r"fooey")]) + self.CheckWithErrors("fooey # name-error") # TODO(kramm): Don't warn about NameErrors that are being caught. self.assertNoCrash(self.Check, """\ try: @@ -89,12 +88,11 @@ def test_global_name_error(self): """) def test_local_name_error(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def fn(): - fooey + fooey # name-error fn() """) - self.assertErrorLogIs(errors, [(2, "name-error", r"fooey")]) def test_catch_local_name_error(self): self.assertNoCrash(self.Check, """\ @@ -108,17 +106,16 @@ def fn(): """) def test_reraise(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def fn(): try: - fooey + fooey # name-error print("Yes fooey?") except NameError: print("No fooey") raise fn() """) - self.assertErrorLogIs(errors, [(3, "name-error", r"fooey")]) def test_reraise_explicit_exception(self): self.Check("""\ @@ -312,7 +309,7 @@ def f() -> int """) def test_return_or_raise_set_attribute(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def f(): raise ValueError() def g(): @@ -320,17 +317,16 @@ def g(): def h(): func = f if __random__ else g v = func() - v.attr = None + v.attr = None # not-writable """) - self.assertErrorLogIs(errors, [(8, "not-writable")]) def test_bad_type_self(self): errors = self.CheckWithErrors("""\ class Foo(object): def __init__(self): - type(42, self) + type(42, self) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-arg-count", r"2.*3")]) + self.assertErrorRegexes(errors, {"e": r"2.*3"}) def test_value(self): ty = self.Infer(""" @@ -375,16 +371,15 @@ def test_bad_type(self): errors = self.CheckWithErrors("""\ try: pass - except None: + except None: # mro-error[e1] pass try: pass - except type(None): + except type(None): # mro-error[e2] pass """) - self.assertErrorLogIs( - errors, [(3, "mro-error", r"Not a class"), - (7, "mro-error", r"None.*BaseException")]) + self.assertErrorRegexes( + errors, {"e1": r"Not a class", "e2": r"None.*BaseException"}) def test_unknown_type(self): self.Check(""" diff --git a/pytype/tests/test_flow.py b/pytype/tests/test_flow.py index 56d3ea19e..abda994de 100644 --- a/pytype/tests/test_flow.py +++ b/pytype/tests/test_flow.py @@ -339,9 +339,9 @@ def f(): try: func = None except: - func() + func() # name-error[e] """, deep=True) - self.assertErrorLogIs(errors, [(5, "name-error", r"func")]) + self.assertErrorRegexes(errors, {"e": r"func"}) def test_nested_break(self): self.assertNoCrash(self.Infer, """ diff --git a/pytype/tests/test_functions.py b/pytype/tests/test_functions.py index 7fca59b60..76e7aa1b3 100644 --- a/pytype/tests/test_functions.py +++ b/pytype/tests/test_functions.py @@ -108,14 +108,13 @@ def g(y): """) def test_unbound_closure_variable(self): - err = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ def foo(): def bar(): return tuple(xs) # name-error xs = bar() foo() """) - self.assertErrorsMatch(err, []) class TestGenerators(test_base.TargetIndependentTest): @@ -209,9 +208,11 @@ def setUp(self): self.options.tweak(precise_return=True) def test_pytd_return(self): - ty, errors = self.InferWithErrors("x = 'hello'.startswith(0)") + ty, errors = self.InferWithErrors("""\ + x = 'hello'.startswith(0) # wrong-arg-types[e] + """) self.assertTypesMatchPytd(ty, "x: bool") - self.assertErrorLogIs(errors, [(1, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_param_return(self): with file_utils.Tempdir() as d: @@ -220,32 +221,29 @@ def test_param_return(self): T = TypeVar("T") def f(x: T) -> T: ... """) - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import foo - x = foo.f() + x = foo.f() # missing-parameter """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any foo: module x: Any """) - self.assertErrorLogIs(errors, [(2, "missing-parameter")]) def test_binop(self): - ty, errors = self.InferWithErrors("x = 'oops' + 0") + ty, _ = self.InferWithErrors("x = 'oops' + 0 # unsupported-operands") self.assertTypesMatchPytd(ty, "x: str") - self.assertErrorLogIs(errors, [(1, "unsupported-operands")]) def test_inplace_op(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ x = [] - x += 0 + x += 0 # unsupported-operands """) self.assertTypesMatchPytd(ty, """ from typing import List x: List[nothing] """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands")]) class TestFunctions(test_base.TargetIndependentTest): @@ -438,9 +436,9 @@ def test_named_arg_unsolvable_max_depth(self): # maximum depth. _, errors = self.InferWithErrors("""\ def f(x): - return max(foo=repr(__any_object__)) + return max(foo=repr(__any_object__)) # wrong-keyword-args[e] """, deep=True, maximum_depth=1) - self.assertErrorLogIs(errors, [(2, "wrong-keyword-args", r"foo.*max")]) + self.assertErrorRegexes(errors, {"e": r"foo.*max"}) def test_multiple_signatures_with_type_parameter(self): with file_utils.Tempdir() as d: @@ -657,9 +655,9 @@ def test_wrong_keyword(self): _, errors = self.InferWithErrors("""\ def f(x): pass - f("", y=42) + f("", y=42) # wrong-keyword-args[e] """) - self.assertErrorLogIs(errors, [(3, "wrong-keyword-args", r"y")]) + self.assertErrorRegexes(errors, {"e": r"y"}) def test_staticmethod_class(self): ty = self.Infer("""\ @@ -730,9 +728,9 @@ def test_interpreter_function_in_class(self): class A(object): bar = lambda x: x def f(self): - self.bar(42) + self.bar(42) # wrong-arg-count[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-count", "1.*2")]) + self.assertErrorRegexes(errors, {"e": r"1.*2"}) def test_nested_lambda(self): # Inspired by b/37869955 @@ -780,12 +778,11 @@ def c(x: int, y: int, z: int = ...): ... """) def test_bad_defaults(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections X = collections.namedtuple("X", "a b c") - X.__new__.__defaults__ = (1) + X.__new__.__defaults__ = (1) # bad-function-defaults """) - self.assertErrorLogIs(errors, [(3, "bad-function-defaults")]) def test_multiple_valid_defaults(self): self.Check(""" @@ -807,12 +804,11 @@ def test_set_defaults_to_expression(self): def test_set_defaults_non_tuple_instance(self): # Test that get_atomic_python_constant fails and get_atomic_value pulls out # a non-tuple Instance. - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections X = collections.namedtuple("X", "a b c") - X.__new__.__defaults__ = (lambda x: x)(0) - """) - self.assertErrorLogIs(errors, [(3, "bad-function-defaults")]) + X.__new__.__defaults__ = (lambda x: x)(0) # bad-function-defaults + """) def test_set_builtin_defaults(self): self.assertNoCrash(self.Check, """ @@ -835,33 +831,27 @@ def test(a, b, c = 4): z = test(1, 2) z = test(1, 2, 3) """) - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def test(a, b, c): return a + b + c - x = test(1, 2) # should fail + x = test(1, 2) # missing-parameter test.__defaults__ = (3,) x = test(1, 2) - x = test(1) # should fail + x = test(1) # missing-parameter """) - self.assertErrorLogIs(errors, - [(3, "missing-parameter"), - (6, "missing-parameter")]) def test_interpreter_function_defaults_on_class(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ class Foo(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c - a = Foo() # should fail + a = Foo() # missing-parameter Foo.__init__.__defaults__ = (1, 2) b = Foo(0) - c = Foo() # should fail + c = Foo() # missing-parameter """) - self.assertErrorLogIs(errors, - [(6, "missing-parameter"), - (9, "missing-parameter")]) def test_split_on_kwargs(self): ty = self.Infer(""" @@ -883,11 +873,10 @@ def test_pyi_starargs(self): d.create_file("foo.pyi", """ def f(x: str, ...) -> None: ... """) - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import foo - foo.f(True, False) + foo.f(True, False) # wrong-arg-types """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types")]) def test_infer_bound_pytd_func(self): ty = self.Infer(""" @@ -971,24 +960,20 @@ def __init__(self, a, b=None): def test_functools_partial_bad_call(self): errors = self.CheckWithErrors("""\ import functools - functools.partial() - functools.partial(42) + functools.partial() # missing-parameter + functools.partial(42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [ - (2, "missing-parameter"), - (3, "wrong-arg-types", r"Callable.*int")]) + self.assertErrorRegexes(errors, {"e": r"Callable.*int"}) def test_bad_comprehensions(self): # Test that we report errors in comprehensions and generators only once # while still reporting errors in lambdas. - errors = self.CheckWithErrors("""\ - [name_error1 for x in ()] - {name_error2 for x in ()} - (name_error3 for x in ()) - lambda x: name_error4 + self.CheckWithErrors("""\ + [name_error1 for x in ()] # name-error + {name_error2 for x in ()} # name-error + (name_error3 for x in ()) # name-error + lambda x: name_error4 # name-error """) - self.assertErrorLogIs(errors, [(1, "name-error"), (2, "name-error"), - (3, "name-error"), (4, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_future_overlay.py b/pytype/tests/test_future_overlay.py index 2c38aefb3..fa705b7c1 100644 --- a/pytype/tests/test_future_overlay.py +++ b/pytype/tests/test_future_overlay.py @@ -33,11 +33,10 @@ def get_foo(self): """, pythonpath=[d.path]) def test_missing_import(self): - errors = self.CheckWithErrors("""\ - from future.utils import iteritems - from future.utils import with_metaclass + self.CheckWithErrors("""\ + from future.utils import iteritems # import-error + from future.utils import with_metaclass # import-error """) - self.assertErrorLogIs(errors, [(1, "import-error"), (2, "import-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_import.py b/pytype/tests/test_import.py index 7988c3f86..887338922 100644 --- a/pytype/tests/test_import.py +++ b/pytype/tests/test_import.py @@ -108,9 +108,9 @@ class Y(X): ... """) def testBadStarImport(self): - ty, errors = self.InferWithErrors(""" - from nonsense import * - from other_nonsense import * + ty, _ = self.InferWithErrors("""\ + from nonsense import * # import-error + from other_nonsense import * # import-error x = foo.bar() """) self.assertTypesMatchPytd(ty, """ @@ -118,8 +118,6 @@ def testBadStarImport(self): def __getattr__(name) -> Any x = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "import-error", r"nonsense"), - (3, "import-error", r"other_nonsense")]) def testPathImport(self): with file_utils.Tempdir() as d: @@ -426,7 +424,7 @@ def testDotDotPackageInPyi(self): from ..bar import X """) d.create_file("up2/bar.pyi", "class X: ...") - d.create_file("top.py", """\ + d.create_file("top.py", """ from up2.baz.foo import X x = X() """) @@ -442,7 +440,7 @@ def testDotDotInPyi(self): # Similar to testDotDot except in a pyi file. with file_utils.Tempdir() as d: d.create_file("foo/baz.pyi", "x: int") - d.create_file("foo/deep/bar.py", """\ + d.create_file("foo/deep/bar.py", """ from .. import baz a = baz.x """) @@ -459,18 +457,18 @@ def testTooManyDotsInPackageInPyi(self): d.create_file("up/foo.pyi", "from ..bar import X") d.create_file("up/bar.pyi", "class X: ...") _, err = self.InferWithErrors( - "from up.foo import X", pythonpath=[d.path]) - self.assertErrorLogIs( - err, [(1, "pyi-error", "Cannot resolve relative import ..bar")]) + "from up.foo import X # pyi-error[e]", pythonpath=[d.path]) + self.assertErrorRegexes( + err, {"e": r"Cannot resolve relative import \.\.bar"}) def testFromDotInPyi(self): # from . import module with file_utils.Tempdir() as d: d.create_file("foo/a.pyi", "class X: ...") - d.create_file("foo/b.pyi", """\ + d.create_file("foo/b.pyi", """ from . import a Y = a.X""") - d.create_file("top.py", """\ + d.create_file("top.py", """ import foo.b x = foo.b.Y() """) ty = self.InferFromFile(filename=d["top.py"], pythonpath=[d.path]) @@ -749,10 +747,10 @@ class B(a.A): pass """) _, errors = self.InferWithErrors("""\ - import b + import b # pyi-error[e] x = b.B() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"a\.pyi")]) + self.assertErrorRegexes(errors, {"e": r"a\.pyi"}) def testSubdirAndModuleWithSameNameAsPackage(self): with file_utils.Tempdir() as d: @@ -798,20 +796,17 @@ class object: def foo(self) -> None: ... def f(x: object) -> object """) - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import foo x = foo.f(foo.object()) y = foo.f(foo.object()) - foo.f(object()) # error + foo.f(object()) # wrong-arg-types """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ foo = ... # type: module x = ... # type: foo.object y = ... # type: foo.object """) - self.assertErrorLogIs(errors, [ - (4, "wrong-arg-types"), - ]) def testNoFailOnBadSymbolLookup(self): with file_utils.Tempdir() as d: @@ -873,14 +868,11 @@ def testAttributeOnModule(self): foo = ... # type: int """) _, errors = self.InferWithErrors("""\ - from a import foo, bar + from a import foo, bar # import-error[e1] import a - a.baz + a.baz # module-attr[e2] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [ - (1, "import-error", r"bar"), - (3, "module-attr", r"baz"), - ]) + self.assertErrorRegexes(errors, {"e1": r"bar", "e2": r"baz"}) def testFromImport(self): with file_utils.Tempdir() as d: @@ -906,7 +898,7 @@ def testImportMapFilter(self): Qux = bar.Quack """.format(imp_path) init_fn = d.create_file("foo/__init__.py", init_body) - initpyi_fn = d.create_file("foo/__init__.pyi~", """\ + initpyi_fn = d.create_file("foo/__init__.pyi~", """ from typing import Any bar = ... # type: Any baz = ... # type: Any @@ -914,7 +906,7 @@ def testImportMapFilter(self): """) bar_fn = d.create_file("foo/bar.py", "class Quack(object): pass") barpyi_fn = d.create_file("foo/bar.pyi", "class Quack(object): pass") - imports_fn = d.create_file("imports_info", """\ + imports_fn = d.create_file("imports_info", """ {0} {1} {2} {3} """.format(init_fn[1:-3], initpyi_fn, bar_fn[1:-3], barpyi_fn)) @@ -1133,19 +1125,18 @@ def testUnimportedSubmoduleFailure(self): _, errors = self.InferWithErrors("""\ import sub.bar.baz x = sub.bar.baz.A() - y = sub.bar.quux.B() + y = sub.bar.quux.B() # module-attr[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "module-attr", r"quux.*sub\.bar")]) + self.assertErrorRegexes(errors, {"e": r"quux.*sub\.bar"}) def testSubmoduleAttributeError(self): with file_utils.Tempdir() as d: d.create_file("package/__init__.pyi", "submodule: module") d.create_file("package/submodule.pyi", "") - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ from package import submodule - submodule.asd + submodule.asd # module-attr """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "module-attr")]) def testInitOnlySubmodule(self): """Test a submodule without its own stub file.""" diff --git a/pytype/tests/test_list.py b/pytype/tests/test_list.py index 6839db1a1..98ece81f1 100644 --- a/pytype/tests/test_list.py +++ b/pytype/tests/test_list.py @@ -75,7 +75,7 @@ def test_getitem_slot(self): b = a[1] c = 1 if __random__ else 2 d = a[c] - e = a["s"] + e = a["s"] # unsupported-operands[e] f = a[-1] g = a[slice(1,2)] # should be List[str] """) @@ -89,8 +89,7 @@ def test_getitem_slot(self): f = ... # type: int g = ... # type: List[Union[int, str]] """) - self.assertErrorLogIs(errors, [(5, "unsupported-operands", - r"__getitem__ on List")]) + self.assertErrorRegexes(errors, {"e": r"__getitem__ on List"}) def test_index_out_of_range(self): ty = self.Infer(""" diff --git a/pytype/tests/test_namedtuple.py b/pytype/tests/test_namedtuple.py index 6c22dadbf..72dd9e0f9 100644 --- a/pytype/tests/test_namedtuple.py +++ b/pytype/tests/test_namedtuple.py @@ -79,22 +79,15 @@ def test_str_args2(self): """) def test_bad_fieldnames(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import collections - collections.namedtuple("_", ["abc", "def", "ghi"]) - collections.namedtuple("_", "_") - collections.namedtuple("_", "a, 1") - collections.namedtuple("_", "a, !") - collections.namedtuple("_", "a, b, c, a") - collections.namedtuple("1", "") + collections.namedtuple("_", ["abc", "def", "ghi"]) # invalid-namedtuple-arg + collections.namedtuple("_", "_") # invalid-namedtuple-arg + collections.namedtuple("_", "a, 1") # invalid-namedtuple-arg + collections.namedtuple("_", "a, !") # invalid-namedtuple-arg + collections.namedtuple("_", "a, b, c, a") # invalid-namedtuple-arg + collections.namedtuple("1", "") # invalid-namedtuple-arg """) - self.assertErrorLogIs(errorlog, - [(2, "invalid-namedtuple-arg"), - (3, "invalid-namedtuple-arg"), - (4, "invalid-namedtuple-arg"), - (5, "invalid-namedtuple-arg"), - (6, "invalid-namedtuple-arg"), - (7, "invalid-namedtuple-arg")]) def test_rename(self): ty = self.Infer(""" @@ -106,19 +99,15 @@ def test_rename(self): ty, self._namedtuple_def(S=("S", ["abc", "_1", "ghi", "_3"]))) def test_bad_initialize(self): - _, errlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ from collections import namedtuple X = namedtuple("X", "y z") - a = X(1) - b = X(y = 2) - c = X(w = 3) + a = X(1) # missing-parameter + b = X(y = 2) # missing-parameter + c = X(w = 3) # wrong-keyword-args d = X(y = "hello", z = 4j) # works """) - self.assertErrorLogIs(errlog, [ - (4, "missing-parameter"), - (5, "missing-parameter"), - (6, "wrong-keyword-args")]) def test_class_name(self): ty = self.Infer( @@ -155,15 +144,14 @@ class X(NamedTuple('X', [('y', str), ('z', int)])): ... """) _, errors = self.InferWithErrors("""\ import foo - foo.X() # wrong arg count - foo.X(0, "") # wrong types - foo.X(z="", y=0) # wrong types + foo.X() # missing-parameter[e1] + foo.X(0, "") # wrong-arg-types[e2] + foo.X(z="", y=0) # wrong-arg-types[e3] foo.X("", 0) foo.X(y="", z=0) """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(2, "missing-parameter", r"y"), - (3, "wrong-arg-types", r"str.*int"), - (4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes( + errors, {"e1": r"y", "e2": r"str.*int", "e3": r"str.*int"}) def test_use_pyi_namedtuple(self): with file_utils.Tempdir() as d: @@ -173,9 +161,9 @@ class X(NamedTuple("X", [])): ... _, errors = self.InferWithErrors("""\ import foo foo.X()._replace() - foo.X().nonsense + foo.X().nonsense # attribute-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"nonsense.*X")]) + self.assertErrorRegexes(errors, {"e": r"nonsense.*X"}) def test_subclass_pyi_namedtuple(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_operators.py b/pytype/tests/test_operators.py index 217570b40..28eb75490 100644 --- a/pytype/tests/test_operators.py +++ b/pytype/tests/test_operators.py @@ -328,9 +328,9 @@ def test_unknown_right(self): class Foo(object): def __sub__(self, other): return "" - (Foo() - __any_object__).real + (Foo() - __any_object__).real # attribute-error[e] """) - self.assertErrorLogIs(errors, [(4, "attribute-error", r"real.*str")]) + self.assertErrorRegexes(errors, {"e": r"real.*str"}) class InplaceTest(test_base.TargetIndependentTest, @@ -371,9 +371,9 @@ def test_list_add(self): _, errors = self.InferWithErrors("""\ class A(object): pass v = [] - v += A() + v += A() # unsupported-operands[e] """) - self.assertErrorLogIs(errors, [(3, "unsupported-operands", r"A.*Iterable")]) + self.assertErrorRegexes(errors, {"e": r"A.*Iterable"}) class BindingsTest(test_base.TargetIndependentTest): diff --git a/pytype/tests/test_pyi.py b/pytype/tests/test_pyi.py index 60c32c0e8..a48637f15 100644 --- a/pytype/tests/test_pyi.py +++ b/pytype/tests/test_pyi.py @@ -336,15 +336,15 @@ def testMultipleGetAttr(self): from typing import Any def __getattr__(name) -> Any """) - ty, errors = self.InferWithErrors(""" + ty, errors = self.InferWithErrors("""\ from foo import * - from bar import * # Nonsense import generates a top-level __getattr__ + from bar import * # Nonsense import generates a top-level __getattr__ # import-error[e] """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any def __getattr__(name) -> Any """) - self.assertErrorLogIs(errors, [(3, "import-error", r"bar")]) + self.assertErrorRegexes(errors, {"e": r"bar"}) def testPyiListItem(self): with file_utils.Tempdir() as d: @@ -436,8 +436,8 @@ def foo(a: K, *b, c: V, **d) -> Dict[K, V]: ... import foo a = foo.foo(*tuple(), **dict()) b = foo.foo(*(1,), **{"c": 3j}) - c = foo.foo(*(1,)) - d = foo.foo(*(), **{"d": 3j}) + c = foo.foo(*(1,)) # missing-parameter[e1] + d = foo.foo(*(), **{"d": 3j}) # missing-parameter[e2] """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ from typing import Any, Dict @@ -447,10 +447,7 @@ def foo(a: K, *b, c: V, **d) -> Dict[K, V]: ... c = ... # type: Any d = ... # type: Any """) - self.assertErrorLogIs(errors, [ - (4, "missing-parameter", r"\bc\b"), - (5, "missing-parameter", r"\ba\b"), - ]) + self.assertErrorRegexes(errors, {"e1": r"\bc\b", "e2": r"\ba\b"}) def testUnionWithSuperclass(self): with file_utils.Tempdir() as d: @@ -521,8 +518,8 @@ def testTypeVarConflict(self): from typing import List, Sequence class A(List[int], Sequence[str]): ... """) - ty, errors = self.InferWithErrors("""\ - import foo + ty, _ = self.InferWithErrors("""\ + import foo # pyi-error x = [] + foo.A() """, pythonpath=[d.path]) self.assertTypesMatchPytd(ty, """ @@ -530,7 +527,6 @@ class A(List[int], Sequence[str]): ... foo = ... # type: Any x = ... # type: list """) - self.assertErrorLogIs(errors, [(1, "pyi-error")]) def testSameTypeVarName(self): with file_utils.Tempdir() as d: @@ -585,11 +581,11 @@ def bar(self): """) # We should get an error at import time rather than at use time here. _, errors = self.InferWithErrors("""\ - import foo + import foo # pyi-error[e] x = foo.Bar() x.bar() """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", "T2")]) + self.assertErrorRegexes(errors, {"e": r"T2"}) def testStarImport(self): with file_utils.Tempdir() as d: @@ -725,7 +721,7 @@ def f(x: foo.Foo) -> None: ... def testAliasStaticMethod(self): with file_utils.Tempdir() as d: - d.create_file("foo.pyi", """\ + d.create_file("foo.pyi", """ class A: @staticmethod def t(a: str) -> None: ... diff --git a/pytype/tests/test_quick.py b/pytype/tests/test_quick.py index 78390ae32..92672c421 100644 --- a/pytype/tests/test_quick.py +++ b/pytype/tests/test_quick.py @@ -77,11 +77,11 @@ def testAnalyzeAnnotatedMaxDepth(self): # --output with --analyze-annotated has the same max depth as --check. _, errors = self.InferWithErrors("""\ def make_greeting(user_id): - return 'hello, user' + user_id + return 'hello, user' + user_id # unsupported-operands[e] def print_greeting(): print(make_greeting(0)) """, quick=True) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_recovery.py b/pytype/tests/test_recovery.py index 1a42b674b..c0232a56e 100644 --- a/pytype/tests/test_recovery.py +++ b/pytype/tests/test_recovery.py @@ -99,17 +99,13 @@ class A(object): """) def testMethodWithUnknownDecorator(self): - _, errors = self.InferWithErrors("""\ - from nowhere import decorator + self.InferWithErrors("""\ + from nowhere import decorator # import-error class Foo(object): @decorator def f(): - name_error + name_error # name-error """, deep=True) - self.assertErrorLogIs(errors, [ - (1, "import-error"), - (5, "name-error"), - ]) def testAssertInConstructor(self): self.Check("""\ @@ -133,27 +129,21 @@ def __str__(self): """) def testAttributeAccessInImpossiblePath(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ x = 3.14 if __random__ else 42 if isinstance(x, int): if isinstance(x, float): x.upper # not reported - 3 in x + 3 in x # unsupported-operands """) - self.assertErrorLogIs(errors, [ - (5, "unsupported-operands"), - ]) def testBinaryOperatorOnImpossiblePath(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ x = "" if __random__ else [] if isinstance(x, list): if isinstance(x, str): - x / x + x / x # unsupported-operands """) - self.assertErrorLogIs(errors, [ - (4, "unsupported-operands"), - ]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_reingest.py b/pytype/tests/test_reingest.py index cedd50b3b..f5b114448 100644 --- a/pytype/tests/test_reingest.py +++ b/pytype/tests/test_reingest.py @@ -123,9 +123,9 @@ def __new__(cls, a, b): _, errors = self.InferWithErrors("""\ import foo foo.X("hello", "world") - foo.X(42) # missing parameters + foo.X(42) # missing-parameter[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "missing-parameter", "b.*__new__")]) + self.assertErrorRegexes(errors, {"e": r"b.*__new__"}) def testAlias(self): foo = self.Infer(""" @@ -151,7 +151,7 @@ def testDynamicAttributes(self): with file_utils.Tempdir() as d: d.create_file("foo1.pyi", pytd_utils.Print(foo1)) d.create_file("foo2.pyi", pytd_utils.Print(foo2)) - d.create_file("bar.pyi", """\ + d.create_file("bar.pyi", """ from foo1 import xyz from foo2 import zyx """) diff --git a/pytype/tests/test_slots.py b/pytype/tests/test_slots.py index 1f6f5a16d..b922d1d59 100644 --- a/pytype/tests/test_slots.py +++ b/pytype/tests/test_slots.py @@ -64,14 +64,11 @@ class Foo(object): """) def testSlotWithNonStrings(self): - _, errors = self.InferWithErrors(""" - class Foo(object): + _, errors = self.InferWithErrors("""\ + class Foo(object): # bad-slots[e] __slots__ = (1, 2, 3) """) - self.assertErrorLogIs( - errors, - [(2, "bad-slots", r"Invalid __slot__ entry: '1'")] - ) + self.assertErrorRegexes(errors, {"e": r"Invalid __slot__ entry: '1'"}) def testSetSlot(self): self.Check(""" @@ -111,20 +108,15 @@ class Foo(object): foo = Foo() foo.x = 1 # ok foo.y = 2 # ok - foo.z = 3 # error + foo.z = 3 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(7, "not-writable", r"z")] - ) + self.assertErrorRegexes(errors, {"e": r"z"}) def testObject(self): _, errors = self.InferWithErrors("""\ - object().foo = 42 + object().foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (1, "not-writable", r"object") - ]) + self.assertErrorRegexes(errors, {"e": r"object"}) def testAnyBaseClass(self): self.Check(""" @@ -138,22 +130,17 @@ def testParameterizedBaseClass(self): from typing import List class Foo(List[int]): __slots__ = () - Foo().foo = 42 + Foo().foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (4, "not-writable", r"foo") - ]) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testEmptySlots(self): _, errors = self.InferWithErrors("""\ class Foo(object): __slots__ = () - Foo().foo = 42 + Foo().foo = 42 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(3, "not-writable", r"foo")] - ) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testNamedTuple(self): _, errors = self.InferWithErrors("""\ @@ -163,47 +150,38 @@ def testNamedTuple(self): foo.a = 1 foo.b = 2 foo.c = 3 - foo.d = 4 # error + foo.d = 4 # not-writable[e] """) - self.assertErrorLogIs(errors, [ - (7, "not-writable", r"d") - ]) + self.assertErrorRegexes(errors, {"e": r"d"}) def testBuiltinAttr(self): - _, errors = self.InferWithErrors("""\ - "foo".bar = 1 - u"foo".bar = 2 - ().bar = 3 - [].bar = 4 - {}.bar = 5 - set().bar = 6 - frozenset().bar = 7 - frozenset().bar = 8 - Ellipsis.bar = 9 - bytearray().bar = 10 - enumerate([]).bar = 11 - True.bar = 12 - (42).bar = 13 - (3.14).bar = 14 - (3j).bar = 15 - slice(1,10).bar = 17 - memoryview(b"foo").bar = 18 - range(10).bar = 19 - """) - self.assertErrorLogIs( - errors, - [(line, "not-writable") for line in range(1, 19)] - ) + self.InferWithErrors("""\ + "foo".bar = 1 # not-writable + u"foo".bar = 2 # not-writable + ().bar = 3 # not-writable + [].bar = 4 # not-writable + {}.bar = 5 # not-writable + set().bar = 6 # not-writable + frozenset().bar = 7 # not-writable + frozenset().bar = 8 # not-writable + Ellipsis.bar = 9 # not-writable + bytearray().bar = 10 # not-writable + enumerate([]).bar = 11 # not-writable + True.bar = 12 # not-writable + (42).bar = 13 # not-writable + (3.14).bar = 14 # not-writable + (3j).bar = 15 # not-writable + slice(1,10).bar = 16 # not-writable + memoryview(b"foo").bar = 17 # not-writable + range(10).bar = 18 # not-writable + """) def testGeneratorAttr(self): _, errors = self.InferWithErrors("""\ def f(): yield 42 - f().foo = 42 + f().foo = 42 # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(2, "not-writable", r"foo")] - ) + self.assertErrorRegexes(errors, {"e": r"foo"}) def testSetAttr(self): self.Check("""\ @@ -241,12 +219,9 @@ class Foo(Bar): __slots__ = ["__foo"] def __init__(self): self.__foo = 42 - self.__baz = 42 # __baz is class-private + self.__baz = 42 # __baz is class-private # not-writable[e] """) - self.assertErrorLogIs( - errors, - [(9, "not-writable", "__baz")] - ) + self.assertErrorRegexes(errors, {"e": r"__baz"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_special_builtins.py b/pytype/tests/test_special_builtins.py index 3a01be077..c0d714e79 100644 --- a/pytype/tests/test_special_builtins.py +++ b/pytype/tests/test_special_builtins.py @@ -201,9 +201,9 @@ def foo(self): foo1 = Foo() foo2 = Foo() if isinstance(foo1.foo, str): - x = foo2.foo.upper() # line 10 + x = foo2.foo.upper() # attribute-error[e] """) - self.assertErrorLogIs(errors, [(10, "attribute-error", r"upper.*int")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_splits.py b/pytype/tests/test_splits.py index 4e74f19a8..f267fb0c1 100644 --- a/pytype/tests/test_splits.py +++ b/pytype/tests/test_splits.py @@ -655,14 +655,13 @@ def testPrimitiveNotEq(self): def testBuiltinFullNameCheck(self): # Don't get confused by a class named int - _, errorlog = self.InferWithErrors(""" + self.InferWithErrors("""\ class int(): pass x = "foo" if __random__ else int() if x == "foo": - x.upper() + x.upper() # attribute-error """) - self.assertNotEqual(len(errorlog), 0) def testTypeParameterInBranch(self): ty = self.Infer(""" @@ -761,12 +760,11 @@ class Value(int): value1 = ... # type: int value2 = ... # type: Value """) - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import foo if foo.value1 == foo.value2: - name_error + name_error # name-error """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(3, "name-error")]) def testListElement(self): ty = self.Infer(""" diff --git a/pytype/tests/test_super.py b/pytype/tests/test_super.py index 5ec5e237f..ad1e9edf0 100644 --- a/pytype/tests/test_super.py +++ b/pytype/tests/test_super.py @@ -75,9 +75,9 @@ def testSet(self): _, errors = self.InferWithErrors("""\ class Foo(object): def foo(self, name, value): - super(Foo, self).__set__(name, value) + super(Foo, self).__set__(name, value) # attribute-error[e] """) - self.assertErrorLogIs(errors, [(3, "attribute-error", r"__set__.*super")]) + self.assertErrorRegexes(errors, {"e": r"__set__.*super"}) def testInheritedSet(self): self.Check(""" @@ -149,9 +149,9 @@ class Y(object): class Foo(Y): def hello(self): - return super(Foo, self)() + return super(Foo, self)() # not-callable[e] """) - self.assertErrorLogIs(errorlog, [(6, "not-callable", r"super")]) + self.assertErrorRegexes(errorlog, {"e": r"super"}) def testSuperType(self): ty = self.Infer(""" @@ -196,25 +196,23 @@ def testSuperWithAny(self): def testSingleArgumentSuper(self): _, errors = self.InferWithErrors("""\ super(object) - super(object()) + super(object()) # wrong-arg-types[e] """) - self.assertErrorLogIs( - errors, [(2, "wrong-arg-types", r"cls: type.*cls: object")]) + self.assertErrorRegexes(errors, {"e": r"cls: type.*cls: object"}) def testMethodOnSingleArgumentSuper(self): ty, errors = self.InferWithErrors("""\ sup = super(object) - sup.foo - sup.__new__(object) + sup.foo # attribute-error[e1] + sup.__new__(object) # wrong-arg-types[e2] v = sup.__new__(super) """) self.assertTypesMatchPytd(ty, """ sup = ... # type: super v = ... # type: super """) - self.assertErrorLogIs(errors, [ - (2, "attribute-error", r"'foo' on super"), - (3, "wrong-arg-types", r"Type\[super\].*Type\[object\]")]) + self.assertErrorRegexes(errors, {"e1": r"'foo' on super", + "e2": r"Type\[super\].*Type\[object\]"}) def testSuperUnderDecorator(self): self.Check("""\ @@ -233,18 +231,18 @@ def testSuperSetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(object): def __init__(self): - super(Foo, self).foo = 42 + super(Foo, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(3, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperSubclassSetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(object): pass class Bar(Foo): def __init__(self): - super(Bar, self).foo = 42 + super(Bar, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(4, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperNothingSetAttr(self): with file_utils.Tempdir() as d: @@ -255,17 +253,17 @@ class Foo(nothing): ... import foo class Bar(foo.Foo): def __init__(self): - super(foo.Foo, self).foo = 42 + super(foo.Foo, self).foo = 42 # not-writable[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(4, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) def testSuperAnySetAttr(self): _, errors = self.InferWithErrors("""\ class Foo(__any_object__): def __init__(self): - super(Foo, self).foo = 42 + super(Foo, self).foo = 42 # not-writable[e] """) - self.assertErrorLogIs(errors, [(3, "not-writable", r"super")]) + self.assertErrorRegexes(errors, {"e": r"super"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_tracebacks.py b/pytype/tests/test_tracebacks.py index 8ea8407f8..832da8638 100644 --- a/pytype/tests/test_tracebacks.py +++ b/pytype/tests/test_tracebacks.py @@ -9,78 +9,70 @@ class TracebackTest(test_base.TargetIndependentTest): def test_no_traceback(self): _, errors = self.InferWithErrors("""\ def f(x): - "hello" + 42 + "hello" + 42 # unsupported-operands[e] f("world") """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"expects str$")]) + self.assertErrorRegexes(errors, {"e": r"expects str$"}) def test_same_traceback(self): _, errors = self.InferWithErrors("""\ def f(x, _): - x + 42 + x + 42 # unsupported-operands[e] def g(x): f("hello", x) g("world") """, deep=True) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Called from.*:\n" - r" line 4, in g")]) + self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g"}) def test_different_tracebacks(self): _, errors = self.InferWithErrors("""\ def f(x): - x + 42 + x + 42 # unsupported-operands[e1] # unsupported-operands[e2] f("hello") f("world") """) - self.assertErrorLogIs(errors, [(2, "unsupported-operands", - r"Called from.*:\n" - r" line 3, in current file"), - (2, "unsupported-operands", - r"Called from.*:\n" - r" line 4, in current file")]) + self.assertErrorRegexes(errors, { + "e1": r"Called from.*:\n line 3, in current file", + "e2": r"Called from.*:\n line 4, in current file"}) def test_comprehension(self): _, errors = self.InferWithErrors("""\ def f(): - return {x.upper() for x in range(10)} + return {x.upper() for x in range(10)} # attribute-error[e] """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"upper.*int$")]) + self.assertErrorRegexes(errors, {"e": r"upper.*int$"}) error, = errors self.assertEqual(error.methodname, "f") def test_comprehension_in_traceback(self): _, errors = self.InferWithErrors("""\ def f(x): - return x.upper() + return x.upper() # attribute-error[e] def g(): return {f(x) for x in range(10)} """) - self.assertErrorLogIs(errors, [(2, "attribute-error", - r"Called from.*:\n line 4, in g$")]) + self.assertErrorRegexes(errors, {"e": r"Called from.*:\n line 4, in g$"}) def test_no_argument_function(self): errors = self.CheckWithErrors("""\ def f(): - return None.attr + return None.attr # attribute-error[e] f() """) - self.assertErrorLogIs(errors, [(2, "attribute-error", r"attr.*None$")]) + self.assertErrorRegexes(errors, {"e": r"attr.*None$"}) def test_max_callsites(self): errors = self.CheckWithErrors("""\ def f(s): - return "hello, " + s + return "hello, " + s # unsupported-operands[e1] # unsupported-operands[e2] # unsupported-operands[e3] f(0) f(1) f(2) f(3) """) # We limit the number of tracebacks shown for the same error. - self.assertErrorLogIs(errors, [(2, "unsupported-operands", r"line 3"), - (2, "unsupported-operands", r"line 4"), - (2, "unsupported-operands", r"line 5")]) + self.assertErrorRegexes( + errors, {"e1": r"line 3", "e2": r"line 4", "e3": r"line 5"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_tuple.py b/pytype/tests/test_tuple.py index 5fea56993..091f3f9f0 100644 --- a/pytype/tests/test_tuple.py +++ b/pytype/tests/test_tuple.py @@ -64,8 +64,8 @@ def testUnpackTuple(self): def testBadUnpacking(self): ty, errors = self.InferWithErrors("""\ tup = (1, "") - a, = tup - b, c, d = tup + a, = tup # bad-unpacking[e1] + b, c, d = tup # bad-unpacking[e2] """) self.assertTypesMatchPytd(ty, """ from typing import Tuple @@ -75,9 +75,8 @@ def testBadUnpacking(self): c = ... # type: int or str d = ... # type: int or str """) - self.assertErrorLogIs(errors, [ - (2, "bad-unpacking", "2 values.*1 variable"), - (3, "bad-unpacking", "2 values.*3 variables")]) + self.assertErrorRegexes( + errors, {"e1": r"2 values.*1 variable", "e2": r"2 values.*3 variables"}) def testMutableItem(self): ty = self.Infer(""" @@ -95,9 +94,9 @@ def testMutableItem(self): def testBadTupleClassGetItem(self): _, errors = self.InferWithErrors("""\ v = type((3, "")) - w = v[0] + w = v[0] # not-indexable[e] """) - self.assertErrorLogIs(errors, [(2, "not-indexable", r"tuple")]) + self.assertErrorRegexes(errors, {"e": r"tuple"}) def testTupleIsInstance(self): ty = self.Infer(""" diff --git a/pytype/tests/test_type_comments.py b/pytype/tests/test_type_comments.py index a0885ec8f..b5f3dda78 100644 --- a/pytype/tests/test_type_comments.py +++ b/pytype/tests/test_type_comments.py @@ -73,22 +73,20 @@ def foo(x: int, y: str, z: float) -> None """) def testFunctionCommentOnColon(self): - _, errors = self.InferWithErrors(""" + self.InferWithErrors("""\ def f(x) \\ : # type: (None) -> None - return True + return True # bad-return-type """) - self.assertErrorLogIs(errors, [(4, "bad-return-type")]) def testMultipleFunctionComments(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ def f(x): # type: (None) -> bool - # type: (str) -> str + # type: (str) -> str # ignored-type-comment[e] return True """) - self.assertErrorLogIs(errors, [(4, "ignored-type-comment", - r"Stray type comment:.*str")]) + self.assertErrorRegexes(errors, {"e": r"Stray type comment:.*str"}) def testFunctionNoneInArgs(self): ty = self.Infer(""" @@ -183,85 +181,75 @@ class A: def testTypeCommentAfterDocstring(self): """Type comments after the docstring should not be picked up.""" - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x, y): '''Ceci n'est pas une type.''' - # type: (int, str) -> None + # type: (int, str) -> None # ignored-type-comment """) - self.assertErrorLogIs(errors, [(3, "ignored-type-comment")]) def testFunctionNoReturn(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(): - # type: () -> + # type: () -> # invalid-function-type-comment pass """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment")]) def testFunctionTooManyArgs(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 1 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 1 args, 2 given"}) def testFunctionTooFewArgs(self): _, errors = self.InferWithErrors("""\ def foo(x, y, z): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 3 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionTooFewArgsDoNotCountSelf(self): _, errors = self.InferWithErrors("""\ def foo(self, x, y, z): - # type: (int, str) -> None + # type: (int, str) -> None # invalid-function-type-comment[e] y = x return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"Expected 3 args, 2 given")]) + self.assertErrorRegexes(errors, {"e": r"Expected 3 args, 2 given"}) def testFunctionMissingArgs(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x): - # type: () -> int + # type: () -> int # invalid-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment")]) def testInvalidFunctionTypeComment(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ def foo(x): - # type: blah blah blah + # type: blah blah blah # invalid-function-type-comment return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"blah blah blah")]) def testInvalidFunctionArgs(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (abc def) -> int + # type: (abc def) -> int # invalid-function-type-comment[e] return x """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"abc def.*unexpected EOF")]) + self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) def testAmbiguousAnnotation(self): _, errors = self.InferWithErrors("""\ def foo(x): - # type: (int if __random__ else str) -> None + # type: (int if __random__ else str) -> None # invalid-function-type-comment[e] pass """) - self.assertErrorLogIs(errors, [(2, "invalid-function-type-comment", - r"int.*str.*constant")]) + self.assertErrorRegexes(errors, {"e": r"int.*str.*constant"}) class AssignmentCommentTest(test_base.TargetIndependentTest): @@ -334,10 +322,9 @@ def f() -> Tuple[Mapping, dict]: ... def testBadComment(self): ty, errors = self.InferWithErrors("""\ - X = None # type: abc def + X = None # type: abc def # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", - r"abc def.*unexpected EOF")]) + self.assertErrorRegexes(errors, {"e": r"abc def.*unexpected EOF"}) self.assertTypesMatchPytd(ty, """ from typing import Any X = ... # type: Any @@ -345,10 +332,9 @@ def testBadComment(self): def testConversionError(self): ty, errors = self.InferWithErrors("""\ - X = None # type: 1 if __random__ else 2 + X = None # type: 1 if __random__ else 2 # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", - r"1 if __random__ else 2.*constant")]) + self.assertErrorRegexes(errors, {"e": r"1 if __random__ else 2.*constant"}) self.assertTypesMatchPytd(ty, """ from typing import Any X = ... # type: Any @@ -356,18 +342,17 @@ def testConversionError(self): def testNameErrorInsideComment(self): _, errors = self.InferWithErrors("""\ - X = None # type: Foo + X = None # type: Foo # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs(errors, [(1, "invalid-type-comment", r"Foo")]) + self.assertErrorRegexes(errors, {"e": r"Foo"}) def testWarnOnIgnoredTypeComment(self): _, errors = self.InferWithErrors("""\ X = [] - X[0] = None # type: str - # type: int + X[0] = None # type: str # ignored-type-comment[e1] + # type: int # ignored-type-comment[e2] """, deep=True) - self.assertErrorLogIs(errors, [(2, "ignored-type-comment", r"str"), - (3, "ignored-type-comment", r"int")]) + self.assertErrorRegexes(errors, {"e1": r"str", "e2": r"int"}) def testAttributeInitialization(self): ty = self.Infer(""" @@ -395,15 +380,14 @@ def testNoneToNoneType(self): def testModuleInstanceAsBadTypeComment(self): _, errors = self.InferWithErrors("""\ import sys - x = None # type: sys + x = None # type: sys # invalid-annotation[e] """) - self.assertErrorLogIs(errors, [(2, "invalid-annotation", - r"instance of module.*x")]) + self.assertErrorRegexes(errors, {"e": r"instance of module.*x"}) def testForwardReference(self): ty, errors = self.InferWithErrors("""\ a = None # type: "A" - b = None # type: "Nonexistent" + b = None # type: "Nonexistent" # name-error[e] class A(object): def __init__(self): self.x = 42 @@ -418,7 +402,7 @@ def f(self) -> int a = ... # type: A b = ... # type: Any """) - self.assertErrorLogIs(errors, [(2, "name-error", r"Nonexistent")]) + self.assertErrorRegexes(errors, {"e": r"Nonexistent"}) def testClassVariableForwardReference(self): ty = self.Infer("""\ @@ -473,29 +457,27 @@ def g() -> A: ... """) def testClassVariableForwardReferenceError(self): - _, err = self.InferWithErrors("""\ + self.InferWithErrors("""\ class A(object): a = None # type: 'A' - g = A().a.foo() + g = A().a.foo() # attribute-error """) - self.assertErrorLogIs(err, [(3, "attribute-error")]) def testMultilineValue(self): ty, errors = self.InferWithErrors("""\ v = [ { - "a": 1 # type: complex + "a": 1 # type: complex # ignored-type-comment[e1] - } # type: dict[str, int] + } # type: dict[str, int] # ignored-type-comment[e2] ] # type: list[dict[str, float]] """) self.assertTypesMatchPytd(ty, """ v = ... # type: list[dict[str, float]] """) - self.assertErrorLogIs(errors, [(3, "ignored-type-comment", - r"Stray type comment: complex"), - (5, "ignored-type-comment", - r"Stray type comment: dict\[str, int\]")]) + self.assertErrorRegexes(errors, { + "e1": r"Stray type comment: complex", + "e2": r"Stray type comment: dict\[str, int\]"}) def testMultilineValueWithBlankLines(self): ty = self.Infer("""\ @@ -512,18 +494,16 @@ def testMultilineValueWithBlankLines(self): def testTypeCommentNameError(self): _, errors = self.InferWithErrors("""\ def f(): - x = None # type: Any + x = None # type: Any # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "invalid-type-comment", r"not defined$")]) + self.assertErrorRegexes(errors, {"e": r"not defined$"}) def testTypeCommentInvalidSyntax(self): _, errors = self.InferWithErrors("""\ def f(): - x = None # type: y = 1 + x = None # type: y = 1 # invalid-type-comment[e] """, deep=True) - self.assertErrorLogIs( - errors, [(2, "invalid-type-comment", r"invalid syntax$")]) + self.assertErrorRegexes(errors, {"e": r"invalid syntax$"}) def testDiscardedTypeComment(self): """Discard the first whole-line comment, keep the second.""" @@ -540,10 +520,9 @@ def hello_world() -> str: ... def testMultipleTypeComments(self): """We should not allow multiple type comments on one line.""" _, errors = self.InferWithErrors("""\ - a = 42 # type: int # type: float + a = 42 # type: int # type: float # invalid-directive[e] """) - self.assertErrorLogIs( - errors, [(1, "invalid-directive", r"Multiple")]) + self.assertErrorRegexes(errors, {"e": r"Multiple"}) def testMultipleDirectives(self): """We should support multiple directives on one line.""" @@ -613,10 +592,9 @@ def testRecursiveTypeAlias(self): errors = self.CheckWithErrors("""\ from typing import List, Union Foo = Union[str, List['Foo']] - x = 'hello' # type: Foo + x = 'hello' # type: Foo # not-supported-yet[e] """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet", - r"Recursive.*Foo")]) + self.assertErrorRegexes(errors, {"e": r"Recursive.*Foo"}) def testInstantiateFullyQuotedType(self): ty, errors = self.InferWithErrors("""\ @@ -624,7 +602,7 @@ def testInstantiateFullyQuotedType(self): x = None # type: "Optional[A]" class A(object): a = 0 - y = x.a + y = x.a # attribute-error[e] """) self.assertTypesMatchPytd(ty, """ from typing import Optional @@ -633,7 +611,7 @@ class A(object): a: int y: int """) - self.assertErrorLogIs(errors, [(5, "attribute-error", r"a.*None")]) + self.assertErrorRegexes(errors, {"e": r"a.*None"}) def testDoNotResolveLateTypeToFunction(self): ty = self.Infer(""" @@ -649,19 +627,17 @@ def A(self) -> None: ... """) def testIllegalFunctionLateType(self): - errors = self.CheckWithErrors("""\ - v = None # type: "F" + self.CheckWithErrors("""\ + v = None # type: "F" # invalid-annotation def F(): pass """) - self.assertErrorLogIs(errors, [(1, "invalid-annotation")]) def testBadTypeCommentInConstructor(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ class Foo(object): def __init__(self): - self.x = None # type: "Bar" + self.x = None # type: "Bar" # name-error """) - self.assertErrorLogIs(errors, [(3, "name-error")]) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_typevar.py b/pytype/tests/test_typevar.py index ace53ac3f..a9dedb306 100644 --- a/pytype/tests/test_typevar.py +++ b/pytype/tests/test_typevar.py @@ -32,13 +32,13 @@ def testInvalidTypeVar(self): ty, errors = self.InferWithErrors("""\ from typing import TypeVar typevar = TypeVar - T = typevar() + T = typevar() # invalid-typevar[e1] T = typevar("T") # ok - T = typevar(42) - T = typevar(str()) - T = typevar("T", str, int if __random__ else float) - T = typevar("T", 0, float) - T = typevar("T", str) + T = typevar(42) # invalid-typevar[e2] + T = typevar(str()) # invalid-typevar[e3] + T = typevar("T", str, int if __random__ else float) # invalid-typevar[e4] + T = typevar("T", 0, float) # invalid-typevar[e5] + T = typevar("T", str) # invalid-typevar[e6] # pytype: disable=not-supported-yet S = typevar("S", covariant=False) # ok T = typevar("T", covariant=False) # duplicate ok @@ -50,14 +50,11 @@ def testInvalidTypeVar(self): S = TypeVar("S") T = TypeVar("T") """) - self.assertErrorLogIs(errors, [ - (3, "invalid-typevar", r"wrong arguments"), - (5, "invalid-typevar", r"Expected.*str.*Actual.*int"), - (6, "invalid-typevar", r"constant str"), - (7, "invalid-typevar", r"must be constant"), - (8, "invalid-typevar", r"Expected.*_1:.*type.*Actual.*_1: int"), - (9, "invalid-typevar", r"0 or more than 1"), - ]) + self.assertErrorRegexes(errors, { + "e1": r"wrong arguments", "e2": r"Expected.*str.*Actual.*int", + "e3": r"constant str", "e4": r"must be constant", + "e5": r"Expected.*_1:.*type.*Actual.*_1: int", "e6": r"0 or more than 1" + }) def testPrintConstraints(self): ty = self.Infer(""" @@ -114,14 +111,12 @@ def return_arg_or_42(x: _T0) -> Union[_T0, int] """) def testTypeVarInTypeComment(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import List, TypeVar T = TypeVar("T") - x = None # type: T - y = None # type: List[T] + x = None # type: T # not-supported-yet + y = None # type: List[T] # not-supported-yet """) - self.assertErrorLogIs(errors, [(3, "not-supported-yet"), - (4, "not-supported-yet")]) def testBaseClassWithTypeVar(self): ty = self.Infer("""\ @@ -145,41 +140,33 @@ class X(l): pass """) def testBound(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", int, float, bound=str) - S = TypeVar("S", bound="") + T = TypeVar("T", int, float, bound=str) # invalid-typevar + S = TypeVar("S", bound="") # invalid-typevar U = TypeVar("U", bound=str) # ok - V = TypeVar("V", bound=int if __random__ else float) + V = TypeVar("V", bound=int if __random__ else float) # invalid-typevar """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"mutually exclusive"), - (3, "invalid-typevar", r"empty string"), - (5, "invalid-typevar", r"must be constant")]) def testCovariant(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", covariant=True) - S = TypeVar("S", covariant=42) - U = TypeVar("U", covariant=True if __random__ else False) + T = TypeVar("T", covariant=True) # not-supported-yet + S = TypeVar("S", covariant=42) # invalid-typevar[e1] + U = TypeVar("U", covariant=True if __random__ else False) # invalid-typevar[e2] """) - self.assertErrorLogIs(errors, [ - (2, "not-supported-yet"), - (3, "invalid-typevar", r"Expected.*bool.*Actual.*int"), - (4, "invalid-typevar", r"constant")]) + self.assertErrorRegexes( + errors, {"e1": r"Expected.*bool.*Actual.*int", "e2": r"constant"}) def testContravariant(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar - T = TypeVar("T", contravariant=True) - S = TypeVar("S", contravariant=42) - U = TypeVar("U", contravariant=True if __random__ else False) + T = TypeVar("T", contravariant=True) # not-supported-yet + S = TypeVar("S", contravariant=42) # invalid-typevar[e1] + U = TypeVar("U", contravariant=True if __random__ else False) # invalid-typevar[e2] """) - self.assertErrorLogIs(errors, [ - (2, "not-supported-yet"), - (3, "invalid-typevar", r"Expected.*bool.*Actual.*int"), - (4, "invalid-typevar", r"constant")]) + self.assertErrorRegexes( + errors, {"e1": r"Expected.*bool.*Actual.*int", "e2": r"constant"}) def testDontPropagatePyval(self): # in functions like f(x: T) -> T, if T has constraints we should not copy @@ -381,20 +368,18 @@ def testStoreTypeVarInDict(self): def testLateBound(self): _, errors = self.InferWithErrors("""\ from typing import TypeVar, Union - T = TypeVar("T", int, float, bound="str") - S = TypeVar("S", bound="") + T = TypeVar("T", int, float, bound="str") # invalid-typevar[e1] + S = TypeVar("S", bound="") # invalid-typevar[e2] U = TypeVar("U", bound="str") # ok - V = TypeVar("V", bound="int if __random__ else float") + V = TypeVar("V", bound="int if __random__ else float") # invalid-typevar[e3] W = TypeVar("W", bound="Foo") # ok, forward reference - X = TypeVar("X", bound="Bar") + X = TypeVar("X", bound="Bar") # name-error[e4] class Foo: pass """) - self.assertErrorLogIs(errors, [ - (2, "invalid-typevar", r"mutually exclusive"), - (3, "invalid-typevar", r"empty string"), - (5, "invalid-typevar", r"Must be constant"), - (7, "name-error", r"Name.*Bar")]) + self.assertErrorRegexes(errors, { + "e1": r"mutually exclusive", "e2": r"empty string", + "e3": r"Must be constant", "e4": r"Name.*Bar"}) def testLateConstraints(self): ty = self.Infer(""" diff --git a/pytype/tests/test_typing.py b/pytype/tests/test_typing.py index e937a94f8..efa64c16c 100644 --- a/pytype/tests/test_typing.py +++ b/pytype/tests/test_typing.py @@ -38,10 +38,10 @@ def test_cast2(self): """) def test_process_annotation_for_cast(self): - ty, errors = self.InferWithErrors("""\ + ty, _ = self.InferWithErrors("""\ import typing v1 = typing.cast(None, __any_object__) - v2 = typing.cast(typing.Union, __any_object__) + v2 = typing.cast(typing.Union, __any_object__) # invalid-annotation v3 = typing.cast("A", __any_object__) class A(object): pass @@ -53,21 +53,17 @@ class A(object): v3: A class A(object): ... """) - self.assertErrorLogIs(errors, [(3, "invalid-annotation")]) def test_no_typevars_for_cast(self): - _, errors = self.InferWithErrors("""\ + self.InferWithErrors("""\ from typing import cast, AnyStr, Type, TypeVar, _T def f(x): - return cast(AnyStr, x) + return cast(AnyStr, x) # invalid-typevar f("hello") def g(x): - return cast(AnyStr if __random__ else int, x) + return cast(AnyStr if __random__ else int, x) # invalid-typevar g("quack") """) - self.assertErrorLogIs(errors, - [(3, "invalid-typevar"), - (6, "invalid-typevar")]) def test_cast_args(self): self.assertNoCrash(self.Check, """\ @@ -139,23 +135,18 @@ def test_not_type_checking(self): """) def test_new_type_arg_error(self): - _, errors = self.InferWithErrors(""" + _, errors = self.InferWithErrors("""\ from typing import NewType - MyInt = NewType(int, 'MyInt') - MyStr = NewType(tp='str', name='MyStr') - MyFunnyNameType = NewType(name=123 if __random__ else 'Abc', tp=int) - MyFunnyType = NewType(name='Abc', tp=int if __random__ else 'int') + MyInt = NewType(int, 'MyInt') # wrong-arg-types[e1] + MyStr = NewType(tp='str', name='MyStr') # wrong-arg-types[e2] + MyFunnyNameType = NewType(name=123 if __random__ else 'Abc', tp=int) # wrong-arg-types[e3] + MyFunnyType = NewType(name='Abc', tp=int if __random__ else 'int') # wrong-arg-types[e4] """) - self.assertErrorLogIs( - errors, - [(3, "wrong-arg-types", - r".*Expected:.*str.*\nActually passed:.*Type\[int\].*"), - (4, "wrong-arg-types", - r".*Expected:.*type.*\nActually passed:.*str.*"), - (5, "wrong-arg-types", - r".*Expected:.*str.*\nActually passed:.*Union.*"), - (6, "wrong-arg-types", - r".*Expected:.*type.*\nActually passed:.*Union.*"),]) + self.assertErrorRegexes(errors, { + "e1": r".*Expected:.*str.*\nActually passed:.*Type\[int\].*", + "e2": r".*Expected:.*type.*\nActually passed:.*str.*", + "e3": r".*Expected:.*str.*\nActually passed:.*Union.*", + "e4": r".*Expected:.*type.*\nActually passed:.*Union.*"}) def test_classvar(self): ty = self.Infer("""\ @@ -188,17 +179,18 @@ class X: v: ClassVar[int, int] """) errors = self.CheckWithErrors("""\ - import foo + import foo # pyi-error[e] """, pythonpath=[d.path]) - self.assertErrorLogIs(errors, [(1, "pyi-error", r"ClassVar.*1.*2")]) + self.assertErrorRegexes(errors, {"e": r"ClassVar.*1.*2"}) class LiteralTest(test_base.TargetIndependentTest): """Tests for typing.Literal.""" def test_py(self): - errors = self.CheckWithErrors("from typing import Literal") - self.assertErrorLogIs(errors, [(1, "not-supported-yet")]) + self.CheckWithErrors("""\ + from typing import Literal # not-supported-yet + """) def test_pyi_parameter(self): with file_utils.Tempdir() as d: diff --git a/pytype/tests/test_typing_namedtuple.py b/pytype/tests/test_typing_namedtuple.py index 983006382..047aaaa0e 100644 --- a/pytype/tests/test_typing_namedtuple.py +++ b/pytype/tests/test_typing_namedtuple.py @@ -7,48 +7,37 @@ class NamedTupleTest(test_base.TargetIndependentTest): """Tests for the typing.NamedTuple overlay.""" def test_basic_calls(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing Basic = typing.NamedTuple("Basic", [('a', str)]) ex = Basic("hello world") ea = ex.a - ey = Basic() # Should fail - ez = Basic("a", "b") # Should fail + ey = Basic() # missing-parameter + ez = Basic("a", "b") # wrong-arg-count """) - self.assertErrorLogIs(errors, [ - (5, "missing-parameter"), - (6, "wrong-arg-count")]) def test_optional_field_type(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing X = typing.NamedTuple("X", [('a', str), ('b', typing.Optional[int])]) xa = X('hello', None) xb = X('world', 2) - xc = X('nope', '2') # Should fail - xd = X() # Should fail - xe = X(1, "nope") # Should fail + xc = X('nope', '2') # wrong-arg-types + xd = X() # missing-parameter + xe = X(1, "nope") # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (6, "missing-parameter"), - (7, "wrong-arg-types")]) def test_class_field_type(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing class Foo(object): pass Y = typing.NamedTuple("Y", [('a', str), ('b', Foo)]) ya = Y('a', Foo()) - yb = Y('a', 1) # Should fail - yc = Y(Foo()) # Should fail - yd = Y(1) # Should fail + yb = Y('a', 1) # wrong-arg-types + yc = Y(Foo()) # missing-parameter + yd = Y(1) # missing-parameter """) - self.assertErrorLogIs(errors, [ - (6, "wrong-arg-types"), - (7, "missing-parameter"), - (8, "missing-parameter")]) def test_late_annotation(self): errors = self.CheckWithErrors("""\ @@ -56,55 +45,44 @@ def test_late_annotation(self): class Foo(object): pass X = typing.NamedTuple("X", [('a', 'Foo')]) # should be fine - Y = typing.NamedTuple("Y", [('a', 'Bar')]) # should fail + Y = typing.NamedTuple("Y", [('a', 'Bar')]) # should fail # name-error[e] """) - self.assertErrorLogIs(errors, [(5, "name-error", "Bar")]) + self.assertErrorRegexes(errors, {"e": r"Bar"}) def test_nested_containers(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing Z = typing.NamedTuple("Z", [('a', typing.List[typing.Optional[int]])]) za = Z([1]) zb = Z([None, 2]) - zc = Z(1) # Should fail + zc = Z(1) # wrong-arg-types import typing A = typing.NamedTuple("A", [('a', typing.Dict[int, str]), ('b', typing.Tuple[int, int])]) aa = A({1: '1'}, (1, 2)) ab = A({}, (1, 2)) - ac = A(1, 2) # Should fail + ac = A(1, 2) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "wrong-arg-types"), - (11, "wrong-arg-types")]) def test_pytd_field(self): - errors = self.CheckWithErrors("""\ + self.CheckWithErrors("""\ import typing import datetime B = typing.NamedTuple("B", [('a', datetime.date)]) ba = B(datetime.date(1,2,3)) - bb = B() # Should fail - bc = B(1) # Should fail + bb = B() # missing-parameter + bc = B(1) # wrong-arg-types """) - self.assertErrorLogIs(errors, [ - (5, "missing-parameter"), - (6, "wrong-arg-types")]) def test_bad_calls(self): - _, errorlog = self.InferWithErrors("""\ + self.InferWithErrors("""\ import typing - typing.NamedTuple("_", ["abc", "def", "ghi"]) + typing.NamedTuple("_", ["abc", "def", "ghi"]) # wrong-arg-types # "def" is a keyword, so the call on the next line fails. - typing.NamedTuple("_", [("abc", int), ("def", int), ("ghi", int)]) - typing.NamedTuple("1", [("a", int)]) - typing.NamedTuple("_", [[int, "a"]]) + typing.NamedTuple("_", [("abc", int), ("def", int), ("ghi", int)]) # invalid-namedtuple-arg + typing.NamedTuple("1", [("a", int)]) # invalid-namedtuple-arg + typing.NamedTuple("_", [[int, "a"]]) # wrong-arg-types """) - self.assertErrorLogIs(errorlog, - [(2, "wrong-arg-types"), - (4, "invalid-namedtuple-arg"), - (5, "invalid-namedtuple-arg"), - (6, "wrong-arg-types")]) def test_empty_args(self): self.Check( @@ -118,27 +96,26 @@ def test_tuple_fields(self): from typing import NamedTuple X = NamedTuple("X", (("a", str),)) X(a="") - X(a=42) + X(a=42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_list_field(self): errors = self.CheckWithErrors("""\ from typing import NamedTuple X = NamedTuple("X", [["a", str]]) X(a="") - X(a=42) + X(a=42) # wrong-arg-types[e] """) - self.assertErrorLogIs(errors, [(4, "wrong-arg-types", r"str.*int")]) + self.assertErrorRegexes(errors, {"e": r"str.*int"}) def test_str_fields_error(self): errors = self.CheckWithErrors("""\ from typing import NamedTuple - X = NamedTuple("X", "a b") - Y = NamedTuple("Y", ["ab"]) + X = NamedTuple("X", "a b") # wrong-arg-types[e1] + Y = NamedTuple("Y", ["ab"]) # wrong-arg-types[e2] """) - self.assertErrorLogIs(errors, [(2, "wrong-arg-types", r"List.*str"), - (3, "wrong-arg-types", r"Tuple.*str")]) + self.assertErrorRegexes(errors, {"e1": r"List.*str", "e2": r"Tuple.*str"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_unions.py b/pytype/tests/test_unions.py index 006aaf7ba..47be85bc5 100644 --- a/pytype/tests/test_unions.py +++ b/pytype/tests/test_unions.py @@ -29,17 +29,14 @@ def f(): x = 42 if __random__: # Should not appear in output - x.__class__ = float - x.__class__ = str + x.__class__ = float # not-writable[e1] + x.__class__ = str # not-writable[e2] return type(x)() """, deep=True) self.assertTypesMatchPytd(ty, """ def f() -> int """) - self.assertErrorLogIs(errors, [ - (5, "not-writable", "int"), - (6, "not-writable", "int"), - ]) + self.assertErrorRegexes(errors, {"e1": r"int", "e2": r"int"}) test_base.main(globals(), __name__ == "__main__") diff --git a/pytype/tests/test_utils.py b/pytype/tests/test_utils.py index ee20cd10b..e552745d0 100644 --- a/pytype/tests/test_utils.py +++ b/pytype/tests/test_utils.py @@ -163,9 +163,9 @@ def _testCollectionsObject(self, obj, good_arg, bad_arg, error): # pylint: disa import collections def f(x: collections.{obj}): ... f({good_arg}) - f({bad_arg}) # line 5 + f({bad_arg}) # wrong-arg-types[e] """.format(obj=obj, good_arg=good_arg, bad_arg=bad_arg)) - self.assertErrorLogIs(result, [(4, "wrong-arg-types", error)]) + self.assertErrorRegexes(result, {"e": error}) class MakeCodeMixin(object):