Run q through ordinary IPython and Jupyter kernels with portable KX results
Project description
kx-notebook
kx-notebook lets a normal Python/IPython/Jupyter kernel execute q and publish
portable, bounded notebook output. Direct q IPC is built in; PyKX is optional.
The rich result MIME type is application/vnd.kx.result+json, matching the
contract already consumed by
dreth/vscode-kdb. Every rich result also
has escaped text/html and text/plain fallbacks, so saved notebooks remain
readable without a custom renderer.
This is the source for version 0.1.0. The installation below intentionally uses a source checkout; do not assume PyPI availability until a release is published.
Install from a checkout
Python 3.9 through 3.13 is supported. Install into the same environment as the IPython or Jupyter kernel that will run q cells:
git clone https://github.com/dreth/kx-notebook.git
cd kx-notebook
# uv
uv venv
uv pip install .
# or pip in an already activated environment
python -m pip install .
PyKX and keyring integrations are opt-in:
uv pip install '.[pykx]'
uv pip install '.[keyring]'
The direct IPC path does not import or require PyKX. KX q itself is not bundled; you need access to a q process and must comply with the applicable KX license.
Five-minute quickstart
Start a local q process on port 5000 in one terminal:
q -p 5000
Then start IPython or a Python-backed Jupyter kernel:
%load_ext kx_notebook
%kx connect localhost:5000
Run a cell through the ordinary Run/Shift+Enter lifecycle:
%%q
([] sym:`AAPL`MSFT; price:224.1 442.8)
Useful management commands are:
%kx status
%kx profiles
%kx use PROFILE
%kx disconnect
%kx help
Per-cell overrides are explicit:
%%q --profile local --max-rows 100 --max-bytes 524288 --timeout 5 --label "quote preview"
select from quote
The profile selects the evaluator for that cell; the label is display metadata. Credentials are never copied into the result.
Before display, all three fully serialized MIME representations are checked
against the active direct password or broker token. If serialization itself
would reconstruct a runtime credential across values or schema boundaries, the
entire output is discarded and replaced with a content-free omission notice.
If even fixed contract text matches the credential, display is suppressed.
The %%q lifecycle wires this automatically; an embedder calling
display_result directly should pass its evaluator's redact_text method.
Direct IPC
Direct IPC performs the q authentication handshake and synchronous request over a TCP socket. It decodes common q atoms, vectors, dictionaries, keyed and unkeyed tables, temporal values, symbols, strings, and nulls, and surfaces q errors normally. Values outside the supported decoder are represented as bounded q text when a safe representation is available; the package does not invent a Python value.
Timeout or local cancellation closes the client socket. That stops waiting in the notebook, but it cannot guarantee that an already-running server-side q calculation was interrupted. One connection handles one synchronous request at a time; requests are not multiplexed. The timeout covers response I/O, decompression, and cooperative decoding. An operating-system DNS lookup or TCP connect call cannot always be interrupted immediately by another thread.
TLS transport is not implemented in 0.1.0. Use a trusted local/private network or a separately managed secure tunnel; do not expose an unauthenticated q port to an untrusted network.
Profiles and credentials
Profiles are strict TOML records stored in the platform-appropriate user config directory. They contain kind-specific connection metadata and secret lookup names only. Unknown fields and invalid types are rejected.
Find, validate, and list the effective configuration with:
kx-notebook config path
kx-notebook config validate
kx-notebook config profiles
KX_NOTEBOOK_CONFIG may point at a different TOML file for an isolated
environment.
A direct profile looks like this:
default_profile = "local"
[profiles.local]
kind = "direct"
host = "127.0.0.1"
port = 5000
username = "analyst"
password_env = "KX_NOTEBOOK_LOCAL_PASSWORD"
connect_timeout = 5.0
query_timeout = 30.0
max_receive_bytes = 67108864
username, password_env, and timeout fields are optional. kind must match
an implemented evaluator; TLS fields are rejected because 0.1.0 does not
implement TLS. max_receive_bytes may lower the direct decoder cap; 64 MiB is
the package maximum.
Do not put a password, broker bearer token, or other secret in the TOML file.
Passwords can be supplied to the Python API for the current process, resolved
through the profile's named environment variable, or read from a system
keyring when the keyring extra is installed. Runtime secrets are never
written back to the profile file.
For a one-off direct connection, the equivalent magic is:
%kx connect localhost:5000 --username analyst --password-env KX_NOTEBOOK_LOCAL_PASSWORD --connect-timeout 5 --query-timeout 30
Avoid entering a password directly in a notebook cell: notebook source and shell/IPython history are outside this package's output redaction boundary. Prefer a named environment variable, a system keyring, or a secure host application that passes an explicit runtime value.
Evaluator modes
Direct IPC is the default standalone evaluator. Three explicit alternatives are available:
- Callback: embed
kx-notebookaround a synchronous application-owned evaluator. The callback owns execution;kx-notebookowns bounded display. - PyKX: install the
pykxextra and select the adapter explicitly. PyKX is imported only then, and its own licensing/configuration requirements apply. Tables/keyed tables are bounded before Python conversion; vectors and dictionaries use bounded q-text previews. - Local broker HTTP: supply the broker URL and bearer token at runtime. The
adapter defines an authenticated request/response boundary for future
vscode-kdbintegration; it does not discover a broker or persist its token. Version 0.1.0 accepts loopback broker URLs only and rejects redirects and ambient HTTP proxies.
Configure an application-owned callback directly:
from kx_notebook import configure_evaluator
configure_evaluator(my_synchronous_q_callback, label="application q session")
Select PyKX explicitly (this is the point where the optional dependency may be imported):
from kx_notebook import configure_evaluator
from kx_notebook.evaluators import PyKXEvaluator
configure_evaluator(PyKXEvaluator())
Or construct the broker adapter with runtime values:
import os
from kx_notebook import configure_evaluator
from kx_notebook.evaluators import BrokerEvaluator
configure_evaluator(
BrokerEvaluator(
os.environ["KX_NOTEBOOK_BROKER_URL"],
os.environ["KX_NOTEBOOK_BROKER_TOKEN"],
)
)
A broker profile may persist only non-secret lookup metadata:
[profiles.local_broker]
kind = "broker"
base_url = "http://127.0.0.1:8765"
token_env = "KX_NOTEBOOK_BROKER_TOKEN"
timeout = 10.0
The bearer token is read from the named environment variable at runtime. The package does not bundle or launch a broker.
See Architecture for trust boundaries and the evaluator contract.
Optional IPython startup hook
Loading the extension in a notebook is explicit and requires no installation hook. If you want one IPython profile to load it automatically, inspect the planned change first:
kx-notebook install --profile default --dry-run
kx-notebook install --profile default
kx-notebook status --profile default
kx-notebook uninstall --profile default --dry-run
kx-notebook uninstall --profile default
Install and uninstall are idempotent and affect only the selected IPython
profile. kx-notebook never silently modifies every Python or Jupyter
environment.
Portable result contract
Contract version 1 persists either a table preview or bounded qText.
Table output records the declared total row count, persisted preview row count,
row/byte limits, and truncation reasons. A preview is never described as the
full result. Cell values use explicit portable kinds including temporal,
bigint, null, and JSON; symbols are losslessly displayed as string cells.
The package emits:
application/vnd.kx.result+jsonfor a compatible renderer;- self-contained, escaped
text/htmlwith no network-loaded assets; and text/plainfor terminals and basic notebook viewers.
Default output is limited to a 20-row preview and 1,000,000 total MIME bytes. Raise limits only for results that are safe to embed permanently in a notebook. A notebook file is not a secret store.
Static chart metadata can accompany compatible table results. Renderers may offer richer interaction, but saved output contains only the bounded preview, not a hidden live-result handle.
Jupyter and Dev Containers
Install the package into the environment backing the selected kernel, then use
%load_ext kx_notebook. Installing only the console command in another virtual
environment will not make the extension importable by that kernel.
No repository-specific Dev Container is shipped in 0.1.0. In an existing Dev
Container, install Python 3.9–3.13 plus uv, run
uv sync --all-extras --group dev --locked,
and ensure the container can reach the intended q host. Keep credentials in the
container's secret/environment facility, not in the image or repository.
Troubleshooting
ModuleNotFoundError: kx_notebook
The notebook is using a different Python environment. In the notebook, inspect
sys.executable, then install kx-notebook into that interpreter's environment.
%kx connect cannot reach q
Check host/port, q's -p setting, container/VM networking, and authentication.
The direct connection is TCP, not HTTP.
A q query timed out
The local socket is closed. Treat the server-side calculation as potentially still running and inspect q before retrying an expensive query.
A value appears as qText
The IPC decoder did not have a lossless portable representation for that value, or a configured output bound was reached. The bounded text is intentional.
Keyring lookup fails in a headless container
Install and configure a supported OS keyring backend, or use a named environment variable for that runtime instead.
Current limitations
- Direct IPC is synchronous and supports a documented subset of q IPC values.
- TLS, asynchronous q messages, and server-side query cancellation are not implemented.
- Local cancellation cannot preempt every operating-system DNS/connect call; connect deadlines are still enforced when that call returns.
- Persisted results are bounded previews; there is no promise that a full result can be reopened after the source session ends.
- The HTTP broker adapter is a client-side contract, not a bundled broker or
automatic
vscode-kdbbridge. - PyKX is optional, separately distributed, and never used implicitly.
- Configuration and IPython profile directories are local trust boundaries: keep them owned and writable only by the account running the kernel. Profile metadata can select an endpoint and name a credential environment variable.
Development and release checks are in CONTRIBUTING.md.
License
MIT. See LICENSE.
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 kx_notebook-0.1.0.tar.gz.
File metadata
- Download URL: kx_notebook-0.1.0.tar.gz
- Upload date:
- Size: 75.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07035130f00725b61833b261517f26f532cdf30f2735d730f5972358f440ff1a
|
|
| MD5 |
a3221356ea5cb5943e67f3444637ed54
|
|
| BLAKE2b-256 |
b5b56d33bbfba715432e93eccae4e1cf4f011c3c5b8672ebf1a3f2f0c97eb1fd
|
Provenance
The following attestation bundles were made for kx_notebook-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on dreth/kx-notebook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kx_notebook-0.1.0.tar.gz -
Subject digest:
07035130f00725b61833b261517f26f532cdf30f2735d730f5972358f440ff1a - Sigstore transparency entry: 2257379668
- Sigstore integration time:
-
Permalink:
dreth/kx-notebook@a5305ade0fa57b052f3eab1f2f91e12328a7ddc4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dreth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a5305ade0fa57b052f3eab1f2f91e12328a7ddc4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kx_notebook-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kx_notebook-0.1.0-py3-none-any.whl
- Upload date:
- Size: 52.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
083f313640d6ace36741a14f308aeefef378161b82b429793c106a85622085ef
|
|
| MD5 |
e787e514711317e6c1cbde7a8f46e7c8
|
|
| BLAKE2b-256 |
ac3d2ffd810309799d17d30ab338319fdd7d518164ae0674102cb79207404f32
|
Provenance
The following attestation bundles were made for kx_notebook-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on dreth/kx-notebook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kx_notebook-0.1.0-py3-none-any.whl -
Subject digest:
083f313640d6ace36741a14f308aeefef378161b82b429793c106a85622085ef - Sigstore transparency entry: 2257379694
- Sigstore integration time:
-
Permalink:
dreth/kx-notebook@a5305ade0fa57b052f3eab1f2f91e12328a7ddc4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dreth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a5305ade0fa57b052f3eab1f2f91e12328a7ddc4 -
Trigger Event:
release
-
Statement type: