# cjm-nbdev-overview
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
## How to use
### Automatic Module Documentation
This project includes functionality to automatically update your
`index.ipynb` with comprehensive module documentation. You can either:
1. **Use the CLI command:**
``` bash
nbdev-overview update-index
```
2. **Use the Python API:**
``` python
from cjm_nbdev_overview.api_docs import update_index_module_docs
update_index_module_docs()
```
This will add a “Module Overview” section to your index.ipynb containing
detailed documentation for all modules in your project.
## Project Structure
nbs/
├── 00_core.ipynb # Core utilities and data models for nbdev project overview generation
├── 01_parsers.ipynb # Parse notebook metadata, content, and extract function/class signatures with docments
├── 02_tree.ipynb # Generate tree visualizations for nbdev project structure
├── 03_api_docs.ipynb # Generate module overviews with formatted signatures for nbdev projects
├── 04_dependencies.ipynb # Analyze cross-notebook imports and generate Mermaid.js dependency diagrams
├── 05_generators.ipynb # Auto-generate folder_name.ipynb notebooks for nbdev project organization
└── 06_cli.ipynb # CLI commands for nbdev project overview generation and analysis
Total: 8 notebooks
## Module Dependencies
``` mermaid
graph LR
core[core<br/>Core Utilities]
parsers[parsers<br/>Notebook and Module Parsing]
tree[tree<br/>Directory Tree Visualization]
api_docs[api_docs<br/>API Documentation Generation]
dependencies[dependencies<br/>Dependency Analysis and Visualization]
generators[generators<br/>Auto-generation Utilities]
cli[cli<br/>Command-Line Interface]
parsers --> core
parsers --> tree
tree --> core
api_docs --> core
api_docs --> parsers
api_docs --> dependencies
api_docs --> tree
dependencies --> core
dependencies --> parsers
generators --> tree
generators --> core
cli --> tree
cli --> api_docs
cli --> parsers
cli --> dependencies
classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px
```
*15 cross-module dependencies detected*
## CLI Reference
### `nbdev-overview` Command
usage: nbdev-overview [-h]
{tree,api,deps,overview,update-index,update-comprehensive}
...
Generate comprehensive overviews for nbdev projects
positional arguments:
{tree,api,deps,overview,update-index,update-comprehensive}
Available commands
tree Generate directory tree visualization
api Generate API documentation
deps Analyze module dependencies
overview Generate complete project overview
update-index Update index.ipynb with module documentation
update-comprehensive
Comprehensive update of index.ipynb with all sections
options:
-h, --help show this help message and exit
For detailed help on any command, use `nbdev-overview <command> --help`.
## Module Overview
Detailed documentation for each module in the project:
### Core Utilities (`00_core.ipynb`)
> Core utilities and data models for nbdev project overview generation
#### Import
``` python
from cjm-nbdev-overview.core import (
NotebookInfo,
DirectoryInfo,
get_notebook_files,
get_subdirectories,
read_notebook,
get_cell_source
)
```
#### Functions
``` python
def get_notebook_files(path: Path = None, # Directory to search (defaults to nbs_path)
recursive: bool = True # Search subdirectories
) -> List[Path]: # List of notebook paths
"Get all notebook files in a directory"
```
``` python
def get_subdirectories(path: Path = None, # Directory to search (defaults to nbs_path)
recursive: bool = False # Include all nested subdirectories
) -> List[Path]: # List of directory paths
"Get subdirectories in a directory"
```
``` python
def read_notebook(path: Path # Path to notebook file
) -> Dict[str, Any]: # Notebook content as dict
"Read a notebook file and return its content"
```
``` python
def get_cell_source(cell: Dict[str, Any] # Notebook cell
) -> str: # Cell source as string
"Get source from a notebook cell"
```
#### Classes
``` python
@dataclass
class NotebookInfo:
"Information about a single notebook"
path: Path # Path to the notebook file
name: str # Notebook filename without extension
title: Optional[str] # H1 title from first cell
description: Optional[str] # Blockquote description from first cell
export_module: Optional[str] # Module name from default_exp
def relative_path(self) -> Path: # Path relative to nbs directory
"Get path relative to nbs directory"
```
``` python
@dataclass
class DirectoryInfo:
"Information about a directory in the nbs folder"
path: Path # Path to the directory
name: str # Directory name
notebook_count: int = 0 # Number of notebooks in directory
description: Optional[str] # Description from folder's main notebook
subdirs: List[DirectoryInfo] = field(...) # Subdirectories
notebooks: List[NotebookInfo] = field(...) # Notebooks in this directory
def total_notebook_count(self) -> int: # Total notebooks including subdirs
"Get total notebook count including subdirectories"
```
### Notebook and Module Parsing (`01_parsers.ipynb`)
> Parse notebook metadata, content, and extract function/class
> signatures with docments
#### Import
``` python
from cjm-nbdev-overview.parsers import (
FunctionInfo,
VariableInfo,
ClassInfo,
ModuleInfo,
extract_docments_signature,
parse_function,
parse_class,
parse_variable,
parse_code_cell,
parse_notebook,
parse_python_file
)
```
#### Functions
``` python
def extract_docments_signature(node: ast.FunctionDef, # AST function node
source_lines: List[str] # Source code lines
) -> str: # Function signature
"Extract function signature with docments-style comments"
```
``` python
def _parse_decorators(node: Union[ast.ClassDef, ast.FunctionDef] # AST node with decorators
) -> List[str]: # List of decorator names
"Parse decorators from an AST node"
```
``` python
def parse_function(node: ast.FunctionDef, # AST function node
source_lines: List[str], # Source code lines
is_exported: bool = False # Has #| export
) -> FunctionInfo: # Function information
"Parse a function definition from AST"
```
``` python
def _parse_class_methods(node: ast.ClassDef, # AST class node
source_lines: List[str], # Source code lines
is_exported: bool = False # Has #| export
) -> List[FunctionInfo]: # List of method information
"Parse methods from a class definition"
```
``` python
def _parse_dataclass_attributes(node: ast.ClassDef, # AST class node
source_lines: List[str], # Source code lines
is_exported: bool = False # Has #| export
) -> List[VariableInfo]: # List of attribute information
"Parse dataclass attributes from a class definition"
```
``` python
def _generate_class_signature(node: ast.ClassDef, # AST class node
methods: List[FunctionInfo] # List of class methods
) -> str: # Class signature
"Generate a class signature including __init__ if present"
```
``` python
def parse_class(node: ast.ClassDef, # AST class node
source_lines: List[str], # Source code lines
is_exported: bool = False # Has #| export
) -> ClassInfo: # Class information
"Parse a class definition from AST"
```
``` python
def parse_variable(node: Union[ast.Assign, ast.AnnAssign], # AST assignment node
source_lines: List[str], # Source code lines
is_exported: bool = False # Has #| export
) -> List[VariableInfo]: # Variable information
"Parse variable assignments from AST"
```
``` python
def parse_code_cell(cell: Dict[str, Any] # Notebook code cell
) -> Tuple[List[FunctionInfo], List[ClassInfo], List[VariableInfo], List[str]]: # TODO: Add return description
"Parse a notebook code cell for functions, classes, variables, and imports"
```
``` python
def parse_notebook(path: Path # Path to notebook
) -> ModuleInfo: # Module information
"Parse a notebook file for module information"
```
``` python
def parse_python_file(path: Path # Path to Python file
) -> ModuleInfo: # Module information
"Parse a Python file for module information"
```
#### Classes
``` python
@dataclass
class FunctionInfo:
"Information about a function"
name: str # Function name
signature: str # Full signature with docments
docstring: Optional[str] # Function docstring
decorators: List[str] = field(...) # List of decorators
is_exported: bool = False # Has #| export
source_line: Optional[int] # Line number in source
```
``` python
@dataclass
class VariableInfo:
"Information about a module-level variable"
name: str # Variable name
value: Optional[str] # String representation of value
type_hint: Optional[str] # Type annotation if present
comment: Optional[str] # Inline comment
is_exported: bool = False # Has #| export
```
``` python
@dataclass
class ClassInfo:
"Information about a class"
name: str # Class name
signature: str # Class signature with __init__
docstring: Optional[str] # Class docstring
methods: List[FunctionInfo] = field(...) # Class methods
decorators: List[str] = field(...) # Class decorators
attributes: List[VariableInfo] = field(...) # Class attributes (for dataclasses)
is_exported: bool = False # Has #| export
source_line: Optional[int] # Line number in source
```
``` python
@dataclass
class ModuleInfo:
"Information about a module (notebook or Python file)"
path: Path # Path to module
name: str # Module name
title: Optional[str] # H1 title from notebook
description: Optional[str] # Module description
functions: List[FunctionInfo] = field(...) # Functions in module
classes: List[ClassInfo] = field(...) # Classes in module
variables: List[VariableInfo] = field(...) # Variables in module
imports: List[str] = field(...) # Import statements
```
### Directory Tree Visualization (`02_tree.ipynb`)
> Generate tree visualizations for nbdev project structure
#### Import
``` python
from cjm-nbdev-overview.tree import (
generate_tree_lines,
generate_tree,
extract_notebook_info,
generate_tree_with_descriptions,
generate_subdirectory_tree,
get_tree_summary
)
```
#### Functions
``` python
def generate_tree_lines(path: Path, # Directory to visualize
prefix: str = "", # Line prefix for tree structure
is_last: bool = True, # Is this the last item in parent
show_notebooks_only: bool = False, # Only show notebooks, not directories
max_depth: Optional[int] = None, # Maximum depth to traverse
current_depth: int = 0, # Current depth in traversal
exclude_index: bool = True # Exclude index.ipynb from tree
) -> List[str]: # Lines of tree output
"Generate tree visualization lines for a directory"
```
``` python
def generate_tree(path: Path = None, # Directory to visualize (defaults to nbs_path)
show_notebooks_only: bool = False, # Only show notebooks, not directories
max_depth: Optional[int] = None, # Maximum depth to traverse
exclude_index: bool = True # Exclude index.ipynb from tree
) -> str: # Tree visualization as string
"Generate a tree visualization for a directory"
```
``` python
def extract_notebook_info(path: Path # Path to notebook file
) -> NotebookInfo: # Notebook information
"Extract title and description from a notebook"
```
``` python
def generate_tree_with_descriptions(path: Path = None, # Directory to visualize
show_counts: bool = True, # Show notebook counts for directories
max_depth: Optional[int] = None, # Maximum depth to traverse
exclude_index: bool = True # Exclude index.ipynb from tree
) -> str: # Tree with descriptions
"Generate tree visualization with descriptions from notebooks"
```
``` python
def _generate_nested_tree_lines(path: Path, # Directory to process
prefix: str = "", # Line prefix
show_counts: bool = True, # Show notebook counts
max_depth: Optional[int] = None, # Maximum depth
current_depth: int = 0, # Current depth
exclude_index: bool = True # Exclude index.ipynb from tree
) -> List[str]: # Tree lines
"Generate tree lines for nested directory structure"
```
``` python
def generate_subdirectory_tree(subdir_path: Path, # Path to subdirectory
show_descriptions: bool = True # Include notebook descriptions
) -> str: # Tree visualization
"Generate tree visualization for a specific subdirectory showing all notebooks"
```
``` python
def _generate_subdirectory_lines(item: Path, # Item to process
prefix: str, # Line prefix
is_last: bool, # Is last item
is_dir: bool, # Is directory
show_descriptions: bool, # Show descriptions
depth: int # Current depth
) -> List[str]: # Tree lines
"Generate tree lines for subdirectory visualization"
```
``` python
def get_tree_summary(path: Path = None # Directory to analyze
) -> str: # Summary string
"Get summary statistics for notebooks in directory tree"
```
### API Documentation Generation (`03_api_docs.ipynb`)
> Generate module overviews with formatted signatures for nbdev projects
#### Import
``` python
from cjm-nbdev-overview.api_docs import (
format_function_doc,
format_class_doc,
format_variable_doc,
generate_module_overview,
generate_project_api_docs,
update_index_module_docs,
add_project_structure_section,
add_dependencies_section,
add_cli_reference_section,
update_index_comprehensive
)
```
#### Functions
``` python
def format_function_doc(func: FunctionInfo, # Function information
indent: str = "" # Indentation prefix
) -> str: # Formatted documentation
"Format a function with its signature for documentation"
```
``` python
def format_class_doc(cls: ClassInfo # Class information
) -> str: # Formatted documentation
"Format a class with its signature and methods for documentation"
```
``` python
def format_variable_doc(var: VariableInfo # Variable information
) -> str: # Formatted documentation
"Format a variable for documentation"
```
``` python
def _generate_module_header(module: ModuleInfo # Module information
) -> List[str]: # Header lines
"Generate module title and description lines"
```
``` python
def _generate_import_statement(module: ModuleInfo # Module information
) -> List[str]: # Import statement lines
"Generate import statement lines for a module"
```
``` python
def _filter_module_items(module: ModuleInfo, # Module information
show_all: bool = False # Show all items including private
) -> tuple: # (functions, classes, variables)
"Filter module items based on show_all and is_exported flags"
```
``` python
def _generate_functions_section(functions: List[FunctionInfo] # List of functions
) -> List[str]: # Section lines
"Generate the functions section of module documentation"
```
``` python
def _generate_classes_section(classes: List[ClassInfo] # List of classes
) -> List[str]: # Section lines
"Generate the classes section of module documentation"
```
``` python
def _generate_variables_section(variables: List[VariableInfo] # List of variables
) -> List[str]: # Section lines
"Generate the variables section of module documentation"
```
``` python
def generate_module_overview(module: ModuleInfo, # Module information
show_all: bool = False # Show all items including private
) -> str: # Module overview markdown
"Generate a markdown overview for a module"
```
``` python
def generate_project_api_docs(path: Path = None, # Project path (defaults to nbs_path)
show_all: bool = False # Show all items including private
) -> str: # Full API documentation
"Generate API documentation for all modules in a project"
```
``` python
def _filter_cells_removing_sections(cells: List, # List of notebook cells
start_marker: str # Section marker to remove
) -> List: # Filtered cells
"Remove all cells from a section marked by start_marker until the next ## section"
```
``` python
def _sort_notebooks_by_prefix(notebooks: List[Path] # List of notebook paths
) -> List[Path]: # Sorted notebook paths
"Sort notebooks by their numeric prefix, putting non-numbered notebooks at the end"
```
``` python
def _get_notebooks_with_exports(notebooks: List[Path] # List of notebook paths
) -> List[Path]: # Notebooks with exported content
"Filter notebooks to only include those with exported content"
```
``` python
def _generate_module_overview_cells(notebooks: List[Path] # List of notebook paths
) -> List: # List of notebook cells
"Generate markdown cells containing module overview documentation"
```
``` python
def update_index_module_docs(index_path: Path = None, # Path to index.ipynb (defaults to nbs/index.ipynb)
start_marker: str = "## Module Overview" # Marker to identify module docs section
) -> None: # Updates index.ipynb in place
"Update the module documentation section in index.ipynb"
```
``` python
def add_project_structure_section(index_path: Path = None, # Path to index.ipynb
marker: str = "## Project Structure", # Section marker
exclude_index: bool = True # Exclude index.ipynb from tree
) -> str: # Generated structure content
"Generate project structure tree content for index.ipynb"
```
``` python
def add_dependencies_section(index_path: Path = None, # Path to index.ipynb
marker: str = "## Module Dependencies", # Section marker
direction: str = "LR" # Diagram direction
) -> str: # Generated dependencies content
"Generate module dependencies diagram content for index.ipynb"
```
``` python
def add_cli_reference_section(marker: str = "## CLI Reference" # Section marker
) -> str: # Generated CLI content
"Generate CLI reference content for index.ipynb based on project's console scripts"
```
``` python
def update_index_comprehensive(index_path: Path = None, # Path to index.ipynb
include_structure: bool = True, # Include project structure
include_dependencies: bool = True, # Include module dependencies
include_cli: bool = True, # Include CLI reference
include_modules: bool = True # Include module documentation
) -> None: # Updates index.ipynb in place
"Comprehensively update index.ipynb with project structure, dependencies, CLI, and modules"
```
### Dependency Analysis and Visualization (`04_dependencies.ipynb`)
> Analyze cross-notebook imports and generate Mermaid.js dependency
> diagrams
#### Import
``` python
from cjm-nbdev-overview.dependencies import (
ModuleDependency,
DependencyGraph,
extract_project_imports,
analyze_module_dependencies,
build_dependency_graph,
generate_mermaid_diagram,
generate_dependency_matrix
)
```
#### Functions
``` python
def extract_project_imports(import_str: str, # Import statement
project_name: str # Project package name
) -> Optional[ModuleDependency]: # Dependency if internal
"Extract project-internal imports from an import statement"
```
``` python
def analyze_module_dependencies(module: ModuleInfo, # Module to analyze
project_name: str # Project package name
) -> List[ModuleDependency]: # Dependencies found
"Analyze a module's imports to find project-internal dependencies"
```
``` python
def build_dependency_graph(path: Path = None, # Project path
project_name: Optional[str] = None # Override project name
) -> DependencyGraph: # Dependency graph
"Build a dependency graph for all modules in a project"
```
``` python
def generate_mermaid_diagram(graph: DependencyGraph, # Dependency graph
direction: str = "TD", # Diagram direction (TD/LR)
show_imports: bool = False # Show imported names
) -> str: # Mermaid diagram code
"Generate a Mermaid.js dependency diagram from a dependency graph"
```
``` python
def generate_dependency_matrix(graph: DependencyGraph # Dependency graph
) -> str: # Markdown table
"Generate a dependency matrix showing which modules depend on which"
```
#### Classes
``` python
@dataclass
class ModuleDependency:
"Represents a dependency between modules"
source: str # Source module name
target: str # Target module name
import_type: str # Type of import (from/import)
imported_names: List[str] = field(...) # Specific names imported
```
``` python
@dataclass
class DependencyGraph:
"Dependency graph for a project"
modules: Dict[str, ModuleInfo] = field(...) # Module name -> ModuleInfo
dependencies: List[ModuleDependency] = field(...) # All dependencies
def add_module(
self,
module: ModuleInfo # TODO: Add description
): # Add a module to the graph - TODO: Add type hint
"Add a module to the dependency graph"
def add_dependency(
self,
dep: ModuleDependency # TODO: Add description
): # Add a dependency - TODO: Add type hint
"Add a dependency to the graph"
def get_module_dependencies(self, module_name: str # Module to query
) -> List[ModuleDependency]: # Dependencies
"Get all dependencies for a specific module"
def get_module_dependents(self, module_name: str # Module to query
) -> List[ModuleDependency]: # Dependents
"Get all modules that depend on a specific module"
```
### Auto-generation Utilities (`05_generators.ipynb`)
> Auto-generate folder_name.ipynb notebooks for nbdev project
> organization
#### Import
``` python
from cjm-nbdev-overview.generators import (
create_folder_notebook,
generate_folder_notebook,
generate_all_folder_notebooks,
interactive_folder_notebook_generator
)
```
#### Functions
``` python
def create_folder_notebook(folder_path: Path, # Path to folder
title: str, # Notebook title
description: str # Folder description
) -> List[NbCell]: # List of notebook cells
"Create cells for a folder notebook with proper nbdev structure"
```
``` python
def generate_folder_notebook(folder_path: Path, # Path to folder
title: Optional[str] = None, # Custom title
description: Optional[str] = None, # Custom description
overwrite: bool = False # Overwrite existing
) -> Path: # Path to created notebook
"Generate a folder_name.ipynb notebook for a folder"
```
``` python
def generate_all_folder_notebooks(base_path: Path = None, # Base path (defaults to nbs)
recursive: bool = True, # Include nested folders
overwrite: bool = False, # Overwrite existing
dry_run: bool = False # Just show what would be created
) -> List[Path]: # Created notebook paths
"Generate folder notebooks for all folders that don't have them"
```
``` python
def interactive_folder_notebook_generator(base_path: Path = None # Base path
) -> List[Path]: # Created notebooks
"Interactively generate folder notebooks with custom titles and descriptions"
```
### Command-Line Interface (`06_cli.ipynb`)
> CLI commands for nbdev project overview generation and analysis
#### Import
``` python
from cjm-nbdev-overview.cli import (
tree_cmd,
api_cmd,
deps_cmd,
overview_cmd,
update_index_cmd,
update_comprehensive_cmd,
main
)
```
#### Functions
``` python
def tree_cmd(args): # Command line arguments
"Generate tree visualization for nbdev project"
# Get project path
path = Path(args.path) if args.path else None
# Determine exclude_index flag (default True, but --include-index overrides)
exclude_index = not getattr(args, 'include_index', False)
if args.basic
"Generate tree visualization for nbdev project"
```
``` python
def api_cmd(
args # TODO: Add type hint and description
): # Command line arguments - TODO: Add type hint
"Generate API documentation for nbdev project"
```
``` python
def deps_cmd(
args # TODO: Add type hint and description
): # Command line arguments - TODO: Add type hint
"Analyze and visualize module dependencies"
```
``` python
def overview_cmd(
args # TODO: Add type hint and description
): # Command line arguments - TODO: Add type hint
"Generate complete project overview"
```
``` python
def update_index_cmd(
args # TODO: Add type hint and description
): # Command line arguments - TODO: Add type hint
"Update index.ipynb with module documentation"
```
``` python
def update_comprehensive_cmd(
args # TODO: Add type hint and description
): # Command line arguments - TODO: Add type hint
"Comprehensively update index.ipynb with all sections"
```
``` python
def main()
"Main CLI entry point for nbdev-overview"
```
Raw data
{
"_id": null,
"home_page": "https://github.com/cj-mills/cjm-nbdev-overview",
"name": "cjm-nbdev-overview",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "nbdev jupyter notebook python",
"author": "Christian J. Mills",
"author_email": "9126128+cj-mills@users.noreply.github.com",
"download_url": "https://files.pythonhosted.org/packages/ca/0b/afa68b7df0d942f66d21949c22d0029758e23f702ffef546b7656209f813/cjm_nbdev_overview-0.0.2.tar.gz",
"platform": null,
"description": "# cjm-nbdev-overview\n\n\n<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->\n\n## How to use\n\n### Automatic Module Documentation\n\nThis project includes functionality to automatically update your\n`index.ipynb` with comprehensive module documentation. You can either:\n\n1. **Use the CLI command:**\n\n ``` bash\n nbdev-overview update-index\n ```\n\n2. **Use the Python API:**\n\n ``` python\n from cjm_nbdev_overview.api_docs import update_index_module_docs\n update_index_module_docs()\n ```\n\nThis will add a \u201cModule Overview\u201d section to your index.ipynb containing\ndetailed documentation for all modules in your project.\n\n## Project Structure\n\n nbs/\n \u251c\u2500\u2500 00_core.ipynb # Core utilities and data models for nbdev project overview generation\n \u251c\u2500\u2500 01_parsers.ipynb # Parse notebook metadata, content, and extract function/class signatures with docments\n \u251c\u2500\u2500 02_tree.ipynb # Generate tree visualizations for nbdev project structure\n \u251c\u2500\u2500 03_api_docs.ipynb # Generate module overviews with formatted signatures for nbdev projects\n \u251c\u2500\u2500 04_dependencies.ipynb # Analyze cross-notebook imports and generate Mermaid.js dependency diagrams\n \u251c\u2500\u2500 05_generators.ipynb # Auto-generate folder_name.ipynb notebooks for nbdev project organization\n \u2514\u2500\u2500 06_cli.ipynb # CLI commands for nbdev project overview generation and analysis\n\nTotal: 8 notebooks\n\n## Module Dependencies\n\n``` mermaid\ngraph LR\n core[core<br/>Core Utilities]\n parsers[parsers<br/>Notebook and Module Parsing]\n tree[tree<br/>Directory Tree Visualization]\n api_docs[api_docs<br/>API Documentation Generation]\n dependencies[dependencies<br/>Dependency Analysis and Visualization]\n generators[generators<br/>Auto-generation Utilities]\n cli[cli<br/>Command-Line Interface]\n\n parsers --> core\n parsers --> tree\n tree --> core\n api_docs --> core\n api_docs --> parsers\n api_docs --> dependencies\n api_docs --> tree\n dependencies --> core\n dependencies --> parsers\n generators --> tree\n generators --> core\n cli --> tree\n cli --> api_docs\n cli --> parsers\n cli --> dependencies\n\n classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px\n```\n\n*15 cross-module dependencies detected*\n\n## CLI Reference\n\n### `nbdev-overview` Command\n\n usage: nbdev-overview [-h]\n {tree,api,deps,overview,update-index,update-comprehensive}\n ...\n\n Generate comprehensive overviews for nbdev projects\n\n positional arguments:\n {tree,api,deps,overview,update-index,update-comprehensive}\n Available commands\n tree Generate directory tree visualization\n api Generate API documentation\n deps Analyze module dependencies\n overview Generate complete project overview\n update-index Update index.ipynb with module documentation\n update-comprehensive\n Comprehensive update of index.ipynb with all sections\n\n options:\n -h, --help show this help message and exit\n\nFor detailed help on any command, use `nbdev-overview <command> --help`.\n\n## Module Overview\n\nDetailed documentation for each module in the project:\n\n### Core Utilities (`00_core.ipynb`)\n\n> Core utilities and data models for nbdev project overview generation\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.core import (\n NotebookInfo,\n DirectoryInfo,\n get_notebook_files,\n get_subdirectories,\n read_notebook,\n get_cell_source\n)\n```\n\n#### Functions\n\n``` python\ndef get_notebook_files(path: Path = None, # Directory to search (defaults to nbs_path)\n recursive: bool = True # Search subdirectories\n ) -> List[Path]: # List of notebook paths\n \"Get all notebook files in a directory\"\n```\n\n``` python\ndef get_subdirectories(path: Path = None, # Directory to search (defaults to nbs_path)\n recursive: bool = False # Include all nested subdirectories\n ) -> List[Path]: # List of directory paths\n \"Get subdirectories in a directory\"\n```\n\n``` python\ndef read_notebook(path: Path # Path to notebook file\n ) -> Dict[str, Any]: # Notebook content as dict\n \"Read a notebook file and return its content\"\n```\n\n``` python\ndef get_cell_source(cell: Dict[str, Any] # Notebook cell\n ) -> str: # Cell source as string\n \"Get source from a notebook cell\"\n```\n\n#### Classes\n\n``` python\n@dataclass\nclass NotebookInfo:\n \"Information about a single notebook\"\n \n path: Path # Path to the notebook file\n name: str # Notebook filename without extension\n title: Optional[str] # H1 title from first cell\n description: Optional[str] # Blockquote description from first cell\n export_module: Optional[str] # Module name from default_exp\n \n def relative_path(self) -> Path: # Path relative to nbs directory\n \"Get path relative to nbs directory\"\n```\n\n``` python\n@dataclass\nclass DirectoryInfo:\n \"Information about a directory in the nbs folder\"\n \n path: Path # Path to the directory\n name: str # Directory name\n notebook_count: int = 0 # Number of notebooks in directory\n description: Optional[str] # Description from folder's main notebook\n subdirs: List[DirectoryInfo] = field(...) # Subdirectories\n notebooks: List[NotebookInfo] = field(...) # Notebooks in this directory\n \n def total_notebook_count(self) -> int: # Total notebooks including subdirs\n \"Get total notebook count including subdirectories\"\n```\n\n### Notebook and Module Parsing (`01_parsers.ipynb`)\n\n> Parse notebook metadata, content, and extract function/class\n> signatures with docments\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.parsers import (\n FunctionInfo,\n VariableInfo,\n ClassInfo,\n ModuleInfo,\n extract_docments_signature,\n parse_function,\n parse_class,\n parse_variable,\n parse_code_cell,\n parse_notebook,\n parse_python_file\n)\n```\n\n#### Functions\n\n``` python\ndef extract_docments_signature(node: ast.FunctionDef, # AST function node\n source_lines: List[str] # Source code lines\n ) -> str: # Function signature\n \"Extract function signature with docments-style comments\"\n```\n\n``` python\ndef _parse_decorators(node: Union[ast.ClassDef, ast.FunctionDef] # AST node with decorators\n ) -> List[str]: # List of decorator names\n \"Parse decorators from an AST node\"\n```\n\n``` python\ndef parse_function(node: ast.FunctionDef, # AST function node\n source_lines: List[str], # Source code lines\n is_exported: bool = False # Has #| export\n ) -> FunctionInfo: # Function information\n \"Parse a function definition from AST\"\n```\n\n``` python\ndef _parse_class_methods(node: ast.ClassDef, # AST class node\n source_lines: List[str], # Source code lines\n is_exported: bool = False # Has #| export\n ) -> List[FunctionInfo]: # List of method information\n \"Parse methods from a class definition\"\n```\n\n``` python\ndef _parse_dataclass_attributes(node: ast.ClassDef, # AST class node\n source_lines: List[str], # Source code lines\n is_exported: bool = False # Has #| export\n ) -> List[VariableInfo]: # List of attribute information\n \"Parse dataclass attributes from a class definition\"\n```\n\n``` python\ndef _generate_class_signature(node: ast.ClassDef, # AST class node\n methods: List[FunctionInfo] # List of class methods\n ) -> str: # Class signature\n \"Generate a class signature including __init__ if present\"\n```\n\n``` python\ndef parse_class(node: ast.ClassDef, # AST class node\n source_lines: List[str], # Source code lines\n is_exported: bool = False # Has #| export\n ) -> ClassInfo: # Class information\n \"Parse a class definition from AST\"\n```\n\n``` python\ndef parse_variable(node: Union[ast.Assign, ast.AnnAssign], # AST assignment node\n source_lines: List[str], # Source code lines\n is_exported: bool = False # Has #| export\n ) -> List[VariableInfo]: # Variable information\n \"Parse variable assignments from AST\"\n```\n\n``` python\ndef parse_code_cell(cell: Dict[str, Any] # Notebook code cell\n ) -> Tuple[List[FunctionInfo], List[ClassInfo], List[VariableInfo], List[str]]: # TODO: Add return description\n \"Parse a notebook code cell for functions, classes, variables, and imports\"\n```\n\n``` python\ndef parse_notebook(path: Path # Path to notebook\n ) -> ModuleInfo: # Module information\n \"Parse a notebook file for module information\"\n```\n\n``` python\ndef parse_python_file(path: Path # Path to Python file\n ) -> ModuleInfo: # Module information\n \"Parse a Python file for module information\"\n```\n\n#### Classes\n\n``` python\n@dataclass\nclass FunctionInfo:\n \"Information about a function\"\n \n name: str # Function name\n signature: str # Full signature with docments\n docstring: Optional[str] # Function docstring\n decorators: List[str] = field(...) # List of decorators\n is_exported: bool = False # Has #| export\n source_line: Optional[int] # Line number in source\n```\n\n``` python\n@dataclass\nclass VariableInfo:\n \"Information about a module-level variable\"\n \n name: str # Variable name\n value: Optional[str] # String representation of value\n type_hint: Optional[str] # Type annotation if present\n comment: Optional[str] # Inline comment\n is_exported: bool = False # Has #| export\n```\n\n``` python\n@dataclass\nclass ClassInfo:\n \"Information about a class\"\n \n name: str # Class name\n signature: str # Class signature with __init__\n docstring: Optional[str] # Class docstring\n methods: List[FunctionInfo] = field(...) # Class methods\n decorators: List[str] = field(...) # Class decorators\n attributes: List[VariableInfo] = field(...) # Class attributes (for dataclasses)\n is_exported: bool = False # Has #| export\n source_line: Optional[int] # Line number in source\n```\n\n``` python\n@dataclass\nclass ModuleInfo:\n \"Information about a module (notebook or Python file)\"\n \n path: Path # Path to module\n name: str # Module name\n title: Optional[str] # H1 title from notebook\n description: Optional[str] # Module description\n functions: List[FunctionInfo] = field(...) # Functions in module\n classes: List[ClassInfo] = field(...) # Classes in module\n variables: List[VariableInfo] = field(...) # Variables in module\n imports: List[str] = field(...) # Import statements\n```\n\n### Directory Tree Visualization (`02_tree.ipynb`)\n\n> Generate tree visualizations for nbdev project structure\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.tree import (\n generate_tree_lines,\n generate_tree,\n extract_notebook_info,\n generate_tree_with_descriptions,\n generate_subdirectory_tree,\n get_tree_summary\n)\n```\n\n#### Functions\n\n``` python\ndef generate_tree_lines(path: Path, # Directory to visualize\n prefix: str = \"\", # Line prefix for tree structure\n is_last: bool = True, # Is this the last item in parent\n show_notebooks_only: bool = False, # Only show notebooks, not directories\n max_depth: Optional[int] = None, # Maximum depth to traverse\n current_depth: int = 0, # Current depth in traversal\n exclude_index: bool = True # Exclude index.ipynb from tree\n ) -> List[str]: # Lines of tree output\n \"Generate tree visualization lines for a directory\"\n```\n\n``` python\ndef generate_tree(path: Path = None, # Directory to visualize (defaults to nbs_path)\n show_notebooks_only: bool = False, # Only show notebooks, not directories\n max_depth: Optional[int] = None, # Maximum depth to traverse\n exclude_index: bool = True # Exclude index.ipynb from tree\n ) -> str: # Tree visualization as string\n \"Generate a tree visualization for a directory\"\n```\n\n``` python\ndef extract_notebook_info(path: Path # Path to notebook file\n ) -> NotebookInfo: # Notebook information\n \"Extract title and description from a notebook\"\n```\n\n``` python\ndef generate_tree_with_descriptions(path: Path = None, # Directory to visualize\n show_counts: bool = True, # Show notebook counts for directories\n max_depth: Optional[int] = None, # Maximum depth to traverse\n exclude_index: bool = True # Exclude index.ipynb from tree\n ) -> str: # Tree with descriptions\n \"Generate tree visualization with descriptions from notebooks\"\n```\n\n``` python\ndef _generate_nested_tree_lines(path: Path, # Directory to process\n prefix: str = \"\", # Line prefix\n show_counts: bool = True, # Show notebook counts\n max_depth: Optional[int] = None, # Maximum depth\n current_depth: int = 0, # Current depth\n exclude_index: bool = True # Exclude index.ipynb from tree\n ) -> List[str]: # Tree lines\n \"Generate tree lines for nested directory structure\"\n```\n\n``` python\ndef generate_subdirectory_tree(subdir_path: Path, # Path to subdirectory\n show_descriptions: bool = True # Include notebook descriptions\n ) -> str: # Tree visualization\n \"Generate tree visualization for a specific subdirectory showing all notebooks\"\n```\n\n``` python\ndef _generate_subdirectory_lines(item: Path, # Item to process\n prefix: str, # Line prefix\n is_last: bool, # Is last item\n is_dir: bool, # Is directory\n show_descriptions: bool, # Show descriptions\n depth: int # Current depth\n ) -> List[str]: # Tree lines\n \"Generate tree lines for subdirectory visualization\"\n```\n\n``` python\ndef get_tree_summary(path: Path = None # Directory to analyze\n ) -> str: # Summary string\n \"Get summary statistics for notebooks in directory tree\"\n```\n\n### API Documentation Generation (`03_api_docs.ipynb`)\n\n> Generate module overviews with formatted signatures for nbdev projects\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.api_docs import (\n format_function_doc,\n format_class_doc,\n format_variable_doc,\n generate_module_overview,\n generate_project_api_docs,\n update_index_module_docs,\n add_project_structure_section,\n add_dependencies_section,\n add_cli_reference_section,\n update_index_comprehensive\n)\n```\n\n#### Functions\n\n``` python\ndef format_function_doc(func: FunctionInfo, # Function information\n indent: str = \"\" # Indentation prefix\n ) -> str: # Formatted documentation\n \"Format a function with its signature for documentation\"\n```\n\n``` python\ndef format_class_doc(cls: ClassInfo # Class information\n ) -> str: # Formatted documentation\n \"Format a class with its signature and methods for documentation\"\n```\n\n``` python\ndef format_variable_doc(var: VariableInfo # Variable information\n ) -> str: # Formatted documentation\n \"Format a variable for documentation\"\n```\n\n``` python\ndef _generate_module_header(module: ModuleInfo # Module information\n ) -> List[str]: # Header lines\n \"Generate module title and description lines\"\n```\n\n``` python\ndef _generate_import_statement(module: ModuleInfo # Module information\n ) -> List[str]: # Import statement lines\n \"Generate import statement lines for a module\"\n```\n\n``` python\ndef _filter_module_items(module: ModuleInfo, # Module information\n show_all: bool = False # Show all items including private\n ) -> tuple: # (functions, classes, variables)\n \"Filter module items based on show_all and is_exported flags\"\n```\n\n``` python\ndef _generate_functions_section(functions: List[FunctionInfo] # List of functions\n ) -> List[str]: # Section lines\n \"Generate the functions section of module documentation\"\n```\n\n``` python\ndef _generate_classes_section(classes: List[ClassInfo] # List of classes\n ) -> List[str]: # Section lines\n \"Generate the classes section of module documentation\"\n```\n\n``` python\ndef _generate_variables_section(variables: List[VariableInfo] # List of variables\n ) -> List[str]: # Section lines\n \"Generate the variables section of module documentation\"\n```\n\n``` python\ndef generate_module_overview(module: ModuleInfo, # Module information\n show_all: bool = False # Show all items including private\n ) -> str: # Module overview markdown\n \"Generate a markdown overview for a module\"\n```\n\n``` python\ndef generate_project_api_docs(path: Path = None, # Project path (defaults to nbs_path)\n show_all: bool = False # Show all items including private\n ) -> str: # Full API documentation\n \"Generate API documentation for all modules in a project\"\n```\n\n``` python\ndef _filter_cells_removing_sections(cells: List, # List of notebook cells\n start_marker: str # Section marker to remove\n ) -> List: # Filtered cells\n \"Remove all cells from a section marked by start_marker until the next ## section\"\n```\n\n``` python\ndef _sort_notebooks_by_prefix(notebooks: List[Path] # List of notebook paths\n ) -> List[Path]: # Sorted notebook paths\n \"Sort notebooks by their numeric prefix, putting non-numbered notebooks at the end\"\n```\n\n``` python\ndef _get_notebooks_with_exports(notebooks: List[Path] # List of notebook paths\n ) -> List[Path]: # Notebooks with exported content\n \"Filter notebooks to only include those with exported content\"\n```\n\n``` python\ndef _generate_module_overview_cells(notebooks: List[Path] # List of notebook paths\n ) -> List: # List of notebook cells\n \"Generate markdown cells containing module overview documentation\"\n```\n\n``` python\ndef update_index_module_docs(index_path: Path = None, # Path to index.ipynb (defaults to nbs/index.ipynb)\n start_marker: str = \"## Module Overview\" # Marker to identify module docs section\n ) -> None: # Updates index.ipynb in place\n \"Update the module documentation section in index.ipynb\"\n```\n\n``` python\ndef add_project_structure_section(index_path: Path = None, # Path to index.ipynb\n marker: str = \"## Project Structure\", # Section marker\n exclude_index: bool = True # Exclude index.ipynb from tree\n ) -> str: # Generated structure content\n \"Generate project structure tree content for index.ipynb\"\n```\n\n``` python\ndef add_dependencies_section(index_path: Path = None, # Path to index.ipynb\n marker: str = \"## Module Dependencies\", # Section marker\n direction: str = \"LR\" # Diagram direction\n ) -> str: # Generated dependencies content\n \"Generate module dependencies diagram content for index.ipynb\"\n```\n\n``` python\ndef add_cli_reference_section(marker: str = \"## CLI Reference\" # Section marker\n ) -> str: # Generated CLI content\n \"Generate CLI reference content for index.ipynb based on project's console scripts\"\n```\n\n``` python\ndef update_index_comprehensive(index_path: Path = None, # Path to index.ipynb\n include_structure: bool = True, # Include project structure\n include_dependencies: bool = True, # Include module dependencies\n include_cli: bool = True, # Include CLI reference\n include_modules: bool = True # Include module documentation\n ) -> None: # Updates index.ipynb in place\n \"Comprehensively update index.ipynb with project structure, dependencies, CLI, and modules\"\n```\n\n### Dependency Analysis and Visualization (`04_dependencies.ipynb`)\n\n> Analyze cross-notebook imports and generate Mermaid.js dependency\n> diagrams\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.dependencies import (\n ModuleDependency,\n DependencyGraph,\n extract_project_imports,\n analyze_module_dependencies,\n build_dependency_graph,\n generate_mermaid_diagram,\n generate_dependency_matrix\n)\n```\n\n#### Functions\n\n``` python\ndef extract_project_imports(import_str: str, # Import statement\n project_name: str # Project package name\n ) -> Optional[ModuleDependency]: # Dependency if internal\n \"Extract project-internal imports from an import statement\"\n```\n\n``` python\ndef analyze_module_dependencies(module: ModuleInfo, # Module to analyze\n project_name: str # Project package name\n ) -> List[ModuleDependency]: # Dependencies found\n \"Analyze a module's imports to find project-internal dependencies\"\n```\n\n``` python\ndef build_dependency_graph(path: Path = None, # Project path\n project_name: Optional[str] = None # Override project name\n ) -> DependencyGraph: # Dependency graph\n \"Build a dependency graph for all modules in a project\"\n```\n\n``` python\ndef generate_mermaid_diagram(graph: DependencyGraph, # Dependency graph\n direction: str = \"TD\", # Diagram direction (TD/LR)\n show_imports: bool = False # Show imported names\n ) -> str: # Mermaid diagram code\n \"Generate a Mermaid.js dependency diagram from a dependency graph\"\n```\n\n``` python\ndef generate_dependency_matrix(graph: DependencyGraph # Dependency graph\n ) -> str: # Markdown table\n \"Generate a dependency matrix showing which modules depend on which\"\n```\n\n#### Classes\n\n``` python\n@dataclass\nclass ModuleDependency:\n \"Represents a dependency between modules\"\n \n source: str # Source module name\n target: str # Target module name\n import_type: str # Type of import (from/import)\n imported_names: List[str] = field(...) # Specific names imported\n```\n\n``` python\n@dataclass\nclass DependencyGraph:\n \"Dependency graph for a project\"\n \n modules: Dict[str, ModuleInfo] = field(...) # Module name -> ModuleInfo\n dependencies: List[ModuleDependency] = field(...) # All dependencies\n \n def add_module(\n self,\n module: ModuleInfo # TODO: Add description\n ): # Add a module to the graph - TODO: Add type hint\n \"Add a module to the dependency graph\"\n \n def add_dependency(\n self,\n dep: ModuleDependency # TODO: Add description\n ): # Add a dependency - TODO: Add type hint\n \"Add a dependency to the graph\"\n \n def get_module_dependencies(self, module_name: str # Module to query\n ) -> List[ModuleDependency]: # Dependencies\n \"Get all dependencies for a specific module\"\n \n def get_module_dependents(self, module_name: str # Module to query\n ) -> List[ModuleDependency]: # Dependents\n \"Get all modules that depend on a specific module\"\n```\n\n### Auto-generation Utilities (`05_generators.ipynb`)\n\n> Auto-generate folder_name.ipynb notebooks for nbdev project\n> organization\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.generators import (\n create_folder_notebook,\n generate_folder_notebook,\n generate_all_folder_notebooks,\n interactive_folder_notebook_generator\n)\n```\n\n#### Functions\n\n``` python\ndef create_folder_notebook(folder_path: Path, # Path to folder\n title: str, # Notebook title\n description: str # Folder description\n ) -> List[NbCell]: # List of notebook cells\n \"Create cells for a folder notebook with proper nbdev structure\"\n```\n\n``` python\ndef generate_folder_notebook(folder_path: Path, # Path to folder\n title: Optional[str] = None, # Custom title\n description: Optional[str] = None, # Custom description\n overwrite: bool = False # Overwrite existing\n ) -> Path: # Path to created notebook\n \"Generate a folder_name.ipynb notebook for a folder\"\n```\n\n``` python\ndef generate_all_folder_notebooks(base_path: Path = None, # Base path (defaults to nbs)\n recursive: bool = True, # Include nested folders\n overwrite: bool = False, # Overwrite existing\n dry_run: bool = False # Just show what would be created\n ) -> List[Path]: # Created notebook paths\n \"Generate folder notebooks for all folders that don't have them\"\n```\n\n``` python\ndef interactive_folder_notebook_generator(base_path: Path = None # Base path\n ) -> List[Path]: # Created notebooks\n \"Interactively generate folder notebooks with custom titles and descriptions\"\n```\n\n### Command-Line Interface (`06_cli.ipynb`)\n\n> CLI commands for nbdev project overview generation and analysis\n\n#### Import\n\n``` python\nfrom cjm-nbdev-overview.cli import (\n tree_cmd,\n api_cmd,\n deps_cmd,\n overview_cmd,\n update_index_cmd,\n update_comprehensive_cmd,\n main\n)\n```\n\n#### Functions\n\n``` python\ndef tree_cmd(args): # Command line arguments\n \"Generate tree visualization for nbdev project\"\n # Get project path\n path = Path(args.path) if args.path else None\n \n # Determine exclude_index flag (default True, but --include-index overrides)\n exclude_index = not getattr(args, 'include_index', False)\n \n if args.basic\n \"Generate tree visualization for nbdev project\"\n```\n\n``` python\ndef api_cmd(\n args # TODO: Add type hint and description\n): # Command line arguments - TODO: Add type hint\n \"Generate API documentation for nbdev project\"\n```\n\n``` python\ndef deps_cmd(\n args # TODO: Add type hint and description\n): # Command line arguments - TODO: Add type hint\n \"Analyze and visualize module dependencies\"\n```\n\n``` python\ndef overview_cmd(\n args # TODO: Add type hint and description\n): # Command line arguments - TODO: Add type hint\n \"Generate complete project overview\"\n```\n\n``` python\ndef update_index_cmd(\n args # TODO: Add type hint and description\n): # Command line arguments - TODO: Add type hint\n \"Update index.ipynb with module documentation\"\n```\n\n``` python\ndef update_comprehensive_cmd(\n args # TODO: Add type hint and description\n): # Command line arguments - TODO: Add type hint\n \"Comprehensively update index.ipynb with all sections\"\n```\n\n``` python\ndef main()\n \"Main CLI entry point for nbdev-overview\"\n```\n",
"bugtrack_url": null,
"license": "Apache Software License 2.0",
"summary": "Automated documentation and visualization tools for nbdev projects.",
"version": "0.0.2",
"project_urls": {
"Homepage": "https://github.com/cj-mills/cjm-nbdev-overview"
},
"split_keywords": [
"nbdev",
"jupyter",
"notebook",
"python"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "e936811ded851d4366a2d4eddcd525cc69b1794b0873ff8902465d376c11e3a3",
"md5": "e7f41c28995e19fea783db28ff40930d",
"sha256": "5df46d918a00d224815265febc2bd3a987f8d8300fc87c8ce94800412852d50a"
},
"downloads": -1,
"filename": "cjm_nbdev_overview-0.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e7f41c28995e19fea783db28ff40930d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 37907,
"upload_time": "2025-07-08T21:27:18",
"upload_time_iso_8601": "2025-07-08T21:27:18.163243Z",
"url": "https://files.pythonhosted.org/packages/e9/36/811ded851d4366a2d4eddcd525cc69b1794b0873ff8902465d376c11e3a3/cjm_nbdev_overview-0.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ca0bafa68b7df0d942f66d21949c22d0029758e23f702ffef546b7656209f813",
"md5": "fedb0737c985fb851ec9309dff192a38",
"sha256": "43a5cfd91e637dcf5b9291c46c2d5f1e5473ff34dd4b84b92b9bfd439778993c"
},
"downloads": -1,
"filename": "cjm_nbdev_overview-0.0.2.tar.gz",
"has_sig": false,
"md5_digest": "fedb0737c985fb851ec9309dff192a38",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 40198,
"upload_time": "2025-07-08T21:27:19",
"upload_time_iso_8601": "2025-07-08T21:27:19.496381Z",
"url": "https://files.pythonhosted.org/packages/ca/0b/afa68b7df0d942f66d21949c22d0029758e23f702ffef546b7656209f813/cjm_nbdev_overview-0.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-08 21:27:19",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "cj-mills",
"github_project": "cjm-nbdev-overview",
"github_not_found": true,
"lcname": "cjm-nbdev-overview"
}