From b2ab3dc5fc7520e2db9c446ad3430c23cb3db7fb Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sat, 3 Oct 2020 18:43:18 -0700 Subject: [PATCH 1/2] reexport from missing module test --- test-data/unit/check-modules.test | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 From f5c51ee607278540996b6a180344a2082c3bde6c Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sat, 3 Oct 2020 18:43:57 -0700 Subject: [PATCH 2/2] semanal: propagate module_hidden for unknown symbols Fixes #9517 --- mypy/semanal.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) 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