Skip to content

Commit d701109

Browse files
committed
fix: statement variables in python
1 parent 0c71ed2 commit d701109

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

scubatrace/python/statement.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from functools import cached_property
44

5+
from ..identifier import Identifier
56
from ..statement import BlockStatement, SimpleStatement, Statement
67

78

@@ -31,6 +32,30 @@ def right_uncle_ancestor(self) -> Statement | None:
3132
cur = cur.parent
3233
return None
3334

35+
@cached_property
36+
def variables(self) -> list[Identifier]:
37+
"""
38+
Variables in the statement.
39+
"""
40+
variables = []
41+
for identifier in self.identifiers:
42+
node = identifier.node
43+
parent = node.parent
44+
if parent is not None:
45+
if parent.type in [
46+
"ERROR",
47+
"call",
48+
"function_definition",
49+
]:
50+
continue
51+
if (
52+
parent.type == "keyword_argument"
53+
and parent.child_by_field_name("name") == node
54+
):
55+
continue
56+
variables.append(identifier)
57+
return variables
58+
3459

3560
class PythonBlockStatement(BlockStatement):
3661
@cached_property

tests/samples/python/test.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import scubatrace
22

33

4+
def add(a, b):
5+
return a + b
6+
7+
8+
def main():
9+
a = 3
10+
b = 4
11+
c = add(a, b=b)
12+
return c
13+
14+
415
def test_cfg():
516
project = scubatrace.PythonProject(".")
617
file = project.files["test.py"]
718
file.export_cfg_dot("test.dot")
819

920

1021
if __name__ == "__main__":
11-
test_cfg()
22+
main()

tests/test_statement.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ def test_statement_is_taint_from_entry(self):
6565
self.assertIsInstance(is_taint_from_entry, bool)
6666

6767

68+
class TestPythonStatement(unittest.TestCase):
69+
def setUp(self):
70+
self.test_dir = Path(__file__).parent
71+
self.samples_dir = self.test_dir / "samples"
72+
self.project_path = self.samples_dir / "python"
73+
self.project = scubatrace.Project.create(
74+
str(self.project_path), language=scubatrace.language.PYTHON
75+
)
76+
self.file = self.project.files.get("test.py") or self.fail()
77+
statement = self.file.statements_by_line(11)
78+
self.statement = statement[0]
79+
80+
def test_statement_create(self):
81+
statement = scubatrace.SimpleStatement.create(
82+
self.statement.node, self.statement.parent
83+
)
84+
self.assertIsNotNone(statement)
85+
86+
def test_statement_variables(self):
87+
variables = self.statement.variables
88+
self.assertEqual(len(variables), 3)
89+
90+
6891
class TestJavaScriptStatement(unittest.TestCase):
6992
def setUp(self):
7093
self.test_dir = Path(__file__).parent
@@ -86,3 +109,13 @@ def test_statement_create(self):
86109
def test_statement_walk_backward(self):
87110
for stmt in self.statement.walk_backward(depth=3, base="control"):
88111
self.assertIn(stmt.start_line, [1, 2, 3, 4])
112+
113+
114+
if __name__ == "__main__":
115+
project = scubatrace.Project.create(
116+
"/Users/sunbk201/Downloads/python-xxhash",
117+
language=scubatrace.language.PYTHON,
118+
enable_lsp=True,
119+
)
120+
for impor in project.files["setup.py"].imports:
121+
print(impor._path)

0 commit comments

Comments
 (0)