Skip to content

Commit 3fd0ec7

Browse files
authored
Python: Deprecate importNode
Unsurprisingly, the only thing affected by this was the `import-helper` tests. These have lost all of the results relating to `ImportMember`s, but apart from that the underlying behaviour should be the same. I also limited the test to only `CfgNode`s, as a bunch of `EssaNode`s suddenly appeared when I switched to API graphs. Finally, I used `API::moduleImport` with a dotted name in the type tracking tests. This goes against the API graphs interface, but I think it's more correct for this use case, as these type trackers are doing the "module attribute lookup" bit manually.
1 parent d282f6a commit 3fd0ec7

File tree

6 files changed

+31
-13
lines changed

6 files changed

+31
-13
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The `importNode` predicate from the data-flow library has been deprecated. In its place, we
3+
recommend using the API graphs library, accessible via `import semmle.python.ApiGraphs`.
4+

python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
1818
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
1919

2020
/**
21+
* DEPRECATED. Use the API graphs library instead.
22+
*
23+
* For a drop-in replacement, use `API::moduleImport(name).getAUse()`.
24+
*
2125
* Gets a `Node` that refers to the module referenced by `name`.
2226
* Note that for the statement `import pkg.mod`, the new variable introduced is `pkg` that is a
2327
* reference to the module `pkg`.
@@ -37,7 +41,7 @@ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
3741
* `mypkg/foo.py` but the variable `foo` containing `42` -- however, `import mypkg.foo` will always cause `mypkg.foo`
3842
* to refer to the module.
3943
*/
40-
Node importNode(string name) {
44+
deprecated Node importNode(string name) {
4145
exists(Variable var, Import imp, Alias alias |
4246
alias = imp.getAName() and
4347
alias.getAsname() = var.getAStore() and

python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
| test1.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg |
2+
| test1.py:2:7:2:11 | ControlFlowNode for mypkg | mypkg |
3+
| test1.py:4:11:4:15 | ControlFlowNode for mypkg | mypkg |
24
| test2.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg |
35
| test2.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg |
4-
| test2.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo |
5-
| test2.py:1:24:1:26 | ControlFlowNode for ImportMember | mypkg.bar |
66
| test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg |
77
| test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg |
8+
| test3.py:3:7:3:11 | ControlFlowNode for mypkg | mypkg |
9+
| test3.py:4:7:4:11 | ControlFlowNode for mypkg | mypkg |
810
| test4.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo |
911
| test4.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar |
12+
| test4.py:3:7:3:10 | ControlFlowNode for _foo | mypkg.foo |
13+
| test4.py:4:7:4:10 | ControlFlowNode for _bar | mypkg.bar |
1014
| test5.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg |
15+
| test5.py:3:7:3:11 | ControlFlowNode for mypkg | mypkg |
16+
| test5.py:5:11:5:15 | ControlFlowNode for mypkg | mypkg |
1117
| test5.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg |
12-
| test5.py:9:19:9:29 | ControlFlowNode for ImportMember | mypkg.bar |
18+
| test5.py:10:7:10:11 | ControlFlowNode for mypkg | mypkg |
1319
| test6.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg |
20+
| test6.py:3:7:3:11 | ControlFlowNode for mypkg | mypkg |
1421
| test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg |
22+
| test6.py:6:7:6:11 | ControlFlowNode for mypkg | mypkg |
1523
| test7.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg |
16-
| test7.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo |
1724
| test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg |
25+
| test7.py:7:7:7:11 | ControlFlowNode for mypkg | mypkg |
1826
| test7.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg |
19-
| test7.py:9:19:9:21 | ControlFlowNode for ImportMember | mypkg.foo |
2027
| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end |
2128
| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end |
22-
| test_deep.py:1:30:1:32 | ControlFlowNode for ImportMember | start.middle.end.foo |
23-
| test_deep.py:1:35:1:37 | ControlFlowNode for ImportMember | start.middle.end.bar |
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import python
22
import semmle.python.dataflow.new.DataFlow
3+
import semmle.python.ApiGraphs
34

4-
query predicate importNode(DataFlow::Node res, string name) { res = DataFlow::importNode(name) }
5+
query predicate importNode(DataFlow::CfgNode res, string name) {
6+
res = API::moduleImport(name).getAUse()
7+
}

python/ql/test/experimental/dataflow/typetracking/moduleattr.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import python
22
import semmle.python.dataflow.new.DataFlow
33
import semmle.python.dataflow.new.TypeTracker
4+
import semmle.python.ApiGraphs
45

56
private DataFlow::TypeTrackingNode module_tracker(TypeTracker t) {
67
t.start() and
7-
result = DataFlow::importNode("module")
8+
result = API::moduleImport("module").getAUse()
89
or
910
exists(TypeTracker t2 | result = module_tracker(t2).track(t2, t))
1011
}

python/ql/test/experimental/dataflow/typetracking/tracked.ql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import python
22
import semmle.python.dataflow.new.DataFlow
33
import semmle.python.dataflow.new.TypeTracker
44
import TestUtilities.InlineExpectationsTest
5+
import semmle.python.ApiGraphs
56

67
// -----------------------------------------------------------------------------
78
// tracked
@@ -119,7 +120,7 @@ class TrackedSelfTest extends InlineExpectationsTest {
119120
/** Gets a reference to `foo` (fictive module). */
120121
private DataFlow::TypeTrackingNode foo(DataFlow::TypeTracker t) {
121122
t.start() and
122-
result = DataFlow::importNode("foo")
123+
result = API::moduleImport("foo").getAUse()
123124
or
124125
exists(DataFlow::TypeTracker t2 | result = foo(t2).track(t2, t))
125126
}
@@ -130,7 +131,7 @@ DataFlow::Node foo() { foo(DataFlow::TypeTracker::end()).flowsTo(result) }
130131
/** Gets a reference to `foo.bar` (fictive module). */
131132
private DataFlow::TypeTrackingNode foo_bar(DataFlow::TypeTracker t) {
132133
t.start() and
133-
result = DataFlow::importNode("foo.bar")
134+
result = API::moduleImport("foo.bar").getAUse()
134135
or
135136
t.startInAttr("bar") and
136137
result = foo()
@@ -144,7 +145,7 @@ DataFlow::Node foo_bar() { foo_bar(DataFlow::TypeTracker::end()).flowsTo(result)
144145
/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
145146
private DataFlow::TypeTrackingNode foo_bar_baz(DataFlow::TypeTracker t) {
146147
t.start() and
147-
result = DataFlow::importNode("foo.bar.baz")
148+
result = API::moduleImport("foo.bar.baz").getAUse()
148149
or
149150
t.startInAttr("baz") and
150151
result = foo_bar()

0 commit comments

Comments
 (0)