Bisect package versions in PEP 723 Python scripts using git bisect and uv
Project description
script-bisect
Bisect package versions in PEP 723 Python scripts using git bisect and uv.
Overview
script-bisect combines the power of git bisect with PEP 723 inline script metadata to automatically find the commit that introduced a regression in a Python package dependency. It works by:
- 📄 Parsing your PEP 723 script to extract dependency information
- 📥 Cloning the package repository automatically
- 🔄 Running git bisect with intelligent test automation
- ✏️ Updating package references for each commit tested
- 🎯 Finding the exact commit that caused the issue
Perfect for debugging package regressions, testing new features, and creating reliable bug reports.
Super Quick Start 🚀
Point script-bisect directly at a real GitHub issue:
# Bisect a real xarray issue directly from GitHub
uvx script-bisect https://github.com/pydata/xarray/issues/10712 xarray v2025.07.1 v2025.08.0
That's it! script-bisect will:
- Extract the code from the GitHub issue
- Create a test script automatically
- Detect the package and repository
- Run the bisection to find the problematic commit
For xarray issue #10712, this will show you exactly which commit introduced the regression!
You can also omit the REFs and fill them in using using the UI
# Bisect a real xarray issue directly from GitHub
uvx script-bisect https://github.com/pydata/xarray/issues/10712 xarray
Installation
Using uvx (Recommended)
uvx script-bisect script.py package_name good_ref bad_ref
Using uv
uv tool install script-bisect
script-bisect script.py package_name good_ref bad_ref
Development Installation
git clone https://github.com/user/script-bisect.git
cd script-bisect
uv sync --extra dev
uv run script-bisect --help
Quick Start
Try It Now! 🚀
Manual Script Method
You can also create your own test script:
1. Create Your Own Script
Create a script that demonstrates your issue:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "xarray@git+https://github.com/pydata/xarray.git@main",
# ]
# ///
import xarray as xr
import numpy as np
# Your reproducer code here
data = xr.Dataset({'temp': (['time'], np.random.randn(10))})
result = data.some_method() # This might fail in certain versions
print("✅ Test passed!")
2. Run the Bisection
# Find when something broke
script-bisect bug_report.py xarray v2024.01.0 v2024.03.0
# Find when something was fixed (inverse mode)
script-bisect bug_report.py pandas v1.5.0 v2.0.0 --inverse
3. Get Results
🔍 script-bisect v0.1.0
Bisect package versions in PEP 723 Python scripts
📦 Package: xarray
🔗 Repository: https://github.com/pydata/xarray.git
✅ Good ref: v2024.01.0 (commit: abc123...)
❌ Bad ref: v2024.03.0 (commit: def456...)
🔄 Starting bisection (approximately 7 steps)...
✨ Found first bad commit:
Commit: 234pqr890...
Author: John Doe <john@example.com>
Date: 2024-02-15 10:30:00
Message: Refactor array indexing logic
View on GitHub: https://github.com/pydata/xarray/commit/234pqr890
Usage
Basic Usage
script-bisect SCRIPT PACKAGE GOOD_REF BAD_REF
- SCRIPT: Path to your PEP 723 Python script
- PACKAGE: Name of the package to bisect
- GOOD_REF: Git reference (tag/commit/branch) where it works
- BAD_REF: Git reference where it's broken
Options
--repo-url URL: Override repository URL (auto-detected from git dependencies)--test-command CMD: Custom test command (default:uv run SCRIPT)--inverse: Find when something was fixed (not broken)--keep-clone: Keep cloned repository for inspection--dry-run: Show what would be done without executing--verbose: Enable detailed logging--yes: Auto-confirm all prompts for automated usage--verify-endpoints: Verify good/bad references before starting--refresh-cache: Force refresh of cached repositories and metadata--full-traceback: Show full Python tracebacks on errors
Examples
Basic Package Regression
# Your script has: numpy>=1.24.0
script-bisect reproducer.py numpy 1.24.0 1.26.0
Git Dependency Already Present
# Your script has: xarray@git+https://github.com/pydata/xarray.git@main
script-bisect bug_report.py xarray v2024.01.0 main
Custom Repository
script-bisect test.py numpy v1.24.0 main \\
--repo-url https://github.com/numpy/numpy.git
Custom Test Command
script-bisect test.py pandas v2.0.0 main \\
--test-command "python -m pytest {script}"
Finding Fixes (Inverse Mode)
# Find when a bug was fixed
script-bisect regression_test.py scipy v1.10.0 v1.11.0 --inverse
Automated Usage
# Auto-confirm all prompts for CI/automated use
script-bisect test.py numpy v1.24.0 v1.26.0 --yes --verbose
# Force refresh cached data and verify endpoints
script-bisect test.py xarray v2024.01.0 main --refresh-cache --verify-endpoints
Advanced Examples
# Full automation with error details
script-bisect regression.py pandas v1.5.0 v2.0.0 \\
--yes --full-traceback --keep-clone
# Interactive mode with custom test command
script-bisect integration_test.py requests v2.28.0 v2.31.0 \\
--test-command "python -m pytest {script} -v"
Requirements
System Requirements
- Python 3.11+
- uv package manager (installation guide)
- git version control
Script Requirements
Your Python script must contain PEP 723 inline metadata with dependencies:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "package_name>=1.0",
# # OR for git dependencies:
# "package_name@git+https://github.com/org/repo.git@ref",
# ]
# ///
The tool will automatically convert PyPI package specs to git dependencies during bisection.
Interactive Features
Parameter Editing
Before starting bisection, you can interactively modify parameters:
🔄 Bisection Summary
[s] 📄 Script test_script.py
[p] 📦 Package xarray
[r] 🔗 Repository https://github.com/pydata/xarray.git
[g] ✅ Good ref v2024.01.0
[b] ❌ Bad ref v2024.03.0
[t] 🧪 Test command uv run test_script.py
[i] 🔄 Mode Normal (find when broken)
Press the highlighted key to edit that parameter, or:
Enter/y - Start bisection
n/q - Cancel
- Press any highlighted key (s, p, r, g, b, t, i) to edit that parameter
- Edit scripts directly in your configured editor (respects
git config core.editor) - Toggle between normal and inverse bisection modes
- Modify test commands and repository URLs on the fly
End State Options
After bisection completes, choose what to do next:
- Exit - Complete the bisection
- Re-run with different refs - Try different good/bad references
- Re-run with different script - Edit or change the test script
- Re-run with modified parameters - Change package, repo URL, or test command
Intelligent Caching
script-bisect includes a smart caching system for better performance:
- Repository Caching: Cloned repositories are cached in
~/.cache/script-bisect/repos/ - Metadata Caching: Package metadata is cached to avoid repeated PyPI lookups
- Automatic Updates: Cached repos are updated with
git fetchfor new commits - Auto-cleanup: Expired cache entries are cleaned up automatically
- Force Refresh: Use
--refresh-cacheto bypass cache and fetch fresh data
Cache locations follow XDG Base Directory standards:
- Linux/macOS:
~/.cache/script-bisect/ - Windows:
%LOCALAPPDATA%\script-bisect\cache\
How It Works
1. Script Analysis
- Parses PEP 723 metadata from your script
- Validates package dependencies and requirements
- Auto-detects repository URLs for PyPI packages using multiple sources
2. Repository Management
- Clones the package repository (with intelligent caching)
- Validates that good/bad references exist
- Updates cached repositories with latest commits
- Manages cleanup automatically (unless
--keep-cloneis used)
3. Bisection Process
- Uses
git bisect runwith an automated test script - For each commit, updates your script's dependency reference
- Runs
uv run script.pyto test the specific commit - Returns appropriate exit codes for git bisect (0=good, 1=bad, 125=skip)
4. Result Reporting
- Identifies the exact problematic commit
- Shows commit details (author, date, message)
- Provides GitHub/GitLab links when possible
- Offers interactive options for follow-up actions
Troubleshooting
Common Issues
"Package not found in dependencies"
- Ensure the package name matches exactly what's in your dependencies list
- Use
--verboseto see available packages
"Could not auto-detect repository URL"
- Use
--repo-urlto specify the repository manually - Ensure the package has repository metadata on PyPI
"uv not found"
- Install uv:
curl -LsSf https://astral.sh/uv/install.sh | sh - Ensure uv is in your PATH
Test always fails/passes
- Check your script logic with
--dry-run - Use
--verboseto see test output - Verify your script correctly demonstrates the issue
Getting Help
- Check the troubleshooting guide
- Review example scripts in
examples/ - Open an issue on GitHub
Future Features
Roadmap 🗺️
- Multiple Package Bisection: Bisect multiple related packages simultaneously
- PyPI Metadata Lookup: Automatic repository detection for more packages
- Regression Test Suite: Generate test suites from bisection results
- CI Integration: GitHub Actions and other CI platform support
Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
Development Setup
git clone https://github.com/user/script-bisect.git
cd script-bisect
uv sync --extra dev
uv run pre-commit install
# Run tests
uv run pytest
uv run pytest --cov=script_bisect
# Format and lint
uv run ruff format
uv run ruff check --fix
License
MIT License - see LICENSE for details.
Acknowledgments
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file script_bisect-0.1.2.tar.gz.
File metadata
- Download URL: script_bisect-0.1.2.tar.gz
- Upload date:
- Size: 5.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ee92c131dc7750dce34d12b1779cc00402a9b47c8562131393aa8c7d128621f
|
|
| MD5 |
5daa79ebb2aa88cb083a0c765164224b
|
|
| BLAKE2b-256 |
18acfbfd9ebaa219a1e198f51386c2cb4e561836edd68d566a47442340a78ca1
|
Provenance
The following attestation bundles were made for script_bisect-0.1.2.tar.gz:
Publisher:
publish.yml on ianhi/script-bisect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
script_bisect-0.1.2.tar.gz -
Subject digest:
5ee92c131dc7750dce34d12b1779cc00402a9b47c8562131393aa8c7d128621f - Sigstore transparency entry: 495487505
- Sigstore integration time:
-
Permalink:
ianhi/script-bisect@b454e2cbf2a2edd63d44197fa1ce0efe38d6e742 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/ianhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b454e2cbf2a2edd63d44197fa1ce0efe38d6e742 -
Trigger Event:
release
-
Statement type:
File details
Details for the file script_bisect-0.1.2-py3-none-any.whl.
File metadata
- Download URL: script_bisect-0.1.2-py3-none-any.whl
- Upload date:
- Size: 80.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e792db919631c6a121895403e3383f08e4eabec0a5572d1f8ace174eb09256f6
|
|
| MD5 |
a5c9140c53b8fb15eadce0ba60b457d7
|
|
| BLAKE2b-256 |
dc5dabdf542eecfcebb3ce034bc185e1f0a1d09504261fae91a07babe54e5ee9
|
Provenance
The following attestation bundles were made for script_bisect-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on ianhi/script-bisect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
script_bisect-0.1.2-py3-none-any.whl -
Subject digest:
e792db919631c6a121895403e3383f08e4eabec0a5572d1f8ace174eb09256f6 - Sigstore transparency entry: 495487515
- Sigstore integration time:
-
Permalink:
ianhi/script-bisect@b454e2cbf2a2edd63d44197fa1ce0efe38d6e742 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/ianhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b454e2cbf2a2edd63d44197fa1ce0efe38d6e742 -
Trigger Event:
release
-
Statement type: