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 when_target_has_explicit_type_that_type_is_used_as_type_hint(): node = nodes.assign( [nodes.ref("x")], nodes.list_literal([nodes.str_literal("Hello")]), type=nodes.type_apply(nodes.ref("list"), [nodes.ref("object")]) ) context = update_context(node, type_bindings={ "list": types.meta_type(types.list_type), "object": types.meta_type(types.object_type), }) assert_equal(types.list_type(types.object_type), context.lookup_name("x"))
def type_of_function_signature_is_metatype_of_function(): type_bindings = { "str": types.meta_type(types.str_type), "int": types.meta_type(types.int_type), } node = nodes.signature( args=[nodes.signature_arg(nodes.ref("int"))], returns=nodes.ref("str") ) inferred_type = infer(node, type_bindings=type_bindings) assert types.is_meta_type(inferred_type) assert_equal(types.func([types.int_type], types.str_type), inferred_type.type)
def _update_context(func_node, *, type_bindings=None, declared_names_in_node=None): if type_bindings is None: type_bindings = {} else: type_bindings = type_bindings.copy() type_bindings.update({ "int": types.meta_type(types.int_type), "str": types.meta_type(types.str_type), "none": types.meta_type(types.none_type), "list": types.meta_type(types.list_type), }) return update_context(func_node, type_bindings=type_bindings, declared_names_in_node=declared_names_in_node)
def _infer_func_type(func_node, type_bindings=None): if type_bindings is None: type_bindings = {} else: type_bindings = type_bindings.copy() type_bindings.update({ "int": types.meta_type(types.int_type), "str": types.meta_type(types.str_type), "none": types.meta_type(types.none_type), "list": types.meta_type(types.list_type), }) context = update_context(func_node, type_bindings=type_bindings) return context.lookup(func_node)
def can_infer_type_of_function_with_explicit_signature_of_aliased_function_type(): args = nodes.arguments([]) node = nodes.func("f", args=args, body=[], type=nodes.ref("Action")) type_bindings = { "Action": types.meta_type(types.func([], types.none_type)) } assert_equal(types.func([], types.none_type), _infer_func_type(node, type_bindings))
def error_if_base_class_is_not_object(): type_bindings = {"Person": types.meta_type(types.class_type("Person"))} node = nodes.class_("User", [], base_classes=[nodes.ref("Person")]) try: _infer_class_type(node, [], type_bindings=type_bindings) assert False, "Expected error" except errors.UnsupportedError as error: assert_equal("base classes other than 'object' are not supported", str(error))
def type_of_structural_type_is_as_definition(): type_bindings = { "str": types.meta_type(types.str_type), "int": types.meta_type(types.int_type), } node = nodes.structural_type("Song", [ ("description", nodes.ref("str")), ("length", nodes.ref("int")), ]) context = update_context(node, type_bindings=type_bindings) declared_type = context.lookup_name("Song") assert types.is_meta_type(declared_type) expected_type = types.structural_type("Song", [ types.attr("description", types.str_type), types.attr("length", types.int_type), ]) assert types.is_equivalent_type(expected_type, declared_type.type)
def _infer_meta_type(class_node, names, names_in_nodes=None, type_bindings=None): if type_bindings is None: type_bindings = {} else: type_bindings = type_bindings.copy() if names_in_nodes is None: names_in_nodes = [] type_bindings["bool"] = types.meta_type(types.bool_type) type_bindings["object"] = types.meta_type(types.object_type) type_bindings["none"] = types.meta_type(types.none_type) type_bindings["str"] = types.meta_type(types.str_type) context = update_context( class_node, declared_names_in_node=NodeDict(names_in_nodes + [(class_node, names + ["Self"])]), type_bindings=type_bindings, ) meta_type = context.lookup(class_node) assert isinstance(meta_type, types.MetaType) assert types.is_class_type(meta_type.type) or types.is_generic_type(meta_type.type) return meta_type
def except_handler_updates_type_of_error_target(): node = nodes.try_([], handlers=[ nodes.except_( nodes.ref("Exception"), "error", [nodes.expression_statement(nodes.ref("error"))] ), ]) type_bindings = { "Exception": types.meta_type(types.exception_type) } context = update_context(node, type_bindings=type_bindings) assert_equal(types.exception_type, context.lookup_name("error"))
def given_explicit_type_when_value_does_not_have_that_type_an_error_is_raised(): value_node = nodes.none() node = nodes.assign( [nodes.ref("x")], value_node, type=nodes.ref("int") ) try: update_context(node, type_bindings={ "int": types.meta_type(types.int_type), }) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(value_node, error.node) assert_equal(types.none_type, error.actual) assert_equal(types.int_type, error.expected)
def any_meta_type_is_super_type_of_meta_types(self): assert types.is_sub_type(types.any_meta_type, types.meta_type(types.int_type)) assert not types.is_sub_type(types.meta_type(types.int_type), types.any_meta_type)