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 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 children_of_for_loop_are_checked(): _assert_child_expression_is_checked(lambda generate: nodes.for_( nodes.attr(generate.unbound_ref(), "blah"), nodes.list_literal([]), [], [] ) ) _assert_child_expression_is_checked(lambda generate: nodes.for_( generate.target(), generate.unbound_ref(), [], [] ), ) _assert_child_statement_is_checked(lambda generate: nodes.for_( generate.target(), nodes.list_literal([]), [generate.unbound_ref_statement()], [] ), ) _assert_child_statement_is_checked(lambda generate: nodes.for_( generate.target(), nodes.list_literal([]), [], [generate.unbound_ref_statement()], ), )
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 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 type_error_if_attribute_does_not_exist(): type_bindings = {"x": types.str_type} node = nodes.attr(nodes.ref("x"), "swizzlify") try: infer(node, type_bindings=type_bindings) assert False, "Expected error" except errors.NoSuchAttributeError as error: assert_equal("'str' object has no attribute 'swizzlify'", str(error)) assert error.node is node
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_has_child_names_resolved(): _assert_children_resolved( lambda ref: nodes.list_comprehension(ref, nodes.none(), nodes.none()), ) _assert_children_resolved( lambda ref: nodes.list_comprehension(nodes.none(), nodes.attr(ref, "name"), nodes.none()), ) _assert_children_resolved( lambda ref: nodes.list_comprehension(nodes.none(), nodes.none(), ref), )
def context_manager_of_with_statement_must_have_exit_method(): cls = types.class_type("Manager", [types.attr("__enter__", enter_method())]) context_manager_node = nodes.ref("x") node = nodes.with_(context_manager_node, None, []) try: update_context(node, type_bindings={"x": cls}) assert False, "Expected error" except errors.NoSuchAttributeError as error: assert_equal(nodes.attr(context_manager_node, "__exit__"), error.node)
def declarations_in_list_comprehension_are_variable_reference_targets(): node = nodes.list_comprehension( nodes.none(), nodes.tuple_literal([nodes.ref("target"), nodes.attr(nodes.ref("other"), "name")]), nodes.ref("iterable") ) declarations = _declarations_in(node) assert isinstance(declarations.declaration("target"), name_declaration.VariableDeclarationNode) assert not declarations.is_declared("other") assert not declarations.is_declared("iterable")
def cannot_reassign_read_only_attribute(): cls = types.class_type("X", [types.attr("y", types.str_type, read_only=True)]) attr_node = nodes.attr(nodes.ref("x"), "y") node = nodes.assign([attr_node], nodes.str_literal("Hello")) type_bindings = {"x": cls} try: update_context(node, type_bindings=type_bindings) assert False, "Expected error" except errors.ReadOnlyAttributeError as error: assert_equal(attr_node, error.node) assert_equal("'X' attribute 'y' is read-only", str(error))
def assignment_to_attribute_does_not_allow_strict_supertype(): cls = types.class_type("X", [types.attr("y", types.str_type, read_only=True)]) attr_node = nodes.attr(nodes.ref("x"), "y") node = nodes.assign([attr_node], nodes.ref("obj")) type_bindings = {"x": cls, "obj": types.object_type} try: update_context(node, type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(attr_node, error.node) assert_equal(types.object_type, error.value_type) assert_equal(types.str_type, error.target_type)
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 children_of_list_comprehension_are_checked(): _assert_child_expression_is_checked(lambda generate: nodes.list_comprehension( generate.unbound_ref(), generate.bound_ref("x", types.int_type), nodes.list_literal([]), ) ) _assert_child_expression_is_checked(lambda generate: nodes.list_comprehension( nodes.none(), nodes.attr(generate.unbound_ref(), "x"), nodes.list_literal([]), ) ) _assert_child_expression_is_checked(lambda generate: nodes.list_comprehension( nodes.none(), generate.bound_ref("x", types.int_type), generate.unbound_ref(), ) )
def children_of_try_statement_are_checked(): _assert_child_statement_is_checked(lambda generate: nodes.try_([generate.unbound_ref_statement()]), ) _assert_child_statement_is_checked(lambda generate: nodes.try_([], handlers=[ nodes.except_(None, None, [generate.unbound_ref_statement()]) ]), ) _assert_child_expression_is_checked(lambda generate: nodes.try_([], handlers=[ nodes.except_(generate.unbound_ref(), None, []) ]), ) _assert_child_expression_is_checked(lambda generate: nodes.try_([], handlers=[ nodes.except_(nodes.none(), nodes.attr(generate.unbound_ref(), "blah"), []) ]), ) _assert_child_statement_is_checked(lambda generate: nodes.try_([], finally_body=[ generate.unbound_ref_statement() ]), )
def children_of_with_statement_are_checked(): context_manager_type = context_manager_class(exit_type=types.none_type) _assert_child_expression_is_checked(lambda generate: nodes.with_( generate.unbound_ref(), None, [] ), ) _assert_child_expression_is_checked(lambda generate: nodes.with_( generate.bound_ref("manager", context_manager_type), nodes.attr(generate.unbound_ref(), "blah"), [] ), ) _assert_child_statement_is_checked(lambda generate: nodes.with_( generate.bound_ref("manager", context_manager_type), None, [generate.unbound_ref_statement()] ), )
def can_infer_type_of_attribute(): type_bindings = {"x": types.str_type} assert_equal( types.func([types.str_type], types.int_type), infer(nodes.attr(nodes.ref("x"), "find"), type_bindings=type_bindings), )
def attribute_access_has_child_names_resolved(): _assert_children_resolved( lambda ref: nodes.attr(ref, "blah"), )
def test_attribute_access(): expected = nodes.attr(nodes.ref("x"), "y") _assert_expression_parse(expected, "x.y")
def targets_are_evaluated_left_to_right(): target_node = nodes.ref("x") ref_node = nodes.ref("x") node = nodes.assign([nodes.attr(ref_node, "blah"), target_node], nodes.none()) _assert_is_unbound_error(ref_node, lambda: _updated_bindings(node))
def assignment_to_attribute_allows_subtype(): cls = types.class_type("X", [types.attr("y", types.object_type, read_only=False)]) node = nodes.assign([nodes.attr(nodes.ref("x"), "y")], nodes.str_literal("Hello")) type_bindings = {"x": cls} update_context(node, type_bindings=type_bindings)