Srihari Thyagarajan commited on
Commit
888d8d2
Β·
unverified Β·
2 Parent(s): d46f7d6 91245b4

Merge pull request #115 from marimo-team/haleshot/add-empty-cell-workflow

Browse files
.github/workflows/check-empty-cells.yml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Check for Empty Cells
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ paths:
7
+ - '**/*.py'
8
+
9
+ jobs:
10
+ check-empty-cells:
11
+ name: Check for empty cells in marimo notebooks
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: πŸ›‘ Cancel Previous Runs
15
+ uses: styfle/cancel-workflow-action@0.12.1
16
+
17
+ - name: πŸ”„ Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: 🐍 Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: 3.12
24
+
25
+ - name: πŸ” Check for empty cells
26
+ run: |
27
+ python scripts/check_empty_cells.py
28
+
29
+ - name: πŸ“Š Report results
30
+ if: failure()
31
+ run: |
32
+ echo "❌ Empty cells found in marimo notebooks!"
33
+ echo "Please remove or add content to empty cells before merging."
34
+ echo "Empty cells look like:"
35
+ echo "@app.cell"
36
+ echo "def _():"
37
+ echo " return"
polars/06_Dataframe_Transformer.py CHANGED
@@ -62,7 +62,7 @@ def _(json_data, pl):
62
  def _(mo):
63
  mo.md(
64
  r"""
65
- Above, you will notice that when you reference the object as a standalone, you get out-of-the-box convenince from `marimo`. You have the `Table` and `Query Plan` options to choose from.
66
 
67
  - πŸ’‘ Try out the `Table` view! You can click the `Preview data` button to get a quick view of your data.
68
  - πŸ’‘ Take a look at the `Query plan`. Learn more about Polar's query plan here: https://docs.pola.rs/user-guide/lazy/query-plan/
@@ -111,7 +111,7 @@ def _(mo):
111
  r"""
112
  Note how much functionality we have right out-of-the-box. Click on column names to see rich features like sorting, freezing, filtering, searching, and more!
113
 
114
- Notice how `order_quantity` has a green bar chart under it indicating the ditribution of values for the field!
115
 
116
  Don't miss the `Download` feature as well which supports downloading in CSV, json, or parquet format!
117
  """
 
62
  def _(mo):
63
  mo.md(
64
  r"""
65
+ Above, you will notice that when you reference the object as a standalone, you get out-of-the-box convenience from `marimo`. You have the `Table` and `Query Plan` options to choose from.
66
 
67
  - πŸ’‘ Try out the `Table` view! You can click the `Preview data` button to get a quick view of your data.
68
  - πŸ’‘ Take a look at the `Query plan`. Learn more about Polar's query plan here: https://docs.pola.rs/user-guide/lazy/query-plan/
 
111
  r"""
112
  Note how much functionality we have right out-of-the-box. Click on column names to see rich features like sorting, freezing, filtering, searching, and more!
113
 
114
+ Notice how `order_quantity` has a green bar chart under it indicating the distribution of values for the field!
115
 
116
  Don't miss the `Download` feature as well which supports downloading in CSV, json, or parquet format!
117
  """
scripts/check_empty_cells.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to detect empty cells in marimo notebooks.
4
+
5
+ An empty cell is defined as:
6
+ @app.cell
7
+ def _():
8
+ return
9
+
10
+ This script will:
11
+ 1. Find all Python files in the repository
12
+ 2. Check if they contain marimo app definitions
13
+ 3. Look for empty cell patterns
14
+ 4. Report any empty cells found
15
+ """
16
+
17
+ import os
18
+ import re
19
+ import sys
20
+ from pathlib import Path
21
+ from typing import List, Tuple
22
+
23
+
24
+ def is_marimo_notebook(file_path: Path) -> bool:
25
+ """Check if a Python file is a marimo notebook."""
26
+ try:
27
+ with open(file_path, 'r', encoding='utf-8') as f:
28
+ content = f.read()
29
+ # Look for marimo app defn
30
+ return 'marimo.App' in content and '@app.cell' in content
31
+ except (UnicodeDecodeError, IOError):
32
+ return False
33
+
34
+
35
+ def find_empty_cells(file_path: Path) -> List[Tuple[int, str]]:
36
+ """Find empty cells in a marimo notebook."""
37
+ empty_cells = []
38
+
39
+ try:
40
+ with open(file_path, 'r', encoding='utf-8') as f:
41
+ lines = f.readlines()
42
+ except (UnicodeDecodeError, IOError):
43
+ return empty_cells
44
+
45
+ i = 0
46
+ while i < len(lines):
47
+ line = lines[i].strip()
48
+
49
+ # if line starts with @app.cell decorator
50
+ if line.startswith('@app.cell'):
51
+ # look for the function definition on the next non-empty line
52
+ j = i + 1
53
+ while j < len(lines) and not lines[j].strip():
54
+ j += 1
55
+
56
+ if j < len(lines) and lines[j].strip() == 'def _():':
57
+ # found function definition, now look for return statement
58
+ k = j + 1
59
+ while k < len(lines) and not lines[k].strip():
60
+ k += 1
61
+
62
+ if k < len(lines) and lines[k].strip() == 'return':
63
+ # if any content after return (before next @app.cell or end of file)
64
+ has_content = False
65
+ m = k + 1
66
+ while m < len(lines):
67
+ line_content = lines[m].strip()
68
+ if line_content.startswith('@app.cell'):
69
+ break
70
+ if line_content and not line_content.startswith('#'):
71
+ has_content = True
72
+ break
73
+ m += 1
74
+
75
+ if not has_content:
76
+ empty_cells.append((i + 1, lines[i].strip()))
77
+
78
+ i = k + 1
79
+ else:
80
+ i += 1
81
+ else:
82
+ i += 1
83
+
84
+ return empty_cells
85
+
86
+
87
+ def main():
88
+ """Main function to check for empty cells."""
89
+ print("πŸ” Checking for empty cells in marimo notebooks...")
90
+
91
+ python_files = []
92
+ for root, dirs, files in os.walk('.'):
93
+ # skip hidden directories and common build/cache
94
+ dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['__pycache__', 'node_modules', 'build', 'dist']]
95
+
96
+ for file in files:
97
+ if file.endswith('.py'):
98
+ python_files.append(Path(root) / file)
99
+
100
+ marimo_notebooks = []
101
+ for file_path in python_files:
102
+ if is_marimo_notebook(file_path):
103
+ marimo_notebooks.append(file_path)
104
+
105
+ print(f"πŸ“ Found {len(marimo_notebooks)} marimo notebooks")
106
+
107
+ # each notebook checked for empty cells
108
+ total_empty_cells = 0
109
+ files_with_empty_cells = []
110
+
111
+ for notebook_path in marimo_notebooks:
112
+ empty_cells = find_empty_cells(notebook_path)
113
+ if empty_cells:
114
+ total_empty_cells += len(empty_cells)
115
+ files_with_empty_cells.append((notebook_path, empty_cells))
116
+ print(f"❌ {notebook_path}: {len(empty_cells)} empty cell(s)")
117
+ for line_num, line_content in empty_cells:
118
+ print(f" Line {line_num}: {line_content}")
119
+
120
+ if files_with_empty_cells:
121
+ print(f"\nπŸ’₯ Found {total_empty_cells} empty cells in {len(files_with_empty_cells)} files")
122
+ print("\nEmpty cells should be removed or contain meaningful content.")
123
+ print("An empty cell looks like:")
124
+ print("@app.cell")
125
+ print("def _():")
126
+ print(" return")
127
+ print("\nConsider either:")
128
+ print("1. Removing the empty cell entirely")
129
+ print("2. Adding meaningful content to the cell")
130
+ print("3. Adding a comment explaining why the cell is empty")
131
+
132
+ sys.exit(1)
133
+ else:
134
+ print("βœ… No empty cells found!")
135
+ sys.exit(0)
136
+
137
+
138
+ if __name__ == "__main__":
139
+ main()