def can_parse_signature_comment_with_one_formal_type_parameter(): expected_signature = nodes.signature( type_params=[nodes.formal_type_parameter("T")], args=[nodes.signature_arg(nodes.ref("T"))], returns=nodes.ref("T") ) assert_equal(expected_signature, parse_explicit_type("T => T -> T"))
def exception_handler_targets_cannot_be_accessed_from_nested_function(): target_node = nodes.ref("error") ref_node = nodes.ref("error") body = [nodes.ret(ref_node)] func_node = nodes.func("f", nodes.arguments([]), body, type=None) try_node = nodes.try_( [], handlers=[ nodes.except_(nodes.none(), target_node, [func_node]) ], ) declaration = name_declaration.ExceptionHandlerTargetNode("error") references = References([ (target_node, declaration), (ref_node, declaration), (func_node, name_declaration.VariableDeclarationNode("f")), ]) try: _updated_bindings(try_node, references=references) assert False, "Expected error" except errors.UnboundLocalError as error: assert_equal(ref_node, error.node) assert_is("error", error.name)
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 test_parse_if_else_statement(): expected = nodes.if_( nodes.ref("b"), [nodes.ret(nodes.ref("x"))], [nodes.ret(nodes.ref("y"))], ) _assert_statement_parse(expected, "if b:\n return x\nelse:\n return y")
def test_parse_with_statement_single_context_manager_with_target(): expected_node = nodes.with_( nodes.ref("x"), nodes.ref("x2"), [nodes.ret(nodes.ref("y"))], ) _assert_statement_parse(expected_node, "with x as x2:\n return y")
def test_parse_try_finally(): expected = nodes.try_( [nodes.expression_statement(nodes.ref("x"))], finally_body=[nodes.expression_statement(nodes.ref("y"))], ) _assert_statement_parse(expected, "try:\n x\nfinally:\n y")
def type_of_add_method_argument_allows_super_type(): cls = types.class_type("Addable", {}) cls.attrs.add("__add__", types.func([types.object_type], cls)) type_bindings = {"x": cls, "y": cls} addition = nodes.add(nodes.ref("x"), nodes.ref("y")) assert_equal(cls, infer(addition, type_bindings=type_bindings))
def return_type_of_add_can_differ_from_original_type(): cls = types.class_type("Addable", {}) cls.attrs.add("__add__", types.func([types.object_type], types.object_type)) type_bindings = {"x": cls, "y": cls} addition = nodes.add(nodes.ref("x"), nodes.ref("y")) assert_equal(types.object_type, infer(addition, type_bindings=type_bindings))
def type_parameters_of_function_are_definitely_bound(): param = nodes.formal_type_parameter("T") arg_ref = nodes.ref("T") returns_ref = nodes.ref("T") explicit_type = nodes.signature(type_params=[param], args=[nodes.signature_arg(arg_ref)], returns=returns_ref) func_node = nodes.func("f", nodes.arguments([]), [], type=explicit_type) _updated_bindings(func_node)
def list_comprehension_target_is_definitely_bound(): node = nodes.list_comprehension( nodes.ref("x"), nodes.ref("x"), nodes.list_literal([]), ) _updated_bindings(node)
def attributes_with_function_type_defined_in_class_definition_body_are_not_present_on_meta_type(): node = nodes.class_("User", [ nodes.assign([nodes.ref("is_person")], nodes.ref("true_func")), ]) meta_type = _infer_meta_type(node, ["is_person"], type_bindings={ "true_func": types.func([types.object_type], types.none_type) }) assert "is_person" not in meta_type.attrs
def type_name_is_definitely_bound_after_type_definition(): int_ref = nodes.ref("int") str_ref = nodes.ref("str") node = nodes.type_definition("Identifier", nodes.type_union([int_ref, str_ref])) bindings = _updated_bindings(node, is_definitely_bound=["int", "str"]) assert_equal(True, bindings.is_definitely_bound(node))
def operands_of_sub_operation_must_support_sub(): type_bindings = {"x": types.none_type, "y": types.none_type} subtraction = nodes.sub(nodes.ref("x"), nodes.ref("y")) try: infer(subtraction, type_bindings=type_bindings) assert False, "Expected error" except errors.NoSuchAttributeError as error: assert_equal(nodes.attr(subtraction.left, "__sub__"), error.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 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 test_parse_chained_boolean_operators(): _assert_expression_parse( nodes.bool_and( nodes.bool_and(nodes.ref("a"), nodes.ref("b")), nodes.ref("c"), ), "a and b and c" )
def test_parse_for_loop_with_else_body(): expected = nodes.for_( nodes.ref("x"), nodes.ref("xs"), [], [nodes.ret(nodes.ref("x"))], ) _assert_statement_parse(expected, "for x in xs:\n pass\nelse:\n return x")
def test_transform_setitem_subscript(self): _assert_transform( nodes.assign([nodes.subscript(nodes.ref("x"), nodes.ref("y"))], nodes.ref("z")), """ var __nope_u_tmp0 = z x.__setitem__(y, __nope_u_tmp0) """ )
def test_parse_single_comparison(): x = nodes.ref("x") y = nodes.ref("y") _assert_expression_parse(nodes.eq(x, y), "x == y") _assert_expression_parse(nodes.ne(x, y), "x != y") _assert_expression_parse(nodes.lt(x, y), "x < y") _assert_expression_parse(nodes.le(x, y), "x <= y") _assert_expression_parse(nodes.gt(x, y), "x > y") _assert_expression_parse(nodes.ge(x, y), "x >= y")
def test_transform_boolean_or(self): _assert_transform( nodes.bool_or(nodes.ref("x"), nodes.ref("y")), cc.ternary_conditional( cc.call(cc.builtin("bool"), [cc.ref("x")]), cc.ref("x"), cc.ref("y") ), )
def type_of_type_union_is_metatype_of_unioned_types(): type_bindings = { "str": types.meta_type(types.str_type), "int": types.meta_type(types.int_type), } node = nodes.type_union([nodes.ref("str"), nodes.ref("int")]) inferred_type = infer(node, type_bindings=type_bindings) assert types.is_meta_type(inferred_type) assert_equal(types.union(types.str_type, types.int_type), inferred_type.type)
def operands_of_add_operation_must_support_add(): type_bindings = {"x": types.none_type, "y": types.none_type} addition = nodes.add(nodes.ref("x"), nodes.ref("y")) try: infer(addition, type_bindings=type_bindings) assert False, "Expected error" except errors.NoSuchAttributeError as error: assert_equal(nodes.attr(addition.left, "__add__"), error.node) assert_equal(addition.left, ephemeral.root_node(error.node))
def list_comprehension_generator_is_not_in_same_scope_as_element(): target = nodes.ref("target") ref = nodes.ref("target") iterable = nodes.ref("target") node = nodes.list_comprehension(target, ref, iterable) declarations = _create_declarations(["target"]) references = resolve(node, declarations) assert_is_not(references.referenced_declaration(target), references.referenced_declaration(iterable))
def list_comprehension_adds_target_names_to_body_context(): target = nodes.ref("target") ref = nodes.ref("target") node = nodes.list_comprehension(target, ref, nodes.none()) declarations = _create_declarations([]) references = resolve(node, declarations) assert not declarations.is_declared("target") assert_is(references.referenced_declaration(target), references.referenced_declaration(ref))
def function_adds_arguments_to_context(): signature = nodes.signature( args=[nodes.signature_arg(nodes.ref("int"))], returns=nodes.ref("int") ) args = nodes.arguments([nodes.argument("x")]) body = [nodes.ret(nodes.ref("x"))] node = nodes.func("f", args, body, type=signature) assert_equal(types.func([types.int_type], types.int_type), _infer_func_type(node))
def can_parse_signature_with_multiple_args(): expected_signature = nodes.signature( args=[ nodes.signature_arg(nodes.ref("int")), nodes.signature_arg(nodes.ref("str")) ], returns=nodes.ref("str") ) assert_equal(expected_signature, parse_explicit_type("int, str -> str"))
def assignment_to_tuple_declares_variables_in_tuple(): first_definition_node = nodes.ref("x") second_definition_node = nodes.ref("y") node = nodes.assign([nodes.tuple_literal([first_definition_node, second_definition_node])], nodes.none()) declarations = find_declarations(node) assert_equal("x", declarations.declaration("x").name) assert_equal("y", declarations.declaration("y").name) assert isinstance(declarations.declaration("x"), name_declaration.VariableDeclarationNode) assert isinstance(declarations.declaration("y"), name_declaration.VariableDeclarationNode)
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 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]))