diff --git a/mypy/semanal.py b/mypy/semanal.py index ffd7bda925c39..2ea444bf4ab26 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1776,11 +1776,15 @@ def visit_import_from(self, imp: ImportFrom) -> None: ) elif module and not missing_submodule: # Target module exists but the imported name is missing or hidden. - self.report_missing_module_attribute(module_id, id, imported_id, imp) + self.report_missing_module_attribute( + module_id, id, imported_id, module_public=module_public, + module_hidden=not module_public, context=imp + ) else: # Import of a missing (sub)module. self.add_unknown_imported_symbol( - imported_id, imp, target_name=fullname, module_public=module_public + imported_id, imp, target_name=fullname, module_public=module_public, + module_hidden=not module_public ) def process_imported_symbol(self, @@ -1795,7 +1799,10 @@ def process_imported_symbol(self, if isinstance(node.node, PlaceholderNode): if self.final_iteration: - self.report_missing_module_attribute(module_id, id, imported_id, context) + self.report_missing_module_attribute( + module_id, id, imported_id, module_public=module_public, + module_hidden=module_hidden, context=context + ) return else: # This might become a type. @@ -1820,8 +1827,10 @@ def process_imported_symbol(self, module_public=module_public, module_hidden=module_hidden) - def report_missing_module_attribute(self, import_id: str, source_id: str, imported_id: str, - context: Node) -> None: + def report_missing_module_attribute( + self, import_id: str, source_id: str, imported_id: str, module_public: bool, + module_hidden: bool, context: Node + ) -> None: # Missing attribute. if self.is_incomplete_namespace(import_id): # We don't know whether the name will be there, since the namespace @@ -1842,7 +1851,10 @@ def report_missing_module_attribute(self, import_id: str, source_id: str, import suggestion = "; maybe {}?".format(pretty_seq(matches, "or")) message += "{}".format(suggestion) self.fail(message, context, code=codes.ATTR_DEFINED) - self.add_unknown_imported_symbol(imported_id, context) + self.add_unknown_imported_symbol( + imported_id, context, target_name=None, module_public=module_public, + module_hidden=not module_public + ) if import_id == 'typing': # The user probably has a missing definition in a test fixture. Let's verify. @@ -4438,7 +4450,8 @@ def add_module_symbol(self, module_hidden=module_hidden) else: self.add_unknown_imported_symbol( - as_id, context, target_name=id, module_public=module_public + as_id, context, target_name=id, module_public=module_public, + module_hidden=module_hidden ) def add_imported_symbol(self, @@ -4457,8 +4470,9 @@ def add_imported_symbol(self, def add_unknown_imported_symbol(self, name: str, context: Context, - target_name: Optional[str] = None, - module_public: bool = True) -> None: + target_name: Optional[str], + module_public: bool, + module_hidden: bool) -> None: """Add symbol that we don't know what it points to because resolving an import failed. This can happen if a module is missing, or it is present, but doesn't have @@ -4486,7 +4500,9 @@ def add_unknown_imported_symbol(self, any_type = AnyType(TypeOfAny.from_unimported_type, missing_import_name=var._fullname) var.type = any_type var.is_suppressed_import = True - self.add_symbol(name, var, context, module_public=module_public) + self.add_symbol( + name, var, context, module_public=module_public, module_hidden=module_hidden + ) # # Other helpers diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index c2d505c5cb89f..140a0c017bfd9 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2812,3 +2812,16 @@ CustomDict = TypedDict( ) [typing fixtures/typing-full.pyi] [builtins fixtures/tuple.pyi] + +[case testNoReExportFromMissingStubs] +from stub import a # E: Module 'stub' has no attribute 'a' +from stub import b +from stub import c # E: Module 'stub' has no attribute 'c' +from stub import d # E: Module 'stub' has no attribute 'd' + +[file stub.pyi] +from mystery import a, b as b, c as d + +[out] +tmp/stub.pyi:1: error: Cannot find implementation or library stub for module named 'mystery' +tmp/stub.pyi:1: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports