跳到主要内容

Python

Goose Python 包拥有独立仓库 kumose/goose-python,并使用 pybind11 构建 Goose 的 Python 绑定。

前置条件

本指南默认你已满足:

  1. 已获得可工作的 Goose Python 源码副本(含 git submodule 和 tags)
  2. 已安装 Astral UV >= 0.8.0
  3. goose-python 源码根目录执行命令

我们推荐使用 Astral UV 进行 Python 环境与依赖管理。虽然也可使用 pip 配合可编辑安装(且关闭构建隔离)搭建开发环境,但本指南不覆盖该路径。

我们使用 CLion 作为 IDE。本指南不提供其他 IDE 的专门步骤,但整体流程应类似。

1. Goose Python 仓库

先将 goose-python fork 到个人仓库,再克隆你的 fork:

git clone --recurse-submodules YOUR_FORK_URL
cd goose-python
git remote add upstream https://github.com/kumose/goose-python.git
git fetch --all

如果你之前克隆时未带 submodules:

git submodule update --init --recursive
git remote add upstream https://github.com/kumose/goose-python.git
git fetch --all

重要说明:

  • Goose 以 git submodule 方式 vendored,必须初始化
  • Goose 版本判定依赖本地可用的 git tags
  • 若在引用不同 submodule 的分支间切换,请添加 git hooks:
git config --local core.hooksPath .githooks/

2. 安装 Astral uv

安装 uv(版本 >= 0.8.0)。

开发环境搭建

1. 平台相关准备

所有平台:

  • Python 3.9+ supported
  • uv >= 0.8.0 required
  • CMake and Ninja (installed via UV)
  • C++ compiler toolchain

Linux(Ubuntu 24.04):

sudo apt-get update
sudo apt-get install ccache

macOS:

# Xcode command line tools
xcode-select --install

Windows:

  • Visual Studio 2019+ with C++ support
  • Git for Windows

2. 安装依赖并构建

分两步搭建开发环境:

# Install all development dependencies without building the project
uv sync --no-install-project

# Build and install the project without build isolation
uv sync --no-build-isolation

为什么分两步?

  • uv sync 默认会通过 scikit-build-core 进行可编辑安装,并使用持久化 build 目录
  • 构建会在隔离且临时的环境中进行,cmake 路径可能指向不存在目录
  • 先装依赖、再关闭隔离构建,可确保 cmake 正常集成

3. 启用 Pre-Commit Hooks

CI 会运行多项 lint/format/type-check。你可以手动执行,但更推荐用 pre-commit 安装与 CI 一致的 git hooks(其已包含在开发依赖中):

uvx pre-commit install

这样提交前会自动运行所需检查。

你也可以安装 post-checkout hook,使其始终执行 git submodule update --init --recursive。在 main 与修复分支间切换时,这能确保 goose submodule 始终正确初始化:

uvx pre-commit install --hook-type post-checkout

4. 验证安装

uv run python -c "import goose; print(goose.sql('SELECT 42').fetchall())"

开发工作流

运行测试

运行全部测试:

uv run --no-build-isolation pytest ./tests --verbose

仅运行快速测试(排除 slow 目录):

uv run --no-build-isolation pytest ./tests --verbose --ignore=./tests/slow

测试覆盖率

以 coverage 模式运行(会使用 --coverage 编译扩展以采集 C++ 覆盖率):

COVERAGE=1 uv run --no-build-isolation coverage run -m pytest ./tests --verbose

查看 Python 覆盖率:

uv run coverage html -d htmlcov-python
uv run coverage report --format=markdown

查看 C++ 覆盖率:

uv run gcovr \
--gcov-ignore-errors all \
--root "$PWD" \
--filter "${PWD}/src/goose_py" \
--exclude '.*/\.cache/.*' \
--gcov-exclude '.*/\.cache/.*' \
--gcov-exclude '.*/external/.*' \
--gcov-exclude '.*/site-packages/.*' \
--exclude-unreachable-branches \
--exclude-throw-branches \
--html --html-details -o coverage-cpp.html \
build/coverage/src/goose_py \
--print-summary

构建 Wheels

为当前系统构建 wheel:

uv build

为指定 Python 版本构建:

uv build -p 3.9

清理构建产物

uv cache clean
rm -rf build .venv uv.lock

IDE 设置(CLion)

对于 CLion 用户,可将项目配置为支持 Python 扩展的 C++ 调试:

CMake Profile 配置

SettingsBuild, Execution, DeploymentCMake 中创建 Debug profile:

  • Name: Debug
  • Build type: Debug
  • Generator: Ninja
  • CMake Options:
    -DCMAKE_PREFIX_PATH=$CMakeProjectDir$/.venv;$CMAKE_PREFIX_PATH

Python 调试配置

创建一个 CMake Application 运行配置:

  • Name: Python Debug
  • Target: All targets
  • Executable: ⟨PROJECT_DIR⟩/.venv/bin/python3
  • Program arguments: $FilePath$
  • Working directory: $ProjectFileDir$

这样可设置 C++ 断点并调试使用 Goose 扩展的 Python 脚本。

调试

命令行调试

使用 lldb 打断点并调试:

# Example Python script (test.py)
# import goose
# print(goose.sql("select * from range(1000)").df())

lldb -- .venv/bin/python3 test.py

在 lldb 中:

# Set breakpoint (library loads when imported)
(lldb) br s -n goose::GoosePyRelation::FetchDF
(lldb) r

跨平台测试

你可以在自己的 fork 上对任意分支手动触发 packaging workflow,并在 GitHub Actions 界面选择平台和测试套件。

故障排查

构建问题

缺少 git tags: 若你 fork 了 Goose Python,请确保同步 upstream tags:

git remote add upstream https://github.com/kumose/goose-python.git
git fetch --tags upstream
git push --tags

平台相关问题

Windows 编译: 请确保已安装带 C++ 组件的 Visual Studio 2019+。