1
1
import python
2
2
3
- predicate is_import_time ( Stmt s ) {
4
- not s .getScope + ( ) instanceof Function
5
- }
3
+ predicate is_import_time ( Stmt s ) { not s .getScope + ( ) instanceof Function }
6
4
7
- PythonModuleObject module_imported_by ( PythonModuleObject m ) {
5
+ ModuleValue module_imported_by ( ModuleValue m ) {
8
6
exists ( Stmt imp |
9
7
result = stmt_imports ( imp ) and
10
- imp .getEnclosingModule ( ) = m .getModule ( ) and
8
+ imp .getEnclosingModule ( ) = m .getScope ( ) and
11
9
// Import must reach exit to be part of a cycle
12
10
imp .getAnEntryNode ( ) .getBasicBlock ( ) .reachesExit ( )
13
11
)
14
12
}
15
13
16
14
/** Is there a circular import of 'm1' beginning with 'm2'? */
17
- predicate circular_import ( PythonModuleObject m1 , PythonModuleObject m2 ) {
15
+ predicate circular_import ( ModuleValue m1 , ModuleValue m2 ) {
18
16
m1 != m2 and
19
- m2 = module_imported_by ( m1 ) and m1 = module_imported_by + ( m2 )
17
+ m2 = module_imported_by ( m1 ) and
18
+ m1 = module_imported_by + ( m2 )
20
19
}
21
20
22
- ModuleObject stmt_imports ( ImportingStmt s ) {
23
- exists ( string name |
24
- result . importedAs ( name ) and not name = "__main__" |
25
- name = s . getAnImportedModuleName ( )
21
+ ModuleValue stmt_imports ( ImportingStmt s ) {
22
+ exists ( string name | result . importedAs ( name ) and not name = "__main__" |
23
+ name = s . getAnImportedModuleName ( ) and
24
+ s . getASubExpression ( ) . pointsTo ( result )
26
25
)
27
26
}
28
27
29
- predicate import_time_imported_module ( PythonModuleObject m1 , PythonModuleObject m2 , Stmt imp ) {
30
- imp .getEnclosingModule ( ) = m1 .getModule ( ) and
28
+ predicate import_time_imported_module ( ModuleValue m1 , ModuleValue m2 , Stmt imp ) {
29
+ imp .getEnclosingModule ( ) = m1 .getScope ( ) and
31
30
is_import_time ( imp ) and
32
31
m2 = stmt_imports ( imp )
33
32
}
34
33
35
34
/** Is there a cyclic import of 'm1' beginning with an import 'm2' at 'imp' where all the imports are top-level? */
36
- predicate import_time_circular_import ( PythonModuleObject m1 , PythonModuleObject m2 , Stmt imp ) {
35
+ predicate import_time_circular_import ( ModuleValue m1 , ModuleValue m2 , Stmt imp ) {
37
36
m1 != m2 and
38
- import_time_imported_module ( m1 , m2 , imp ) and
37
+ import_time_imported_module ( m1 , m2 , imp ) and
39
38
import_time_transitive_import ( m2 , _, m1 )
40
39
}
41
40
42
- predicate import_time_transitive_import ( PythonModuleObject base , Stmt imp , PythonModuleObject last ) {
41
+ predicate import_time_transitive_import ( ModuleValue base , Stmt imp , ModuleValue last ) {
43
42
last != base and
44
43
(
45
44
import_time_imported_module ( base , last , imp )
46
45
or
47
- exists ( PythonModuleObject mid |
48
- import_time_transitive_import ( base , imp , mid ) and
46
+ exists ( ModuleValue mid |
47
+ import_time_transitive_import ( base , imp , mid ) and
49
48
import_time_imported_module ( mid , last , _)
50
49
)
51
50
) and
@@ -56,12 +55,12 @@ predicate import_time_transitive_import(PythonModuleObject base, Stmt imp, Pytho
56
55
/**
57
56
* Returns import-time usages of module 'm' in module 'enclosing'
58
57
*/
59
- predicate import_time_module_use ( PythonModuleObject m , PythonModuleObject enclosing , Expr use , string attr ) {
60
- exists ( Expr mod |
61
- use .getEnclosingModule ( ) = enclosing .getModule ( ) and
62
- not use .getScope + ( ) instanceof Function
63
- and mod .refersTo ( m )
64
- |
58
+ predicate import_time_module_use ( ModuleValue m , ModuleValue enclosing , Expr use , string attr ) {
59
+ exists ( Expr mod |
60
+ use .getEnclosingModule ( ) = enclosing .getScope ( ) and
61
+ not use .getScope + ( ) instanceof Function and
62
+ mod .pointsTo ( m )
63
+ |
65
64
// either 'M.foo'
66
65
use .( Attribute ) .getObject ( ) = mod and use .( Attribute ) .getName ( ) = attr
67
66
or
@@ -70,20 +69,24 @@ predicate import_time_module_use(PythonModuleObject m, PythonModuleObject enclos
70
69
)
71
70
}
72
71
73
- /** Whether importing module 'first' before importing module 'other' will fail at runtime, due to an
74
- AttributeError at 'use' (in module 'other') caused by 'first.attr' not being defined as its definition can
75
- occur after the import 'other' in 'first'.
76
- */
77
- predicate failing_import_due_to_cycle ( PythonModuleObject first , PythonModuleObject other , Stmt imp ,
78
- ControlFlowNode defn , Expr use , string attr ) {
72
+ /**
73
+ * Whether importing module 'first' before importing module 'other' will fail at runtime, due to an
74
+ * AttributeError at 'use' (in module 'other') caused by 'first.attr' not being defined as its definition can
75
+ * occur after the import 'other' in 'first'.
76
+ */
77
+ predicate failing_import_due_to_cycle (
78
+ ModuleValue first , ModuleValue other , Stmt imp , ControlFlowNode defn , Expr use , string attr
79
+ ) {
79
80
import_time_imported_module ( other , first , _) and
80
81
import_time_transitive_import ( first , imp , other ) and
81
82
import_time_module_use ( first , other , use , attr ) and
82
- exists ( ImportTimeScope n , SsaVariable v |
83
+ exists ( ImportTimeScope n , SsaVariable v |
83
84
defn = v .getDefinition ( ) and
84
- n = first .getModule ( ) and v .getVariable ( ) .getScope ( ) = n and v .getId ( ) = attr |
85
+ n = first .getScope ( ) and
86
+ v .getVariable ( ) .getScope ( ) = n and
87
+ v .getId ( ) = attr
88
+ |
85
89
not defn .strictlyDominates ( imp .getAnEntryNode ( ) )
86
- )
87
- and not exists ( If i | i .isNameEqMain ( ) and i .contains ( use ) )
90
+ ) and
91
+ not exists ( If i | i .isNameEqMain ( ) and i .contains ( use ) )
88
92
}
89
-
0 commit comments