Files
zed-playground/py_workspace/UV_LOCAL_PACKAGE_GUIDE.md
2026-02-04 15:42:08 +08:00

3.1 KiB

Integrating Local Binary Extensions with uv

This guide explains how we packaged the local pyzed binary extension (originally from a system installation) so that uv can manage it as a project dependency.

The Problem

The ZED SDK installs its Python wrapper (pyzed) as a system-level package (often in /usr/local/lib/...). It consists of compiled extensions (.so or .sl files) and Python bindings.

uv strictly manages virtual environments and dependencies. It cannot directly "see" or import packages from the global system site-packages unless explicitly configured to use system site-packages (which reduces isolation). Furthermore, a raw .so file or a bare directory without metadata isn't a valid package source for uv.

The Solution: A Local Package Wrapper

To make pyzed compatible with uv, we wrapped the raw library files into a proper, minimally compliant Python package located at libs/pyzed_pkg.

1. Directory Structure

We organized the files into a standard package layout:

libs/pyzed_pkg/
├── pyproject.toml       # Package metadata (CRITICAL)
└── pyzed/               # The actual importable package
    ├── __init__.py
    ├── sl.cpython-312-x86_64-linux-gnu.so  # The compiled extension
    └── ...

2. The Local pyproject.toml

We created a pyproject.toml inside libs/pyzed_pkg to tell build tools how to handle the files.

Key configuration points:

  1. Build System: Uses setuptools to bundle the files.
  2. Package Discovery: Explicitly lists pyzed.
  3. Package Data: Crucially, configures setuptools to include binary files (*.so, *.pyi) which are usually ignored by default.
[project]
name = "pyzed"
version = "0.1.0"
description = "Wrapper for ZED SDK"
requires-python = ">=3.12"
dependencies = []

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
packages = ["pyzed"]

# IMPORTANT: Ensure the binary extension is included in the build
[tool.setuptools.package-data]
pyzed = ["*.so", "*.pyi"]

Configuring the Main Project

In the root pyproject.toml of your application, we used [tool.uv.sources] to redirect the pyzed dependency to our local path.

[project]
dependencies = [
    "pyzed",          # Declared as a normal dependency
    "cupy-cuda12x",
    "numpy",
]

# uv-specific configuration
[tool.uv.sources]
pyzed = { path = "libs/pyzed_pkg" }

How uv Processes This

  1. Resolution: When you run uv sync or uv run, uv sees pyzed in the dependencies.
  2. Source Lookup: It checks tool.uv.sources and finds the local path libs/pyzed_pkg.
  3. Build/Install:
    • uv treats the directory as a source distribution.
    • It uses the build-system defined in libs/pyzed_pkg/pyproject.toml to build a temporary wheel.
    • This wheel (containing the .so file) is installed into the project's virtual environment (.venv).

This ensures that your application works seamlessly with import pyzed.sl while maintaining a clean, isolated, and reproducible environment managed by uv.