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 tomllibConverting 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.
_preview = []
root = demo_path("05_convert_example")
try:
root.mkdir()
src = root / "calc.py"
finally:
remove_demo_path(root)
_previewSlicing 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.
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.