Converting Python into notebooks

Move Python modules into nbdev notebooks while preserving an exportable story.

Conversion is a bridge for projects that began as .py files but want nbdev notebooks as the source of truth. The converter keeps the first pass mechanical: preserve source order, create explicit #| default_exp and #| export cells, and split large classes only when that makes future notebook edits easier.

convert("src/tool.py", mode="notebook", nbs_path="nbs")
convert("src", mode="notebook", nbs_path="nbs", preserve_tree=True)
convert("src", mode="project", dest="./nbdev-app")

Production contract

Conversion is Python-first. convert migrates one Python file, a folder of Python files, or a pure-Python package into an nbdev project. The lower-level helpers preserve source order, create stable nbdev cells and ids, support dry-run/force controls, keep package tree choices explicit, and export generated modules when writing real notebooks.

from contextlib import redirect_stdout
from io import StringIO
from fastcore.nbio import read_nb
from nbskill.convert import py2nb as _example_py2nb
from nbskill.foundation import demo_path, remove_demo_path, write_demo_notebook
from fastcore.test import *
import tomllib
_preview = []
root = demo_path("05_convert_example")
try:
    root.mkdir()
    src = root / "calc.py"
finally:
    remove_demo_path(root)
_preview

Slicing Python source with ast

Conversion starts by finding exact source ranges for imports, functions, classes, and methods. Using ast keeps the conversion structured instead of relying on fragile string searches.

Assembling nbdev cells

The converter writes #| default_exp first, collects imports together, skips existing __all__ declarations, and emits exported cells for the definitions that should become the notebook source.

Public conversion command

convert dispatches by mode. mode="notebook" handles either one Python file or a folder of Python files. mode="project" creates a pragmatic nbdev project from a pure-Python package.


source

convert

def convert(
    path:str, # Python file/folder, or existing Python project/package root
    mode:str='notebook', # notebook for file/folder conversion, project for nbdev project creation
    dest:str | None=None, # Notebook path/output folder for notebook mode; project root for project mode
    nbs_path:str='nbs', # Destination notebooks folder
    recursive:bool=True, # Search subfolders in notebook mode
    maxdepth:int | None=None, # Maximum folder scan depth in notebook mode
    preserve_tree:bool=True, # Preserve package folder structure under nbs_path
    class_lines:int=100, # Split classes larger than this line count
    method_lines:int=10, # Split methods larger than this out of large classes
    package:str | None=None, # Package root name
    include:str | None=None, # Comma-separated include globs
    exclude:str | None=None, # Comma-separated exclude globs
    skip_init:bool=True, # Skip __init__.py files in notebook mode
    include_tests:bool=False, # Include test files in notebook mode
    dry_run:bool=False, # Show planned writes without writing
    force:bool=True, # Overwrite existing notebooks/files
    run_validation:bool=True, # Run nbdev validation in project mode
):

Convert Python sources to nbdev notebooks or a small nbdev project.