11import python
22
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 }
64
7- PythonModuleObject module_imported_by ( PythonModuleObject m ) {
5+ ModuleValue module_imported_by ( ModuleValue m ) {
86 exists ( Stmt imp |
97 result = stmt_imports ( imp ) and
10- imp .getEnclosingModule ( ) = m .getModule ( ) and
8+ imp .getEnclosingModule ( ) = m .getScope ( ) and
119 // Import must reach exit to be part of a cycle
1210 imp .getAnEntryNode ( ) .getBasicBlock ( ) .reachesExit ( )
1311 )
1412}
1513
1614/** 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 ) {
1816 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 )
2019}
2120
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 )
2625 )
2726}
2827
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
3130 is_import_time ( imp ) and
3231 m2 = stmt_imports ( imp )
3332}
3433
3534/** 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 ) {
3736 m1 != m2 and
38- import_time_imported_module ( m1 , m2 , imp ) and
37+ import_time_imported_module ( m1 , m2 , imp ) and
3938 import_time_transitive_import ( m2 , _, m1 )
4039}
4140
42- predicate import_time_transitive_import ( PythonModuleObject base , Stmt imp , PythonModuleObject last ) {
41+ predicate import_time_transitive_import ( ModuleValue base , Stmt imp , ModuleValue last ) {
4342 last != base and
4443 (
4544 import_time_imported_module ( base , last , imp )
4645 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
4948 import_time_imported_module ( mid , last , _)
5049 )
5150 ) and
@@ -56,12 +55,12 @@ predicate import_time_transitive_import(PythonModuleObject base, Stmt imp, Pytho
5655/**
5756 * Returns import-time usages of module 'm' in module 'enclosing'
5857 */
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+ |
6564 // either 'M.foo'
6665 use .( Attribute ) .getObject ( ) = mod and use .( Attribute ) .getName ( ) = attr
6766 or
@@ -70,20 +69,24 @@ predicate import_time_module_use(PythonModuleObject m, PythonModuleObject enclos
7069 )
7170}
7271
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+ ) {
7980 import_time_imported_module ( other , first , _) and
8081 import_time_transitive_import ( first , imp , other ) and
8182 import_time_module_use ( first , other , use , attr ) and
82- exists ( ImportTimeScope n , SsaVariable v |
83+ exists ( ImportTimeScope n , SsaVariable v |
8384 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+ |
8589 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 ) )
8892}
89-
0 commit comments