File tree Expand file tree Collapse file tree 4 files changed +34
-4
lines changed
experimental/dataflow/typetracking
library-tests/ApiGraphs/py3 Expand file tree Collapse file tree 4 files changed +34
-4
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ category : minorAnalysis
3
+ ---
4
+ * Change ` .getASubclass() ` on ` API::Node ` so it allows to follow subclasses even if the class has a class decorator.
Original file line number Diff line number Diff line change @@ -680,8 +680,16 @@ module API {
680
680
or
681
681
// Subclassing a node
682
682
lbl = Label:: subclass ( ) and
683
- exists ( DataFlow:: Node superclass | pred .flowsTo ( superclass ) |
684
- ref .asExpr ( ) .( PY:: ClassExpr ) .getABase ( ) = superclass .asExpr ( )
683
+ exists ( PY:: ClassExpr clsExpr , DataFlow:: Node superclass | pred .flowsTo ( superclass ) |
684
+ clsExpr .getABase ( ) = superclass .asExpr ( ) and
685
+ // Potentially a class decorator could do anything, but we assume they are
686
+ // "benign" and let subclasses edges flow through anyway.
687
+ // see example in https://github.com/django/django/blob/c2250cfb80e27cdf8d098428824da2800a18cadf/tests/auth_tests/test_views.py#L40-L46
688
+ (
689
+ ref .asExpr ( ) = clsExpr
690
+ or
691
+ ref .asExpr ( ) = clsExpr .getADecoratorCall ( )
692
+ )
685
693
)
686
694
or
687
695
// awaiting
Original file line number Diff line number Diff line change @@ -65,6 +65,9 @@ def foo():
65
65
also_x = foo () # $ MISSING: tracked
66
66
print (also_x ) # $ MISSING: tracked
67
67
68
+ # ------------------------------------------------------------------------------
69
+ # Function decorator
70
+ # ------------------------------------------------------------------------------
68
71
69
72
def my_decorator (func ):
70
73
# This part doesn't make any sense in a normal decorator, but just shows how we
@@ -135,7 +138,7 @@ def meth3(self):
135
138
def track_self (self ): # $ tracked_self
136
139
self .meth1 () # $ tracked_self
137
140
super ().meth2 ()
138
- super (Bar , self ).foo3 () # $ tracked_self
141
+ super (Bar , self ).meth3 () # $ tracked_self
139
142
140
143
# ------------------------------------------------------------------------------
141
144
# Tracking of attribute lookup after "long" import chain
Original file line number Diff line number Diff line change @@ -16,4 +16,19 @@ class IntMyView(View): #$ use=moduleImport("pflask").getMember("views").getMembe
16
16
def my_internal_method (self ): #$ def=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_method")
17
17
pass
18
18
19
- int_instance = IntMyView () #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()
19
+ int_instance = IntMyView () #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()
20
+
21
+ # ------------------------------------------------------------------------------
22
+ # Class decorator
23
+ # ------------------------------------------------------------------------------
24
+
25
+ def my_class_decorator (cls ):
26
+ print ("dummy decorator" )
27
+ return cls
28
+
29
+ @my_class_decorator
30
+ class MyViewWithDecorator (View ): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
31
+ pass
32
+
33
+ class SubclassFromDecorated (MyViewWithDecorator ): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getASubclass()
34
+ pass
You can’t perform that action at this time.
0 commit comments