Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """ | |
| Script to detect empty cells in marimo notebooks. | |
| An empty cell is defined as: | |
| @app.cell | |
| def _(): | |
| return | |
| This script will: | |
| 1. Find all Python files in the repository | |
| 2. Check if they contain marimo app definitions | |
| 3. Look for empty cell patterns | |
| 4. Report any empty cells found | |
| """ | |
| import os | |
| import re | |
| import sys | |
| from pathlib import Path | |
| from typing import List, Tuple | |
| def is_marimo_notebook(file_path: Path) -> bool: | |
| """Check if a Python file is a marimo notebook.""" | |
| try: | |
| with open(file_path, 'r', encoding='utf-8') as f: | |
| content = f.read() | |
| # Look for marimo app defn | |
| return 'marimo.App' in content and '@app.cell' in content | |
| except (UnicodeDecodeError, IOError): | |
| return False | |
| def find_empty_cells(file_path: Path) -> List[Tuple[int, str]]: | |
| """Find empty cells in a marimo notebook.""" | |
| empty_cells = [] | |
| try: | |
| with open(file_path, 'r', encoding='utf-8') as f: | |
| lines = f.readlines() | |
| except (UnicodeDecodeError, IOError): | |
| return empty_cells | |
| i = 0 | |
| while i < len(lines): | |
| line = lines[i].strip() | |
| # if line starts with @app.cell decorator | |
| if line.startswith('@app.cell'): | |
| # look for the function definition on the next non-empty line | |
| j = i + 1 | |
| while j < len(lines) and not lines[j].strip(): | |
| j += 1 | |
| if j < len(lines) and lines[j].strip() == 'def _():': | |
| # found function definition, now look for return statement | |
| k = j + 1 | |
| while k < len(lines) and not lines[k].strip(): | |
| k += 1 | |
| if k < len(lines) and lines[k].strip() == 'return': | |
| # if any content after return (before next @app.cell or end of file) | |
| has_content = False | |
| m = k + 1 | |
| while m < len(lines): | |
| line_content = lines[m].strip() | |
| if line_content.startswith('@app.cell'): | |
| break | |
| if line_content and not line_content.startswith('#'): | |
| has_content = True | |
| break | |
| m += 1 | |
| if not has_content: | |
| empty_cells.append((i + 1, lines[i].strip())) | |
| i = k + 1 | |
| else: | |
| i += 1 | |
| else: | |
| i += 1 | |
| return empty_cells | |
| def main(): | |
| """Main function to check for empty cells.""" | |
| print("π Checking for empty cells in marimo notebooks...") | |
| python_files = [] | |
| for root, dirs, files in os.walk('.'): | |
| # skip hidden directories and common build/cache | |
| dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['__pycache__', 'node_modules', 'build', 'dist']] | |
| for file in files: | |
| if file.endswith('.py'): | |
| python_files.append(Path(root) / file) | |
| marimo_notebooks = [] | |
| for file_path in python_files: | |
| if is_marimo_notebook(file_path): | |
| marimo_notebooks.append(file_path) | |
| print(f"π Found {len(marimo_notebooks)} marimo notebooks") | |
| # each notebook checked for empty cells | |
| total_empty_cells = 0 | |
| files_with_empty_cells = [] | |
| for notebook_path in marimo_notebooks: | |
| empty_cells = find_empty_cells(notebook_path) | |
| if empty_cells: | |
| total_empty_cells += len(empty_cells) | |
| files_with_empty_cells.append((notebook_path, empty_cells)) | |
| print(f"β {notebook_path}: {len(empty_cells)} empty cell(s)") | |
| for line_num, line_content in empty_cells: | |
| print(f" Line {line_num}: {line_content}") | |
| if files_with_empty_cells: | |
| print(f"\nπ₯ Found {total_empty_cells} empty cells in {len(files_with_empty_cells)} files") | |
| print("\nEmpty cells should be removed or contain meaningful content.") | |
| print("An empty cell looks like:") | |
| print("@app.cell") | |
| print("def _():") | |
| print(" return") | |
| print("\nConsider either:") | |
| print("1. Removing the empty cell entirely") | |
| print("2. Adding meaningful content to the cell") | |
| print("3. Adding a comment explaining why the cell is empty") | |
| sys.exit(1) | |
| else: | |
| print("β No empty cells found!") | |
| sys.exit(0) | |
| if __name__ == "__main__": | |
| main() |