diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 403153fc4293..92abb8b080ba 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -60,7 +60,7 @@ def __init__(self, self.chk = chk self.module_symbol_table = module_symbol_table - def builtin_type(self, name: str) -> Instance: + def named_type(self, name: str) -> Instance: return self.chk.named_type(name) def not_ready_callback(self, name: str, context: Context) -> None: @@ -202,7 +202,7 @@ def analyze_instance_member_access(name: str, return analyze_var(name, first_item.var, typ, info, mx) if mx.is_lvalue: mx.msg.cant_assign_to_method(mx.context) - signature = function_type(method, mx.builtin_type('builtins.function')) + signature = function_type(method, mx.named_type('builtins.function')) signature = freshen_function_type_vars(signature) if name == '__new__': # __new__ is special and behaves like a static method -- don't strip @@ -266,7 +266,7 @@ def analyze_type_type_member_access(name: str, override_info: Optional[TypeInfo]) -> Type: # Similar to analyze_type_callable_attribute_access. item = None - fallback = mx.builtin_type('builtins.type') + fallback = mx.named_type('builtins.type') ignore_messages = mx.msg.copy() ignore_messages.disable_errors().__enter__() if isinstance(typ.item, Instance): @@ -326,10 +326,10 @@ def analyze_none_member_access(name: str, typ: NoneType, mx: MemberContext) -> T return CallableType(arg_types=[], arg_kinds=[], arg_names=[], - ret_type=mx.builtin_type('builtins.bool'), - fallback=mx.builtin_type('builtins.function')) + ret_type=mx.named_type('builtins.bool'), + fallback=mx.named_type('builtins.function')) else: - return _analyze_member_access(name, mx.builtin_type('builtins.object'), mx) + return _analyze_member_access(name, mx.named_type('builtins.object'), mx) def analyze_member_var_access(name: str, @@ -354,7 +354,7 @@ def analyze_member_var_access(name: str, # If the associated variable is a TypeInfo synthesize a Var node for # the purposes of type checking. This enables us to type check things # like accessing class attributes on an inner class. - v = Var(name, type=type_object_type(vv, mx.builtin_type)) + v = Var(name, type=type_object_type(vv, mx.named_type)) v.info = info if isinstance(vv, TypeAlias) and isinstance(get_proper_type(vv.target), Instance): @@ -364,7 +364,7 @@ def analyze_member_var_access(name: str, # class C: # A = List[int] # x = C.A() <- this is OK - typ = instance_alias_type(vv, mx.builtin_type) + typ = instance_alias_type(vv, mx.named_type) v = Var(name, type=typ) v.info = info @@ -388,7 +388,7 @@ def analyze_member_var_access(name: str, # the guard this search will always find object.__getattribute__ and conclude # that the attribute exists if method and method.info.fullname != 'builtins.object': - function = function_type(method, mx.builtin_type('builtins.function')) + function = function_type(method, mx.named_type('builtins.function')) bound_method = bind_self(function, mx.self_type) typ = map_instance_to_supertype(itype, method.info) getattr_type = get_proper_type(expand_type_by_instance(bound_method, typ)) @@ -405,7 +405,7 @@ def analyze_member_var_access(name: str, else: setattr_meth = info.get_method('__setattr__') if setattr_meth and setattr_meth.info.fullname != 'builtins.object': - setattr_func = function_type(setattr_meth, mx.builtin_type('builtins.function')) + setattr_func = function_type(setattr_meth, mx.named_type('builtins.function')) bound_type = bind_self(setattr_func, mx.self_type) typ = map_instance_to_supertype(itype, setattr_meth.info) setattr_type = get_proper_type(expand_type_by_instance(bound_type, typ)) @@ -437,7 +437,7 @@ def check_final_member(name: str, info: TypeInfo, msg: MessageBuilder, ctx: Cont def analyze_descriptor_access(instance_type: Type, descriptor_type: Type, - builtin_type: Callable[[str], Instance], + named_type: Callable[[str], Instance], msg: MessageBuilder, context: Context, *, chk: 'mypy.checker.TypeChecker') -> Type: @@ -459,7 +459,7 @@ def analyze_descriptor_access(instance_type: Type, if isinstance(descriptor_type, UnionType): # Map the access over union types return make_simplified_union([ - analyze_descriptor_access(instance_type, typ, builtin_type, + analyze_descriptor_access(instance_type, typ, named_type, msg, context, chk=chk) for typ in descriptor_type.items ]) @@ -475,7 +475,7 @@ def analyze_descriptor_access(instance_type: Type, msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context) return AnyType(TypeOfAny.from_error) - function = function_type(dunder_get, builtin_type('builtins.function')) + function = function_type(dunder_get, named_type('builtins.function')) bound_method = bind_self(function, descriptor_type) typ = map_instance_to_supertype(descriptor_type, dunder_get.info) dunder_get_type = expand_type_by_instance(bound_method, typ) @@ -517,7 +517,7 @@ def analyze_descriptor_access(instance_type: Type, def instance_alias_type(alias: TypeAlias, - builtin_type: Callable[[str], Instance]) -> Type: + named_type: Callable[[str], Instance]) -> Type: """Type of a type alias node targeting an instance, when appears in runtime context. As usual, we first erase any unbound type variables to Any. @@ -527,7 +527,7 @@ def instance_alias_type(alias: TypeAlias, Instance), "Must be called only with aliases to classes" target = get_proper_type(set_any_tvars(alias, alias.line, alias.column)) assert isinstance(target, Instance) - tp = type_object_type(target.type, builtin_type) + tp = type_object_type(target.type, named_type) return expand_type_by_instance(tp, target) @@ -615,7 +615,7 @@ def analyze_var(name: str, fullname = '{}.{}'.format(var.info.fullname, name) hook = mx.chk.plugin.get_attribute_hook(fullname) if result and not mx.is_lvalue and not implicit: - result = analyze_descriptor_access(mx.original_type, result, mx.builtin_type, + result = analyze_descriptor_access(mx.original_type, result, mx.named_type, mx.msg, mx.context, chk=mx.chk) if hook: result = hook(AttributeContext(get_proper_type(mx.original_type), @@ -792,7 +792,7 @@ def analyze_class_attribute_access(itype: Instance, result = add_class_tvars(t, isuper, is_classmethod, mx.self_type, original_vars=original_vars) if not mx.is_lvalue: - result = analyze_descriptor_access(mx.original_type, result, mx.builtin_type, + result = analyze_descriptor_access(mx.original_type, result, mx.named_type, mx.msg, mx.context, chk=mx.chk) return result elif isinstance(node.node, Var): @@ -805,15 +805,15 @@ def analyze_class_attribute_access(itype: Instance, return AnyType(TypeOfAny.from_error) if isinstance(node.node, TypeInfo): - return type_object_type(node.node, mx.builtin_type) + return type_object_type(node.node, mx.named_type) if isinstance(node.node, MypyFile): # Reference to a module object. - return mx.builtin_type('types.ModuleType') + return mx.named_type('types.ModuleType') if (isinstance(node.node, TypeAlias) and isinstance(get_proper_type(node.node.target), Instance)): - return instance_alias_type(node.node, mx.builtin_type) + return instance_alias_type(node.node, mx.named_type) if is_decorated: assert isinstance(node.node, Decorator) @@ -824,7 +824,7 @@ def analyze_class_attribute_access(itype: Instance, return AnyType(TypeOfAny.from_error) else: assert isinstance(node.node, FuncBase) - typ = function_type(node.node, mx.builtin_type('builtins.function')) + typ = function_type(node.node, mx.named_type('builtins.function')) # Note: if we are accessing class method on class object, the cls argument is bound. # Annotated and/or explicit class methods go through other code paths above, for # unannotated implicit class methods we do this here. @@ -913,7 +913,7 @@ class B(A[str]): pass return t -def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> ProperType: +def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> ProperType: """Return the type of a type object. For a generic type G with type variables T and S the type is generally of form @@ -945,7 +945,7 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> init_index = info.mro.index(init_method.node.info) new_index = info.mro.index(new_method.node.info) - fallback = info.metaclass_type or builtin_type('builtins.type') + fallback = info.metaclass_type or named_type('builtins.type') if init_index < new_index: method: Union[FuncBase, Decorator] = init_method.node is_new = False @@ -963,7 +963,7 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> arg_kinds=[ARG_STAR, ARG_STAR2], arg_names=["_args", "_kwds"], ret_type=any_type, - fallback=builtin_type('builtins.function')) + fallback=named_type('builtins.function')) return class_callable(sig, info, fallback, None, is_new=False) # Otherwise prefer __init__ in a tie. It isn't clear that this diff --git a/mypy/plugin.py b/mypy/plugin.py index 4cd769427ce1..2d6a5d69ec9a 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -298,20 +298,7 @@ def class_type(self, self_type: Type) -> Type: raise NotImplementedError @abstractmethod - def builtin_type(self, fully_qualified_name: str) -> Instance: - """Deprecated: use named_type instead.""" - raise NotImplementedError - - @abstractmethod - def lookup_fully_qualified(self, name: str) -> SymbolTableNode: - """Lookup a symbol by its fully qualified name. - - Raise an error if not found. - """ - raise NotImplementedError - - @abstractmethod - def lookup_fully_qualified_or_none(self, name: str) -> Optional[SymbolTableNode]: + def lookup_fully_qualified(self, name: str) -> Optional[SymbolTableNode]: """Lookup a symbol by its fully qualified name. Return None if not found. diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 0e9174758d38..7ae1fe898f4b 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -96,7 +96,7 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: converter_type: Optional[Type] = None if converter and isinstance(converter.node, TypeInfo): from mypy.checkmember import type_object_type # To avoid import cycle. - converter_type = type_object_type(converter.node, ctx.api.builtin_type) + converter_type = type_object_type(converter.node, ctx.api.named_type_or_none) elif converter and isinstance(converter.node, OverloadedFuncDef): converter_type = converter.node.type elif converter and converter.type: diff --git a/mypy/semanal.py b/mypy/semanal.py index 7bfa3c66e118..fe8fb25e8e4d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -475,7 +475,7 @@ def add_builtin_aliases(self, tree: MypyFile) -> None: if name in tree.names and not isinstance(tree.names[name].node, PlaceholderNode): continue tag = self.track_incomplete_refs() - n = self.lookup_fully_qualified_or_none(target_name) + n = self.lookup_fully_qualified(target_name) if n: if isinstance(n.node, PlaceholderNode): self.mark_incomplete(name, tree) @@ -732,7 +732,7 @@ def analyze_overloaded_func_def(self, defn: OverloadedFuncDef) -> None: # This is a property. first_item.func.is_overload = True self.analyze_property_with_multi_part_definition(defn) - typ = function_type(first_item.func, self.builtin_type('builtins.function')) + typ = function_type(first_item.func, self.named_type_or_none('builtins.function')) assert isinstance(typ, CallableType) types = [typ] else: @@ -789,7 +789,7 @@ def analyze_overload_sigs_and_impl( item.accept(self) # TODO: support decorated overloaded functions properly if isinstance(item, Decorator): - callable = function_type(item.func, self.builtin_type('builtins.function')) + callable = function_type(item.func, self.named_type_or_none('builtins.function')) assert isinstance(callable, CallableType) if not any(refers_to_fullname(dec, 'typing.overload') for dec in item.decorators): @@ -1736,7 +1736,7 @@ def analyze_metaclass(self, defn: ClassDef) -> None: defn.info.metaclass_type.type.fullname == 'builtins.type'): # All protocols and their subclasses have ABCMeta metaclass by default. # TODO: add a metaclass conflict check if there is another metaclass. - abc_meta = self.named_type_or_none('abc.ABCMeta', []) + abc_meta = self.named_type_or_none('abc.ABCMeta') if abc_meta is not None: # May be None in tests with incomplete lib-stub. defn.info.metaclass_type = abc_meta if defn.info.metaclass_type is None: @@ -1910,7 +1910,7 @@ def report_missing_module_attribute( if import_id == 'typing': # The user probably has a missing definition in a test fixture. Let's verify. fullname = 'builtins.{}'.format(source_id.lower()) - if (self.lookup_fully_qualified_or_none(fullname) is None and + if (self.lookup_fully_qualified(fullname) is None and fullname in SUGGESTED_TEST_FIXTURES): # Yes. Generate a helpful note. self.msg.add_fixture_note(fullname, context) @@ -4308,7 +4308,7 @@ def get_module_symbol(self, node: MypyFile, name: str) -> Optional[SymbolTableNo gvar = self.create_getattr_var(names['__getattr__'], name, fullname) if gvar: sym = SymbolTableNode(GDEF, gvar) - elif self.is_missing_module(fullname): + elif fullname in self.missing_modules: # We use the fullname of the original definition so that we can # detect whether two names refer to the same thing. var_type = AnyType(TypeOfAny.from_unimported_type) @@ -4319,9 +4319,6 @@ def get_module_symbol(self, node: MypyFile, name: str) -> Optional[SymbolTableNo sym = None return sym - def is_missing_module(self, module: str) -> bool: - return module in self.missing_modules - def implicit_symbol(self, sym: SymbolTableNode, name: str, parts: List[str], source_type: AnyType) -> SymbolTableNode: """Create symbol for a qualified name reference through Any type.""" @@ -4362,24 +4359,7 @@ def create_getattr_var(self, getattr_defn: SymbolTableNode, return v return None - def lookup_fully_qualified(self, name: str) -> SymbolTableNode: - """Lookup a fully qualified name. - - Assume that the name is defined. This happens in the global namespace -- - the local module namespace is ignored. - - Note that this doesn't support visibility, module-level __getattr__, or - nested classes. - """ - parts = name.split('.') - n = self.modules[parts[0]] - for i in range(1, len(parts) - 1): - next_sym = n.names[parts[i]] - assert isinstance(next_sym.node, MypyFile) - n = next_sym.node - return n.names[parts[-1]] - - def lookup_fully_qualified_or_none(self, fullname: str) -> Optional[SymbolTableNode]: + def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]: """Lookup a fully qualified name that refers to a module-level definition. Don't assume that the name is defined. This happens in the global namespace -- @@ -4402,12 +4382,6 @@ def lookup_fully_qualified_or_none(self, fullname: str) -> Optional[SymbolTableN self.record_incomplete_ref() return result - def builtin_type(self, fully_qualified_name: str) -> Instance: - sym = self.lookup_fully_qualified(fully_qualified_name) - node = sym.node - assert isinstance(node, TypeInfo) - return Instance(node, [AnyType(TypeOfAny.special_form)] * len(node.defn.type_vars)) - def object_type(self) -> Instance: return self.named_type('__builtins__.object') @@ -4426,7 +4400,7 @@ def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> def named_type_or_none(self, qualified_name: str, args: Optional[List[Type]] = None) -> Optional[Instance]: - sym = self.lookup_fully_qualified_or_none(qualified_name) + sym = self.lookup_fully_qualified(qualified_name) if not sym or isinstance(sym.node, PlaceholderNode): return None node = sym.node @@ -4437,7 +4411,7 @@ def named_type_or_none(self, qualified_name: str, if args is not None: # TODO: assert len(args) == len(node.defn.type_vars) return Instance(node, args) - return Instance(node, [AnyType(TypeOfAny.unannotated)] * len(node.defn.type_vars)) + return Instance(node, [AnyType(TypeOfAny.special_form)] * len(node.defn.type_vars)) def lookup_current_scope(self, name: str) -> Optional[SymbolTableNode]: if self.locals[-1] is not None: @@ -4550,7 +4524,7 @@ def add_symbol_table_node(self, if not (isinstance(new, (FuncDef, Decorator)) and self.set_original_def(old, new)): self.name_already_defined(name, context, existing) - elif (name not in self.missing_names[-1] and '*' not in self.missing_names[-1]): + elif name not in self.missing_names[-1] and '*' not in self.missing_names[-1]: names[name] = symbol self.progress = True return True @@ -4886,7 +4860,7 @@ def name_not_defined(self, name: str, ctx: Context, namespace: Optional[str] = N if 'builtins.{}'.format(name) in SUGGESTED_TEST_FIXTURES: # The user probably has a missing definition in a test fixture. Let's verify. fullname = 'builtins.{}'.format(name) - if self.lookup_fully_qualified_or_none(fullname) is None: + if self.lookup_fully_qualified(fullname) is None: # Yes. Generate a helpful note. self.msg.add_fixture_note(fullname, ctx) diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index 6b0fe1251693..9138c17352bc 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -38,11 +38,7 @@ def lookup_qualified(self, name: str, ctx: Context, raise NotImplementedError @abstractmethod - def lookup_fully_qualified(self, name: str) -> SymbolTableNode: - raise NotImplementedError - - @abstractmethod - def lookup_fully_qualified_or_none(self, name: str) -> Optional[SymbolTableNode]: + def lookup_fully_qualified(self, name: str) -> Optional[SymbolTableNode]: raise NotImplementedError @abstractmethod diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 08063cc05451..1f4d18f0ce40 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -288,7 +288,7 @@ def get_trivial_type(self, fdef: FuncDef) -> CallableType: fdef.arg_kinds, fdef.arg_names, AnyType(TypeOfAny.suggestion_engine), - self.builtin_type('builtins.function')) + self.named_type('builtins.function')) def get_starting_type(self, fdef: FuncDef) -> CallableType: if isinstance(fdef.type, CallableType): @@ -351,7 +351,7 @@ def get_default_arg_types(self, state: State, fdef: FuncDef) -> List[Optional[Ty def add_adjustments(self, typs: List[Type]) -> List[Type]: if not self.try_text or self.manager.options.python_version[0] != 2: return typs - translator = StrToText(self.builtin_type) + translator = StrToText(self.named_type) return dedup(typs + [tp.accept(translator) for tp in typs]) def get_guesses(self, is_method: bool, base: CallableType, defaults: List[Optional[Type]], @@ -648,8 +648,10 @@ def ensure_loaded(self, state: State, force: bool = False) -> MypyFile: assert state.tree is not None return state.tree - def builtin_type(self, s: str) -> Instance: - return self.manager.semantic_analyzer.builtin_type(s) + def named_type(self, s: str) -> Instance: + ret = self.manager.semantic_analyzer.named_type_or_none(s) + assert ret + return ret def json_suggestion(self, mod: str, func_name: str, node: FuncDef, suggestion: PyAnnotateSignature) -> str: @@ -850,8 +852,8 @@ def visit_callable_type(self, t: CallableType) -> str: class StrToText(TypeTranslator): - def __init__(self, builtin_type: Callable[[str], Instance]) -> None: - self.text_type = builtin_type('builtins.unicode') + def __init__(self, named_type: Callable[[str], Instance]) -> None: + self.text_type = named_type('builtins.unicode') def visit_type_alias_type(self, t: TypeAliasType) -> Type: exp_t = get_proper_type(t) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 6e2cb350f6e6..3f4a4c2cef33 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -289,7 +289,7 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt self.allow_new_syntax))): # Tuple is special because it is involved in builtin import cycle # and may be not ready when used. - sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') + sym = self.api.lookup_fully_qualified('builtins.tuple') if not sym or isinstance(sym.node, PlaceholderNode): if self.api.is_incomplete_namespace('builtins'): self.api.record_incomplete_ref() @@ -1001,6 +1001,7 @@ def named_type(self, fully_qualified_name: str, line: int = -1, column: int = -1) -> Instance: node = self.lookup_fqn_func(fully_qualified_name) + assert node is not None assert isinstance(node.node, TypeInfo) any_type = AnyType(TypeOfAny.special_form) return Instance(node.node, args or [any_type] * len(node.node.defn.type_vars), diff --git a/test-data/unit/plugins/common_api_incremental.py b/test-data/unit/plugins/common_api_incremental.py index 070bc61ceb3f..c83347a136b5 100644 --- a/test-data/unit/plugins/common_api_incremental.py +++ b/test-data/unit/plugins/common_api_incremental.py @@ -24,7 +24,7 @@ def add_info_hook(ctx) -> None: info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id) class_def.info = info - obj = ctx.api.builtin_type('builtins.object') + obj = ctx.api.named_type_or_none('builtins.object') info.mro = [info, obj.type] info.bases = [obj] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) @@ -33,7 +33,7 @@ def add_info_hook(ctx) -> None: def add_magic_hook(ctx) -> None: info = ctx.cls.info - str_type = ctx.api.named_type_or_none('builtins.str', []) + str_type = ctx.api.named_type_or_none('builtins.str') assert str_type is not None var = Var('__magic__', str_type) var.info = info diff --git a/test-data/unit/plugins/dyn_class.py b/test-data/unit/plugins/dyn_class.py index 56ef89e17869..aeea5c296e36 100644 --- a/test-data/unit/plugins/dyn_class.py +++ b/test-data/unit/plugins/dyn_class.py @@ -23,7 +23,7 @@ def add_info_hook(ctx): info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id) class_def.info = info - obj = ctx.api.builtin_type('builtins.object') + obj = ctx.api.named_type_or_none('builtins.object') info.mro = [info, obj.type] info.bases = [obj] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) @@ -35,7 +35,7 @@ def replace_col_hook(ctx): node = sym.node if isinstance(node, Var) and isinstance(node.type, Instance): if node.type.type.fullname == 'mod.Column': - new_sym = ctx.api.lookup_fully_qualified_or_none('mod.Instr') + new_sym = ctx.api.lookup_fully_qualified('mod.Instr') if new_sym: new_info = new_sym.node assert isinstance(new_info, TypeInfo) diff --git a/test-data/unit/plugins/dyn_class_from_method.py b/test-data/unit/plugins/dyn_class_from_method.py index 8a18f7f1e8e1..63d30bd3106b 100644 --- a/test-data/unit/plugins/dyn_class_from_method.py +++ b/test-data/unit/plugins/dyn_class_from_method.py @@ -17,8 +17,8 @@ def add_info_hook(ctx: DynamicClassDefContext): info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id) class_def.info = info queryset_type_fullname = ctx.call.args[0].fullname - queryset_info = ctx.api.lookup_fully_qualified_or_none(queryset_type_fullname).node # type: TypeInfo - obj = ctx.api.builtin_type('builtins.object') + queryset_info = ctx.api.lookup_fully_qualified(queryset_type_fullname).node # type: TypeInfo + obj = ctx.api.named_type_or_none('builtins.object') info.mro = [info, queryset_info, obj.type] info.bases = [Instance(queryset_info, [])] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))