예제 #1
0
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))
예제 #2
0
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"])
예제 #3
0
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"])])
예제 #4
0
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"))
예제 #5
0
def break_is_not_valid_in_function_in_while_loop_body():
    break_node = nodes.break_()
    func_node = nodes.func("f", nodes.args([]), [break_node], type=None)
    node = nodes.while_(nodes.bool_literal(True), [func_node], [])
    error = assert_raises(errors.TypeCheckError,
        lambda: check_loop_control(node, False))
    assert_equal(break_node, error.node)
    assert_equal("'break' outside loop", str(error))
예제 #6
0
def function_can_have_no_signature_if_it_takes_no_args():
    source = """
def f():
    pass
"""
    
    module_node = parser.parse(source)
    expected = nodes.func("f", nodes.args([]), [], type=None)
    assert_equal(expected, module_node.body[0])
예제 #7
0
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({}),
    })
예제 #8
0
 def test_function_definitions_in_body_are_stored_as_methods(self):
     _assert_transform(
         nodes.class_("Blah", [nodes.func("f", nodes.args([]), [], type=None)]),
         cc.class_(
             "Blah",
             methods=[cc.func("f", [], [cc.ret(cc.none)])],
             body=[cc.declare("f")],
         ),
     )
예제 #9
0
    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)
예제 #10
0
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__"))
예제 #11
0
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
예제 #12
0
def class_definition_functions_ignore_class_scope_when_resolving_references():
    ref = nodes.ref("x")
    node = nodes.class_("User", [
        nodes.assign([nodes.ref("x")], nodes.none()),
        nodes.func("f", nodes.args([]), [nodes.ret(ref)], type=None),
    ])
    
    declarations = _create_declarations(["x", "User"])
    
    references = resolve(node, declarations)
    assert_is(declarations.declaration("x"), references.referenced_declaration(ref))
예제 #13
0
 def test_variables_are_declared(self):
     _assert_transform(
         nodes.func("f", nodes.args([]), [
             nodes.assign([nodes.ref("x")], nodes.ref("y")),
             nodes.ret(nodes.ref("value")),
         ], type=None),
         cc.func("f", [], [
             cc.declare("x"),
             cc.assign(cc.ref("x"), cc.ref("y")),
             cc.ret(cc.ref("value")),
         ]),
     )
예제 #14
0
def can_parse_signature_comment_with_no_args_for_function_after_indent():
    source = """
#:: -> str
def f():
    #:: -> int
    def g():
        pass
"""
    
    module_node = parser.parse(source)
    signature = nodes.signature(returns=nodes.ref("int"))
    expected = nodes.func("g", nodes.args([]), [], type=signature)
    assert_equal(expected, module_node.body[0].body[0])
예제 #15
0
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"))
예제 #16
0
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)
예제 #17
0
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"))
예제 #18
0
    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)
예제 #19
0
 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")),
         ])
     )
예제 #20
0
 def test_does_not_redeclare_variables_with_same_name_as_type_parameter(self):
     _assert_transform(
         nodes.func(
             name="f",
             args=nodes.args([]),
             body=[],
             type=nodes.signature(
                 type_params=[nodes.formal_type_parameter("T")],
                 args=[],
                 returns=nodes.ref("T"),
             ),
         ),
         cc.func("f", [], [
             cc.ret(cc.none),
         ])
     )
예제 #21
0
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))
예제 #22
0
def methods_must_have_at_least_one_argument():
    func_node = nodes.func(
        name="is_person",
        args=nodes.args([]),
        body=[nodes.ret(nodes.bool_literal(True))],
        type=nodes.signature(
            args=[],
            returns=nodes.ref("bool")
        )
    )
    node = nodes.class_("User", [func_node])
    try:
        _infer_class_type(node, ["is_person"])
        assert False, "Expected error"
    except errors.MethodHasNoArgumentsError as error:
        assert_equal(func_node, error.node)
        assert_equal("'is_person' method must have at least one argument", str(error))
예제 #23
0
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))
예제 #24
0
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"))
예제 #25
0
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))
예제 #26
0
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"))
예제 #27
0
 def test_function_without_explicit_return_on_all_paths_returns_none_at_end(self):
     _assert_transform(
         nodes.func(
             name="f",
             args=nodes.args([]),
             body=[
                 nodes.if_(
                     nodes.ref("x"),
                     [nodes.ret(nodes.bool_literal(True))],
                     []
                 ),
             ],
             type=None
         ),
         cc.func("f", [], [
             cc.if_(
                 cc.call(cc.builtin("bool"), [cc.ref("x")]),
                 [cc.ret(cc.true)],
             ),
             cc.ret(cc.none),
         ]),
     )
예제 #28
0
 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"))]),
     )
예제 #29
0
 def test_statements_in_body_are_transformed(self):
     _assert_transform(
         nodes.func("f", nodes.args([]), [nodes.ret(nodes.ref("value"))], type=None),
         cc.func("f", [], [cc.ret(cc.ref("value"))]),
     )