Notebook testing with fixtures, patches, and AI-generated tests
Project description
Ipso - Closing the loop for AI-powered jupyter notebooks
AI works best with a feedback loop - make a change, verify the syntax, run the tests, and iterate.
Notebooks don't really work that way. There are no functions, everything is a global variable, and there's no place to put tests, even if you wanted to.
Ipso connects these worlds by using AI to mantain shadow metadata within a notebook to hardcode, setup, and otherwise mock any setup needed for cells to run, along with tests to ensure the cells behave properly.
This works continuously behind the scenes as you & your agents work on a notebook together. The Ipso LSP server notifies AI when the metadata has gone stale. Next, the MCP server guides the AI to make the appropriate changes, to create and ensure the cells work correctly. Finally, Ipso will run the tests in an independent kernel, to ensure that the code works correctly, without messing with your actual work.
Installing Ipso
Ipso needs to be installed in the python environment that your kernel is running in. pip install ipso will work, and pip install pytest-ipso is also needed if you want to be able to run pytest and have it automatically detect and run any ipso tests (optional)
Next, for the AI loop to work properly, you need to enable the LSP and MCP servers for your AI application. You can either point your AI to the python environment you created, or you can use something like uvx or pipx to create a global instance. For example:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ipso": {
"type": "local",
"command": ["uvx", "ipso", "mcp"]
}
},
"lsp": {
"ipso": {
"command": ["uvx", "ipso", "lsp"],
"extensions": [".ipynb"]
}
}
}
Using Ipso
Just use your notebook how you normally would! As you make changes, the LSP will inform the AI to keep the metadata in sync, and it will use the MCP tool to investigate and fix any errors. Hopefully, this will allow the AI to catch any mistakes in the code it generates, or prompt further discussion as to the desired behavior (especially when changing existing logic)
To see the tests yourself, you can just run pytest "path/to/notebook", or you can use the ipso CLI to investigate, run, and edit the tests.
The CLI
The CLI lets you inspect, edit, and run the metadata that ipso attaches to each cell (fixtures, patches, and tests) without needing an AI in the loop.
Checking notebook health
# Quick check: are any cells out of date?
ipso status notebook.ipynb
# See everything ipso knows about your cells
ipso view notebook.ipynb
# Narrow it down — only cells that have tests
ipso view notebook.ipynb --filter "test:not null"
# Only show the fields you care about
ipso view notebook.ipynb --fields source,status
status exits non-zero when something needs attention, so it works well in CI or pre-commit hooks.
Running tests
# Run all cell tests
ipso test notebook.ipynb
# Run tests for specific cells
ipso test notebook.ipynb --filter "cell:abc123"
# Use a specific python environment
ipso test notebook.ipynb --python .venv/bin/python
Each cell's test runs in its own isolated kernel, so it never interferes with your live notebook state.
Editing metadata by hand
The easiest way to edit fixtures and tests directly is with the editor notebook:
# Open a side-by-side editor notebook
ipso edit notebook.ipynb
# ... make changes in notebook.ipso.ipynb ...
# Apply your edits back to the source notebook
ipso edit --continue notebook.ipynb
The editor notebook lays out each cell's fixtures, patched source, and tests as editable cells you can work with in Jupyter. When you're done, --continue folds everything back into the source notebook's metadata.
If you prefer working with JSON directly, update lets you apply changes programmatically:
# Set a fixture and test on a cell
ipso update notebook.ipynb --data '{
"cell_id": "abc123",
"fixtures": {"setup_db": {"description": "mock database", "source": "db = MockDB()"}},
"test": {"name": "test_query", "source": "assert query(db) == expected"}
}'
# scaffold well-formed JSON fragments to avoid typos
ipso scaffold fixture --name setup_db --source "db = MockDB()"
ipso scaffold test --name test_query --source "assert query(db) == expected"
Accepting changes
When you've reviewed a cell and are satisfied that its metadata is correct despite the diagnostics, you can accept it to clear the warnings:
# Accept all cells
ipso accept notebook.ipynb --all
# Accept only specific cells
ipso accept notebook.ipynb --filter "cell:abc123"
Filtering
Most commands support --filter to target specific cells. Filters can match on cell ID, index, presence of metadata, validity status, and diagnostic type or severity. Multiple filters are AND-ed together; comma-separated values within a filter are OR-ed. Run ipso docs filters for the full reference.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
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 ipso-0.1.3.tar.gz.
File metadata
- Download URL: ipso-0.1.3.tar.gz
- Upload date:
- Size: 289.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be0f13c0ec7e509df6defd6dc61e189ed58020b530681407c3b87e52e3dcf13d
|
|
| MD5 |
f2342c3272fb15177d7d70e6dffb6065
|
|
| BLAKE2b-256 |
4201b0030925d6b982b6c7e0f70b322795a51a9de8e8cf13f2ca157bc494fb5b
|
Provenance
The following attestation bundles were made for ipso-0.1.3.tar.gz:
Publisher:
ipso-publish.yaml on susu-dot-dev/ipso
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipso-0.1.3.tar.gz -
Subject digest:
be0f13c0ec7e509df6defd6dc61e189ed58020b530681407c3b87e52e3dcf13d - Sigstore transparency entry: 1175930365
- Sigstore integration time:
-
Permalink:
susu-dot-dev/ipso@14464a0b57d5dadde22d7bed82268db99dc2623c -
Branch / Tag:
refs/tags/ipso/v0.1.3 - Owner: https://github.com/susu-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ipso-publish.yaml@14464a0b57d5dadde22d7bed82268db99dc2623c -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipso-0.1.3-py3-none-win_amd64.whl.
File metadata
- Download URL: ipso-0.1.3-py3-none-win_amd64.whl
- Upload date:
- Size: 3.2 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
763eaae31603bf75b92d07f3795a5ad41dccbc184510ed573642e3c42b7dca22
|
|
| MD5 |
047310d38aa643b97a384b06a8a3b1db
|
|
| BLAKE2b-256 |
d89a4d2a7958762bff121f3add3ccf674ae35c524e1ee12eec255b3ecb195cff
|
Provenance
The following attestation bundles were made for ipso-0.1.3-py3-none-win_amd64.whl:
Publisher:
ipso-publish.yaml on susu-dot-dev/ipso
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipso-0.1.3-py3-none-win_amd64.whl -
Subject digest:
763eaae31603bf75b92d07f3795a5ad41dccbc184510ed573642e3c42b7dca22 - Sigstore transparency entry: 1175930888
- Sigstore integration time:
-
Permalink:
susu-dot-dev/ipso@14464a0b57d5dadde22d7bed82268db99dc2623c -
Branch / Tag:
refs/tags/ipso/v0.1.3 - Owner: https://github.com/susu-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ipso-publish.yaml@14464a0b57d5dadde22d7bed82268db99dc2623c -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipso-0.1.3-py3-none-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: ipso-0.1.3-py3-none-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 3.7 MB
- Tags: Python 3, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c16c6c1761da9080f4ad0eeea90cf1eff66d60754546cad69c5da5fb1a01a345
|
|
| MD5 |
454a8483076b027ed4c53cb810d3bb49
|
|
| BLAKE2b-256 |
809a8a5c889be424ff73903fb74427e2ba176afc15722fce72ebf9fbbe68ed23
|
Provenance
The following attestation bundles were made for ipso-0.1.3-py3-none-manylinux_2_39_x86_64.whl:
Publisher:
ipso-publish.yaml on susu-dot-dev/ipso
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipso-0.1.3-py3-none-manylinux_2_39_x86_64.whl -
Subject digest:
c16c6c1761da9080f4ad0eeea90cf1eff66d60754546cad69c5da5fb1a01a345 - Sigstore transparency entry: 1175930505
- Sigstore integration time:
-
Permalink:
susu-dot-dev/ipso@14464a0b57d5dadde22d7bed82268db99dc2623c -
Branch / Tag:
refs/tags/ipso/v0.1.3 - Owner: https://github.com/susu-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ipso-publish.yaml@14464a0b57d5dadde22d7bed82268db99dc2623c -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipso-0.1.3-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: ipso-0.1.3-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.4 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b225b8154dd7340bbe8d683f557826a86989486c16f2773eea28ff4048c7be3f
|
|
| MD5 |
858d9da49ef545bbcdfaa554bfb47451
|
|
| BLAKE2b-256 |
0428cf3d78d8da98ab6a2bccbf1a8d5c31d6b4cb6502c8e5ba70a9c994bd4940
|
Provenance
The following attestation bundles were made for ipso-0.1.3-py3-none-macosx_11_0_arm64.whl:
Publisher:
ipso-publish.yaml on susu-dot-dev/ipso
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipso-0.1.3-py3-none-macosx_11_0_arm64.whl -
Subject digest:
b225b8154dd7340bbe8d683f557826a86989486c16f2773eea28ff4048c7be3f - Sigstore transparency entry: 1175930752
- Sigstore integration time:
-
Permalink:
susu-dot-dev/ipso@14464a0b57d5dadde22d7bed82268db99dc2623c -
Branch / Tag:
refs/tags/ipso/v0.1.3 - Owner: https://github.com/susu-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ipso-publish.yaml@14464a0b57d5dadde22d7bed82268db99dc2623c -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipso-0.1.3-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ipso-0.1.3-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.5 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37e481e8f9f4334e6c2f97f3ff05638a3d796103ef8c256572edff14b1a60feb
|
|
| MD5 |
a1dfeb7556ed1a358c9e92ca5b5109d5
|
|
| BLAKE2b-256 |
d124a3f1a5765b9f2d38f80b2cebd730a2ee4168b6f20de1d6280271344555bd
|
Provenance
The following attestation bundles were made for ipso-0.1.3-py3-none-macosx_10_12_x86_64.whl:
Publisher:
ipso-publish.yaml on susu-dot-dev/ipso
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipso-0.1.3-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
37e481e8f9f4334e6c2f97f3ff05638a3d796103ef8c256572edff14b1a60feb - Sigstore transparency entry: 1175930614
- Sigstore integration time:
-
Permalink:
susu-dot-dev/ipso@14464a0b57d5dadde22d7bed82268db99dc2623c -
Branch / Tag:
refs/tags/ipso/v0.1.3 - Owner: https://github.com/susu-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ipso-publish.yaml@14464a0b57d5dadde22d7bed82268db99dc2623c -
Trigger Event:
push
-
Statement type: