Skip to content

API Reference

juplit

juplit.tasks

Core notebook workflow tasks for juplit.

These functions back both the poe task targets and the juplit CLI commands. They can also be imported and called directly from Python.

sync_notebooks()

Sync .py and .ipynb files for all paired percent-format notebooks.

Walks the configured notebook_src_dirs (from [tool.juplit] in pyproject.toml) and calls jupytext --sync on every .py file that has a jupytext percent-format header pairing it with an .ipynb.

Prints a summary of updated, unchanged, and skipped files. Raises SystemExit(1) if jupytext reports any errors.

Source code in juplit/tasks.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
def sync_notebooks() -> None:
    """Sync `.py` and `.ipynb` files for all paired percent-format notebooks.

    Walks the configured `notebook_src_dirs` (from `[tool.juplit]` in
    `pyproject.toml`) and calls `jupytext --sync` on every `.py` file that has
    a jupytext percent-format header pairing it with an `.ipynb`.

    Prints a summary of updated, unchanged, and skipped files.
    Raises `SystemExit(1)` if jupytext reports any errors.
    """
    files = _find_percent_notebook_py_files()
    if not files:
        print("No percent notebook .py files found.")
        return

    groups, errors = _run_jupytext(["--sync"], files)
    if groups["updated"]:
        print(_fmt("sync updated", groups["updated"]))
    if groups["unchanged"]:
        print(_fmt("sync unchanged", groups["unchanged"]))
    if groups["skipped"]:
        print(_fmt("sync skipped (not paired)", groups["skipped"]))
    if not any(groups.values()):
        print("Sync: nothing to do")
    for err in errors:
        print(f"sync error: {err}")
    if errors:
        raise SystemExit(1)

generate_notebooks()

Generate .ipynb files from .py percent-format files.

Calls jupytext --to notebook on every paired .py file found in the configured notebook_src_dirs. Use this after cloning a repo where only the .py sources are committed.

Prints a summary of created/updated, unchanged, and skipped files. Raises SystemExit(1) if jupytext reports any errors.

Source code in juplit/tasks.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def generate_notebooks() -> None:
    """Generate `.ipynb` files from `.py` percent-format files.

    Calls `jupytext --to notebook` on every paired `.py` file found in the
    configured `notebook_src_dirs`. Use this after cloning a repo where only
    the `.py` sources are committed.

    Prints a summary of created/updated, unchanged, and skipped files.
    Raises `SystemExit(1)` if jupytext reports any errors.
    """
    files = _find_percent_notebook_py_files()
    if not files:
        print("No percent notebook .py files found.")
        return

    groups, errors = _run_jupytext(["--to", "notebook"], files)
    if groups["updated"]:
        print(_fmt("nb created/updated", groups["updated"]))
    if groups["unchanged"]:
        print(_fmt("nb unchanged", groups["unchanged"]))
    if groups["skipped"]:
        print(_fmt("nb skipped", groups["skipped"]))
    if not any(groups.values()):
        print("Notebooks: nothing to do")
    for err in errors:
        print(f"nb error: {err}")
    if errors:
        raise SystemExit(1)

clean_notebooks()

Sync then delete all .ipynb files from the source directories.

First calls sync_notebooks() to flush any unsaved changes from the .ipynb files back into their paired .py sources, then removes every .ipynb found under notebook_src_dirs. Keeps the working directory clean for AI agents and CI environments that only need the .py sources.

Prints a summary of removed files.

Source code in juplit/tasks.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def clean_notebooks() -> None:
    """Sync then delete all `.ipynb` files from the source directories.

    First calls `sync_notebooks()` to flush any unsaved changes from the
    `.ipynb` files back into their paired `.py` sources, then removes every
    `.ipynb` found under `notebook_src_dirs`. Keeps the working directory
    clean for AI agents and CI environments that only need the `.py` sources.

    Prints a summary of removed files.
    """
    sync_notebooks()
    removed = []
    for src_dir in _get_src_dirs():
        for f in src_dir.rglob("*.ipynb"):
            removed.append(f.name)
            f.unlink()
    if removed:
        print(_fmt("clean removed", sorted(removed)))
    else:
        print("clean: nothing to remove")

juplit.testing

test() helper — separates exportable logic from inline tests.

test()

Return True when the calling module is run directly or under pytest.

Use this to gate test code in percent-format notebook files so that tests run interactively (in Jupyter) and under pytest, but never on import.

Example::

# %%
from juplit import test

# %%
def add(a, b):
    return a + b

# %%
if test():
    assert add(1, 2) == 3
Source code in juplit/testing.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def test() -> bool:
    """Return True when the calling module is run directly or under pytest.

    Use this to gate test code in percent-format notebook files so that tests
    run interactively (in Jupyter) and under pytest, but never on import.

    Example::

        # %%
        from juplit import test

        # %%
        def add(a, b):
            return a + b

        # %%
        if test():
            assert add(1, 2) == 3
    """
    frame = sys._getframe(1)
    caller_name = frame.f_globals.get("__name__", "")
    return caller_name == "__main__" or "pytest" in sys.modules