-
Notifications
You must be signed in to change notification settings - Fork 4
Add comprehensive Sphinx documentation with MyST-Parser #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: r41k0u <76248539+r41k0u@users.noreply.github.com>
Co-authored-by: r41k0u <76248539+r41k0u@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds comprehensive Sphinx documentation with MyST-Parser support for the PythonBPF project. The documentation provides detailed guides on writing eBPF programs in Python, covering decorators, maps, structs, compilation, and helper functions.
Changes:
- Added complete Sphinx documentation infrastructure with MyST-Parser for Markdown support
- Created comprehensive user guides covering all major PythonBPF features (decorators, maps, structs, compilation, helpers)
- Added getting started guides with installation instructions and quickstart tutorial
- Included API reference documentation with code examples
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/conf.py | Sphinx configuration with autodoc, napoleon, MyST-Parser, and RTD theme |
| docs/index.md | Main landing page with project overview and quick example |
| docs/getting-started/*.md | Installation guide and quickstart tutorial |
| docs/user-guide/*.md | Comprehensive guides for decorators, maps, structs, compilation, and helpers |
| docs/api/index.md | API reference documentation |
| docs/requirements.txt | Documentation build dependencies |
| docs/Makefile, docs/make.bat | Build scripts for Unix and Windows |
| pyproject.toml | Added optional docs dependency group |
| .gitignore | Added documentation build artifact exclusions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
docs/user-guide/structs.md
Outdated
| def capture_packets(ctx: c_void_p) -> c_uint32: | ||
| pkt = PacketEvent() | ||
| pkt.timestamp = ktime() | ||
| # Parse packet data from ctx... | ||
|
|
||
| packets.output(pkt) | ||
|
|
||
| # XDP_PASS | ||
| return c_uint32(2) |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example shows returning c_uint32(2) for XDP_PASS, but the actual XDP_PASS constant in helpers.py is defined as c_int64(2). For consistency and correctness, this should either use the XDP_PASS constant directly or match the type used in the helper definitions.
docs/user-guide/structs.md
Outdated
| # Set fields | ||
| event.timestamp = ktime() | ||
| event.pid = pid() | ||
| event.comm = comm() |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comm() helper function is called without arguments, but according to the actual implementation in helpers.py, comm() requires a buffer parameter: comm(buf). This appears in multiple examples throughout the file and needs to be corrected.
| event.comm = comm() | |
| event.comm = comm(event.comm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed all comm() usages to show the correct signature requiring a buffer parameter, matching the actual implementation in helpers.py. Updated examples to show comm(buffer) or commented out with explanatory notes. Changes in commit c58483a.
docs/user-guide/helpers.md
Outdated
| src = c_void_p(...) # kernel address | ||
|
|
||
| result = probe_read(dst, size, src) | ||
| if result == 0: | ||
| print(f"Read value: {dst}") | ||
| return c_int64(0) | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| * `dst` - Destination buffer | ||
| * `size` - Number of bytes to read | ||
| * `src` - Source kernel address | ||
|
|
||
| **Returns:** `c_int64` - 0 on success, negative on error | ||
|
|
||
| **Safety:** This function performs bounds checking and prevents invalid memory access. | ||
|
|
||
| #### probe_read_str() | ||
|
|
||
| Safely read a null-terminated string from kernel memory. | ||
|
|
||
| ```python | ||
| from pythonbpf.helper import probe_read_str | ||
|
|
||
| @bpf | ||
| def read_filename(ctx: c_void_p) -> c_int64: | ||
| filename = str(256) | ||
| src = c_void_p(...) # pointer to filename in kernel | ||
|
|
||
| result = probe_read_str(filename, src) | ||
| if result > 0: | ||
| print(f"Filename: {filename}") | ||
| return c_int64(0) | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| * `dst` - Destination buffer (string) | ||
| * `src` - Source kernel address | ||
|
|
||
| **Returns:** `c_int64` - Length of string on success, negative on error | ||
|
|
||
| #### deref() | ||
|
|
||
| Dereference a pointer safely. | ||
|
|
||
| ```python | ||
| from pythonbpf.helper import deref | ||
|
|
||
| @bpf | ||
| def access_pointer(ctx: c_void_p) -> c_int64: | ||
| ptr = c_void_p(...) | ||
| value = deref(ptr) | ||
| print(f"Value at pointer: {value}") | ||
| return c_int64(0) | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| * `ptr` - Pointer to dereference | ||
|
|
||
| **Returns:** The dereferenced value or 0 if null | ||
|
|
||
| ### Random Numbers | ||
|
|
||
| #### random() | ||
|
|
||
| Generate a pseudo-random 32-bit number. | ||
|
|
||
| ```python | ||
| from pythonbpf.helper import random | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_open") | ||
| def sample_events(ctx: c_void_p) -> c_int64: | ||
| # Sample 1% of events | ||
| if (random() % 100) == 0: | ||
| print("Sampled event") | ||
| return c_int64(0) | ||
| ``` | ||
|
|
||
| **Returns:** `c_int32` - A pseudo-random number | ||
|
|
||
| **Use cases:** | ||
| * Event sampling | ||
| * Load shedding | ||
| * A/B testing | ||
| * Randomized algorithms | ||
|
|
||
| ### Network Helpers | ||
|
|
||
| #### skb_store_bytes() | ||
|
|
||
| Store bytes into a socket buffer (for network programs). | ||
|
|
||
| ```python | ||
| from pythonbpf.helper import skb_store_bytes | ||
|
|
||
| @bpf | ||
| @section("classifier") | ||
| def modify_packet(ctx: c_void_p) -> c_int32: | ||
| offset = 14 # Skip Ethernet header | ||
| data = b"\x00\x01\x02\x03" | ||
| size = len(data) | ||
|
|
||
| result = skb_store_bytes(offset, data, size) | ||
| return c_int32(0) | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| * `offset` - Offset in the socket buffer | ||
| * `from_buf` - Data to write | ||
| * `size` - Number of bytes to write | ||
| * `flags` - Optional flags | ||
|
|
||
| **Returns:** `c_int64` - 0 on success, negative on error | ||
|
|
||
| ## Userspace Utilities | ||
|
|
||
| PythonBPF provides utilities for working with BPF programs from Python userspace code. | ||
|
|
||
| ### trace_pipe() | ||
|
|
||
| Read and display output from the kernel trace pipe. | ||
|
|
||
| ```python | ||
| from pythonbpf import trace_pipe | ||
|
|
||
| # After loading and attaching BPF programs | ||
| trace_pipe() | ||
| ``` | ||
|
|
||
| **Description:** | ||
|
|
||
| The `trace_pipe()` function reads from `/sys/kernel/tracing/trace_pipe` and displays BPF program output to stdout. This is the output from `print()` statements in BPF programs. | ||
|
|
||
| **Usage:** | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe | ||
| from ctypes import c_void_p, c_int64 | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_execve") | ||
| def trace_exec(ctx: c_void_p) -> c_int64: | ||
| print("Process started") # This goes to trace_pipe | ||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @bpfglobal | ||
| def LICENSE() -> str: | ||
| return "GPL" | ||
|
|
||
| b = BPF() | ||
| b.load_and_attach() | ||
| trace_pipe() # Display BPF output | ||
| ``` | ||
|
|
||
| **Behavior:** | ||
|
|
||
| * Blocks until Ctrl+C is pressed | ||
| * Displays output in real-time | ||
| * Shows task name, PID, CPU, timestamp, and message | ||
| * Automatically handles trace pipe access errors | ||
|
|
||
| **Requirements:** | ||
|
|
||
| * Root or sudo access | ||
| * Accessible `/sys/kernel/tracing/trace_pipe` | ||
|
|
||
| ### trace_fields() | ||
|
|
||
| Parse one line from the trace pipe into structured fields. | ||
|
|
||
| ```python | ||
| from pythonbpf import trace_fields | ||
|
|
||
| # Read and parse trace output | ||
| task, pid, cpu, flags, ts, msg = trace_fields() | ||
| print(f"Task: {task}, PID: {pid}, CPU: {cpu}, Time: {ts}, Message: {msg}") | ||
| ``` | ||
|
|
||
| **Returns:** Tuple of `(task, pid, cpu, flags, timestamp, message)` | ||
|
|
||
| * `task` - String: Task/process name (up to 16 chars) | ||
| * `pid` - Integer: Process ID | ||
| * `cpu` - Integer: CPU number | ||
| * `flags` - Bytes: Trace flags | ||
| * `timestamp` - Float: Timestamp in seconds | ||
| * `message` - String: The actual trace message | ||
|
|
||
| **Description:** | ||
|
|
||
| The `trace_fields()` function reads one line from the trace pipe and parses it into individual fields. This is useful when you need programmatic access to trace data rather than just displaying it. | ||
|
|
||
| **Usage:** | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, section, bpfglobal, BPF, trace_fields | ||
| from ctypes import c_void_p, c_int64 | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_execve") | ||
| def trace_exec(ctx: c_void_p) -> c_int64: | ||
| print(f"PID:{pid()}") | ||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @bpfglobal | ||
| def LICENSE() -> str: | ||
| return "GPL" | ||
|
|
||
| b = BPF() | ||
| b.load_and_attach() | ||
|
|
||
| # Process trace events | ||
| try: | ||
| while True: | ||
| task, pid, cpu, flags, ts, msg = trace_fields() | ||
| print(f"[{ts:.6f}] {task}({pid}) on CPU{cpu}: {msg}") | ||
| except KeyboardInterrupt: | ||
| print("Stopped") | ||
| ``` | ||
|
|
||
| **Error Handling:** | ||
|
|
||
| * Raises `ValueError` if line cannot be parsed | ||
| * Skips lines about lost events | ||
| * Blocks waiting for next line | ||
|
|
||
| ## Helper Function Examples | ||
|
|
||
| ### Example 1: Latency Measurement | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, map, section, bpfglobal, BPF, trace_pipe | ||
| from pythonbpf.maps import HashMap | ||
| from pythonbpf.helper import pid, ktime | ||
| from ctypes import c_void_p, c_int64, c_uint32, c_uint64 | ||
|
|
||
| @bpf | ||
| @map | ||
| def start_times() -> HashMap: | ||
| return HashMap(key=c_uint32, value=c_uint64, max_entries=4096) | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_read") | ||
| def read_start(ctx: c_void_p) -> c_int64: | ||
| process_id = pid() | ||
| start = ktime() | ||
| start_times.update(process_id, start) | ||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_exit_read") | ||
| def read_end(ctx: c_void_p) -> c_int64: | ||
| process_id = pid() | ||
| start = start_times.lookup(process_id) | ||
|
|
||
| if start: | ||
| latency = ktime() - start | ||
| print(f"Read latency: {latency} ns") | ||
| start_times.delete(process_id) | ||
|
|
||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @bpfglobal | ||
| def LICENSE() -> str: | ||
| return "GPL" | ||
|
|
||
| b = BPF() | ||
| b.load_and_attach() | ||
| trace_pipe() | ||
| ``` | ||
|
|
||
| ### Example 2: Process Tracking | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe | ||
| from pythonbpf.helper import pid, comm, uid | ||
| from ctypes import c_void_p, c_int64 | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_execve") | ||
| def track_exec(ctx: c_void_p) -> c_int64: | ||
| process_id = pid() | ||
| process_name = comm() | ||
| user_id = uid() | ||
|
|
||
| print(f"User {user_id} started {process_name} (PID: {process_id})") | ||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @bpfglobal | ||
| def LICENSE() -> str: | ||
| return "GPL" | ||
|
|
||
| b = BPF() | ||
| b.load_and_attach() | ||
| trace_pipe() | ||
| ``` | ||
|
|
||
| ### Example 3: CPU Load Monitoring | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, map, section, bpfglobal, BPF | ||
| from pythonbpf.maps import HashMap | ||
| from pythonbpf.helper import smp_processor_id | ||
| from ctypes import c_void_p, c_int64, c_uint32, c_uint64 | ||
|
|
||
| @bpf | ||
| @map | ||
| def cpu_counts() -> HashMap: | ||
| return HashMap(key=c_uint32, value=c_uint64, max_entries=256) | ||
|
|
||
| @bpf | ||
| @section("tracepoint/sched/sched_switch") | ||
| def count_switches(ctx: c_void_p) -> c_int64: | ||
| cpu = smp_processor_id() | ||
| count = cpu_counts.lookup(cpu) | ||
|
|
||
| if count: | ||
| cpu_counts.update(cpu, count + 1) | ||
| else: | ||
| cpu_counts.update(cpu, c_uint64(1)) | ||
|
|
||
| return c_int64(0) | ||
|
|
||
| @bpf | ||
| @bpfglobal | ||
| def LICENSE() -> str: | ||
| return "GPL" | ||
|
|
||
| b = BPF() | ||
| b.load_and_attach() | ||
|
|
||
| import time | ||
| time.sleep(5) | ||
|
|
||
| # Read results | ||
| from pylibbpf import BpfMap | ||
| map_obj = BpfMap(b, cpu_counts) | ||
| for cpu, count in map_obj.items(): | ||
| print(f"CPU {cpu}: {count} context switches") | ||
| ``` | ||
|
|
||
| ### Example 4: Event Sampling | ||
|
|
||
| ```python | ||
| from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe | ||
| from pythonbpf.helper import random, pid, comm | ||
| from ctypes import c_void_p, c_int64 | ||
|
|
||
| @bpf | ||
| @section("tracepoint/syscalls/sys_enter_open") | ||
| def sample_opens(ctx: c_void_p) -> c_int64: | ||
| # Sample 5% of events | ||
| if (random() % 100) < 5: | ||
| process_id = pid() | ||
| process_name = comm() |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comm() helper function is called without arguments throughout the file, but according to the actual implementation in helpers.py, comm() requires a buffer parameter: comm(buf). This appears in lines 131, 147, 218, 417, 489 and needs to be corrected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected all comm() calls throughout helpers.md to match the actual function signature comm(buf). Updated examples to remove incorrect usage. Changes in commit c58483a.
docs/user-guide/structs.md
Outdated
| event.timestamp = ktime() | ||
| event.pid = pid() | ||
| event.comm = comm() |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that event.comm can be assigned directly from comm(), but this is inconsistent with the function signature which requires a buffer parameter. The code example shows event.comm = comm() which won't work as documented.
docs/conf.py
Outdated
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information | ||
|
|
||
| project = 'PythonBPF' | ||
| copyright = '2024, r41k0u, varun-r-mallya' |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright year is set to 2024, but according to the PR metadata, the current date is January 21, 2026. The copyright year should be updated to 2026 or use a range like 2024-2026.
| copyright = '2024, r41k0u, varun-r-mallya' | |
| copyright = '2024-2026, r41k0u, varun-r-mallya' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated copyright year to '2024-2026, r41k0u, varun-r-mallya' in commit c58483a.
docs/user-guide/structs.md
Outdated
| msg.text = "Hello from BPF" | ||
|
|
||
| # Use helper to get process name | ||
| msg.text = comm() |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comm() helper function is called without arguments, but according to the actual implementation in helpers.py, comm() requires a buffer parameter: comm(buf). This appears in multiple examples (lines 207, 218, 269, 289, 380, 417) and needs to be corrected throughout the file.
| msg.text = comm() | |
| msg.text = comm(msg.text) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected all comm() usages in structs.md to match the actual implementation requiring a buffer parameter. Changes in commit c58483a.
docs/api/index.md
Outdated
| event = Event() | ||
| event.timestamp = ktime() | ||
| event.pid = pid() | ||
| event.comm = comm() |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comm() helper function is called without arguments in multiple examples, but according to the actual implementation in helpers.py, comm() requires a buffer parameter: comm(buf). This appears in lines 453 and needs to be corrected.
| event.comm = comm() | |
| event.comm = comm(event.comm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed comm() usage in api/index.md to show correct signature with buffer parameter. Changes in commit c58483a.
docs/user-guide/decorators.md
Outdated
| from ctypes import c_uint32 | ||
|
|
||
| @section("xdp") | ||
| def xdp_prog(ctx: c_void_p) -> c_uint32: | ||
| # XDP_PASS = 2, XDP_DROP = 1, XDP_ABORTED = 0 | ||
| return c_uint32(2) |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The XDP return values are inconsistent. The code shows XDP actions defined as c_int64 in helpers.py (XDP_PASS = c_int64(2)), but the documentation states to return c_uint32(2). According to the actual XDP specification, XDP programs should return unsigned 32-bit integers (c_uint32), but the helper definitions use c_int64. This needs to be clarified or corrected.
| from ctypes import c_uint32 | |
| @section("xdp") | |
| def xdp_prog(ctx: c_void_p) -> c_uint32: | |
| # XDP_PASS = 2, XDP_DROP = 1, XDP_ABORTED = 0 | |
| return c_uint32(2) | |
| from ctypes import c_void_p, c_uint32 | |
| # XDP return codes must be unsigned 32-bit values | |
| XDP_ABORTED = c_uint32(0) | |
| XDP_DROP = c_uint32(1) | |
| XDP_PASS = c_uint32(2) | |
| @section("xdp") | |
| def xdp_prog(ctx: c_void_p) -> c_uint32: | |
| return XDP_PASS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed XDP examples to use c_int64 return type and XDP_PASS constant, matching the actual implementation in helpers.py and examples/xdp_pass.py. Changes in commit c58483a.
docs/getting-started/quickstart.md
Outdated
| from ctypes import c_uint32 | ||
|
|
||
| @section("xdp") | ||
| def xdp_pass(ctx: c_void_p) -> c_uint32: | ||
| # XDP_PASS = 2 | ||
| return c_uint32(2) |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The XDP example shows returning c_uint32(2), but the XDP_PASS constant is actually defined as c_int64(2) in helpers.py. This type mismatch should be corrected for consistency.
| from ctypes import c_uint32 | |
| @section("xdp") | |
| def xdp_pass(ctx: c_void_p) -> c_uint32: | |
| # XDP_PASS = 2 | |
| return c_uint32(2) | |
| from ctypes import c_void_p, c_int64 | |
| @section("xdp") | |
| def xdp_pass(ctx: c_void_p) -> c_int64: | |
| # XDP_PASS = 2 | |
| return c_int64(2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected XDP example to use c_int64 return type and import XDP_PASS constant from pythonbpf.helper, matching the actual codebase pattern. Changes in commit c58483a.
docs/conf.py
Outdated
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output | ||
|
|
||
| html_theme = 'sphinx_rtd_theme' | ||
| html_static_path = ['_static'] |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assignment to 'html_static_path' is unnecessary as it is redefined before this value is used.
| html_static_path = ['_static'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed duplicate html_static_path assignment in conf.py. Changes in commit c58483a.
|
@copilot it would be better to change the installation steps to use uv instead of pip for package management |
…nd add uv support Co-authored-by: r41k0u <76248539+r41k0u@users.noreply.github.com>
Comprehensive Sphinx Documentation Setup for PythonBPF ✅
This PR adds complete Sphinx-based documentation for PythonBPF with MyST-Parser support, covering all aspects of the library from installation to advanced usage.
📚 Documentation Structure
Created a comprehensive documentation project in
docs/with the following structure:✨ Key Features
Sphinx Configuration (
docs/conf.py):Documentation Content:
Project Configuration:
pyproject.tomlwith optionaldocsdependency group.gitignoreto exclude build artifacts🔧 Recent Fixes
comm()helper usage to require buffer parameter (matches actual implementation)c_int64andXDP_PASSconstant (matches actual examples)html_static_pathin conf.py🛠️ Building the Documentation
Install dependencies and build:
Using uv (recommended):
Using pip:
The generated HTML will be in
docs/_build/html/.📝 Documentation Highlights
🎯 What's Included
📦 Dependencies Added
Documentation-specific dependencies (optional):
Note: The documentation focuses only on the public API exposed through
pythonbpf/__init__.pyas specified in the requirements. No existing code files were modified - only documentation was added.Original prompt
Overview
Create a comprehensive documentation project for PythonBPF using Sphinx with MyST-Parser. The documentation should focus on the code in the
pythonbpf/subdirectory and be placed in a newdocs/directory.Requirements
1. Documentation Infrastructure Setup
Create a
docs/directory with the following structure:2. Sphinx Configuration (
docs/conf.py)Configure Sphinx with:
3. Documentation Dependencies (
docs/requirements.txt)Include:
4. Update
pyproject.tomlAdd an optional
docsdependency group:5. Main Documentation Content
docs/index.mddocs/getting-started/installation.mddocs/getting-started/quickstart.mddocs/user-guide/decorators.mdDocument the decorators from
pythonbpf/decorators.py:@bpf- Mark functions/classes for BPF compilation@map- Define BPF maps@struct- Define BPF structs@section(name)- Specify the BPF section (tracepoint, kprobe, etc.)@bpfglobal- Define BPF global variables (including LICENSE)docs/user-guide/maps.mdDocument from
pythonbpf/maps/:HashMap- Key-value storagePerfEventArray- Event output to userspaceRingBuffer- Efficient ring buffer for eventsdocs/user-guide/structs.mdDocument struct usage:
@bpfand@structdocs/user-guide/compilation.mdDocument from
pythonbpf/codegen.py:compile()- Compile current file to BPF objectcompile_to_ir()- Compile to LLVM IRBPF()- Compile and load BPF program, returns BpfObjectdocs/user-guide/helpers.mdDocument utilities from
pythonbpf/utils.py:trace_pipe()- Read from kernel trace pipetrace_fields()- Parse trace output into fieldsAlso mention helper functions available from
pythonbpf.helper:ktime()- Get kernel timestamppid()- Get process IDcomm()- Get process command name6. Makefile and make.bat
Standard Sphinx build files for:
make html- Build HTML documentationmake clean- Clean build directory7. GitHub Actions Workflow (Optional but Recommended)
Create
.github/workflows/docs.ymlfor automatic documentation building on push to master, deploying to GitHub Pages.Style Guidelines
examples/directory where relevantpythonbpf/__init__.py:Notes
pythonbpf/subdirectory codeThis pull request was created from Copilot chat.
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.