File tree Expand file tree Collapse file tree
src/semmle/python/objects
test/library-tests/overrides Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -105,6 +105,18 @@ class Value extends TObject {
105105 or
106106 this instanceof AbsentModuleAttributeObjectInternal
107107 }
108+
109+ /** Whether this overrides v. In this context, "overrides" means that this object
110+ * is a named attribute of a some class C and `v` is a named attribute of another
111+ * class S, both attributes having the same name, and S is a super class of C.
112+ */
113+ predicate overrides ( Value v ) {
114+ exists ( ClassValue my_class , ClassValue other_class , string name |
115+ my_class .declaredAttribute ( name ) = this and
116+ other_class .declaredAttribute ( name ) = v and
117+ my_class .getABaseType + ( ) = other_class
118+ )
119+ }
108120}
109121
110122/** Class representing modules in the Python program
@@ -461,6 +473,14 @@ abstract class FunctionValue extends CallableValue {
461473
462474 /** Gets the maximum number of parameters that can be correctly passed to this function */
463475 abstract int maxParameters ( ) ;
476+
477+ predicate isOverridingMethod ( ) {
478+ exists ( Value f | this .overrides ( f ) )
479+ }
480+
481+ predicate isOverriddenMethod ( ) {
482+ exists ( Value f | f .overrides ( this ) )
483+ }
464484}
465485
466486/** Class representing Python functions */
Original file line number Diff line number Diff line change 1+ | test.py:3:5:3:20 | Function Wat.upper | overriding | not overridden |
2+ | test.py:6:1:6:26 | Function outside_func | not overriding | overridden |
3+ | test.py:11:11:11:29 | Function Base.lambda | not overriding | overridden |
4+ | test.py:13:24:13:36 | Function Base.lambda | not overriding | not overridden |
5+ | test.py:17:5:17:21 | Function Base.normal | not overriding | overridden |
6+ | test.py:28:5:28:21 | Function Sub2.foo | overriding | overridden |
7+ | test.py:31:5:31:24 | Function Sub2.tricky | overriding | not overridden |
8+ | test.py:36:5:36:21 | Function Sub2Sub.foo | overriding | not overridden |
9+ | test.py:39:5:39:18 | Function Sub2Sub.baz | overriding | not overridden |
Original file line number Diff line number Diff line change 1+ import python
2+
3+ from PythonFunctionValue f , string overriding , string overridden
4+ where
5+ ( if f .isOverridingMethod ( ) then overriding = "overriding" else overriding = "not overriding" ) and
6+ ( if f .isOverriddenMethod ( ) then overridden = "overridden" else overridden = "not overridden" )
7+ select f , overriding , overridden
Original file line number Diff line number Diff line change 1+ class Wat (str ):
2+
3+ def upper (self ):
4+ return self .lower ()
5+
6+ def outside_func (self , x ):
7+ print (x )
8+
9+ class Base (object ):
10+
11+ foo = lambda self , x : x + 1
12+
13+ bar = staticmethod (lambda x : x + 1 )
14+
15+ baz = 123
16+
17+ def normal (self ):
18+ pass
19+
20+ tricky = outside_func
21+
22+ class Sub (Base ):
23+
24+ normal = False
25+
26+ class Sub2 (Base ):
27+
28+ def foo (self , y ):
29+ return y * 100
30+
31+ def tricky (self , x ):
32+ print ('nice!' , x )
33+
34+ class Sub2Sub (Sub2 ):
35+
36+ def foo (self , z ):
37+ return z / 123
38+
39+ def baz (self ):
40+ print ('python is a bit crazy sometimes' )
41+
42+
43+ ws = Wat ('asdf' )
44+ print (ws .upper (), len (ws ))
45+
46+ b = Base ()
47+ print (b .foo (1 ))
48+ print (b .bar (10 ))
49+
50+
51+ ss = SubSub ()
52+ print (ss .foo (1 ))
53+ ss .baz ()
You can’t perform that action at this time.
0 commit comments