From d9dfb61000f547a95eecee8e5cabd800e56f9cfc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:25:29 +0000 Subject: [PATCH] Add remaining docstrings to complete documentation coverage Co-authored-by: varun-r-mallya <100590632+varun-r-mallya@users.noreply.github.com> --- pythonbpf/debuginfo/__init__.py | 2 + pythonbpf/debuginfo/debug_info_generator.py | 39 +++++++++++++++++++ pythonbpf/debuginfo/dtypes.py | 3 ++ pythonbpf/decorators.py | 1 + pythonbpf/functions/func_registry_handlers.py | 3 ++ pythonbpf/functions/functions_pass.py | 10 +++++ pythonbpf/helper/bpf_helper_handler.py | 7 ++++ pythonbpf/helper/helper_utils.py | 1 + pythonbpf/maps/maps_pass.py | 1 + pythonbpf/maps/maps_utils.py | 3 ++ 10 files changed, 70 insertions(+) diff --git a/pythonbpf/debuginfo/__init__.py b/pythonbpf/debuginfo/__init__.py index db3ff9c..a477bdc 100644 --- a/pythonbpf/debuginfo/__init__.py +++ b/pythonbpf/debuginfo/__init__.py @@ -1,3 +1,5 @@ +"""Debug information generation for BPF programs (DWARF/BTF).""" + from .dwarf_constants import * # noqa: F403 from .dtypes import * # noqa: F403 from .debug_info_generator import DebugInfoGenerator diff --git a/pythonbpf/debuginfo/debug_info_generator.py b/pythonbpf/debuginfo/debug_info_generator.py index ab9fed4..bb7b30a 100644 --- a/pythonbpf/debuginfo/debug_info_generator.py +++ b/pythonbpf/debuginfo/debug_info_generator.py @@ -8,11 +8,31 @@ from typing import Any, List class DebugInfoGenerator: + """ + Generator for DWARF/BTF debug information in LLVM IR modules. + + This class provides methods to create debug metadata for BPF programs, + including types, structs, globals, and compilation units. + """ + def __init__(self, module): + """ + Initialize the debug info generator. + + Args: + module: LLVM IR module to attach debug info to + """ self.module = module self._type_cache = {} # Cache for common debug types def generate_file_metadata(self, filename, dirname): + """ + Generate file metadata for debug info. + + Args: + filename: Name of the source file + dirname: Directory containing the source file + """ self.module._file_metadata = self.module.add_debug_info( "DIFile", { # type: ignore @@ -24,6 +44,15 @@ class DebugInfoGenerator: def generate_debug_cu( self, language, producer: str, is_optimized: bool, is_distinct: bool ): + """ + Generate debug compile unit metadata. + + Args: + language: DWARF language code (e.g., DW_LANG_C11) + producer: Compiler/producer string + is_optimized: Whether the code is optimized + is_distinct: Whether the compile unit should be distinct + """ self.module._debug_compile_unit = self.module.add_debug_info( "DICompileUnit", { # type: ignore @@ -83,6 +112,16 @@ class DebugInfoGenerator: @staticmethod def _compute_array_size(base_type: Any, count: int) -> int: + """ + Compute the size of an array in bits. + + Args: + base_type: The base type of the array + count: Number of elements in the array + + Returns: + Total size in bits + """ # Extract size from base_type if possible # For simplicity, assuming base_type has a size attribute return getattr(base_type, "size", 32) * count diff --git a/pythonbpf/debuginfo/dtypes.py b/pythonbpf/debuginfo/dtypes.py index cd20f2f..ac6068a 100644 --- a/pythonbpf/debuginfo/dtypes.py +++ b/pythonbpf/debuginfo/dtypes.py @@ -1,7 +1,10 @@ +"""Debug information types and constants.""" + import llvmlite.ir as ir class DwarfBehaviorEnum: + """DWARF module flag behavior constants for LLVM.""" ERROR_IF_MISMATCH = ir.Constant(ir.IntType(32), 1) WARNING_IF_MISMATCH = ir.Constant(ir.IntType(32), 2) OVERRIDE_USE_LARGEST = ir.Constant(ir.IntType(32), 7) diff --git a/pythonbpf/decorators.py b/pythonbpf/decorators.py index 5bf6f10..8a8969d 100644 --- a/pythonbpf/decorators.py +++ b/pythonbpf/decorators.py @@ -41,6 +41,7 @@ def section(name: str): A decorator function that marks the function with the section name """ def wrapper(fn): + """Decorator that sets the section name on the function.""" fn._section = name return fn diff --git a/pythonbpf/functions/func_registry_handlers.py b/pythonbpf/functions/func_registry_handlers.py index afe54f6..0a0698d 100644 --- a/pythonbpf/functions/func_registry_handlers.py +++ b/pythonbpf/functions/func_registry_handlers.py @@ -1,3 +1,5 @@ +"""Registry for statement handler functions.""" + from typing import Dict @@ -11,6 +13,7 @@ class StatementHandlerRegistry: """Register a handler for a specific statement type.""" def decorator(handler): + """Decorator that registers the handler.""" cls._handlers[stmt_type] = handler return handler diff --git a/pythonbpf/functions/functions_pass.py b/pythonbpf/functions/functions_pass.py index b56efbc..44c2dab 100644 --- a/pythonbpf/functions/functions_pass.py +++ b/pythonbpf/functions/functions_pass.py @@ -25,11 +25,20 @@ logger = logging.getLogger(__name__) @dataclass class LocalSymbol: + """ + Represents a local variable in a BPF function. + + Attributes: + var: LLVM IR alloca instruction for the variable + ir_type: LLVM IR type of the variable + metadata: Optional metadata (e.g., struct type name) + """ var: ir.AllocaInstr ir_type: ir.Type metadata: Any = None def __iter__(self): + """Support tuple unpacking of LocalSymbol.""" yield self.var yield self.ir_type yield self.metadata @@ -692,6 +701,7 @@ def infer_return_type(func_node: ast.FunctionDef): found_type = None def _expr_type(e): + """Helper function to extract type from an expression.""" if e is None: return "None" if isinstance(e, ast.Constant): diff --git a/pythonbpf/helper/bpf_helper_handler.py b/pythonbpf/helper/bpf_helper_handler.py index 55efe20..2a8360a 100644 --- a/pythonbpf/helper/bpf_helper_handler.py +++ b/pythonbpf/helper/bpf_helper_handler.py @@ -24,6 +24,7 @@ logger: Logger = logging.getLogger(__name__) class BPFHelperID(Enum): + """Enumeration of BPF helper function IDs.""" BPF_MAP_LOOKUP_ELEM = 1 BPF_MAP_UPDATE_ELEM = 2 BPF_MAP_DELETE_ELEM = 3 @@ -260,6 +261,11 @@ def bpf_perf_event_output_handler( local_sym_tab=None, struct_sym_tab=None, ): + """ + Emit LLVM IR for bpf_perf_event_output helper function call. + + This allows sending data to userspace via a perf event array. + """ if len(call.args) != 1: raise ValueError( f"Perf event output expects exactly one argument, got {len(call.args)}" @@ -310,6 +316,7 @@ def handle_helper_call( # Helper function to get map pointer and invoke handler def invoke_helper(method_name, map_ptr=None): + """Helper function to look up and invoke a registered handler.""" handler = HelperHandlerRegistry.get_handler(method_name) if not handler: raise NotImplementedError( diff --git a/pythonbpf/helper/helper_utils.py b/pythonbpf/helper/helper_utils.py index 2ac2df1..03f855f 100644 --- a/pythonbpf/helper/helper_utils.py +++ b/pythonbpf/helper/helper_utils.py @@ -26,6 +26,7 @@ class HelperHandlerRegistry: """Decorator to register a handler function for a helper""" def decorator(func): + """Decorator that registers the handler function.""" cls._handlers[helper_name] = func return func diff --git a/pythonbpf/maps/maps_pass.py b/pythonbpf/maps/maps_pass.py index 3729574..dda0c2e 100644 --- a/pythonbpf/maps/maps_pass.py +++ b/pythonbpf/maps/maps_pass.py @@ -43,6 +43,7 @@ def is_map(func_node): class BPFMapType(Enum): + """Enumeration of BPF map types.""" UNSPEC = 0 HASH = 1 ARRAY = 2 diff --git a/pythonbpf/maps/maps_utils.py b/pythonbpf/maps/maps_utils.py index ee3ad08..14bc0e8 100644 --- a/pythonbpf/maps/maps_utils.py +++ b/pythonbpf/maps/maps_utils.py @@ -1,3 +1,5 @@ +"""Registry for BPF map processor functions.""" + from collections.abc import Callable from typing import Any @@ -12,6 +14,7 @@ class MapProcessorRegistry: """Decorator to register a processor function for a map type""" def decorator(func): + """Decorator that registers the processor function.""" cls._processors[map_type_name] = func return func