44import os
55import importlib .util
66from collections import OrderedDict , defaultdict
7- import astroid
87from pathlib import Path
98from uuid import uuid4
109from zt_backend .models .notebook import Notebook , CodeCell
11- from zt_backend .runner .code_cell_parser import get_imports , get_defined_names ,get_loaded_names ,get_loaded_modules ,get_functions
10+ import astroid
11+ from zt_backend .runner .code_cell_parser import (
12+ get_imports ,
13+ get_defined_names ,
14+ get_loaded_names ,
15+ get_loaded_modules ,
16+ get_functions ,
17+ )
1218def parse_cell (func ):
1319 """
1420 Inspect the function to detect:
@@ -39,7 +45,7 @@ def parse_cell(func):
3945 def filter_return_statements (node ):
4046 """Recursively remove trivial returns from function bodies."""
4147 if isinstance (node , ast .FunctionDef ):
42- node .body = [filter_return_statements (subnode ) for subnode in node .body if not (isinstance (subnode , ast .Return ))]
48+ node .body = [filter_return_statements (subnode ) for subnode in node .body if not (isinstance (subnode , ast .Return ) and not subnode . value )]
4349 elif isinstance (node , ast .Module ):
4450 node .body = [filter_return_statements (subnode ) for subnode in node .body ]
4551 return node
@@ -133,15 +139,33 @@ def load_notebook_from_file(file_path, notebook_variable_name="notebook"):
133139 raise AttributeError (f"{ notebook_variable_name } not found in { file_path } " )
134140
135141
136- def build_cell_code_block (fn_name , cell_obj , def_line ):
142+ def update_notebook_file (filepath , notebook_obj ):
143+ """
144+ Update or create a Python file to match the given Notebook’s cell definitions
145+ and *physically remove* the function definition for any cell that was deleted
146+ from the notebook.
147+ This version:
148+ - Keeps exactly one blank line before each cell (if needed).
149+ - Removes old functions if they've been removed from the notebook.
150+ - If a cell is recognized as markdown/sql/text, it writes zt.markdown(...), zt.sql(...), etc. in the file,
151+ but the notebook only loads the raw string (see parse_cell).
152+ """
153+ import re
154+ import_line = "import zero_true as zt\n "
155+
156+ # Helper function to ensure at most one blank line
157+ def maybe_add_blank_line (line_list ):
158+ if line_list and line_list [- 1 ].strip (): # last line not empty
159+ line_list .append ("\n " )
160+
161+ # Helper to build code block for each cell (in the file).
162+ def build_cell_code_block (fn_name , cell_obj , def_line ):
137163 """
138164 If the cell is e.g. sql, we'll put " zt.sql(\" \" \" ...\" )" in the file.
139165 Meanwhile, in the notebook data structure, .code contains only the raw query.
140166 """
141- return_line = " return\n "
142-
143- if cell_obj .cellType == "code" :
144- # 1) Attempt to parse & extract loaded/defined names
167+ return_line = " return"
168+ if cell_obj .cellType == 'code' :
145169 try :
146170 module = astroid .parse (cell_obj .code )
147171 all_imports = get_imports (module )
@@ -166,16 +190,9 @@ def build_cell_code_block(fn_name, cell_obj, def_line):
166190
167191 # 2) Build function signature (optional arguments)
168192 if loaded_names :
169- signature_line = f"def { fn_name } ({ ', ' .join (loaded_names )} ):"
170- else :
171- signature_line = f"def { fn_name } ():"
172-
173- def_line = signature_line
174-
193+ def_line = f"def { fn_name } ({ ', ' .join (loaded_names )} ):"
175194 if defined_names :
176- return_line = f" return { ', ' .join (defined_names )} \n "
177-
178-
195+ return_line = f" return({ ', ' .join (defined_names )} )"
179196
180197 lines = [def_line ] # e.g. "def cell_0():"
181198 if cell_obj .cellType in ["markdown" , "sql" , "text" ]:
@@ -188,28 +205,6 @@ def build_cell_code_block(fn_name, cell_obj, def_line):
188205 lines .append (return_line )
189206 return lines
190207
191-
192-
193- def update_notebook_file (filepath , notebook_obj ):
194- """
195- Update or create a Python file to match the given Notebook’s cell definitions
196- and *physically remove* the function definition for any cell that was deleted
197- from the notebook.
198- This version:
199- - Keeps exactly one blank line before each cell (if needed).
200- - Removes old functions if they've been removed from the notebook.
201- - If a cell is recognized as markdown/sql/text, it writes zt.markdown(...), zt.sql(...), etc. in the file,
202- but the notebook only loads the raw string (see parse_cell).
203- """
204- import re
205- import_line = "import zero_true as zt\n "
206-
207- # Helper function to ensure at most one blank line
208- def maybe_add_blank_line (line_list ):
209- if line_list and line_list [- 1 ].strip (): # last line not empty
210- line_list .append ("\n " )
211-
212-
213208 # 1) Read existing lines or init
214209 try :
215210 with open (filepath , 'r' ) as f :
0 commit comments