From 82eea4c416d90b006b9c740f0dbab9f561c4c0ef Mon Sep 17 00:00:00 2001 From: Orvid King Date: Thu, 24 Mar 2022 16:40:18 -0700 Subject: [PATCH] Fix multi-part imports in the type binder Summary: The root part of the import name ends up visible in python, so track it as such, since readonly doesn't care about anything beyond that. Differential Revision: D35090635 fbshipit-source-id: 1e93f7977e9ea2863a119538f49ddeba9a234282 --- Lib/compiler/readonly/type_binder.py | 11 ++++++++--- .../test_compiler/test_readonly/test_type_binder.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Lib/compiler/readonly/type_binder.py b/Lib/compiler/readonly/type_binder.py index 6b8f554f789..4faf8a58006 100644 --- a/Lib/compiler/readonly/type_binder.py +++ b/Lib/compiler/readonly/type_binder.py @@ -1056,10 +1056,15 @@ def visitarg(self, node: ast.arg) -> None: self.declare(node.arg, node, readonly_value) def visitalias(self, node: ast.alias) -> None: + root_visible_name = node.name if node.asname: - self.declare(node.asname, node, MUTABLE) - else: - self.declare(node.name, node, MUTABLE) + root_visible_name = node.asname + + # If this is a multi-part import, make the root name + # visible in the current scope. + if (loc := root_visible_name.find(".")) != -1: + root_visible_name = root_visible_name[:loc] + self.declare(root_visible_name, node, MUTABLE) def visitModule(self, node: ast.Module) -> None: self.child_scope(ReadonlyModuleBindingScope(node, self)) diff --git a/Lib/test/test_compiler/test_readonly/test_type_binder.py b/Lib/test/test_compiler/test_readonly/test_type_binder.py index 88bab1f2204..196b65ff3e9 100644 --- a/Lib/test/test_compiler/test_readonly/test_type_binder.py +++ b/Lib/test/test_compiler/test_readonly/test_type_binder.py @@ -742,6 +742,19 @@ def somefunc(): errors = self.lint(code) self.assertEqual(errors.errors, []) + def test_import_local_multipart(self) -> None: + code = """ + import e + + def somefunc(): + import d.f + le = e + ld = d + le = d.f + """ + errors = self.lint(code) + self.assertEqual(errors.errors, []) + def test_readonly_walrus(self) -> None: code = """ def g(arr):