Cython compilation support for marimo notebooks
Project description
marimo-cython
Cython compilation support for marimo notebooks. Write Cython-accelerated functions directly in notebook cells and run them at native speed — no build system boilerplate required.
This is the marimo equivalent of Jupyter's %%cython magic, redesigned for marimo's reactive DAG model.
Installation
Requires Python 3.10+.
uv add marimo-cython
Or with pip:
pip install marimo-cython
Runtime dependencies: cython>=3.0 and setuptools (for C extension building).
Quick start
import cython
from marimo_cython import cy
@cy.compile
def fib(n: cython.int) -> cython.int:
a: cython.int = 0
b: cython.int = 1
i: cython.int
for i in range(n):
a, b = b, a + b
return a
fib(50) # runs compiled native code
API
Three entry points, all available via cy.* or as direct imports from marimo_cython:
@cy.compile — decorator
Compiles a pure-Python Cython function. The function must use Cython's pure Python syntax (cython.int, cython.double, typed memoryviews, etc.).
@cy.compile
def fib(n: cython.int) -> cython.int:
a: cython.int = 0
b: cython.int = 1
i: cython.int
for i in range(n):
a, b = b, a + b
return a
With options:
@cy.compile(boundscheck=False, wraparound=False, cdivision=True)
def mandelbrot(
out: cython.int[:, :],
xmin: cython.double,
xmax: cython.double,
ymin: cython.double,
ymax: cython.double,
max_iter: cython.int,
) -> None:
rows: cython.Py_ssize_t = out.shape[0]
cols: cython.Py_ssize_t = out.shape[1]
# ...
Using C library functions
To call C library functions (like sqrt, fabs, etc.) from a decorated function, use from cython.cimports.* at cell/module level above the function. Cython provides runtime Python stubs for these, so they are valid Python imports:
from cython.cimports.libc.math import sqrt, fabs
@cy.compile(boundscheck=False)
def fast_sqrt(x: cython.double) -> cython.double:
return sqrt(fabs(x))
The decorator automatically picks up from cython.cimports.* imports written above the function in the same cell or file, and includes them in the compiled module.
As a fallback, the cimports parameter accepts raw cimport strings (which use Cython syntax, not valid Python):
@cy.compile(cimports=["from libc.math cimport sqrt, fabs"])
def fast_sqrt(x: cython.double) -> cython.double:
return sqrt(fabs(x))
cy.compile_module(source) — compile a string
Compiles a Cython source string into a module. Supports full .pyx syntax including cdef, cimport, and typed function signatures.
mod = cy.compile_module("""
from libc.math cimport sqrt
def norm(double[:] v):
cdef Py_ssize_t i
cdef double s = 0.0
for i in range(v.shape[0]):
s += v[i] * v[i]
return sqrt(s)
""", boundscheck=False, wraparound=False)
mod.norm(np.array([3.0, 4.0])) # => 5.0
cy.compile_file(path) — compile a .pyx file
mod = cy.compile_file("solver.pyx", cplus=True, libraries=["lapack"])
mod.solve(matrix)
cy.clear_cache() — remove compiled artifacts
cy.clear_cache() # removes .marimo_cython_cache/ and all contents
cy.clear_cache(cache_dir="custom_cache/") # custom cache directory
Returns the number of files removed.
Compile options
All three entry points accept the same keyword arguments. These map to the CompileOptions dataclass:
C/C++ compilation
| Option | Type | Default | Description |
|---|---|---|---|
cplus |
bool |
False |
Compile as C++ instead of C |
compile_args |
list[str] |
[] |
Extra compiler flags (e.g. ["-O3", "-march=native"]) |
link_args |
list[str] |
[] |
Extra linker flags |
libraries |
list[str] |
[] |
Libraries to link against |
include_dirs |
list[str] |
[] |
Additional include directories |
library_dirs |
list[str] |
[] |
Additional library directories |
runtime_library_dirs |
list[str] |
[] |
Runtime library search paths |
define_macros |
list[tuple] |
[] |
Preprocessor macros |
undef_macros |
list[str] |
[] |
Macros to undefine |
extra_objects |
list[str] |
[] |
Extra object files to link |
Cython compiler directives
| Option | Type | Default | Description |
|---|---|---|---|
boundscheck |
bool |
None |
Array bounds checking |
wraparound |
bool |
None |
Negative indexing support |
cdivision |
bool |
None |
C-style division (no zero-division check) |
nonecheck |
bool |
None |
Check for None on extension types |
initializedcheck |
bool |
None |
Check memoryview initialization |
overflowcheck |
bool |
None |
Integer overflow checking |
infer_types |
bool |
None |
Automatic type inference |
profile |
bool |
None |
Enable profiling hooks |
linetrace |
bool |
None |
Enable line tracing |
embedsignature |
bool |
None |
Embed function signatures in docstrings |
emit_code_comments |
bool |
None |
Emit source comments in generated C |
freethreading_compatible |
bool |
None |
Mark as free-threading compatible |
language_level |
int|str |
3 |
Cython language level |
compiler_directives |
dict |
{} |
Catch-all for any Cython directive |
None means "use Cython's default". Set to True/False to override.
Other options
| Option | Type | Default | Description |
|---|---|---|---|
module_name |
str |
auto | Name for the compiled module |
cimports |
list[str]|str |
[] |
Fallback: raw cimport statements (for @cy.compile) |
annotate |
bool|str |
False |
Generate Cython annotation HTML |
nthreads |
int |
0 |
Parallel cythonization threads |
force |
bool |
False |
Force recompilation (ignore cache) |
cache_dir |
str|Path |
.marimo_cython_cache/ |
Build artifact directory |
How it works
- Source is extracted (via
inspect.getsourceor marimo's runtime context) import cythonis auto-prepended if missing (detected via AST, not regex)from cython.cimports.*imports above the function are collected via AST and included- A content-addressed cache key is computed (SHA-256 of source + all options + Python/Cython versions)
- On cache miss: write
.pyx-> cythonize to.c-> compile to.sovia setuptools -> load withimportlib - On cache hit: load the existing
.sodirectly - Intermediate build artifacts (
.c,.cpp, temp dirs) are cleaned up after successful compilation
Compiled artifacts live in .marimo_cython_cache/ (add to .gitignore). Numpy includes are auto-detected if the source references numpy.
Annotations
Compile with annotate=True to get Cython's annotation HTML rendered in marimo cell output:
mod = cy.compile_module(source, annotate=True)
mod # displays annotation HTML in marimo
Cross-cell interaction
Compiled modules and functions work across marimo cells like any other Python object. Define a module in one cell and call its functions from another:
# Cell 1
linalg = cy.compile_module("""
from libc.math cimport sqrt
def norm(double[:] v):
...
""")
# Cell 2 — uses linalg from Cell 1
result = linalg.norm(my_array)
Running the demos
uv sync --extra dev
uv run marimo edit demo.py
The demo covers the core API: fibonacci benchmark, cimport patterns, compile_module, and cross-cell interaction.
Examples
The examples/ directory contains standalone notebooks:
examples/mandelbrot.py— Interactive Mandelbrot set with a resolution slider. Runs Cython and Python side-by-side with progressive rendering (Cython result appears instantly, Python fills in when done). PEP 723 compatible — run withuv run --sandbox examples/mandelbrot.py.
uv sync --extra dev
uv run marimo run examples/mandelbrot.py
Development
uv sync --extra dev
uv run ruff check src/
uv run pytest
License
MIT
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 marimo_cython-0.1.0.tar.gz.
File metadata
- Download URL: marimo_cython-0.1.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1db9745090558a124878b75ba268f1a15d6a782b029483fa735e68f5d1bb0490
|
|
| MD5 |
2eb28d1d88fbf85756098c643868b1d4
|
|
| BLAKE2b-256 |
f52b039d31f832963ed8460d66a9cdd7e253ab5ed37ae3e9795c736d96ec71b8
|
Provenance
The following attestation bundles were made for marimo_cython-0.1.0.tar.gz:
Publisher:
publish.yml on cemrehancavdar/marimo-cython
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimo_cython-0.1.0.tar.gz -
Subject digest:
1db9745090558a124878b75ba268f1a15d6a782b029483fa735e68f5d1bb0490 - Sigstore transparency entry: 983381001
- Sigstore integration time:
-
Permalink:
cemrehancavdar/marimo-cython@0caa974e908fa7e27a16515d84c4dbe1029cb1f5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cemrehancavdar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0caa974e908fa7e27a16515d84c4dbe1029cb1f5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file marimo_cython-0.1.0-py3-none-any.whl.
File metadata
- Download URL: marimo_cython-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.5 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 |
9c10939c8373b02243d3d48771f9491c8fa4fa20855290ebb9609d88297f3b60
|
|
| MD5 |
6ac489d42530dae67ffc7e49d2a5f684
|
|
| BLAKE2b-256 |
89447f1c2d79b22fecbc812d8da4ec66aab4d7ad18ca48e1bee3e71ff6a25af8
|
Provenance
The following attestation bundles were made for marimo_cython-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on cemrehancavdar/marimo-cython
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimo_cython-0.1.0-py3-none-any.whl -
Subject digest:
9c10939c8373b02243d3d48771f9491c8fa4fa20855290ebb9609d88297f3b60 - Sigstore transparency entry: 983381003
- Sigstore integration time:
-
Permalink:
cemrehancavdar/marimo-cython@0caa974e908fa7e27a16515d84c4dbe1029cb1f5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cemrehancavdar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0caa974e908fa7e27a16515d84c4dbe1029cb1f5 -
Trigger Event:
release
-
Statement type: