def method_can_call_method_on_same_instance_defined_later_in_body(): node = nodes.class_("User", [ nodes.func( name="f", args=nodes.args([nodes.arg("self_f")]), body=[ nodes.ret(nodes.call(nodes.attr(nodes.ref("self_f"), "g"), [])) ], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ), ), nodes.func( name="g", args=nodes.args([nodes.arg("self_g")]), body=[ nodes.ret(nodes.call(nodes.attr(nodes.ref("self_g"), "f"), [])) ], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ), ) ]) _infer_class_type(node, ["f", "g"])
def function_definitions_in_statement_lists_can_be_mutually_recursive(): f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(nodes.ref("g"), [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(nodes.ref("f"), [])) ]) _update_context([f, g])
def function_definitions_can_be_mutually_recursive(): f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(nodes.ref("g"), [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(nodes.ref("f"), [])) ]) _updated_bindings(nodes.module([f, g]))
def call_has_child_names_resolved(): _assert_children_resolved( lambda ref: nodes.call(ref, []), ) _assert_children_resolved( lambda ref: nodes.call(nodes.none(), [ref]), ) _assert_children_resolved( lambda ref: nodes.call(nodes.none(), [], {"blah": ref}), )
def init_method_cannot_call_other_methods(): node = nodes.class_("User", [ nodes.func( name="__init__", args=nodes.args([nodes.arg("self_init")]), body=[ nodes.assign([nodes.ref("x")], nodes.call(nodes.attr(nodes.ref("self_init"), "g"), [])) ], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ), ), nodes.func( name="g", args=nodes.args([nodes.arg("self_g")]), body=[], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ), ), ]) try: _infer_class_type(node, ["__init__", "g"]) assert False, "Expected error" except errors.InitMethodCannotGetSelfAttributes as error: assert_equal("__init__ methods cannot get attributes of self", str(error))
def function_definitions_in_statement_lists_can_be_defined_out_of_order(): f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(nodes.ref("g"), [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[]) _updated_bindings(nodes.module([f, g]))
def callee_can_be_overloaded_func_type_where_choice_is_unambiguous_given_args(): type_bindings = {"f": types.overloaded_func( types.func([types.str_type], types.int_type), types.func([types.int_type], types.str_type), )} node = nodes.call(nodes.ref("f"), [nodes.str_literal("")]) assert_equal(types.int_type, infer(node, type_bindings=type_bindings))
def attributes_assigned_in_init_can_be_used_outside_of_class(): init_func = nodes.func( name="__init__", args=nodes.args([nodes.arg("self_init")]), body=[ nodes.assign( [nodes.attr(nodes.ref("self_init"), "message")], nodes.str_literal("Hello"), type=nodes.ref("str"), ) ], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ) ) class_node = nodes.class_("User", [init_func]) node = [ class_node, nodes.assign([nodes.ref("x")], nodes.attr(nodes.call(nodes.ref("User"), []), "message")), ] context = _update_context(node, declared_names_in_node=NodeDict([ (class_node, ["Self", "__init__"]), (init_func, ["self_init"]), ])) assert_equal(types.str_type, context.lookup_name("x"))
def test_parse_call_with_keyword_arguments(): expected = nodes.call( nodes.ref("f"), [], {"person": nodes.ref("bob"), "hat": nodes.ref("fedora")}, ) _assert_expression_parse(expected, "f(person=bob, hat=fedora)")
def type_of_keyword_arguments_must_match(): node = nodes.call(nodes.ref("f"), [], {"name": nodes.str_literal("Bob"), "hats": nodes.int_literal(42)}) type_bindings = { "f": types.func( args=[types.func_arg("name", types.str_type)], return_type=types.bool_type, ) } arg_node = nodes.int_literal(4) node = nodes.call(nodes.ref("f"), [], {"name": arg_node}) assert_type_mismatch( lambda: infer(node, type_bindings=type_bindings), expected=types.str_type, actual=types.int_type, node=arg_node, )
def can_infer_type_of_call_with_optional_argument_specified(): type_bindings = { "f": types.func( args=[types.func_arg(None, types.str_type, optional=True)], return_type=types.bool_type, ) } node = nodes.call(nodes.ref("f"), [nodes.str_literal("blah")]) assert_equal(types.bool_type, infer(node, type_bindings=type_bindings))
def test_parse_generator_expression(): _assert_expression_parse( nodes.generator_expression( nodes.call(nodes.ref("f"), [nodes.ref("x")]), nodes.ref("x"), nodes.ref("xs"), ), "(f(x) for x in xs)" )
def test_parse_single_list_comprehension(): _assert_expression_parse( nodes.list_comprehension( nodes.call(nodes.ref("f"), [nodes.ref("x")]), nodes.ref("x"), nodes.ref("xs"), ), "[f(x) for x in xs]" )
def object_can_be_called_if_it_has_call_magic_method_that_returns_callable(): second_cls = types.class_type("Second", [ types.attr("__call__", types.func([types.str_type], types.int_type)), ]) first_cls = types.class_type("First", [ types.attr("__call__", second_cls), ]) type_bindings = {"f": first_cls} assert_equal(types.int_type, infer(nodes.call(nodes.ref("f"), [nodes.str_literal("")]), type_bindings=type_bindings))
def generic_type_arguments_are_covariant(): type_bindings = {"f": types.generic_func(["T"], lambda T: types.func([T, T], T), )} node = nodes.call(nodes.ref("f"), [nodes.str_literal(""), nodes.none()]) assert_equal( types.common_super_type([types.str_type, types.none_type]), infer(node, type_bindings=type_bindings) )
def can_infer_type_of_call_with_keyword_arguments(): type_bindings = { "f": types.func( args=[types.func_arg("name", types.str_type), types.func_arg("hats", types.int_type)], return_type=types.bool_type, ) } node = nodes.call(nodes.ref("f"), [], {"name": nodes.str_literal("Bob"), "hats": nodes.int_literal(42)}) assert_equal(types.bool_type, infer(node, type_bindings=type_bindings))
def return_type_is_common_super_type_of_possible_return_types_of_overloaded_function(): type_bindings = {"f": types.overloaded_func( types.func([types.object_type], types.int_type), types.func([types.str_type], types.str_type), )} node = nodes.call(nodes.ref("f"), [nodes.str_literal("")]) assert_equal( types.common_super_type([types.int_type, types.str_type]), infer(node, type_bindings=type_bindings) )
def test_transform_call_with_positional_arguments(self): func_node = nodes.ref("f") type_lookup = [ (func_node, types.func([types.str_type], types.none_type)) ] _assert_transform( nodes.call(func_node, [nodes.ref("x")]), cc.call(cc.ref("f"), [cc.ref("x")]), type_lookup=type_lookup, )
def type_of_positional_arguments_must_match(): type_bindings = {"f": types.func([types.str_type], types.int_type)} arg_node = nodes.int_literal(4) node = nodes.call(nodes.ref("f"), [arg_node]) assert_type_mismatch( lambda: infer(node, type_bindings=type_bindings), expected=types.str_type, actual=types.int_type, node=arg_node, )
def test_transform_call_magic_method(self): func_node = nodes.ref("str") type_lookup = [ (func_node, types.str_meta_type) ] _assert_transform( nodes.call(func_node, [nodes.ref("x")]), """str.__call__(x)""", type_lookup=type_lookup, )
def call_attribute_must_be_function(): cls = types.class_type("Blah", [types.attr("__call__", types.int_type)]) type_bindings = {"f": cls} callee_node = nodes.ref("f") try: infer(nodes.call(callee_node, []), type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(callee_node, ephemeral.root_node(error.node)) assert_equal("callable object", error.expected) assert_equal(types.int_type, error.actual)
def callee_must_be_function_or_have_call_magic_method(): cls = types.class_type("Blah", {}) type_bindings = {"f": cls} callee_node = nodes.ref("f") try: infer(nodes.call(callee_node, []), type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(callee_node, error.node) assert_equal("callable object", error.expected) assert_equal(cls, error.actual)
def error_if_generic_func_is_passed_wrong_arguments(): type_bindings = {"f": types.generic_func(["T"], lambda T: types.func([T, types.int_type], T), )} node = nodes.call(nodes.ref("f"), [nodes.str_literal(""), nodes.none()]) try: infer(node, type_bindings=type_bindings) assert False, "Expected error" except errors.ArgumentsError as error: assert_is(node, error.node) assert_equal("cannot call function of type: T => T, int -> T\nwith arguments: str, NoneType", str(error))
def method_can_reference_later_function_if_class_is_not_used_in_the_interim(): g_ref = nodes.ref("g") f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(g_ref, [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[]) _updated_bindings(nodes.module([ nodes.class_("a", [f]), g, ]))
def can_infer_type_of_call_with_specified_optional_argument_after_unspecified_optional_argument(): type_bindings = { "f": types.func( args=[ types.func_arg("x", types.str_type, optional=True), types.func_arg("y", types.int_type, optional=True), ], return_type=types.bool_type, ) } node = nodes.call(nodes.ref("f"), [], {"y": nodes.int_literal(42)}) assert_equal(types.bool_type, infer(node, type_bindings=type_bindings))
def error_in_inferring_actual_argument_to_overloaded_function_is_not_failure_to_find_matching_overload(): type_bindings = {"f": types.overloaded_func( types.func([types.object_type], types.any_type), types.func([types.str_type], types.any_type), )} ref = nodes.ref("x") try: infer(nodes.call(nodes.ref("f"), [ref]), type_bindings=type_bindings) assert False, "Expected error" except errors.TypeCheckError as error: assert_equal(ref, error.node)
def function_cannot_be_referenced_before_definition_of_dependencies(): g_ref = nodes.ref("g") f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(g_ref, [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[]) try: _updated_bindings(nodes.module([ f, nodes.expression_statement(nodes.ref("f")), g, ])) assert False, "Expected error" except errors.UnboundLocalError as error: assert_equal(g_ref, error.node)
def class_cannot_be_referenced_if_method_dependencies_are_not_bound(): g_ref = nodes.ref("g") f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[ nodes.ret(nodes.call(g_ref, [])) ]) g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[]) try: _updated_bindings(nodes.module([ nodes.class_("a", [f]), nodes.expression_statement(nodes.ref("a")), g, ])) assert False, "Expected error" except errors.UnboundLocalError as error: assert_equal(g_ref, error.node)
def test_transform_call_with_keyword_arguments(self): func_node = nodes.ref("f") type_lookup = [ (func_node, types.func( [ types.func_arg("first", types.str_type), types.func_arg("second", types.str_type), ], types.none_type )) ] _assert_transform( nodes.call(func_node, [], {"first": nodes.ref("x"), "second": nodes.ref("y")}), cc.call(cc.ref("f"), [cc.ref("x"), cc.ref("y")]), type_lookup=type_lookup, )
def formal_type_of_argument_is_used_as_type_hint_for_actual_argument(): type_bindings = {"f": types.func([types.list_type(types.str_type)], types.int_type)} node = nodes.call(nodes.ref("f"), [nodes.list_literal([])]) assert_equal(types.int_type, infer(node, type_bindings=type_bindings))