diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml index fbba4aa..66dd0e8 100644 --- a/.github/workflows/pip.yml +++ b/.github/workflows/pip.yml @@ -1,29 +1,38 @@ name: Pip on: - workflow_dispatch: - pull_request: push: - branches: - - master - - main + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: jobs: - build: + test: + name: Test on Python ${{ matrix.python-version }} + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - platform: [ubuntu-latest] - python-version: ["3.12", "3.13"] - - runs-on: ${{ matrix.platform }} + python-version: ['3.12', '3.13'] steps: - - uses: actions/checkout@v5 + - name: Checkout code + uses: actions/checkout@v5 with: - submodules: true + submodules: recursive - - uses: actions/setup-python@v6 + - name: Verify submodules + run: | + echo "Checking submodule status:" + git submodule status + echo "Checking libbpf directory:" + ls -la libbpf/ + echo "Checking libbpf/src:" + ls -la libbpf/src/ || echo "libbpf/src not found!" + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -33,19 +42,72 @@ jobs: sudo apt-get install -y \ libbpf-dev \ libelf-dev \ - linux-headers-generic \ + zlib1g-dev \ build-essential \ + clang \ cmake \ - ninja-build + ninja-build \ + pkg-config \ + git \ + make - - name: Add requirements - run: python -m pip install --upgrade pip wheel setuptools + - name: Install Python build dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade "setuptools>=77.0.0" wheel + pip install cmake ninja pybind11 - - name: Build and install - run: pip install --verbose .[test] + - name: Check build requirements + run: | + echo "Python version:" + python --version + echo "CMake version:" + cmake --version + echo "Ninja version:" + ninja --version + echo "Setuptools version:" + python -c "import setuptools; print(setuptools.__version__)" - - name: Test import - run: python -I -c "import pylibbpf; print('Import successful')" + - name: Build and install pylibbpf (verbose) + run: | + pip install -v -e . 2>&1 | tee build.log + continue-on-error: false - - name: Test - run: python -I -m pytest -v + - name: Check build output + run: | + echo "Build directory contents:" + find build -type f -name "*.so" 2>/dev/null || echo "No .so files found in build/" + echo "" + echo "Looking for pylibbpf extension:" + find . -name "pylibbpf*.so" -o -name "pylibbpf*.pyd" + echo "" + echo "Site-packages contents:" + python -c "import site; print(site.getsitepackages())" + ls -la $(python -c "import site; print(site.getsitepackages()[0])")/pylibbpf/ || echo "pylibbpf not in site-packages" + + - name: Try importing extension directly + run: | + python -c " + import sys + print('Python path:', sys.path) + try: + from pylibbpf import pylibbpf + print('Successfully imported pylibbpf.pylibbpf') + print('pylibbpf.pylibbpf members:', dir(pylibbpf)) + except ImportError as e: + print(f'Failed to import pylibbpf.pylibbpf: {e}') + " + + - name: Verify extension loaded + run: | + python -c "import pylibbpf; print('Members:', dir(pylibbpf)); assert hasattr(pylibbpf, 'BpfObject'), 'BpfObject not found!'; print('✓ OK')" + + - name: Install test dependencies + if: success() + run: | + pip install pytest pytest-cov + + - name: Run tests + if: success() + run: | + python -I -m pytest -v -s --cov=pylibbpf --cov-report=term-missing diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 5816d98..b5aa580 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v5 with: - submodules: true + submodules: recursive - name: Build SDist run: pipx run build --sdist @@ -41,22 +41,24 @@ jobs: steps: - uses: actions/checkout@v5 with: - submodules: true + submodules: recursive - name: Build wheels uses: pypa/cibuildwheel@v3.2 env: CIBW_PLATFORM: linux CIBW_ARCHS_LINUX: ${{ matrix.arch }} - CIBW_BUILD: "cp311-*" + CIBW_BUILD: "cp312-* cp313-*" CIBW_SKIP: "*-musllinux*" - CIBW_TEST_COMMAND: "python -c 'import pylibbpf; print(f\"pylibbpf {pylibbpf.__version__} imported successfully\")'" + CIBW_TEST_COMMAND: "python -c 'import pylibbpf; assert hasattr(pylibbpf, \"BpfObject\"), \"BpfObject not found\"; print(f\"pylibbpf {pylibbpf.__version__} OK\")'" CIBW_TEST_SKIP: "*-linux_aarch64" CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 CIBW_BEFORE_ALL_LINUX: | - dnf install -y elfutils-libelf-devel zlib-devel + dnf install -y elfutils-libelf-devel zlib-devel make gcc gcc-c++ git + CIBW_BEFORE_BUILD: > + pip install --upgrade "setuptools>=77.0.0" wheel cmake ninja pybind11 - name: Verify clean directory run: git diff --exit-code diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d917e7..dd129ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,10 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -find_package(Python COMPONENTS Interpreter Development.Module REQUIRED) +find_package( + Python + COMPONENTS Interpreter Development.Module + REQUIRED) # pybind11 include_directories(${CMAKE_SOURCE_DIR}/src) diff --git a/pylibbpf/ir_to_ctypes.py b/pylibbpf/ir_to_ctypes.py index 059e664..99cd125 100644 --- a/pylibbpf/ir_to_ctypes.py +++ b/pylibbpf/ir_to_ctypes.py @@ -1,6 +1,5 @@ import ctypes import logging -from typing import Dict, Type from llvmlite import ir @@ -51,7 +50,7 @@ def __repr__(self): return __repr__ -def convert_structs_to_ctypes(structs_sym_tab) -> Dict[str, Type[ctypes.Structure]]: +def convert_structs_to_ctypes(structs_sym_tab) -> dict[str, type[ctypes.Structure]]: """Convert PythonBPF's structs_sym_tab to ctypes.Structure classes.""" if not structs_sym_tab: return {} diff --git a/pylibbpf/wrappers.py b/pylibbpf/wrappers.py index aa7679c..2b9a92a 100644 --- a/pylibbpf/wrappers.py +++ b/pylibbpf/wrappers.py @@ -1,4 +1,4 @@ -from typing import Callable, Optional +from collections.abc import Callable class PerfEventArrayHelper: @@ -13,7 +13,7 @@ def open_perf_buffer( callback: Callable, struct_name: str = "", page_cnt: int = 8, - lost_callback: Optional[Callable] = None, + lost_callback: Callable | None = None, ): """Open perf buffer with auto-deserialization.""" from .pylibbpf import PerfEventArray diff --git a/pyproject.toml b/pyproject.toml index fce9d11..cfad1fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,3 +80,7 @@ extend-select = [ "RUF", # Ruff-specific "UP", # pyupgrade ] + +[tool.setuptools] +packages = ["pylibbpf"] +package-data = {"pylibbpf" = ["*.py", "*.so", "*.pyd", "py.typed"]} diff --git a/setup.py b/setup.py index ae74c74..e93fdd0 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import sys from pathlib import Path -from setuptools import Extension, find_packages, setup +from setuptools import Extension, setup from setuptools.command.build_ext import build_ext @@ -116,5 +116,4 @@ def build_extension(self, ext: CMakeExtension) -> None: setup( ext_modules=[CMakeExtension("pylibbpf.pylibbpf")], cmdclass={"build_ext": CMakeBuild}, - zip_safe=False, )