Skip to content

Commit 68e9693

Browse files
add import parser
Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>
1 parent e4575a6 commit 68e9693

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed
Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,75 @@
1-
import llvmlite.ir as ir
21
import ast
2+
import logging
3+
import llvmlite.ir as ir
4+
from typing import List, Tuple
5+
6+
logger = logging.getLogger(__name__)
7+
8+
9+
def detect_import_statement(tree: ast.AST) -> List[Tuple[str, str]]:
10+
"""
11+
Parse AST and detect import statements from vmlinux.
12+
13+
Returns a list of tuples (module_name, imported_item) for vmlinux imports.
14+
Raises SyntaxError for invalid import patterns.
15+
16+
Args:
17+
tree: The AST to parse
18+
19+
Returns:
20+
List of tuples containing (module_name, imported_item) for each vmlinux import
21+
22+
Raises:
23+
SyntaxError: If multiple imports from vmlinux are attempted or import * is used
24+
"""
25+
vmlinux_imports = []
26+
27+
for node in ast.walk(tree):
28+
# Handle "from vmlinux import ..." statements
29+
if isinstance(node, ast.ImportFrom):
30+
if node.module == "vmlinux":
31+
# Check for wildcard import: from vmlinux import *
32+
if any(alias.name == "*" for alias in node.names):
33+
raise SyntaxError(
34+
"Wildcard imports from vmlinux are not supported. "
35+
"Please import specific types explicitly."
36+
)
37+
38+
# Check for multiple imports: from vmlinux import A, B, C
39+
if len(node.names) > 1:
40+
imported_names = [alias.name for alias in node.names]
41+
raise SyntaxError(
42+
f"Multiple imports from vmlinux are not supported. "
43+
f"Found: {', '.join(imported_names)}. "
44+
f"Please use separate import statements for each type."
45+
)
46+
47+
# Check if no specific import is specified (should not happen with valid Python)
48+
if len(node.names) == 0:
49+
raise SyntaxError(
50+
"Import from vmlinux must specify at least one type."
51+
)
52+
53+
# Valid single import
54+
for alias in node.names:
55+
import_name = alias.name
56+
# Use alias if provided, otherwise use the original name
57+
as_name = alias.asname if alias.asname else alias.name
58+
vmlinux_imports.append(("vmlinux", import_name))
59+
logger.info(f"Found vmlinux import: {import_name}")
60+
61+
# Handle "import vmlinux" statements (not typical but should be rejected)
62+
elif isinstance(node, ast.Import):
63+
for alias in node.names:
64+
if alias.name == "vmlinux" or alias.name.startswith("vmlinux."):
65+
raise SyntaxError(
66+
f"Direct import of vmlinux module is not supported. "
67+
f"Use 'from vmlinux import <type>' instead."
68+
)
69+
70+
logger.info(f"Total vmlinux imports detected: {len(vmlinux_imports)}")
71+
return vmlinux_imports
372

473
def vmlinux_proc(tree, module):
5-
pass
74+
import_statements = detect_import_statement(tree)
75+
logger.info(f"Import statements {import_statements}")

tests/failing_tests/xdp_pass.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from pythonbpf import bpf, map, section, bpfglobal, compile, compile_to_ir
22
from pythonbpf.maps import HashMap
3-
from vmlinux import struct_xdp_md, XDP_PASS
3+
from pythonbpf.helper import XDP_PASS
4+
from vmlinux import struct_xdp_md
5+
# from vmlinux import XDP_PASS
46
from ctypes import c_int64
57

68
# Instructions to how to run this program
@@ -10,7 +12,6 @@
1012
# 4. Attach object file to any network device with something like ./check.sh xdp examples/xdp_pass.o tailscale0
1113
# 5. send traffic through the device and observe effects
1214

13-
1415
@bpf
1516
@map
1617
def count() -> HashMap:

0 commit comments

Comments
 (0)