Skip to content
Merged
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
7 changes: 1 addition & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ updates:
directory: "/crates/code2prompt-core"
schedule:
interval: "weekly"
- package-ecosystem: "pip" # pyproject.toml
target-branch: "main"
directory: "/crates/code2prompt-python"
schedule:
interval: "weekly"
- package-ecosystem: "uv" # requirements.lock
- package-ecosystem: "uv" # pyproject.toml and uv.lock
target-branch: "main"
directory: "/crates/code2prompt-python"
schedule:
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,29 @@ jobs:
- uses: actions/checkout@v6
- name: Run tests
run: cargo test --verbose

python-bindings:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.14"]

steps:
- uses: actions/checkout@v6
- name: Install uv and Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
version: "0.12.10"
python-version: ${{ matrix.python-version }}
enable-cache: true
cache-dependency-glob: crates/code2prompt-python/uv.lock
- name: Sync Python project
working-directory: crates/code2prompt-python
run: uv sync --locked
- name: Run Python tests
working-directory: crates/code2prompt-python
run: uv run --locked pytest
- name: Build release wheel
if: matrix.python-version == '3.11'
working-directory: crates/code2prompt-python
run: uv run --locked maturin build --release --out ../../dist
3 changes: 1 addition & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ git2 = { version = "0.21.0", default-features = false, features = [
globset = "0.4.15"
handlebars = "6.4.0"
once_cell = "1.19.0"
pyo3 = { version = "0.28.3", features = ["extension-module", "abi3-py312"] }
pyo3 = { version = "0.28.3", features = ["extension-module", "abi3-py311"] }
ratatui = "0.30.1"
regex = "1.10.3"
rayon = "1.11.0"
Expand Down
13 changes: 11 additions & 2 deletions crates/code2prompt-python/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
[package]
name = "code2prompt-python"
version = "3.2.0"
version = "4.3.0"
authors = [
"Olivier D'Ancona <olivier_dancona@hotmail.com>",
"Mufeed VH <contact@mufeedvh.com>",
]
description = "Native Python bindings for code2prompt"
homepage = "https://code2prompt.dev"
documentation = "https://code2prompt.dev/docs/welcome"
repository = "https://github.com/mufeedvh/code2prompt"
license = "MIT"
edition = "2024"
readme = "README.md"

[lib]
name = "code2prompt_rs"
crate-type = ["cdylib"]

[dependencies]
serde_json = { workspace = true }
code2prompt_core = { path = "../code2prompt-core" }
pyo3 = { workspace = true }
115 changes: 115 additions & 0 deletions crates/code2prompt-python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# code2prompt Python bindings

Native Python bindings for the stateful
[`code2prompt_core`](https://crates.io/crates/code2prompt_core) API.

## Installation

```bash
pip install code2prompt_rs
```

Python 3.11 or newer is supported.

Rust `PathBuf` values accept Python strings or `os.PathLike` objects and are exposed as
`pathlib.Path` objects.

## Usage

Create a core configuration, move it into a session, and operate on that session just as you
would from Rust:

```python
from code2prompt_rs import Code2PromptConfig, Code2PromptSession

config = Code2PromptConfig(
".",
include_patterns=["**/*.py", "**/*.rs"],
exclude_patterns=["**/tests/**"],
line_numbers=True,
deselected=True,
)
session = Code2PromptSession(config)

session.select_file("src/main.rs")
session.select_file("src/lib.rs")

result = session.generate_prompt()
print(result.prompt)
print(result.token_count)
print(result.files)
```

Selection methods mutate and return the same session, so calls may also be chained:

```python
session.select_file("src/main.rs").deselect_file("src/generated.rs")
```

## Configuration

Configuration values use native enum classes rather than string aliases:

```python
from code2prompt_rs import (
Code2PromptConfig,
FileProcessorsConfig,
FileSortMethod,
IpynbProcessorConfig,
OutputFormat,
TokenFormat,
TokenizerType,
)

config = Code2PromptConfig(
".",
absolute_path=False,
no_codeblock=False,
output_format=OutputFormat.Markdown,
sort_method=FileSortMethod.NameAsc,
encoding=TokenizerType.Cl100kBase,
token_format=TokenFormat.Raw,
processors=FileProcessorsConfig(
ipynb=IpynbProcessorConfig(
max_code_cells=5,
include_outputs=True,
include_markdown=True,
)
),
)
```

`Code2PromptConfig` exposes the user-facing fields from core 4.3. The optional Rust
`entity-map` feature is not included in the Python wheels.

## Session API

`Code2PromptSession` exposes the core operational methods:

- Pattern updates: `add_include_pattern`, `add_exclude_pattern`
- Selection: `select_file`, `deselect_file`, `toggle_file_selection`,
`is_file_selected`, `get_selected_files`, `clear_user_actions`, `has_user_actions`,
`set_deselected`
- Loading: `load_codebase`, `load_git_diff`, `load_git_diff_between_branches`,
`load_git_log_between_branches`
- Results: `generate_prompt`, `raw_analysis`, `contextual_analysis`

`generate_prompt()` returns a typed `RenderedPrompt`. Loaded codebase and Git values are
available from the typed `session.data` snapshot. Analysis calls return `CodebaseAnalysis`,
whose `raw_files()`, `by_extension()`, and `token_map(options)` methods return typed models.

## Local development

```bash
uv sync
uv run pytest
```

`uv sync` creates `.venv`, installs the development dependencies, and builds the native
extension in editable mode. The lockfile is committed for reproducible development environments.

To build a release wheel locally:

```bash
uv run maturin build --release
```
23 changes: 23 additions & 0 deletions crates/code2prompt-python/examples/basic_usage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Select files and generate a prompt through the native session API."""

from code2prompt_rs import Code2PromptConfig, Code2PromptSession


def main() -> None:
config = Code2PromptConfig(
".",
include_patterns=["**/*.py", "**/*.rs"],
exclude_patterns=["**/tests/**"],
line_numbers=True,
deselected=True,
)
session = Code2PromptSession(config)
session.select_file("src/main.rs").select_file("src/lib.rs")

result = session.generate_prompt()
print(f"Generated {result.token_count} tokens from {len(result.files)} files")
print(result.prompt)


if __name__ == "__main__":
main()
37 changes: 22 additions & 15 deletions crates/code2prompt-python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[project]
name = "code2prompt_rs"
version = "3.2.1"
version = "4.3.0"
description = "Python bindings for code2prompt"
authors = [
{ name = "Olivier D'Ancona", email = "olivier_dancona@hotmail.com" },
{ name = "Mufeed VH", email = "contact@mufeedvh.com" },
]
dependencies = ["pip>=25.0.1", "patchelf>=0.17.2.1"]
dependencies = []
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
Expand All @@ -16,33 +17,39 @@ classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Rust",
"Topic :: Software Development :: Libraries :: Python Modules",
]

[build-system]
requires = ["maturin>=1.0,<2.0"]
requires = ["maturin>=1.8.2,<2.0"]
build-backend = "maturin"

[tool.maturin]
bindings = "pyo3"
module-name = "code2prompt_rs"
manifest-path = "Cargo.toml"
python-source = "python-sdk"
features = ["pyo3/extension-module"]

[tool.rye]
managed = true
dev-dependencies = ["maturin>=1.8.2", "pytest>=8.3.5"]

[tool.rye.scripts]
build = "maturin develop"

[tool.hatch.metadata]
allow-direct-references = true
[dependency-groups]
dev = [
"maturin>=1.8.2,<2.0",
"pytest>=8.3.5",
]

[tool.hatch.build.targets.wheel]
packages = ["src/python_sdk"]
[tool.uv]
cache-keys = [
{ file = "pyproject.toml" },
{ file = "Cargo.toml" },
{ file = "../../Cargo.toml" },
{ file = "../../Cargo.lock" },
{ file = "src/**/*.rs" },
{ file = "../code2prompt-core/Cargo.toml" },
{ file = "../code2prompt-core/src/**/*.rs" },
{ file = "../code2prompt-core/templates/**/*" },
]

[project.urls]
Homepage = "https://code2prompt.dev"
Expand Down
Loading