Skip to content

Commit 419130b

Browse files
authored
Merge pull request #15030 from yoff/python/remove-module-entry-definitions
Python: Remove control flow nodes for module entry definitions from the dataflow graph.
2 parents d8f53e5 + d9c0c8c commit 419130b

File tree

9 files changed

+6
-81
lines changed

9 files changed

+6
-81
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ private import semmle.python.frameworks.data.ModelsAsData
1515
/**
1616
* IPA type for data flow nodes.
1717
*
18-
* Flow between SSA variables are computed in `Essa.qll`
18+
* Nodes broadly fall into three categories.
1919
*
20-
* Flow from SSA variables to control flow nodes are generally via uses.
21-
*
22-
* Flow from control flow nodes to SSA variables are generally via assignments.
23-
*
24-
* The current implementation of these cross flows can be seen in `EssaTaintTracking`.
20+
* - Control flow nodes: Flow between these is based on use-use flow computed via an SSA analysis.
21+
* - Module variable nodes: These represent global variables and act as canonical targets for reads and writes of these.
22+
* - Synthetic nodes: These handle flow in various special cases.
2523
*/
2624
newtype TNode =
2725
/** A node corresponding to a control flow node. */
@@ -30,7 +28,7 @@ newtype TNode =
3028
or
3129
node.getNode() instanceof Pattern
3230
or
33-
node = any(ScopeEntryDefinition def).getDefiningNode()
31+
node = any(ScopeEntryDefinition def | not def.getScope() instanceof Module).getDefiningNode()
3432
} or
3533
/**
3634
* A synthetic node representing the value of an object before a state change.

python/ql/test/experimental/dataflow/basic/local.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
| test.py:0:0:0:0 | Entry node for Module test | test.py:0:0:0:0 | Entry node for Module test |
21
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
32
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |
43
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |

python/ql/test/experimental/dataflow/basic/sinks.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
| test.py:0:0:0:0 | Entry node for Module test |
21
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
32
| test.py:1:1:1:21 | SynthDictSplatParameterNode |
43
| test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |

python/ql/test/experimental/dataflow/basic/sources.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
| test.py:0:0:0:0 | Entry node for Module test |
21
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr |
32
| test.py:1:1:1:21 | SynthDictSplatParameterNode |
43
| test.py:1:5:1:17 | ControlFlowNode for obfuscated_id |

python/ql/test/experimental/dataflow/enclosing-callable/EnclosingCallable.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
| class_example.py:0:0:0:0 | Module class_example | class_example.py:0:0:0:0 | Entry node for Module class_example |
21
| class_example.py:0:0:0:0 | Module class_example | class_example.py:1:1:1:3 | ControlFlowNode for wat |
32
| class_example.py:0:0:0:0 | Module class_example | class_example.py:1:7:1:7 | ControlFlowNode for IntegerLiteral |
43
| class_example.py:0:0:0:0 | Module class_example | class_example.py:3:1:3:10 | ControlFlowNode for ClassExpr |
@@ -13,7 +12,6 @@
1312
| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:1:7:23 | ControlFlowNode for print() |
1413
| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:7:7:17 | ControlFlowNode for Str |
1514
| class_example.py:0:0:0:0 | Module class_example | class_example.py:7:20:7:22 | ControlFlowNode for wat |
16-
| generator.py:0:0:0:0 | Module generator | generator.py:0:0:0:0 | Entry node for Module generator |
1715
| generator.py:0:0:0:0 | Module generator | generator.py:1:1:1:23 | ControlFlowNode for FunctionExpr |
1816
| generator.py:0:0:0:0 | Module generator | generator.py:1:5:1:18 | ControlFlowNode for generator_func |
1917
| generator.py:1:1:1:23 | Function generator_func | generator.py:1:20:1:21 | ControlFlowNode for xs |

python/ql/test/experimental/dataflow/import-star/global.expected

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
| deux.py:0:0:0:0 | Entry node for Module deux | deux.py:2:1:2:5 | ControlFlowNode for print |
2-
| deux.py:0:0:0:0 | Entry node for Module deux | deux.py:2:7:2:9 | ControlFlowNode for foo |
3-
| test1.py:0:0:0:0 | Entry node for Module test1 | test1.py:2:1:2:5 | ControlFlowNode for print |
4-
| test1.py:0:0:0:0 | Entry node for Module test1 | test1.py:2:7:2:9 | ControlFlowNode for foo |
5-
| test2.py:0:0:0:0 | Entry node for Module test2 | test2.py:2:1:2:5 | ControlFlowNode for print |
6-
| test2.py:0:0:0:0 | Entry node for Module test2 | test2.py:2:7:2:9 | ControlFlowNode for foo |
71
| test3.py:1:17:1:19 | ControlFlowNode for ImportMember | test3.py:1:17:1:19 | ControlFlowNode for foo |
82
| test3.py:1:17:1:19 | ControlFlowNode for ImportMember | test3.py:2:7:2:9 | ControlFlowNode for foo |
93
| test3.py:1:17:1:19 | ControlFlowNode for foo | test3.py:2:7:2:9 | ControlFlowNode for foo |
@@ -23,11 +17,6 @@
2317
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | deux.py:2:7:2:9 | ControlFlowNode for foo |
2418
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test2.py:2:7:2:9 | ControlFlowNode for foo |
2519
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | trois.py:1:1:1:3 | ControlFlowNode for foo |
26-
| two.py:0:0:0:0 | Entry node for Module two | test3.py:1:17:1:19 | ControlFlowNode for ImportMember |
27-
| two.py:0:0:0:0 | Entry node for Module two | test3.py:1:17:1:19 | ControlFlowNode for foo |
28-
| two.py:0:0:0:0 | Entry node for Module two | test3.py:2:7:2:9 | ControlFlowNode for foo |
29-
| two.py:0:0:0:0 | Entry node for Module two | two.py:2:1:2:5 | ControlFlowNode for print |
30-
| two.py:0:0:0:0 | Entry node for Module two | two.py:2:7:2:9 | ControlFlowNode for foo |
3120
| two.py:2:7:2:9 | ControlFlowNode for foo | test3.py:1:17:1:19 | ControlFlowNode for ImportMember |
3221
| two.py:2:7:2:9 | ControlFlowNode for foo | test3.py:1:17:1:19 | ControlFlowNode for foo |
3322
| two.py:2:7:2:9 | ControlFlowNode for foo | test3.py:2:7:2:9 | ControlFlowNode for foo |

python/ql/test/experimental/import-resolution/ModuleExport.expected

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,29 @@
11
| attr_clash.__init__ | __file__ | attr_clash/__init__.py:6:6:6:13 | ControlFlowNode for __file__ |
2-
| attr_clash.__init__ | __name__ | attr_clash/__init__.py:0:0:0:0 | Entry node for Module attr_clash.__init__ |
3-
| attr_clash.__init__ | __package__ | attr_clash/__init__.py:0:0:0:0 | Entry node for Module attr_clash.__init__ |
42
| attr_clash.__init__ | clashing_attr | attr_clash/__init__.py:4:1:4:13 | ControlFlowNode for clashing_attr |
53
| attr_clash.__init__ | enter | attr_clash/__init__.py:2:1:2:5 | ControlFlowNode for enter |
64
| attr_clash.__init__ | exit | attr_clash/__init__.py:6:1:6:4 | ControlFlowNode for exit |
75
| attr_clash.clashing_attr | __file__ | attr_clash/clashing_attr.py:4:6:4:13 | ControlFlowNode for __file__ |
8-
| attr_clash.clashing_attr | __name__ | attr_clash/clashing_attr.py:0:0:0:0 | Entry node for Module attr_clash.clashing_attr |
9-
| attr_clash.clashing_attr | __package__ | attr_clash/clashing_attr.py:0:0:0:0 | Entry node for Module attr_clash.clashing_attr |
106
| attr_clash.clashing_attr | enter | attr_clash/clashing_attr.py:2:1:2:5 | ControlFlowNode for enter |
117
| attr_clash.clashing_attr | exit | attr_clash/clashing_attr.py:4:1:4:4 | ControlFlowNode for exit |
128
| attr_clash.non_clashing_submodule | __file__ | attr_clash/non_clashing_submodule.py:4:6:4:13 | ControlFlowNode for __file__ |
13-
| attr_clash.non_clashing_submodule | __name__ | attr_clash/non_clashing_submodule.py:0:0:0:0 | Entry node for Module attr_clash.non_clashing_submodule |
14-
| attr_clash.non_clashing_submodule | __package__ | attr_clash/non_clashing_submodule.py:0:0:0:0 | Entry node for Module attr_clash.non_clashing_submodule |
159
| attr_clash.non_clashing_submodule | enter | attr_clash/non_clashing_submodule.py:2:1:2:5 | ControlFlowNode for enter |
1610
| attr_clash.non_clashing_submodule | exit | attr_clash/non_clashing_submodule.py:4:1:4:4 | ControlFlowNode for exit |
1711
| bar | __file__ | bar.py:6:6:6:13 | ControlFlowNode for __file__ |
18-
| bar | __name__ | bar.py:0:0:0:0 | Entry node for Module bar |
19-
| bar | __package__ | bar.py:0:0:0:0 | Entry node for Module bar |
2012
| bar | bar_attr | bar.py:4:1:4:8 | ControlFlowNode for bar_attr |
2113
| bar | enter | bar.py:2:1:2:5 | ControlFlowNode for enter |
2214
| bar | exit | bar.py:6:1:6:4 | ControlFlowNode for exit |
2315
| baz | __file__ | baz.py:6:6:6:13 | ControlFlowNode for __file__ |
24-
| baz | __name__ | baz.py:0:0:0:0 | Entry node for Module baz |
25-
| baz | __package__ | baz.py:0:0:0:0 | Entry node for Module baz |
2616
| baz | baz_attr | baz.py:4:1:4:8 | ControlFlowNode for baz_attr |
2717
| baz | enter | baz.py:2:1:2:5 | ControlFlowNode for enter |
2818
| baz | exit | baz.py:6:1:6:4 | ControlFlowNode for exit |
2919
| block_flow_check | SOURCE | block_flow_check.py:12:25:12:30 | ControlFlowNode for SOURCE |
3020
| block_flow_check | __file__ | block_flow_check.py:14:6:14:13 | ControlFlowNode for __file__ |
31-
| block_flow_check | __name__ | block_flow_check.py:0:0:0:0 | Entry node for Module block_flow_check |
32-
| block_flow_check | __package__ | block_flow_check.py:0:0:0:0 | Entry node for Module block_flow_check |
3321
| block_flow_check | check | block_flow_check.py:12:1:12:5 | ControlFlowNode for check |
3422
| block_flow_check | enter | block_flow_check.py:2:1:2:5 | ControlFlowNode for enter |
3523
| block_flow_check | exit | block_flow_check.py:14:1:14:4 | ControlFlowNode for exit |
3624
| block_flow_check | globals | block_flow_check.py:12:33:12:39 | ControlFlowNode for globals |
3725
| block_flow_check | object | block_flow_check.py:4:14:4:19 | ControlFlowNode for object |
38-
| block_flow_check | staticmethod | block_flow_check.py:0:0:0:0 | Entry node for Module block_flow_check |
3926
| foo | __file__ | foo.py:14:6:14:13 | ControlFlowNode for __file__ |
40-
| foo | __name__ | foo.py:0:0:0:0 | Entry node for Module foo |
41-
| foo | __package__ | foo.py:0:0:0:0 | Entry node for Module foo |
4227
| foo | __private_foo_attr | foo.py:8:1:8:18 | ControlFlowNode for __private_foo_attr |
4328
| foo | bar_reexported | foo.py:11:8:11:10 | ControlFlowNode for ImportExpr |
4429
| foo | bar_reexported | foo.py:12:34:12:47 | ControlFlowNode for bar_reexported |
@@ -51,41 +36,30 @@
5136
| generous_export | SOURCE | generous_export.py:15:11:15:16 | ControlFlowNode for SOURCE |
5237
| generous_export | SOURCE | generous_export.py:20:25:20:30 | ControlFlowNode for SOURCE |
5338
| generous_export | __file__ | generous_export.py:22:6:22:13 | ControlFlowNode for __file__ |
54-
| generous_export | __name__ | generous_export.py:0:0:0:0 | Entry node for Module generous_export |
55-
| generous_export | __package__ | generous_export.py:0:0:0:0 | Entry node for Module generous_export |
5639
| generous_export | check | generous_export.py:20:1:20:5 | ControlFlowNode for check |
5740
| generous_export | enter | generous_export.py:2:1:2:5 | ControlFlowNode for enter |
5841
| generous_export | eval | generous_export.py:10:4:10:7 | ControlFlowNode for eval |
5942
| generous_export | exit | generous_export.py:22:1:22:4 | ControlFlowNode for exit |
6043
| generous_export | globals | generous_export.py:20:33:20:39 | ControlFlowNode for globals |
6144
| generous_export | object | generous_export.py:4:14:4:19 | ControlFlowNode for object |
6245
| generous_export | print | generous_export.py:15:5:15:9 | ControlFlowNode for print |
63-
| generous_export | staticmethod | generous_export.py:0:0:0:0 | Entry node for Module generous_export |
6446
| has_defined_all | __all__ | has_defined_all.py:7:1:7:7 | ControlFlowNode for __all__ |
6547
| has_defined_all | __file__ | has_defined_all.py:9:6:9:13 | ControlFlowNode for __file__ |
66-
| has_defined_all | __name__ | has_defined_all.py:0:0:0:0 | Entry node for Module has_defined_all |
67-
| has_defined_all | __package__ | has_defined_all.py:0:0:0:0 | Entry node for Module has_defined_all |
6848
| has_defined_all | all_defined_bar | has_defined_all.py:5:1:5:15 | ControlFlowNode for all_defined_bar |
6949
| has_defined_all | all_defined_foo | has_defined_all.py:4:1:4:15 | ControlFlowNode for all_defined_foo |
7050
| has_defined_all | enter | has_defined_all.py:2:1:2:5 | ControlFlowNode for enter |
7151
| has_defined_all | exit | has_defined_all.py:9:1:9:4 | ControlFlowNode for exit |
7252
| has_defined_all_copy | __all__ | has_defined_all_copy.py:9:1:9:7 | ControlFlowNode for __all__ |
7353
| has_defined_all_copy | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ |
74-
| has_defined_all_copy | __name__ | has_defined_all_copy.py:0:0:0:0 | Entry node for Module has_defined_all_copy |
75-
| has_defined_all_copy | __package__ | has_defined_all_copy.py:0:0:0:0 | Entry node for Module has_defined_all_copy |
7654
| has_defined_all_copy | all_defined_bar_copy | has_defined_all_copy.py:7:1:7:20 | ControlFlowNode for all_defined_bar_copy |
7755
| has_defined_all_copy | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | ControlFlowNode for all_defined_foo_copy |
7856
| has_defined_all_copy | enter | has_defined_all_copy.py:4:1:4:5 | ControlFlowNode for enter |
7957
| has_defined_all_copy | exit | has_defined_all_copy.py:11:1:11:4 | ControlFlowNode for exit |
8058
| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:6:6:6:13 | ControlFlowNode for __file__ |
81-
| has_defined_all_indirection | __name__ | has_defined_all_indirection.py:0:0:0:0 | Entry node for Module has_defined_all_indirection |
82-
| has_defined_all_indirection | __package__ | has_defined_all_indirection.py:0:0:0:0 | Entry node for Module has_defined_all_indirection |
8359
| has_defined_all_indirection | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | ControlFlowNode for all_defined_foo_copy |
8460
| has_defined_all_indirection | enter | has_defined_all_indirection.py:2:1:2:5 | ControlFlowNode for enter |
8561
| has_defined_all_indirection | exit | has_defined_all_indirection.py:6:1:6:4 | ControlFlowNode for exit |
8662
| if_then_else | __file__ | if_then_else.py:16:6:16:13 | ControlFlowNode for __file__ |
87-
| if_then_else | __name__ | if_then_else.py:0:0:0:0 | Entry node for Module if_then_else |
88-
| if_then_else | __package__ | if_then_else.py:0:0:0:0 | Entry node for Module if_then_else |
8963
| if_then_else | enter | if_then_else.py:2:1:2:5 | ControlFlowNode for enter |
9064
| if_then_else | eval | if_then_else.py:11:8:11:11 | ControlFlowNode for eval |
9165
| if_then_else | exit | if_then_else.py:16:1:16:4 | ControlFlowNode for exit |
@@ -95,30 +69,22 @@
9569
| if_then_else_refined | SOURCE | if_then_else_refined.py:11:11:11:16 | ControlFlowNode for SOURCE |
9670
| if_then_else_refined | SOURCE | if_then_else_refined.py:13:11:13:16 | ControlFlowNode for SOURCE |
9771
| if_then_else_refined | __file__ | if_then_else_refined.py:19:6:19:13 | ControlFlowNode for __file__ |
98-
| if_then_else_refined | __name__ | if_then_else_refined.py:0:0:0:0 | Entry node for Module if_then_else_refined |
99-
| if_then_else_refined | __package__ | if_then_else_refined.py:0:0:0:0 | Entry node for Module if_then_else_refined |
10072
| if_then_else_refined | check | if_then_else_refined.py:17:1:17:5 | ControlFlowNode for check |
10173
| if_then_else_refined | enter | if_then_else_refined.py:4:1:4:5 | ControlFlowNode for enter |
10274
| if_then_else_refined | eval | if_then_else_refined.py:10:4:10:7 | ControlFlowNode for eval |
10375
| if_then_else_refined | exit | if_then_else_refined.py:19:1:19:4 | ControlFlowNode for exit |
10476
| if_then_else_refined | globals | if_then_else_refined.py:17:24:17:30 | ControlFlowNode for globals |
10577
| if_then_else_refined | src | if_then_else_refined.py:17:19:17:21 | ControlFlowNode for src |
10678
| package.__init__ | __file__ | package/__init__.py:7:6:7:13 | ControlFlowNode for __file__ |
107-
| package.__init__ | __name__ | package/__init__.py:0:0:0:0 | Entry node for Module package.__init__ |
108-
| package.__init__ | __package__ | package/__init__.py:0:0:0:0 | Entry node for Module package.__init__ |
10979
| package.__init__ | attr_used_in_subpackage | package/__init__.py:4:1:4:23 | ControlFlowNode for attr_used_in_subpackage |
11080
| package.__init__ | enter | package/__init__.py:2:1:2:5 | ControlFlowNode for enter |
11181
| package.__init__ | exit | package/__init__.py:7:1:7:4 | ControlFlowNode for exit |
11282
| package.__init__ | package_attr | package/__init__.py:5:1:5:12 | ControlFlowNode for package_attr |
11383
| package.subpackage2.__init__ | __file__ | package/subpackage2/__init__.py:6:6:6:13 | ControlFlowNode for __file__ |
114-
| package.subpackage2.__init__ | __name__ | package/subpackage2/__init__.py:0:0:0:0 | Entry node for Module package.subpackage2.__init__ |
115-
| package.subpackage2.__init__ | __package__ | package/subpackage2/__init__.py:0:0:0:0 | Entry node for Module package.subpackage2.__init__ |
11684
| package.subpackage2.__init__ | enter | package/subpackage2/__init__.py:2:1:2:5 | ControlFlowNode for enter |
11785
| package.subpackage2.__init__ | exit | package/subpackage2/__init__.py:6:1:6:4 | ControlFlowNode for exit |
11886
| package.subpackage2.__init__ | subpackage2_attr | package/subpackage2/__init__.py:4:1:4:16 | ControlFlowNode for subpackage2_attr |
11987
| package.subpackage.__init__ | __file__ | package/subpackage/__init__.py:14:6:14:13 | ControlFlowNode for __file__ |
120-
| package.subpackage.__init__ | __name__ | package/subpackage/__init__.py:0:0:0:0 | Entry node for Module package.subpackage.__init__ |
121-
| package.subpackage.__init__ | __package__ | package/subpackage/__init__.py:0:0:0:0 | Entry node for Module package.subpackage.__init__ |
12288
| package.subpackage.__init__ | check | package/subpackage/__init__.py:12:1:12:5 | ControlFlowNode for check |
12389
| package.subpackage.__init__ | enter | package/subpackage/__init__.py:2:1:2:5 | ControlFlowNode for enter |
12490
| package.subpackage.__init__ | exit | package/subpackage/__init__.py:14:1:14:4 | ControlFlowNode for exit |
@@ -130,24 +96,18 @@
13096
| package.subpackage.__init__ | submodule | package/subpackage/__init__.py:12:35:12:43 | ControlFlowNode for submodule |
13197
| package.subpackage.__init__ | subpackage_attr | package/subpackage/__init__.py:4:1:4:15 | ControlFlowNode for subpackage_attr |
13298
| package.subpackage.submodule | __file__ | package/subpackage/submodule.py:7:6:7:13 | ControlFlowNode for __file__ |
133-
| package.subpackage.submodule | __name__ | package/subpackage/submodule.py:0:0:0:0 | Entry node for Module package.subpackage.submodule |
134-
| package.subpackage.submodule | __package__ | package/subpackage/submodule.py:0:0:0:0 | Entry node for Module package.subpackage.submodule |
13599
| package.subpackage.submodule | enter | package/subpackage/submodule.py:2:1:2:5 | ControlFlowNode for enter |
136100
| package.subpackage.submodule | exit | package/subpackage/submodule.py:7:1:7:4 | ControlFlowNode for exit |
137101
| package.subpackage.submodule | irrelevant_attr | package/subpackage/submodule.py:5:1:5:15 | ControlFlowNode for irrelevant_attr |
138102
| package.subpackage.submodule | submodule_attr | package/subpackage/submodule.py:4:1:4:14 | ControlFlowNode for submodule_attr |
139103
| refined | SOURCE | refined.py:12:25:12:30 | ControlFlowNode for SOURCE |
140104
| refined | __file__ | refined.py:14:6:14:13 | ControlFlowNode for __file__ |
141-
| refined | __name__ | refined.py:0:0:0:0 | Entry node for Module refined |
142-
| refined | __package__ | refined.py:0:0:0:0 | Entry node for Module refined |
143105
| refined | check | refined.py:12:1:12:5 | ControlFlowNode for check |
144106
| refined | enter | refined.py:2:1:2:5 | ControlFlowNode for enter |
145107
| refined | exit | refined.py:14:1:14:4 | ControlFlowNode for exit |
146108
| refined | globals | refined.py:12:33:12:39 | ControlFlowNode for globals |
147109
| refined | object | refined.py:4:14:4:19 | ControlFlowNode for object |
148110
| simplistic_reexport | __file__ | simplistic_reexport.py:19:6:19:13 | ControlFlowNode for __file__ |
149-
| simplistic_reexport | __name__ | simplistic_reexport.py:0:0:0:0 | Entry node for Module simplistic_reexport |
150-
| simplistic_reexport | __package__ | simplistic_reexport.py:0:0:0:0 | Entry node for Module simplistic_reexport |
151111
| simplistic_reexport | bar_attr | simplistic_reexport.py:6:17:6:24 | ControlFlowNode for ImportMember |
152112
| simplistic_reexport | bar_attr | simplistic_reexport.py:10:19:10:26 | ControlFlowNode for bar_attr |
153113
| simplistic_reexport | baz_attr | baz.py:4:1:4:8 | ControlFlowNode for baz_attr |

python/ql/test/experimental/import-resolution/package/subpackage/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
# Importing an irrelevant attribute from a sibling module binds the name to the module.
1111
from .submodule import irrelevant_attr
12-
check("submodule.submodule_attr", submodule.submodule_attr, "submodule_attr", globals()) #$ prints=submodule_attr
12+
check("submodule.submodule_attr", submodule.submodule_attr, "submodule_attr", globals()) #$ MISSING:prints=submodule_attr
1313

1414
exit(__file__)

0 commit comments

Comments
 (0)