|
16 | 16 | import textwrap |
17 | 17 | import types |
18 | 18 | import warnings |
19 | | -from collections.abc import Iterator, Sequence |
| 19 | +from collections.abc import Collection, Iterator, Sequence |
20 | 20 | from io import TextIOWrapper |
21 | 21 | from tokenize import detect_encoding |
22 | | -from typing import TYPE_CHECKING |
| 22 | +from typing import TYPE_CHECKING, cast |
23 | 23 |
|
24 | 24 | from astroid import bases, modutils, nodes, raw_building, rebuilder, util |
25 | 25 | from astroid._ast import ParserModule, get_parser_module |
@@ -163,11 +163,11 @@ def _post_build( |
163 | 163 | module.file_encoding = encoding |
164 | 164 | self._manager.cache_module(module) |
165 | 165 | # post tree building steps after we stored the module in the cache: |
166 | | - for from_node in builder._import_from_nodes: |
| 166 | + for from_node, global_names in builder._import_from_nodes: |
167 | 167 | if from_node.modname == "__future__": |
168 | 168 | for symbol, _ in from_node.names: |
169 | 169 | module.future_imports.add(symbol) |
170 | | - self.add_from_names_to_locals(from_node) |
| 170 | + self.add_from_names_to_locals(from_node, global_names) |
171 | 171 | # handle delayed assattr nodes |
172 | 172 | for delayed in builder._delayed_assattr: |
173 | 173 | self.delayed_assattr(delayed) |
@@ -210,31 +210,40 @@ def _data_build( |
210 | 210 | module = builder.visit_module(node, modname, node_file, package) |
211 | 211 | return module, builder |
212 | 212 |
|
213 | | - def add_from_names_to_locals(self, node: nodes.ImportFrom) -> None: |
| 213 | + def add_from_names_to_locals( |
| 214 | + self, node: nodes.ImportFrom, global_name: Collection[str] |
| 215 | + ) -> None: |
214 | 216 | """Store imported names to the locals. |
215 | 217 |
|
216 | 218 | Resort the locals if coming from a delayed node |
217 | 219 | """ |
218 | 220 |
|
219 | | - def _key_func(node: nodes.NodeNG) -> int: |
220 | | - return node.fromlineno or 0 |
221 | | - |
222 | | - def sort_locals(my_list: list[nodes.NodeNG]) -> None: |
223 | | - my_list.sort(key=_key_func) |
| 221 | + def add_local(parent_or_root: nodes.NodeNG, name: str) -> None: |
| 222 | + parent_or_root.set_local(name, node) |
| 223 | + my_list = parent_or_root.scope().locals[name] |
| 224 | + if TYPE_CHECKING: |
| 225 | + my_list = cast(list[nodes.NodeNG], my_list) |
| 226 | + my_list.sort(key=lambda n: n.fromlineno or 0) |
224 | 227 |
|
225 | 228 | assert node.parent # It should always default to the module |
| 229 | + module = node.root() |
226 | 230 | for name, asname in node.names: |
227 | 231 | if name == "*": |
228 | 232 | try: |
229 | 233 | imported = node.do_import_module() |
230 | 234 | except AstroidBuildingError: |
231 | 235 | continue |
232 | 236 | for name in imported.public_names(): |
233 | | - node.parent.set_local(name, node) |
234 | | - sort_locals(node.parent.scope().locals[name]) # type: ignore[arg-type] |
| 237 | + if name in global_name: |
| 238 | + add_local(module, name) |
| 239 | + else: |
| 240 | + add_local(node.parent, name) |
235 | 241 | else: |
236 | | - node.parent.set_local(asname or name, node) |
237 | | - sort_locals(node.parent.scope().locals[asname or name]) # type: ignore[arg-type] |
| 242 | + name = asname or name |
| 243 | + if name in global_name: |
| 244 | + add_local(module, name) |
| 245 | + else: |
| 246 | + add_local(node.parent, name) |
238 | 247 |
|
239 | 248 | def delayed_assattr(self, node: nodes.AssignAttr) -> None: |
240 | 249 | """Visit an AssignAttr node. |
|
0 commit comments