6
6
7
7
from .alias_helper import (
8
8
as_alias_handler ,
9
+ fully_qualify_alias_labels ,
9
10
handle_aliases_in_init_files ,
10
11
handle_fdid_aliases ,
11
12
not_as_alias_handler ,
@@ -624,6 +625,11 @@ def add_blackbox_or_builtin_call(self, node, blackbox): # noqa: C901
624
625
625
626
call_function_label = call_label_visitor .result [:call_label_visitor .result .find ('(' )]
626
627
628
+ # Check if function call matches a blackbox/built-in alias and if so, resolve it
629
+ # This resolves aliases like "from os import system as mysys" as: mysys -> os.system
630
+ local_definitions = self .module_definitions_stack [- 1 ]
631
+ call_function_label = fully_qualify_alias_labels (call_function_label , local_definitions .import_alias_mapping )
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,7 @@ 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
819
+ # Here, in `visit_Import` and in `visit_ImportFrom` are the only places the ` import_alias_mapping` is updated
814
820
parent_definitions .import_alias_mapping .update (import_alias_mapping )
815
821
parent_definitions .import_names = local_names
816
822
@@ -919,10 +925,10 @@ def from_directory_import(
919
925
if init_exists and not skip_init :
920
926
package_name = os .path .split (module_path )[1 ]
921
927
return self .add_module (
922
- (module [0 ], init_file_location ),
923
- package_name ,
924
- local_names ,
925
- import_alias_mapping ,
928
+ module = (module [0 ], init_file_location ),
929
+ module_or_package_name = package_name ,
930
+ local_names = local_names ,
931
+ import_alias_mapping = import_alias_mapping ,
926
932
is_init = True ,
927
933
from_from = True
928
934
)
@@ -932,10 +938,10 @@ def from_directory_import(
932
938
new_init_file_location = os .path .join (full_name , '__init__.py' )
933
939
if os .path .isfile (new_init_file_location ):
934
940
self .add_module (
935
- (real_name , new_init_file_location ),
936
- real_name ,
937
- local_names ,
938
- import_alias_mapping ,
941
+ module = (real_name , new_init_file_location ),
942
+ module_or_package_name = real_name ,
943
+ local_names = local_names ,
944
+ import_alias_mapping = import_alias_mapping ,
939
945
is_init = True ,
940
946
from_from = True ,
941
947
from_fdid = True
@@ -945,10 +951,10 @@ def from_directory_import(
945
951
else :
946
952
file_module = (real_name , full_name + '.py' )
947
953
self .add_module (
948
- file_module ,
949
- real_name ,
950
- local_names ,
951
- import_alias_mapping ,
954
+ module = file_module ,
955
+ module_or_package_name = real_name ,
956
+ local_names = local_names ,
957
+ import_alias_mapping = import_alias_mapping ,
952
958
from_from = True
953
959
)
954
960
return IgnoredNode ()
@@ -959,10 +965,10 @@ def import_package(self, module, module_name, local_name, import_alias_mapping):
959
965
init_exists = os .path .isfile (init_file_location )
960
966
if init_exists :
961
967
return self .add_module (
962
- (module [0 ], init_file_location ),
963
- module_name ,
964
- local_name ,
965
- import_alias_mapping ,
968
+ module = (module [0 ], init_file_location ),
969
+ module_or_package_name = module_name ,
970
+ local_names = local_name ,
971
+ import_alias_mapping = import_alias_mapping ,
966
972
is_init = True
967
973
)
968
974
else :
@@ -1005,10 +1011,10 @@ def handle_relative_import(self, node):
1005
1011
# Is it a file?
1006
1012
if name_with_dir .endswith ('.py' ):
1007
1013
return self .add_module (
1008
- (node .module , name_with_dir ),
1009
- None ,
1010
- as_alias_handler (node .names ),
1011
- retrieve_import_alias_mapping (node .names ),
1014
+ module = (node .module , name_with_dir ),
1015
+ module_or_package_name = None ,
1016
+ local_names = as_alias_handler (node .names ),
1017
+ import_alias_mapping = retrieve_import_alias_mapping (node .names ),
1012
1018
from_from = True
1013
1019
)
1014
1020
return self .from_directory_import (
@@ -1031,10 +1037,10 @@ def visit_Import(self, node):
1031
1037
retrieve_import_alias_mapping (node .names )
1032
1038
)
1033
1039
return self .add_module (
1034
- module ,
1035
- name .name ,
1036
- name .asname ,
1037
- retrieve_import_alias_mapping (node .names )
1040
+ module = module ,
1041
+ module_or_package_name = name .name ,
1042
+ local_names = name .asname ,
1043
+ import_alias_mapping = retrieve_import_alias_mapping (node .names )
1038
1044
)
1039
1045
for module in self .project_modules :
1040
1046
if name .name == module [0 ]:
@@ -1046,55 +1052,69 @@ def visit_Import(self, node):
1046
1052
retrieve_import_alias_mapping (node .names )
1047
1053
)
1048
1054
return self .add_module (
1049
- module ,
1050
- name .name ,
1051
- name .asname ,
1052
- retrieve_import_alias_mapping (node .names )
1055
+ module = module ,
1056
+ module_or_package_name = name .name ,
1057
+ local_names = name .asname ,
1058
+ import_alias_mapping = retrieve_import_alias_mapping (node .names )
1053
1059
)
1054
1060
for alias in node .names :
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
+ local_definitions = self .module_definitions_stack [- 1 ]
1066
+ local_definitions .import_alias_mapping [name .asname ] = alias .name
1055
1067
if alias .name not in uninspectable_modules :
1056
- log .warn ("Cannot inspect module %s" , alias .name )
1068
+ log .warning ("Cannot inspect module %s" , alias .name )
1057
1069
uninspectable_modules .add (alias .name ) # Don't repeatedly warn about this
1058
1070
return IgnoredNode ()
1059
1071
1060
1072
def visit_ImportFrom (self , node ):
1061
1073
# Is it relative?
1062
1074
if node .level > 0 :
1063
1075
return self .handle_relative_import (node )
1064
- else :
1065
- for module in self .local_modules :
1066
- if node .module == module [0 ]:
1067
- if os .path .isdir (module [1 ]):
1068
- return self .from_directory_import (
1069
- module ,
1070
- not_as_alias_handler (node .names ),
1071
- as_alias_handler (node .names )
1072
- )
1073
- return self .add_module (
1076
+ # not relative
1077
+ for module in self .local_modules :
1078
+ if node .module == module [0 ]:
1079
+ if os .path .isdir (module [1 ]):
1080
+ return self .from_directory_import (
1074
1081
module ,
1075
- None ,
1076
- as_alias_handler (node .names ),
1077
- retrieve_import_alias_mapping (node .names ),
1078
- from_from = True
1082
+ not_as_alias_handler (node .names ),
1083
+ as_alias_handler (node .names )
1079
1084
)
1080
- for module in self .project_modules :
1081
- name = module [0 ]
1082
- if node .module == name :
1083
- if os .path .isdir (module [1 ]):
1084
- return self .from_directory_import (
1085
- module ,
1086
- not_as_alias_handler (node .names ),
1087
- as_alias_handler (node .names ),
1088
- retrieve_import_alias_mapping (node .names )
1089
- )
1090
- return self .add_module (
1085
+ return self .add_module (
1086
+ module = module ,
1087
+ module_or_package_name = None ,
1088
+ local_names = as_alias_handler (node .names ),
1089
+ import_alias_mapping = retrieve_import_alias_mapping (node .names ),
1090
+ from_from = True
1091
+ )
1092
+ for module in self .project_modules :
1093
+ name = module [0 ]
1094
+ if node .module == name :
1095
+ if os .path .isdir (module [1 ]):
1096
+ return self .from_directory_import (
1091
1097
module ,
1092
- None ,
1098
+ not_as_alias_handler ( node . names ) ,
1093
1099
as_alias_handler (node .names ),
1094
- retrieve_import_alias_mapping (node .names ),
1095
- from_from = True
1100
+ retrieve_import_alias_mapping (node .names )
1096
1101
)
1102
+ return self .add_module (
1103
+ module = module ,
1104
+ module_or_package_name = None ,
1105
+ local_names = as_alias_handler (node .names ),
1106
+ import_alias_mapping = retrieve_import_alias_mapping (node .names ),
1107
+ from_from = True
1108
+ )
1109
+
1110
+ # Remember aliases for uninspectable modules 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
+ local_definitions = self .module_definitions_stack [- 1 ]
1115
+ local_definitions .import_alias_mapping [name .asname or name .name ] = "{}.{}" .format (node .module , name .name )
1116
+
1097
1117
if node .module not in uninspectable_modules :
1098
- log .warn ("Cannot inspect module %s" , node .module )
1118
+ log .warning ("Cannot inspect module %s" , node .module )
1099
1119
uninspectable_modules .add (node .module )
1100
1120
return IgnoredNode ()
0 commit comments