def test_no_source_kwarg(self): src = utils.func_from_source("def test(): pass") hint = utils.func_from_source("def test(**a): ...") err = errors.WrongKwarg(src, hint) self.assertRegex( err.message, r"Type hint for function test should not have " r"keyword argument '\*\*a'\.")
def test_no_hint_vararg(self): src = utils.func_from_source("def test(*c): pass") hint = utils.func_from_source("def test(a, b): ...") err = errors.WrongVararg(src, hint) self.assertRegex( err.message, r"Type hint for function test is missing the vararg '\*c'.")
def test_no_source_vararg(self): src = utils.func_from_source("def test(a, b, **g): pass") hint = utils.func_from_source("def test(*a, **g): ...") err = errors.WrongVararg(src, hint) self.assertRegex( err.message, r"Type hint for function test should not have vararg '\*a'.")
def test_wrong_arg_name(self): src = utils.func_from_source("def test(a, b, e): pass") hint = utils.func_from_source("def test(a, b, c): ...") err = errors.WrongArgName(src, hint, "c") self.assertRegex( err.message, r"Function test has no argument named 'c'.\n" r".*Source:\s*def test\(a, b, e\)\n", r".*Type hint:\s*def test\(a, b, c\)\n")
def test_wrong_vararg_name(self): src = utils.func_from_source("def test(a, b, *c, d, e): pass") hint = utils.func_from_source("def test(a, b, *z, d, e): ...") err = errors.WrongVararg(src, hint) self.assertRegex( err.message, r"Type hint for function test has wrong vararg name.\n" r".*Source:\s*def test\(\.\.\., \*c, \.\.\.\)\n" r".*Type hint:\s*def test\(\.\.\., \*z, \.\.\.\)$")
def test_function_sigs_differ(self): # Since definitions are dataclasses, they're compared is if they were tuples # of elements. Therefore these two Function instances should be considered # different, since they have different keyword-only argument orders. # The richer comparison performed by the pyi checker would consider them # the same, since keyword-only argument order doesn't really matter. func1 = utils.func_from_source("def foo(a, *c, d, e): pass") func2 = utils.func_from_source("def foo(a, *c, e, d): pass") self.assertNotEqual(func1, func2)
def test_no_source_kwonly_count(self): src = utils.func_from_source("def test(): pass") hint = utils.func_from_source("def test(*, a, b,): ...") err = errors.WrongKwonlyCount(src, hint) self.assertRegex( err.message, r"Type hint for function test has the wrong number " r"of keyword-only arguments.\n" r".*Source:\s*def test\(\)\n" r".*Type hint:\s*def test\(\*, a, b\)$")
def test_no_hint_arg_count(self): src = utils.func_from_source("def test(a, b): pass") hint = utils.func_from_source("def test(*c): ...") err = errors.WrongArgCount(src, hint) self.assertRegex( err.message, r"Type hint for function test has the wrong number of arguments.\n" r".*Source:\s*def test\(a, b\)\n" r".*Type hint:\s*def test\(\.\.\.\)$")
def test_wrong_kwonly_name(self): src = utils.func_from_source("def test(*, d, e, f): pass") hint = utils.func_from_source("def test(*, d, c, f): ...") err = errors.WrongKwonlyName(src, hint, "c") self.assertRegex( err.message, r"Function test has no keyword-only argument named 'c'.\n" r".*Source:\s*def test\(\*, d, e, f\)\n" r".*Type hint:\s*def test\(\*, d, c, f\)$")
def test_wrong_kwarg_name(self): src = utils.func_from_source("def test(a, b, **e): pass") hint = utils.func_from_source("def test(a, b, **c): ...") err = errors.WrongKwarg(src, hint) self.assertRegex( err.message, r"Type hint for function test has wrong keyword argument name.\n" r".*Source:\s*def test\(\.\.\., \*\*e\)\n" r".*Type hint:\s*def test\(\.\.\., \*\*c\)$")
def test_wrong_kwonly_count(self): src = utils.func_from_source("def test(a, b, *c, d, e, f, **g): pass") hint = utils.func_from_source( "def test(a, b, *c, d, e, f, h, **g): ...") err = errors.WrongKwonlyCount(src, hint) self.assertRegex( err.message, r"Type hint for function test has the wrong number " r"of keyword-only arguments.\n" r".*Source:\s*def test\(\.\.\., \*c, d, e, f, \.\.\.\)\n", r".*Type hint:\s*def test\(\.\.\., \*c, d, e, f, h, \.\.\.\)$")
def test_extra_type_hint(self): src = utils.func_from_source("def test(a, b) -> int: ...") err = errors.ExtraTypeHint(src) self.assertRegex( err.message, "Type hint for function test has no corresponding source definition." )
def test_wrong_decorators(self): src = utils.func_from_source(""" @dec1 @dec2 @dec3 def test(): ... """) hint = utils.func_from_source(""" @dec1 @decZ def test(): ... """) err = errors.WrongDecorators(src, hint) self.assertRegex( err.message, r"^Type hint for function test has incorrect decorators.\n" r".*Missing.*: dec2, dec3\n.*Extras.*: decZ$")
def test_function_async(self): func_str = "async def test(): pass" expected = utils.make_func( name="test", col_offset=6, # "async" doesn't count as part of definition. is_async=True) actual = utils.func_from_source(func_str) self.assertEqual(expected, actual)
def test_wrong_type_hint(self): src = utils.func_from_source("def test(a, b) -> int: ...") hint = utils.class_from_source("class test: ...") err = errors.WrongTypeHint(src, hint) self.assertRegex( err.message, r"^Type hint kind does not match source definition.\n.*" r"function test.*\n.*class test$")
def test_function_all_args(self): func_str = "def foo(arg1, arg2=2, *var, key1, key2=2, **keys): pass" expected = utils.make_func( name="foo", params=[utils.make_arg("arg1", col_offset=8), utils.make_arg("arg2", col_offset=14, has_default=True)], vararg=utils.make_arg("var", col_offset=23), kwonlyargs=[utils.make_arg("key1", col_offset=28), utils.make_arg("key2", col_offset=34, has_default=True)], kwarg=utils.make_arg("keys", col_offset=44)) actual = utils.func_from_source(func_str) self.assertEqual(expected, actual)
def test_function_decorators(self): func_str = textwrap.dedent("""\ @some_decorator @another_decorator def test(): pass """) expected = utils.make_func( name="test", lineno=1, # Decorators all count as 1 line. decorators=["some_decorator", "another_decorator"]) actual = utils.func_from_source(func_str) self.assertEqual(expected, actual)
def test_function_async(self): func_str = "async def test(): pass" expected = utils.make_func(name="test", col_offset=0, is_async=True) actual = utils.func_from_source(func_str) self.assertEqual(expected, actual)
def test_function_basic(self): expected = utils.make_func(name="foo") actual = utils.func_from_source("def foo(): pass") self.assertEqual(expected, actual)
def test_missing_type_hint(self): src = utils.func_from_source("def test(a, b): return a + b") err = errors.MissingTypeHint(src) self.assertRegex(err.message, "No type hint found for function test.")