Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions .github/workflows/python-wheels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
name: python-wheels

on:
push:
tags:
- "fff-py-v*"
workflow_dispatch:
inputs:
publish:
description: "Publish to PyPI (requires PYPI_API_TOKEN secret)"
required: false
default: "false"

permissions:
contents: read

jobs:
linux:
name: linux ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build wheels (manylinux)
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --manifest-path crates/fff-py/Cargo.toml
manylinux: auto
working-directory: .
- name: Build sdist (x86_64 only)
if: matrix.target == 'x86_64'
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist --manifest-path crates/fff-py/Cargo.toml
- uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.target }}
path: dist

musllinux:
name: musllinux ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build wheels (musllinux)
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --manifest-path crates/fff-py/Cargo.toml
manylinux: musllinux_1_2
- uses: actions/upload-artifact@v4
with:
name: wheels-musllinux-${{ matrix.target }}
path: dist

macos:
name: macos ${{ matrix.target }}
runs-on: ${{ matrix.target == 'aarch64' && 'macos-14' || 'macos-13' }}
strategy:
fail-fast: false
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --manifest-path crates/fff-py/Cargo.toml
- uses: actions/upload-artifact@v4
with:
name: wheels-macos-${{ matrix.target }}
path: dist

windows:
name: windows ${{ matrix.target }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
target: [x64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
architecture: ${{ matrix.target == 'x64' && 'x64' || 'x86' }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --manifest-path crates/fff-py/Cargo.toml
- uses: actions/upload-artifact@v4
with:
name: wheels-windows-${{ matrix.target }}
path: dist

smoke-test:
name: smoke-test ${{ matrix.os }} py${{ matrix.python }}
needs: [linux, macos, windows]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, windows-latest]
python: ["3.9", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
merge-multiple: true
path: dist
- name: Install built wheel
shell: bash
run: |
pip install --no-index --find-links=dist fff-search
- name: Smoke test
shell: bash
run: |
python -c "from fff_search import FileFinder, __version__; print('fff_search', __version__); f = FileFinder.create(base_path='.'); f.wait_for_scan(timeout_ms=10000); print('files indexed:', f.get_scan_progress().scanned_files_count); r = f.file_search('readme'); print('matched:', r.total_matched); f.destroy()"

release:
name: release to PyPI
needs: [linux, musllinux, macos, windows, smoke-test]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/fff-py-v') || github.event.inputs.publish == 'true'
environment:
name: pypi
url: https://pypi.org/p/fff-search
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
merge-multiple: true
path: dist
- name: Publish via maturin
uses: PyO3/maturin-action@v1
with:
command: upload
args: --non-interactive --skip-existing dist/*
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
doc/tags
big-repo
target/

# Python (fff-py SDK)
.venv-py/
.venv*/
__pycache__/
*.egg-info/
.pytest_cache/
*.pyc
.archive.lua
_*.lua
.lazy.lua
Expand All @@ -27,3 +35,6 @@ scripts/benchmark-results/

# Instruments traces
*.trace/
# Built python extension
*.pyd
*.so
110 changes: 110 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"crates/fff-core",
"crates/fff-mcp",
"crates/fff-nvim",
"crates/fff-py",
"crates/fff-query-parser",
"crates/fff-grep",
]
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,32 @@ Every method returns a `Result<T>` (`{ ok: true, value } | { ok: false, error }`

TypeScript wrapper over the C library for nodejs and bun. Build custom agent tools, CLIs, or IDE integrations on top of FFF.

<details id="python-sdk">
<summary>
<h2>Python SDK</h2>
</summary>

```bash
pip install fff-search
```

```python
from fff_search import FileFinder

with FileFinder.create(base_path=".", ai_mode=True) as f:
f.wait_for_scan(timeout_ms=10_000)
files = f.file_search("incognito profile", page_size=20)
hits = f.grep("GetOffTheRecordProfile", classify_definitions=True)
```

Errors raise `FffError`. Type stubs bundled (`py.typed`). Wheels for Linux (x86_64, aarch64), macOS (x86_64, aarch64), Windows (x86_64) on Python 3.9+ via abi3.

Source: [`crates/fff-py/`](./crates/fff-py/).

</details>

PyO3 bindings on the same Rust core.

<details id="rust-crate">
<summary>
<h2>Rust crate</h2>
Expand Down Expand Up @@ -540,6 +566,7 @@ If you are running one grep from a terminal, `rg` is still the right tool. If yo
- `crates/fff-c` - C FFI used by every language binding.
- `crates/fff-nvim` - Lua/mlua bindings for the Neovim plugin.
- `crates/fff-mcp` - MCP server binary.
- `crates/fff-py` - Python SDK (PyO3, `pip install fff-search`).
- `packages/fff-node` - Node.js SDK (`@ff-labs/fff-node`).
- `packages/fff-bun` - Bun SDK (`@ff-labs/fff-node`).
- `packages/pi-fff` - pi extension (`@ff-labs/pi-fff`).
Expand Down
Loading
Loading