@@ -34,6 +34,14 @@ def get_binding(name, namespace):
3434 namespace .bindings .append (binding )
3535 return binding
3636
37+ def get_binding_disallow_class_namespace_rename (name , namespace ):
38+ binding = get_binding (name , namespace )
39+
40+ if isinstance (namespace , ast .ClassDef ):
41+ # This name will become an attribute of a class, so it can't be renamed
42+ binding .disallow_rename ()
43+
44+ return binding
3745
3846def resolve_names (node ):
3947 """
@@ -47,39 +55,49 @@ def resolve_names(node):
4755 if isinstance (node , ast .Name ) and isinstance (node .ctx , ast .Load ):
4856 get_binding (node .id , node .namespace ).add_reference (node )
4957 elif isinstance (node , ast .Name ) and node .id in node .namespace .nonlocal_names :
50- get_binding (node .id , node .namespace ).add_reference (node )
58+ binding = get_binding (node .id , node .namespace )
59+ binding .add_reference (node )
60+
61+ if isinstance (node .ctx , ast .Store ) and isinstance (node .namespace , ast .ClassDef ):
62+ binding .disallow_rename ()
5163
5264 elif isinstance (node , ast .ClassDef ) and node .name in node .namespace .nonlocal_names :
53- get_binding (node .name , node .namespace ).add_reference (node )
65+ binding = get_binding_disallow_class_namespace_rename (node .name , node .namespace )
66+ binding .add_reference (node )
67+
5468 elif is_ast_node (node , (ast .FunctionDef , 'AsyncFunctionDef' )) and node .name in node .namespace .nonlocal_names :
55- get_binding (node .name , node .namespace ).add_reference (node )
69+ binding = get_binding_disallow_class_namespace_rename (node .name , node .namespace )
70+ binding .add_reference (node )
71+
5672 elif isinstance (node , ast .alias ):
5773
5874 if node .asname is not None :
5975 if node .asname in node .namespace .nonlocal_names :
60- get_binding (node .asname , node .namespace ).add_reference (node )
76+ binding = get_binding_disallow_class_namespace_rename (node .asname , node .namespace )
77+ binding .add_reference (node )
78+
6179 else :
6280 # This binds the root module only for a dotted import
6381 root_module = node .name .split ('.' )[0 ]
6482
6583 if root_module in node .namespace .nonlocal_names :
66- binding = get_binding (root_module , node .namespace )
84+ binding = get_binding_disallow_class_namespace_rename (root_module , node .namespace )
6785 binding .add_reference (node )
6886
6987 if '.' in node .name :
7088 binding .disallow_rename ()
7189
7290 elif isinstance (node , ast .ExceptHandler ) and node .name is not None :
7391 if isinstance (node .name , str ) and node .name in node .namespace .nonlocal_names :
74- get_binding (node .name , node .namespace ).add_reference (node )
92+ get_binding_disallow_class_namespace_rename (node .name , node .namespace ).add_reference (node )
7593
7694 elif is_ast_node (node , 'Nonlocal' ):
7795 for name in node .names :
78- get_binding (name , node .namespace ).add_reference (node )
96+ get_binding_disallow_class_namespace_rename (name , node .namespace ).add_reference (node )
7997 elif is_ast_node (node , ('MatchAs' , 'MatchStar' )) and node .name in node .namespace .nonlocal_names :
80- get_binding (node .name , node .namespace ).add_reference (node )
98+ get_binding_disallow_class_namespace_rename (node .name , node .namespace ).add_reference (node )
8199 elif is_ast_node (node , 'MatchMapping' ) and node .rest in node .namespace .nonlocal_names :
82- get_binding (node .rest , node .namespace ).add_reference (node )
100+ get_binding_disallow_class_namespace_rename (node .rest , node .namespace ).add_reference (node )
83101
84102 elif is_ast_node (node , 'Exec' ):
85103 get_global_namespace (node ).tainted = True
0 commit comments