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 attributes_assigned_in_init_can_be_used_in_methods_when_init_method_is_defined_after_other_method(): 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") ), ) node = nodes.class_("User", [ nodes.func( name="g", args=nodes.args([nodes.arg("self_g")]), body=[nodes.ret(nodes.attr(nodes.ref("self_g"), "message"))], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("str") ), ), init_func, ]) _infer_class_type(node, ["__init__", "g"], [(init_func, ["self_init"])])
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 init_method_is_used_as_call_method_on_meta_type(): node = _create_class_with_init( signature=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self")), nodes.signature_arg(nodes.ref("str"))], returns=nodes.ref("none") ), args=nodes.args([nodes.arg("self"), nodes.arg("name")]), body=[], ) meta_type = _infer_meta_type(node, ["__init__"]) assert_equal(types.func([types.str_type], meta_type.type), meta_type.attrs.type_of("__call__"))
def can_have_required_arguments_before_optional_arguments(self): source = """ #:: str, str, ?str, ?str -> str def f(a, b, c=None, d=None): pass """ module_node = parser.parse(source) expected = nodes.args([ nodes.arg("a"), nodes.arg("b"), nodes.arg("c", optional=True), nodes.arg("d", optional=True), ]) assert_equal(expected, module_node.body[0].args)
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 optional_arg_can_have_default_value_of_none(self): source = """ #:: ?str -> str def f(x=None): pass """ module_node = parser.parse(source) expected = nodes.args([nodes.arg("x", optional=True)]) assert_equal(expected, module_node.body[0].args)
def init_method_is_not_present_on_instance(): node = _create_class_with_init( signature=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("none") ), args=nodes.args([nodes.arg("self")]), body=[], ) meta_type = _infer_meta_type(node, ["__init__"]) assert not "__init__" in meta_type.type.attrs
def attributes_with_function_type_defined_in_class_definition_body_are_bound_to_class_type(): node = nodes.class_("User", [ nodes.func( name="is_person", args=nodes.args([nodes.arg("self")]), body=[nodes.ret(nodes.bool_literal(True))], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("bool") ), ), ]) class_type = _infer_class_type(node, ["is_person"]) assert_equal(types.func([], types.bool_type), class_type.attrs.type_of("is_person"))
def first_argument_in_method_signature_can_be_strict_supertype_of_class(): node = nodes.class_("User", [ nodes.func( name="is_person", args=nodes.args([nodes.arg("self")]), body=[nodes.ret(nodes.bool_literal(True))], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("object"))], returns=nodes.ref("bool") ), ) ]) class_type = _infer_class_type(node, ["is_person"]) assert_equal(types.func([], types.bool_type), class_type.attrs.type_of("is_person"))
def init_method_must_return_none(): node = _create_class_with_init( signature=nodes.signature( args=[nodes.signature_arg(nodes.ref("Self"))], returns=nodes.ref("str") ), args=nodes.args([nodes.arg("self")]), body=[nodes.ret(nodes.str_literal(""))], ) try: _infer_meta_type(node, ["__init__"]) assert False, "Expected error" except errors.InitMethodsMustReturnNoneError as error: assert_equal(node.body[0], error.node)
def test_does_not_redeclare_variables_with_same_name_as_argument(self): _assert_transform( nodes.func( name="f", args=nodes.args([nodes.arg("x")]), body=[ nodes.assign(["x"], nodes.ref("y")), nodes.ret(nodes.ref("value")), ], type=None, ), cc.func("f", [cc.arg("x")], [ cc.assign(cc.ref("x"), cc.ref("y")), cc.ret(cc.ref("value")), ]) )
def self_argument_in_method_signature_cannot_be_unrelated_type(): func_node = nodes.func( name="is_person", args=nodes.args([nodes.arg("self")]), body=[nodes.ret(nodes.bool_literal(True))], type=nodes.signature( args=[nodes.signature_arg(nodes.ref("bool"))], returns=nodes.ref("bool") ), ) node = nodes.class_("User", [func_node]) try: _infer_class_type(node, ["is_person"]) assert False, "Expected error" except errors.UnexpectedReceiverTypeError as error: assert_equal(func_node, error.node) assert_equal(types.bool_type, error.receiver_type) assert_equal("first argument of methods should have Self type but was 'bool'", str(error))
def can_assign_literal_to_attribute(): init_func = nodes.func( name="__init__", args=nodes.args([nodes.arg("self")]), body=[ nodes.assign( [nodes.attr(nodes.ref("self"), "value")], nodes.none(), ) ], type=_no_arg_init_signature, ) node = nodes.class_("Box", [ init_func ]) class_type = _infer_class_type( node, ["__init__"], [(init_func, ["self"])]) assert_equal(types.none_type, class_type.attrs.type_of("value"))
def error_is_raised_if_attribute_assignment_has_no_explicit_and_not_literal_nor_argument_value(): init_func = nodes.func( name="__init__", args=nodes.args([nodes.arg("self")]), body=[ nodes.assign( [nodes.attr(nodes.ref("self"), "message")], nodes.ref("message"), ) ], type=_no_arg_init_signature, ) node = nodes.class_("User", [ init_func ]) error = assert_raises(errors.ClassAttributeTypeError, lambda: _infer_class_type( node, ["__init__"], [(init_func, ["self"])], type_bindings={"message": types.str_type})) assert_equal("Could not infer type of attribute. Attribute assignments must be explicitly typed, or a literal, or an argument", str(error))
def can_assign_any_value_to_attribute_if_assignment_is_explicitly_typed(): init_func = nodes.func( name="__init__", args=nodes.args([nodes.arg("self")]), body=[ nodes.assign( [nodes.attr(nodes.ref("self"), "message")], nodes.ref("message"), type=nodes.ref("str"), ) ], type=_no_arg_init_signature, ) node = nodes.class_("User", [ init_func ]) class_type = _infer_class_type( node, ["__init__"], [(init_func, ["self"])], type_bindings={"message": types.str_type}) assert_equal(types.str_type, class_type.attrs.type_of("message"))
def test_arguments_are_transformed(self): _assert_transform( nodes.func("f", nodes.args([nodes.arg("value")]), [nodes.ret(nodes.ref("value"))], type=None), cc.func("f", [cc.arg("value")], [cc.ret(cc.ref("value"))]), )
def declarations_in_function_include_argument_declarations(): node = nodes.func("f", nodes.arguments([nodes.arg("x")]), [], type=None) declarations = _declarations_in(node) assert isinstance(declarations.declaration("x"), name_declaration.VariableDeclarationNode) assert not declarations.is_declared("f")
def argument_adds_declaration_to_declarations(): node = nodes.arg("x") declarations = find_declarations(node) assert isinstance(declarations.declaration("x"), name_declaration.VariableDeclarationNode)
def arguments_of_function_are_definitely_bound(): arg = nodes.arg("x") arg_ref = nodes.ref("x") func_node = nodes.func("f", nodes.arguments([arg]), [nodes.expression_statement(arg_ref)], type=None) _updated_bindings(func_node)