def test_parse_dict_literal(): _assert_expression_parse( nodes.dict_literal([ (nodes.str_literal("hello"), nodes.int_literal(4)), (nodes.str_literal("there"), nodes.int_literal(5)), ]), "{'hello': 4, 'there': 5}" )
def has_unconditional_return_is_true_if_both_branches_of_if_statement_return(): assert returns.has_unconditional_return([ nodes.if_( nodes.int_literal(1), [nodes.ret(nodes.int_literal(1))], [nodes.ret(nodes.int_literal(2))], ) ])
def type_of_dict_is_determined_by_unifying_types_of_keys_and_values(): assert_equal( types.dict_type(types.str_type, types.int_type), infer(nodes.dict_literal([ (nodes.str_literal("Hello"), nodes.int_literal(42)), (nodes.str_literal("Blah"), nodes.int_literal(16)), ])) )
def has_unconditional_return_is_false_if_only_false_branch_of_if_statement_returns(): assert not returns.has_unconditional_return([ nodes.if_( nodes.int_literal(1), [], [nodes.ret(nodes.int_literal(2))], ) ])
def dict_literal_uses_type_hint_when_valid(): assert_equal( types.dict_type(types.object_type, types.int_type), infer(nodes.dict_literal([ (nodes.str_literal("Hello"), nodes.int_literal(42)), ]), hint=types.dict_type(types.object_type, types.int_type)) ) assert_equal( types.dict_type(types.str_type, types.object_type), infer(nodes.dict_literal([ (nodes.str_literal("Hello"), nodes.int_literal(42)), ]), hint=types.dict_type(types.str_type, types.object_type)) )
def dict_literal_type_hint_is_ignored_if_hint_item_type_is_not_super_type_of_actual_item_types(): assert_equal( types.dict_type(types.str_type, types.int_type), infer(nodes.dict_literal([ (nodes.str_literal("Hello"), nodes.int_literal(42)), ]), hint=types.dict_type(types.bottom_type, types.int_type)) ) assert_equal( types.dict_type(types.str_type, types.int_type), infer(nodes.dict_literal([ (nodes.str_literal("Hello"), nodes.int_literal(42)), ]), hint=types.dict_type(types.str_type, types.bottom_type)) )
def can_assign_value_of_subtype_to_variable(): target_node = nodes.ref("x") node = nodes.assign([target_node], nodes.int_literal(1)) type_bindings = {"x": types.object_type} context = update_context(node, type_bindings=type_bindings) assert_equal(types.object_type, context.lookup_name("x"))
def can_infer_type_of_subscript_using_getitem(): cls = types.class_type("Blah", [ types.attr("__getitem__", types.func([types.int_type], types.str_type)), ]) type_bindings = {"x": cls} node = nodes.subscript(nodes.ref("x"), nodes.int_literal(4)) assert_equal(types.str_type, infer(node, type_bindings=type_bindings))
def if_statement_has_false_body_type_checked(): assert_statement_is_type_checked( lambda bad_statement: nodes.if_( nodes.int_literal(1), [], [bad_statement], ) )
def function_definitions_in_statement_lists_are_type_checked_even_if_not_invoked(): node = nodes.func("f", type=None, args=nodes.Arguments([]), body=[nodes.ret(nodes.int_literal(42))]) try: _update_context([node]) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(types.int_type, error.actual) assert_equal(types.none_type, error.expected)
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 for_statement_target_can_be_supertype_of_iterable_element_type(): ref_node = nodes.ref("xs") node = nodes.for_(nodes.subscript(nodes.ref("ys"), nodes.int_literal(0)), ref_node, []) update_context(node, type_bindings={ "xs": types.list_type(types.int_type), "ys": types.list_type(types.object_type), })
def values_can_have_same_name_as_child_module_if_they_are_not_in_module_scope(): value_node = nodes.assign([nodes.ref("x")], nodes.int_literal(1)) node = nodes.module([ nodes.func("f", nodes.args([]), [value_node], type=None) ], is_executable=False) _check_module(LocalModule("root/__init__.py", node), { (".", "x"): module({}), })
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 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 can_infer_type_of_function_with_no_args_and_return_annotation(): node = nodes.func( "f", args=nodes.arguments([]), body=[ nodes.ret(nodes.int_literal(4)) ], type=nodes.signature(returns=nodes.ref("int")), ) assert_equal(types.func([], types.int_type), _infer_func_type(node))
def can_infer_type_of_list_comprehension_over_list(): type_bindings = {"xs": types.list_type(types.str_type)} node = nodes.list_comprehension( nodes.int_literal(1), nodes.ref("x"), nodes.ref("xs"), ) assert_equal( types.list_type(types.int_type), infer(node, type_bindings=type_bindings) )
def module_exports_default_to_values_without_leading_underscore_if_all_is_not_specified(): module_node = nodes.module([ nodes.assign(["x"], nodes.str_literal("one")), nodes.assign(["_y"], nodes.str_literal("two")), nodes.assign(["z"], nodes.int_literal(3)), ]) module, type_lookup = _check(LocalModule(None, module_node)) assert_equal(types.str_type, module.attrs.type_of("x")) assert_equal(None, module.attrs.get("_y")) assert_equal(types.int_type, module.attrs.type_of("z"))
def assignment_to_variable_with_incompatible_type_raises_error(): target_node = nodes.ref("x") node = nodes.assign([target_node], nodes.int_literal(1)) type_bindings = {"x": types.none_type} try: update_context(node, type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(target_node, error.node) assert_equal(types.int_type, error.value_type) assert_equal(types.none_type, error.target_type)
def module_exports_are_specified_using_all(): module_node = nodes.module([ nodes.assign(["__all__"], nodes.list_literal([nodes.str_literal("x"), nodes.str_literal("z")])), nodes.assign(["x"], nodes.str_literal("one")), nodes.assign(["y"], nodes.str_literal("two")), nodes.assign(["z"], nodes.int_literal(3)), ]) module, type_lookup = _check(LocalModule(None, module_node)) assert_equal(types.str_type, module.attrs.type_of("x")) assert_equal(None, module.attrs.get("y")) assert_equal(types.int_type, module.attrs.type_of("z"))
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_is_raised_if_value_in_package_has_same_name_as_module(): target_node = nodes.ref("x") node = nodes.module([nodes.assign([target_node], nodes.int_literal(1))], is_executable=False) try: _check_module(LocalModule("root/__init__.py", node), { (".", "x"): module({}), }) assert False, "Expected error" except errors.ImportedValueRedeclaration as error: assert_equal(target_node, error.node) assert_equal("Cannot declare value 'x' in module scope due to child module with the same name", str(error))
def check_generates_type_lookup_for_all_expressions(): int_ref_node = nodes.ref("a") int_node = nodes.int_literal(3) str_node = nodes.str_literal("Hello") module_node = nodes.module([ nodes.assign(["a"], int_node), nodes.func("f", nodes.args([]), [ nodes.assign("b", int_ref_node), nodes.assign("c", str_node), ], type=None), ]) module, type_lookup = _check(LocalModule(None, module_node)) assert_equal(types.int_type, type_lookup.type_of(int_node)) assert_equal(types.int_type, type_lookup.type_of(int_ref_node)) assert_equal(types.str_type, type_lookup.type_of(str_node))
def assignment_to_list_does_not_allow_supertype(): target_sequence_node = nodes.ref("x") value_node = nodes.ref("y") node = nodes.assign([nodes.subscript(target_sequence_node, nodes.int_literal(0))], value_node) type_bindings = { "x": types.list_type(types.str_type), "y": types.object_type, } try: update_context(node, type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(target_sequence_node, ephemeral.root_node(error.node)) assert_equal( ephemeral.FormalArg(ephemeral.attr(target_sequence_node, "__setitem__"), 1), ephemeral.underlying_node(error.node) ) assert_equal(types.object_type, error.value_type) assert_equal(types.str_type, error.target_type)
def for_statement_target_cannot_be_strict_subtype_of_iterable_element_type(): target_sequence_node = nodes.ref("ys") target_node = nodes.subscript(target_sequence_node, nodes.int_literal(0)) iterable_node = nodes.ref("xs") node = nodes.for_(target_node, iterable_node, []) try: update_context(node, type_bindings={ "xs": types.list_type(types.object_type), "ys": types.list_type(types.int_type), }) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(target_sequence_node, ephemeral.root_node(error.node)) assert_equal( ephemeral.FormalArg(ephemeral.attr(target_sequence_node, "__setitem__"), 1), ephemeral.underlying_node(error.node) ) assert_equal(types.object_type, error.value_type) assert_equal(types.int_type, error.target_type)
def int_has_no_references(): _assert_no_references(nodes.int_literal(4))
def has_unconditional_return_is_true_if_list_contains_a_return_statement(): assert returns.has_unconditional_return([ nodes.ret(nodes.int_literal(1)) ])
def operands_of_is_operation_are_type_checked(): assert_subexpression_is_type_checked(lambda bad_ref: nodes.is_(bad_ref, nodes.int_literal(1))) assert_subexpression_is_type_checked(lambda bad_ref: nodes.is_(nodes.int_literal(1), bad_ref))
def can_infer_type_of_subscript_of_list(): type_bindings = {"x": types.list_type(types.str_type)} node = nodes.subscript(nodes.ref("x"), nodes.int_literal(4)) assert_equal(types.str_type, infer(node, type_bindings=type_bindings))
def can_infer_type_of_slice(): node = nodes.slice(nodes.str_literal(""), nodes.int_literal(4), nodes.none()) assert_equal( types.slice_type(types.str_type, types.int_type, types.none_type), infer(node) )