Scan nbdev notebooks for exported functions and classes
get_export_cells
def get_export_cells( nb_path:Path, # Path to the notebook file)->List: # List of cells with export directives
Extract all code cells from a notebook that have export directives
extract_definitions
def extract_definitions( source:str, # Python source code)->List: # List of function/class definitions with metadata
Extract function and class definitions from source code
scan_notebook
def scan_notebook( nb_path:Path, # Path to the notebook to scan nbs_root:Optional=None, # Root notebooks directory (for relative paths))->List: # List of exported definitions with metadata
Scan a notebook and extract all exported function/class definitions
scan_project
def scan_project( nbs_path:Optional=None, # Path to notebooks directory (defaults to config.nbs_path) pattern:str='*.ipynb', # Pattern for notebook files to scan)->List: # All exported definitions found in the project
Scan all notebooks in a project for exported definitions
# Test scanning this projectdefinitions = scan_project()print(f"Found {len(definitions)} exported definitions")for defn in definitions[:5]: # Show first 5print(f"- {defn['type']}: {defn['name']} in {defn['notebook']}")
Found 59 exported definitions
- FunctionDef: create_parser in cli.ipynb
- FunctionDef: handle_autofix in cli.ipynb
- FunctionDef: generate_report in cli.ipynb
- FunctionDef: output_report in cli.ipynb
- FunctionDef: main in cli.ipynb
# Test if nested folders would be detectedimport tempfileimport shutilfrom pathlib import Path# Create a temporary directory structure to test nested scanningwith tempfile.TemporaryDirectory() as tmpdir: tmp_path = Path(tmpdir)# Create nested structure (tmp_path /"actions").mkdir() (tmp_path /"data_display").mkdir()# Create dummy notebooks dummy_nb = {"cells": [ {"cell_type": "code", "source": "#| export\ndef test_func(): pass", "id": "cell-1"} ],"metadata": {},"nbformat": 4,"nbformat_minor": 5 }import json# Create notebooks in rootwithopen(tmp_path /"index.ipynb", "w") as f: json.dump(dummy_nb, f)# Create notebooks in subdirectorieswithopen(tmp_path /"actions"/"button.ipynb", "w") as f: json.dump(dummy_nb, f)withopen(tmp_path /"data_display"/"table.ipynb", "w") as f: json.dump(dummy_nb, f)# Test scanningprint("Testing nested folder scanning:") notebooks =list(tmp_path.rglob("*.ipynb"))print(f"Created {len(notebooks)} test notebooks:")for nb insorted(notebooks):print(f" - {nb.relative_to(tmp_path)}")# Test scan_project with nested folders definitions = scan_project(nbs_path=tmp_path)print(f"\nscan_project found {len(definitions)} definitions")for defn in definitions:print(f" - {defn['name']} in {defn['notebook']}")
Testing nested folder scanning:
Created 3 test notebooks:
- actions/button.ipynb
- data_display/table.ipynb
- index.ipynb
scan_project found 3 definitions
- test_func in index.ipynb
- test_func in actions/button.ipynb
- test_func in data_display/table.ipynb