Skip to content

Commit 6c36f48

Browse files
ref: split ast parsing / class exec loops (#7248)
* Split ast parsing / class exec loops * remove unnecessary module check * remove comment * [autofix.ci] apply automated fixes * ruff * [autofix.ci] apply automated fixes * Ruff * [autofix.ci] apply automated fixes * ruff --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 2407fe3 commit 6c36f48

File tree

2 files changed

+63
-36
lines changed

2 files changed

+63
-36
lines changed

Diff for: src/backend/base/langflow/custom/custom_component/component.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,10 @@ def set_class_code(self) -> None:
306306
if module is None:
307307
msg = "Could not find module for class"
308308
raise ValueError(msg)
309+
309310
class_code = inspect.getsource(module)
310311
self._code = class_code
311-
except OSError as e:
312+
except (OSError, TypeError) as e:
312313
msg = f"Could not find source code for {self.__class__.__name__}"
313314
raise ValueError(msg) from e
314315

Diff for: src/backend/base/langflow/utils/validate.py

+61-35
Original file line numberDiff line numberDiff line change
@@ -185,25 +185,35 @@ def create_class(code, class_name):
185185
if not hasattr(ast, "TypeIgnore"):
186186
ast.TypeIgnore = create_type_ignore_class()
187187

188-
# Replace from langflow import CustomComponent with from langflow.custom import CustomComponent
189188
code = code.replace("from langflow import CustomComponent", "from langflow.custom import CustomComponent")
190189
code = code.replace(
191190
"from langflow.interface.custom.custom_component import CustomComponent",
192191
"from langflow.custom import CustomComponent",
193192
)
194-
# Add DEFAULT_IMPORT_STRING
195-
code = DEFAULT_IMPORT_STRING + "\n" + code
196-
module = ast.parse(code)
197-
exec_globals = prepare_global_scope(module)
198193

199-
class_code = extract_class_code(module, class_name)
200-
compiled_class = compile_class_code(class_code)
194+
code = DEFAULT_IMPORT_STRING + "\n" + code
201195
try:
196+
module = ast.parse(code)
197+
exec_globals = prepare_global_scope(module)
198+
199+
class_code = extract_class_code(module, class_name)
200+
compiled_class = compile_class_code(class_code)
201+
202202
return build_class_constructor(compiled_class, exec_globals, class_name)
203+
204+
except SyntaxError as e:
205+
msg = f"Syntax error in code: {e!s}"
206+
raise ValueError(msg) from e
207+
except NameError as e:
208+
msg = f"Name error (possibly undefined variable): {e!s}"
209+
raise ValueError(msg) from e
203210
except ValidationError as e:
204211
messages = [error["msg"].split(",", 1) for error in e.errors()]
205212
error_message = "\n".join([message[1] if len(message) > 1 else message[0] for message in messages])
206213
raise ValueError(error_message) from e
214+
except Exception as e:
215+
msg = f"Error creating class: {e!s}"
216+
raise ValueError(msg) from e
207217

208218

209219
def create_type_ignore_class():
@@ -232,40 +242,56 @@ def prepare_global_scope(module):
232242
ModuleNotFoundError: If a module is not found in the code
233243
"""
234244
exec_globals = globals().copy()
245+
imports = []
246+
import_froms = []
247+
definitions = []
248+
235249
for node in module.body:
236250
if isinstance(node, ast.Import):
237-
for alias in node.names:
238-
try:
239-
exec_globals[alias.asname or alias.name] = importlib.import_module(alias.name)
240-
except ModuleNotFoundError as e:
241-
msg = f"Module {alias.name} not found. Please install it and try again."
242-
raise ModuleNotFoundError(msg) from e
251+
imports.append(node)
243252
elif isinstance(node, ast.ImportFrom) and node.module is not None:
253+
import_froms.append(node)
254+
elif isinstance(node, ast.ClassDef | ast.FunctionDef | ast.Assign):
255+
definitions.append(node)
256+
257+
for node in imports:
258+
for alias in node.names:
244259
try:
245-
with warnings.catch_warnings():
246-
warnings.simplefilter("ignore", LangChainDeprecationWarning)
247-
imported_module = importlib.import_module(node.module)
248-
for alias in node.names:
249-
try:
250-
# First try getting it as an attribute
251-
exec_globals[alias.name] = getattr(imported_module, alias.name)
252-
except AttributeError:
253-
# If that fails, try importing the full module path
254-
full_module_path = f"{node.module}.{alias.name}"
255-
exec_globals[alias.name] = importlib.import_module(full_module_path)
260+
module_name = alias.name
261+
variable_name = alias.asname or alias.name
262+
exec_globals[variable_name] = importlib.import_module(module_name)
256263
except ModuleNotFoundError as e:
257-
msg = f"Module {node.module} not found. Please install it and try again"
264+
msg = f"Module {alias.name} not found. Please install it and try again."
258265
raise ModuleNotFoundError(msg) from e
259-
elif isinstance(node, ast.ClassDef):
260-
# Compile and execute the class definition to properly create the class
261-
class_code = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
262-
exec(class_code, exec_globals)
263-
elif isinstance(node, ast.FunctionDef):
264-
function_code = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
265-
exec(function_code, exec_globals)
266-
elif isinstance(node, ast.Assign):
267-
assign_code = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
268-
exec(assign_code, exec_globals)
266+
267+
for node in import_froms:
268+
try:
269+
module_name = node.module
270+
# Apply warning suppression only when needed
271+
if "langchain" in module_name:
272+
with warnings.catch_warnings():
273+
warnings.simplefilter("ignore", LangChainDeprecationWarning)
274+
imported_module = importlib.import_module(module_name)
275+
else:
276+
imported_module = importlib.import_module(module_name)
277+
278+
for alias in node.names:
279+
try:
280+
# First try getting it as an attribute
281+
exec_globals[alias.name] = getattr(imported_module, alias.name)
282+
except AttributeError:
283+
# If that fails, try importing the full module path
284+
full_module_path = f"{module_name}.{alias.name}"
285+
exec_globals[alias.name] = importlib.import_module(full_module_path)
286+
except ModuleNotFoundError as e:
287+
msg = f"Module {node.module} not found. Please install it and try again"
288+
raise ModuleNotFoundError(msg) from e
289+
290+
if definitions:
291+
combined_module = ast.Module(body=definitions, type_ignores=[])
292+
compiled_code = compile(combined_module, "<string>", "exec")
293+
exec(compiled_code, exec_globals)
294+
269295
return exec_globals
270296

271297

0 commit comments

Comments
 (0)