Skip to content

Commit f227fe9

Browse files
add dependency_node format and also cache results of symbol loader.
1 parent 7940d02 commit f227fe9

File tree

4 files changed

+126
-7
lines changed

4 files changed

+126
-7
lines changed

pythonbpf/vmlinux_parser/dependency_data.py

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
from dataclasses import dataclass, field
2+
from typing import Dict, Any, Optional
3+
4+
5+
@dataclass
6+
class Field:
7+
"""Represents a field in a dependency node with its type and readiness state."""
8+
name: str
9+
type: type
10+
value: Any = None
11+
ready: bool = False
12+
13+
def set_ready(self, is_ready: bool = True) -> None:
14+
"""Set the readiness state of this field."""
15+
self.ready = is_ready
16+
17+
def set_value(self, value: Any, mark_ready: bool = True) -> None:
18+
"""Set the value of this field and optionally mark it as ready."""
19+
self.value = value
20+
if mark_ready:
21+
self.ready = True
22+
23+
24+
@dataclass
25+
class DependencyNode:
26+
"""
27+
A node with typed fields and readiness tracking.
28+
29+
Example usage:
30+
# Create a dependency node for a Person
31+
somestruct = DependencyNode(name="struct_1")
32+
33+
# Add fields with their types
34+
somestruct.add_field("field_1", str)
35+
somestruct.add_field("field_2", int)
36+
somestruct.add_field("field_3", str)
37+
38+
# Check if the node is ready (should be False initially)
39+
print(f"Is node ready? {somestruct.is_ready}") # False
40+
41+
# Set some field values
42+
somestruct.set_field_value("field_1", "someproperty")
43+
somestruct.set_field_value("field_2", 30)
44+
45+
# Check if the node is ready (still False because email is not ready)
46+
print(f"Is node ready? {somestruct.is_ready}") # False
47+
48+
# Set the last field and make the node ready
49+
somestruct.set_field_value("field_3", "anotherproperty")
50+
51+
# Now the node should be ready
52+
print(f"Is node ready? {somestruct.is_ready}") # True
53+
54+
# You can also mark a field as not ready
55+
somestruct.set_field_ready("field_3", False)
56+
57+
# Now the node is not ready again
58+
print(f"Is node ready? {somestruct.is_ready}") # False
59+
60+
# Get all field values
61+
print(somestruct.get_field_values()) # {'field_1': 'someproperty', 'field_2': 30, 'field_3': 'anotherproperty'}
62+
63+
# Get only ready fields
64+
ready_fields = somestruct.get_ready_fields()
65+
print(f"Ready fields: {[field.name for field in ready_fields.values()]}") # ['field_1', 'field_2']
66+
"""
67+
name: str
68+
fields: Dict[str, Field] = field(default_factory=dict)
69+
_ready_cache: Optional[bool] = field(default=None, repr=False)
70+
71+
def add_field(self, name: str, field_type: type, initial_value: Any = None, ready: bool = False) -> None:
72+
"""Add a field to the node with an optional initial value and readiness state."""
73+
self.fields[name] = Field(name=name, type=field_type, value=initial_value, ready=ready)
74+
# Invalidate readiness cache
75+
self._ready_cache = None
76+
77+
def get_field(self, name: str) -> Field:
78+
"""Get a field by name."""
79+
return self.fields[name]
80+
81+
def set_field_value(self, name: str, value: Any, mark_ready: bool = True) -> None:
82+
"""Set a field's value and optionally mark it as ready."""
83+
if name not in self.fields:
84+
raise KeyError(f"Field '{name}' does not exist in node '{self.name}'")
85+
86+
self.fields[name].set_value(value, mark_ready)
87+
# Invalidate readiness cache
88+
self._ready_cache = None
89+
90+
def set_field_ready(self, name: str, is_ready: bool = True) -> None:
91+
"""Mark a field as ready or not ready."""
92+
if name not in self.fields:
93+
raise KeyError(f"Field '{name}' does not exist in node '{self.name}'")
94+
95+
self.fields[name].set_ready(is_ready)
96+
# Invalidate readiness cache
97+
self._ready_cache = None
98+
99+
@property
100+
def is_ready(self) -> bool:
101+
"""Check if the node is ready (all fields are ready)."""
102+
# Use cached value if available
103+
if self._ready_cache is not None:
104+
return self._ready_cache
105+
106+
# Calculate readiness only when needed
107+
if not self.fields:
108+
self._ready_cache = False
109+
return False
110+
111+
self._ready_cache = all(elem.ready for elem in self.fields.values())
112+
return self._ready_cache
113+
114+
def get_field_values(self) -> Dict[str, Any]:
115+
"""Get a dictionary of field names to their values."""
116+
return {name: elem.value for name, elem in self.fields.items()}
117+
118+
def get_ready_fields(self) -> Dict[str, Field]:
119+
"""Get all fields that are marked as ready."""
120+
return {name: elem for name, elem in self.fields.items() if elem.ready}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# dependency tree creation handling
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import ast
22
import logging
3+
from functools import lru_cache
34
import importlib
45

56
logger = logging.getLogger(__name__)
67

7-
8+
@lru_cache(maxsize=1)
89
def get_module_symbols(module_name: str):
910
module = importlib.import_module(module_name)
1011
return [name for name in dir(module)]
1112

12-
def process_vmlinux_class(node, module):
13-
# Process ClassDef nodes that use vmlinux imports
14-
symbols = get_module_symbols("vmlinux")
15-
# print(symbols)
16-
pass
13+
def process_vmlinux_class(node, module, num=0):
14+
symbols_in_module = get_module_symbols("vmlinux")
15+

0 commit comments

Comments
 (0)