|
9 | 9 | handle_aliases_in_init_files,
|
10 | 10 | handle_fdid_aliases,
|
11 | 11 | not_as_alias_handler,
|
12 | | - retrieve_import_alias_mapping |
| 12 | + retrieve_import_alias_mapping, |
| 13 | + fully_qualify_alias_labels |
13 | 14 | )
|
14 | 15 | from ..core.ast_helper import (
|
15 | 16 | generate_ast,
|
|
61 | 62 | class StmtVisitor(ast.NodeVisitor):
|
62 | 63 | def __init__(self, allow_local_directory_imports=True):
|
63 | 64 | self._allow_local_modules = allow_local_directory_imports
|
| 65 | + self.bb_or_bi_aliases = {} |
64 | 66 | super().__init__()
|
65 | 67 |
|
66 | 68 | def visit_Module(self, node):
|
@@ -624,6 +626,10 @@ def add_blackbox_or_builtin_call(self, node, blackbox): # noqa: C901
|
624 | 626 |
|
625 | 627 | call_function_label = call_label_visitor.result[:call_label_visitor.result.find('(')]
|
626 | 628 |
|
| 629 | + # Check if function call matches a blackbox/built-in alias and if so, resolve it |
| 630 | + # This resolves aliases like "from os import system as mysys" as: mysys -> os.system |
| 631 | + call_function_label = fully_qualify_alias_labels(call_function_label, self.bb_or_bi_aliases) |
| 632 | + |
627 | 633 | # Create e.g. ~call_1 = ret_func_foo
|
628 | 634 | LHS = CALL_IDENTIFIER + 'call_' + str(saved_function_call_index)
|
629 | 635 | RHS = 'ret_' + call_function_label + '('
|
@@ -810,7 +816,6 @@ def add_module( # noqa: C901
|
810 | 816 | module_path = module[1]
|
811 | 817 |
|
812 | 818 | parent_definitions = self.module_definitions_stack[-1]
|
813 | | - # The only place the import_alias_mapping is updated |
814 | 819 | parent_definitions.import_alias_mapping.update(import_alias_mapping)
|
815 | 820 | parent_definitions.import_names = local_names
|
816 | 821 |
|
@@ -1052,7 +1057,13 @@ def visit_Import(self, node):
|
1052 | 1057 | retrieve_import_alias_mapping(node.names)
|
1053 | 1058 | )
|
1054 | 1059 | for alias in node.names:
|
1055 | | - if alias.name not in uninspectable_modules: |
| 1060 | + if alias.name in uninspectable_modules: |
| 1061 | + # The module is uninspectable (so blackbox or built-in). If it has an alias, we remember |
| 1062 | + # the alias so we can do fully qualified name resolution for blackbox- and built-in trigger words |
| 1063 | + # e.g. we want a call to "os.system" be recognised, even if we do "import os as myos" |
| 1064 | + if alias.asname is not None and alias.asname != alias.name: |
| 1065 | + self.bb_or_bi_aliases[alias.asname] = alias.name |
| 1066 | + else: |
1056 | 1067 | log.warn("Cannot inspect module %s", alias.name)
|
1057 | 1068 | uninspectable_modules.add(alias.name) # Don't repeatedly warn about this
|
1058 | 1069 | return IgnoredNode()
|
@@ -1094,7 +1105,14 @@ def visit_ImportFrom(self, node):
|
1094 | 1105 | retrieve_import_alias_mapping(node.names),
|
1095 | 1106 | from_from=True
|
1096 | 1107 | )
|
1097 | | - if node.module not in uninspectable_modules: |
| 1108 | + |
| 1109 | + if node.module in uninspectable_modules: |
| 1110 | + # Remember aliases for blackboxed and built-in imports such that we can label them fully qualified |
| 1111 | + # e.g. we want a call to "os.system" be recognised, even if we do "from os import system" |
| 1112 | + # from os import system as mysystem -> module=os, name=system, asname=mysystem |
| 1113 | + for name in node.names: |
| 1114 | + self.bb_or_bi_aliases[name.asname or name.name] = "{}.{}".format(node.module, name.name) |
| 1115 | + else: |
1098 | 1116 | log.warn("Cannot inspect module %s", node.module)
|
1099 | 1117 | uninspectable_modules.add(node.module)
|
1100 | 1118 | return IgnoredNode()
|
0 commit comments