A small, readable, Python-only Jupyter kernel with strong IPython parity.
Project description
ipymini
ipymini is a Python-only Jupyter kernel for Python with a small, readable codebase and strong IPython parity.
The design goal is: a small, readable, testable kernel with first‑class IPython behavior.
This was almost entirely implemented by AI, closely referencing the ipykernel, xeus, xeus-python, and jupyter_kernel_test projects during development. So all credit for this project belongs to the authors of those packages, and to authors of the excellent documentation and specifications referred to (e.g DAP spec; JEPs; etc).
What we’ve aimed to do
- Implement a full Jupyter kernel in pure Python.
- Match
ipykernelbehavior where it matters (IOPub ordering, message shapes, history, inspect, etc.). - Use IPython instead of re‑implementing Python semantics.
- Expand protocol‑level tests (IOPub, interrupts, completions, etc.) to approach upstream parity.
Repository layout
ipymini/kernel.py: kernel loop + Jupyter protocol handling (ZMQ)bridge.py: IPython integration (execute, display, history, comms, debug)__main__.py: CLI entry (python -m ipymini -f <connection_file>)
ipymini_bridge.py: comm manager surface for testspytests/: protocol + behavior testsshare/jupyter/kernels/ipymini/kernel.json: kernel spec
Requirements
Python / Jupyter
- Python 3.11+ recommended (we test with 3.12)
jupyter_client,jupyter_core,ipython,pyzmqpytestif running testsipykernelis a test-only dependency (used by some e2e/debug harnesses)
ZMQ
pyzmq bundles or links against libzmq. If you need to install system libs on MacOS:
brew install libzmq
Install (editable)
From the repo root:
pip install -e .
Optional test deps:
pip install -e ".[test]"
Installing the kernel spec
You have a few options:
Option A: Use the built-in installer
python -m ipymini install --user
Or install into the current environment:
python -m ipymini install --sys-prefix
After either option, you should see it in:
jupyter kernelspec list
Option B: Install the spec into your user Jupyter dir
jupyter kernelspec install --user /path/to/ipymini/share/jupyter/kernels/ipymini
Option C: Use the repo’s JUPYTER_PATH
Set JUPYTER_PATH to include the repo’s share/jupyter:
export JUPYTER_PATH=/path/to/ipymini/share/jupyter:$JUPYTER_PATH
Running manually
ipymini is a normal Jupyter kernel executable. It expects a connection file:
python -m ipymini -f /path/to/connection.json
(When run via Jupyter, that file is created and passed automatically.)
Configuring env and working directory
For per-launch configuration, rely on the kernel launcher:
- KernelManager: pass
envandcwdtostart_kernel(...). - Kernelspec: add an
"env"dict toshare/jupyter/kernels/ipymini/kernel.jsonfor static defaults.
Example (KernelManager):
from jupyter_client import KernelManager
km = KernelManager(kernel_name="ipymini")
km.start_kernel(env={"MY_FLAG": "1"}, cwd="/path/to/workdir")
Tests
All tests must pass before changes are considered complete:
pytest -q
Note: e2e tests launch the kernel via jupyter_client.KernelManager in a separate process; make sure the kernelspec is discoverable (see JUPYTER_PATH above).
Note: debugger breakpoint-stop tests are enabled and pass; the kernel forces PYDEVD_USE_SYS_MONITORING=0 to avoid sys.monitoring stalls (see DEVLOG.md).
PRs and releases
Create a PR (GitHub CLI required):
tools/pr.sh [label] ["Message"]
Release flow (tags trigger GitHub Actions publish):
tools/release.sh [patch|minor|major]
Initial PyPI permission setup (one-time):
hatch build
twine upload dist/*
After the initial manual release, bump the version before running the release script.
Behavior implemented so far
kernel_inforepliesconnect_requestreplies- stdout/stderr stream messages
execute_resultdisplay_data+update_display_dataclear_output- comms (open/msg/close/info)
- history (tail/search/range)
- inspect
is_complete- completion (IPython-based; can use Jedi and the experimental completion API)
- interrupts (signal‑based)
stop_on_error(aborts queued execute requests by default)- stdin input requests
- kernel subshells (create/list/delete; concurrent shell handling; per‑subshell execution counts/history)
- pager payloads (
?/help) set_next_inputpayloads (coalesced to one per execute)iopub_welcome(XPUB)debug_request(debugpy in-process adapter: initialize/attach/evaluate, breakpoints, stackTrace/scopes/variables, continue)
Design notes
- The parent subshell runs on the main thread; shell/control I/O live on background threads.
- Interrupts use the kernelspec
interrupt_mode = signal; SIGINT is handled by the kernel to interrupt active execution without killing the kernel when idle. set_next_inputis injected onto the IPython shell to emit the expected payloads.stop_on_erroraborts queued execute requests only; non-execute requests still return replies.- Subshells run in per‑subshell threads with a shared user namespace and thread‑local IO routing.
- IOPub forwards
buffersfor display and comm messages when provided; comm handlers also accept binary buffers. - Interrupts while blocked on input cancel pending input waits and surface
KeyboardInterrupt.
Style notes (fastcore)
- Prefer
store_attr()with no args when storing all params (exceptself). - If most params are stored and only a few are excluded, use
store_attr(but='a,b'). - Pass an explicit list (e.g.
store_attr("a,b")) only when storing a subset of params.
Completion configuration (no traitlets required)
ipymini reads simple environment flags at startup:
IPYMINI_USE_JEDI=0|1(defaults to IPython’s own default)IPYMINI_EXPERIMENTAL_COMPLETIONS=0|1(default: enabled if IPython supports it)
Where to start reading
ipymini/kernel.py– message loop + protocol handlingipymini/bridge.py– IPython integration and output capturepytests/– protocol expectations
Coding style
We follow the fastai style guide (not PEP8). A summary lives in style.md. Key points from the style guide:
- Favor brevity and clarity: aim for one idea per line
- Use single-line
if/defwhen the body is a single statement.
- Use single-line
- Keep code readable at a glance: wrap at ~140 chars and avoid unnecessary vertical whitespace
- e.g., group imports
- Use short, conventional names and align similar statements where it helps scanning.
- Avoid auto-formatters/linters that fight this style.
- Dicts with 3+ identifier keys use
dict(...)instead of{...}. - Repeated request/response plumbing is factored into small helpers
- e.g., subshell send, DAP breakpoint helpers
- No semicolons for chaining; only single-statement bodies are one-liners.
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 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 ipymini-0.1.3.tar.gz.
File metadata
- Download URL: ipymini-0.1.3.tar.gz
- Upload date:
- Size: 43.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad0d6276bf89879f9269dae0611492189a2f4fd81ea949e35a0640159f688172
|
|
| MD5 |
859800b4a1e22a07cd19f8223cc01aa6
|
|
| BLAKE2b-256 |
e234421e4c53737e6835537777ea15fad269d0d02b56bbcceb207ab584903af1
|
Provenance
The following attestation bundles were made for ipymini-0.1.3.tar.gz:
Publisher:
release.yml on AnswerDotAI/ipymini
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipymini-0.1.3.tar.gz -
Subject digest:
ad0d6276bf89879f9269dae0611492189a2f4fd81ea949e35a0640159f688172 - Sigstore transparency entry: 849830401
- Sigstore integration time:
-
Permalink:
AnswerDotAI/ipymini@5932e7d502a006f4ad0b224d2ba38350b2fe6b28 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/AnswerDotAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5932e7d502a006f4ad0b224d2ba38350b2fe6b28 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipymini-0.1.3-py3-none-any.whl.
File metadata
- Download URL: ipymini-0.1.3-py3-none-any.whl
- Upload date:
- Size: 26.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 |
bb28ab61b8096e39cffdb2beff933c56b438cb73d073edfa8af976f6af618236
|
|
| MD5 |
826dea1922460c4e00f1488a2aed07da
|
|
| BLAKE2b-256 |
a5c0c07b0fbd1e29898dc92532ae2328418dc4c18c7fe58db30bfb2eab707905
|
Provenance
The following attestation bundles were made for ipymini-0.1.3-py3-none-any.whl:
Publisher:
release.yml on AnswerDotAI/ipymini
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipymini-0.1.3-py3-none-any.whl -
Subject digest:
bb28ab61b8096e39cffdb2beff933c56b438cb73d073edfa8af976f6af618236 - Sigstore transparency entry: 849830402
- Sigstore integration time:
-
Permalink:
AnswerDotAI/ipymini@5932e7d502a006f4ad0b224d2ba38350b2fe6b28 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/AnswerDotAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5932e7d502a006f4ad0b224d2ba38350b2fe6b28 -
Trigger Event:
push
-
Statement type: